Changeset: 6b6df5a903f4 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/6b6df5a903f4
Branch: default
Log Message:
Merge with Mar2025 branch.
diffs (truncated from 1428 to 300 lines):
diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -1663,6 +1663,7 @@ list *sa_list(allocator *sa);
char *sa_message(allocator *sa, _In_z_ _Printf_format_string_ const char
*format, ...) __attribute__((__format__(__printf__, 2, 3)));
msettings *sa_msettings_create(allocator *sa);
char *sa_msettings_to_string(const msettings *mp, allocator *sa, size_t
size_hint);
+sql_type *schema_bind_type(mvc *sql, sql_schema *s, const char *name);
str sht_dec2_bte(bte *res, const int *s1, const sht *v);
str sht_dec2_dbl(dbl *res, const int *s1, const sht *v);
str sht_dec2_flt(flt *res, const int *s1, const sht *v);
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -6655,6 +6655,7 @@ rel2bin_update(backend *be, sql_rel *rel
node *m;
sql_rel *tr = rel->l, *prel = rel->r;
sql_table *t = NULL;
+ bool needs_returning = rel->returning;
if ((rel->flag&UPD_COMP)) { /* special case ! */
idx_ups = 1;
@@ -6754,7 +6755,7 @@ rel2bin_update(backend *be, sql_rel *rel
}
stmt* returning = NULL;
- if (rel->returning) {
+ if (needs_returning) {
sql_rel* b = rel->l;
int refcnt = b->ref.refcnt; // HACK: forces recalculation of
base columns since they are assumed to be updated
b->ref.refcnt = 1;
diff --git a/sql/backends/monet5/vaults/odbc/odbc_loader.c
b/sql/backends/monet5/vaults/odbc/odbc_loader.c
--- a/sql/backends/monet5/vaults/odbc/odbc_loader.c
+++ b/sql/backends/monet5/vaults/odbc/odbc_loader.c
@@ -56,6 +56,9 @@ typedef struct {
SQLSMALLINT decimalDigits; /* ODBC dec. digits, contains scale for
decimals */
int battype; /* MonetDB atom type, used to create
the BAT */
BAT * bat; /* MonetDB BAT */
+ SQLSMALLINT targetType; /* needed for SQLGetData */
+ SQLPOINTER * targetValuePtr; /* needed for SQLGetData */
+ SQLLEN bufferLength; /* needed for SQLGetData */
} rescol_t;
/* map ODBC SQL datatype to MonetDB SQL datatype */
@@ -104,6 +107,26 @@ map_rescol_type(SQLSMALLINT dataType, SQ
// prec = scale; /* make precision large enough to
contain all decimal digits */
// return sql_bind_subtype(sql->sa, "decimal", prec, scale);
}
+ case SQL_GUID:
+ {
+ /* represents a uuid of length 36, such as:
dbe7343c-1f11-4fa9-a9c8-a31cd26f92fe */
+ sql_subtype * tp = sql_bind_subtype(sql->sa, "uuid", 0, 0);
// this fails to return a valid pointer
+ if (tp != NULL)
+ return tp;
+ // try a different way
+ sql_schema *syss = mvc_bind_schema(sql, "sys");
+ if (syss) {
+ tp = SA_ZNEW(sql->sa, sql_subtype);
+ if (tp != NULL) {
+ tp->digits = tp->scale = 0;
+ tp->type = schema_bind_type(sql, syss, "uuid");
+ if (tp->type != NULL)
+ return tp;
+ }
+ }
+ /* fall back to map it to a char(36) result column type */
+ return sql_bind_subtype(sql->sa, "char", (unsigned int)
UUID_STRLEN, 0);
+ }
case SQL_BIT:
typenm = "boolean";
@@ -205,11 +228,6 @@ map_rescol_type(SQLSMALLINT dataType, SQ
typenm = "sec_interval";
interval_type = 12;
break;
-
- case SQL_GUID:
- /* represents a uuid of length 36, such as:
dbe7343c-1f11-4fa9-a9c8-a31cd26f92fe */
- typenm = "uuid";
- break;
}
return sql_bind_subtype(sql->sa, typenm, interval_type, 0);
}
@@ -323,6 +341,12 @@ getErrMsg(SQLSMALLINT handleType, SQLHAN
ret = SQLGetDiagRec(handleType, handle, 1, state, &errnr, msg,
SQL_MAX_MESSAGE_LENGTH -1, &msglen);
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
const char format[] = "SQLSTATE %s, Error code %d, Message %s";
+ /* ignore msg when using MS Excel ODBC driver, which does not
support setting connection timeout */
+ if ((strcmp("IM006", (char *)state) == 0)
+ && (strcmp("[Microsoft][ODBC Driver Manager] Driver's
SQLSetConnectAttr failed", (char *)msg) == 0)) {
+ return NULL;
+ }
+
if (msglen <= 0) {
/* e.g SQL_NTS */
msglen = (SQLSMALLINT) strlen((char *)msg);
@@ -383,6 +407,35 @@ bat_create(int adt, BUN nr)
return b;
}
+/* convert interval.day_second.fraction values to millisec fractions as needed
by MonetDB interval types.
+ * we need the columns decimalDigits specification to adjust the fractions
value to millisec.
+ */
+static SQLUINTEGER
+fraction2msec(SQLUINTEGER fraction, SQLSMALLINT decimaldigits) {
+ SQLUINTEGER msec = fraction;
+ if (msec == 0)
+ return 0;
+
+ switch (decimaldigits) {
+ case 6: msec = fraction / 1000; break;
+ case 3: msec = fraction; break;
+ case 0: msec = fraction * 1000; break;
+ case 1: msec = fraction * 100; break;
+ case 2: msec = fraction * 10; break;
+ case 4: msec = fraction / 10; break;
+ case 5: msec = fraction / 100; break;
+ case 7: msec = fraction / 10000; break;
+ case 8: msec = fraction / 100000; break;
+ case 9: msec = fraction / 1000000; break;
+ }
+
+ // millisec value should be no larger than 999
+ while (msec > 999) {
+ msec = msec / 10;
+ }
+ return msec;
+}
+
/*
* odbc_query() contains the logic for both odbc_relation() and ODBCloader()
* the caller argument is ODBC_RELATION when called from odbc_relation and
ODBC_LOADER when called from ODBCloader
@@ -390,8 +443,6 @@ bat_create(int adt, BUN nr)
static str
odbc_query(int caller, mvc *sql, sql_subfunc *f, char *url, list *res_exps,
MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
- bool trace_enabled = false; /* used for development only */
-
if (sql == NULL)
return "Missing mvc value.";
if (f == NULL)
@@ -429,9 +480,7 @@ odbc_query(int caller, mvc *sql, sql_sub
return "Missing ODBC connection string.";
}
- // trace_enabled = true;
- if (trace_enabled)
- printf("\nExtracted ODBC connection string: %s\n and SQL
query: %s\n", odbc_con_str, query);
+ TRC_INFO(LOADER, "\nExtracted ODBC connection string: %s\n and SQL
query: %s\n", odbc_con_str, query);
/* now we can (try to) connect to the ODBC driver and execute the SQL
query */
SQLRETURN ret = SQL_INVALID_HANDLE;
@@ -478,11 +527,11 @@ odbc_query(int caller, mvc *sql, sql_sub
if (ret == SQL_SUCCESS_WITH_INFO && caller == ODBC_RELATION) {
/* show the info warning, but only once */
char * ODBCmsg = getErrMsg(SQL_HANDLE_DBC, dbc);
- printf("SQLDriverConnect(%s) returned %s ODBCmsg: %s\n",
odbc_con_str, nameOfRetCode(ret), (ODBCmsg) ? ODBCmsg : "");
+ TRC_INFO(LOADER, "SQLDriverConnect(%s) returned %s ODBCmsg:
%s\n", odbc_con_str, nameOfRetCode(ret), (ODBCmsg) ? ODBCmsg : "");
if (ODBCmsg)
GDKfree(ODBCmsg);
- } else if (trace_enabled) {
- printf("SQLDriverConnect(%s) returned %s\n", odbc_con_str,
nameOfRetCode(ret));
+ } else {
+ TRC_DEBUG(LOADER, "SQLDriverConnect(%s) returned %s\n",
odbc_con_str, nameOfRetCode(ret));
}
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
errmsg = "SQLDriverConnect failed.";
@@ -503,13 +552,11 @@ odbc_query(int caller, mvc *sql, sql_sub
char DBMSname[128];
ret = SQLGetInfo(dbc, SQL_DBMS_NAME, (SQLPOINTER) &DBMSname,
127, NULL);
if (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
- if (trace_enabled)
- printf("SQLGetInfo(dbc, SQL_DBMS_NAME) returned
%s\n", DBMSname);
+ TRC_DEBUG(LOADER, "SQLGetInfo(dbc, SQL_DBMS_NAME)
returned %s\n", DBMSname);
if (strcmp("MonetDB", DBMSname) == 0) {
- /* enable the MonetDB ODBC driver to return
SQL_HUGEINT as column datatype */
+ /* instruct the MonetDB ODBC driver to return
SQL_HUGEINT as column datatype */
ret = SQLGetTypeInfo(stmt, SQL_HUGEINT);
- if (trace_enabled)
- printf("SQLGetTypeInfo(stmt,
SQL_HUGEINT) returned %s\n", nameOfRetCode(ret));
+ TRC_DEBUG(LOADER, "SQLGetTypeInfo(stmt,
SQL_HUGEINT) returned %s\n", nameOfRetCode(ret));
if (ret == SQL_SUCCESS || ret ==
SQL_SUCCESS_WITH_INFO) {
ret = SQLCloseCursor(stmt);
}
@@ -529,11 +576,11 @@ odbc_query(int caller, mvc *sql, sql_sub
if (ret == SQL_SUCCESS_WITH_INFO && caller == ODBC_RELATION) {
/* show the info warning, but only once */
char * ODBCmsg = getErrMsg(SQL_HANDLE_STMT, stmt);
- printf("SQLExecDirect(%s) returned %s ODBCmsg: %s\n", query,
nameOfRetCode(ret), (ODBCmsg) ? ODBCmsg : "");
+ TRC_INFO(LOADER, "SQLExecDirect(%s) returned %s ODBCmsg: %s\n",
query, nameOfRetCode(ret), (ODBCmsg) ? ODBCmsg : "");
if (ODBCmsg)
GDKfree(ODBCmsg);
- } else if (trace_enabled) {
- printf("SQLExecDirect(%s) returned %s\n", query,
nameOfRetCode(ret));
+ } else {
+ TRC_DEBUG(LOADER, "SQLExecDirect(%s) returned %s\n", query,
nameOfRetCode(ret));
}
if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
errmsg = "SQLExecDirect query failed.";
@@ -553,12 +600,11 @@ odbc_query(int caller, mvc *sql, sql_sub
errmsg = "ODBC query did not return a resultset.";
goto finish;
}
- if (trace_enabled)
- printf("Query has %d result columns\n", nr_cols);
+ TRC_INFO(LOADER, "Query has %d result columns\n", nr_cols);
if (nr_cols > QUERY_MAX_COLUMNS) {
/* limit the number of data columns, as we do not want to block
or blow up the mserver */
nr_cols = QUERY_MAX_COLUMNS;
- printf("\nODBC_loader limited Query result to first %d
columns.\n", nr_cols);
+ TRC_INFO(LOADER, "ODBC_loader limited Query result to first %d
columns.\n", nr_cols);
}
/* when called from odbc_relation() */
@@ -573,6 +619,7 @@ odbc_query(int caller, mvc *sql, sql_sub
sql_subtype * sql_mtype;
list * typelist = sa_list(sql->sa);
list * nameslist = sa_list(sql->sa);
+ strcpy(tname, "");
for (SQLUSMALLINT col = 1; col <= (SQLUSMALLINT) nr_cols;
col++) {
/* for each result column get name, datatype, size and
decdigits */
// TODO use ODBC W function
@@ -582,12 +629,14 @@ odbc_query(int caller, mvc *sql, sql_sub
errmsg = "SQLDescribeCol failed.";
goto finish;
}
- if (trace_enabled)
- printf("ResCol %u, name: %s, type %d (%s), size
%u, decdigits %d\n",
+ TRC_DEBUG(LOADER, "ResCol %u, name: %s, type %d (%s),
size %u, decdigits %d\n",
col, cname, dataType,
nameofSQLtype(dataType), (unsigned int)columnSize, decimalDigits);
+ sql_mtype = map_rescol_type(dataType, columnSize,
decimalDigits, sql);
+ if (sql_mtype == NULL)
+ continue; /* skip this column */
+
colname = sa_strdup(sql->sa, cname);
list_append(nameslist, colname);
- sql_mtype = map_rescol_type(dataType, columnSize,
decimalDigits, sql);
list_append(typelist, sql_mtype);
if (res_exps) {
@@ -620,9 +669,32 @@ odbc_query(int caller, mvc *sql, sql_sub
goto finish;
}
+ /* allocate buffers for each of the fixed size atom types. */
+ bit bit_val = 0;
+ bte bte_val = 0;
+ sht sht_val = 0;
+ int int_val = 0;
+ lng lng_val = 0;
+#ifdef HAVE_HGE
+ hge hge_val = 0; // for hugeint and decimals with
precision > 18
+#endif
+ flt flt_val = 0;
+ dbl dbl_val = 0;
+ DATE_STRUCT date_val;
+ TIME_STRUCT time_val;
+ TIMESTAMP_STRUCT ts_val;
+ SQL_INTERVAL_STRUCT itv_val;
+ SQLGUID guid_val;
+ union {
+ uuid uuid_val;
+ uint8_t u[UUID_SIZE];
+ } u_val;
+
+ bool hasStrCols = false;
SQLULEN largestStringSize = 0;
bool hasBlobCols = false;
SQLULEN largestBlobSize = 0;
+
/* make bats with right atom type */
for (SQLUSMALLINT col = 0; col < (SQLUSMALLINT) nr_cols; col++)
{
char cname[MAX_COL_NAME_LEN +1];
@@ -646,58 +718,203 @@ odbc_query(int caller, mvc *sql, sql_sub
GDKfree(colmetadata);
goto finish;
}
- if (trace_enabled)
- printf("DescCol %u, name: %s, type %d (%s),
size %u, decdigits %d\n",
+ TRC_DEBUG(LOADER, "DescCol %u, name: %s, type %d (%s),
size %u, decdigits %d\n",
col+1, cname, dataType,
nameofSQLtype(dataType), (unsigned int)columnSize, decimalDigits);
- /* use same logic as used in map_rescol_type() for
SQL_FLOAT and SQL_DECIMAL */
- if (dataType == SQL_FLOAT) {
- dataType = (columnSize == 7) ? SQL_REAL :
SQL_DOUBLE;
- } else
- if (dataType == SQL_HUGEINT) {
- dataType = SQL_VARCHAR; /* read it as string */
- columnSize = 50;
- } else
- if (dataType == SQL_DECIMAL || dataType == SQL_NUMERIC)
{
- /* MonetDB has limits for the precision and
scale */
- if (columnSize > MAX_PREC || abs(decimalDigits)
> MAX_PREC) {
- /* very large precision/scale, not
supported by MonetDB. Map this column to a string */
- dataType = SQL_VARCHAR;
-// columnSize += 3; /* add 3 for
sign, leading 0 and decimal separator */
- }
-// columnSize = MAX(1, columnSize); /* precision
must be >= 1 */
-// decimalDigits = MAX(0, decimalDigits); /*
negative scales are not supported by MonetDB */
-// if ((int)columnSize < decimalDigits)
-// columnSize = decimalDigits; /* make
precision large enough to contain all decimal digits */
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]