Changeset: c0bbfa8c3f8f for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/c0bbfa8c3f8f Modified Files: ChangeLog clients/odbc/tests/ODBCtester.c monetdb5/mal/mal_client.c monetdb5/mal/mal_client.h Branch: default Log Message:
Merge with Mar2025 branch. diffs (truncated from 375 to 300 lines): diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,6 @@ # ChangeLog file for devel # This file is updated with Maddlog -* Thu May 8 2025 Sjoerd Mullender <[email protected]> -- It is now possible to specify an idle timeout using --set - idle_timeout=<seconds> (see mserver5 manual page) which gets triggered - if a connection to the server is idle (i.e. does not send any queries - to the server) while there is a SQL transaction active. - * Mon Apr 28 2025 Niels Nes <[email protected]> - Changed the way complex AND and OR expressions are handled. The new expression tree uses 2 new cmp flag (cmp_con/cmp_dis), both expressions diff --git a/ChangeLog.Mar2025 b/ChangeLog.Mar2025 --- a/ChangeLog.Mar2025 +++ b/ChangeLog.Mar2025 @@ -1,3 +1,9 @@ # ChangeLog file for devel # This file is updated with Maddlog +* Thu May 8 2025 Sjoerd Mullender <[email protected]> +- It is now possible to specify an idle timeout using --set + idle_timeout=<seconds> (see mserver5 manual page) which gets triggered + if a connection to the server is idle (i.e. does not send any queries + to the server) while there is a SQL transaction active. + diff --git a/clients/odbc/driver/ODBCConvert.c b/clients/odbc/driver/ODBCConvert.c --- a/clients/odbc/driver/ODBCConvert.c +++ b/clients/odbc/driver/ODBCConvert.c @@ -1019,23 +1019,39 @@ ODBCFetch(ODBCStmt *stmt, if (type == SQL_C_DEFAULT) type = ODBCDefaultType(irdrec); - if (precision == UNAFFECTED || - scale == UNAFFECTED || - datetime_interval_precision == UNAFFECTED) { + if (precision == UNAFFECTED) { + precision = (ardrec) ? ardrec->sql_desc_precision : (type == SQL_C_NUMERIC) ? 10 : 6; + } + if (scale == UNAFFECTED) { + scale = (ardrec) ? ardrec->sql_desc_scale : 0; + } + if (datetime_interval_precision == UNAFFECTED) { if (ardrec) { - if (precision == UNAFFECTED) - precision = ardrec->sql_desc_precision; - if (scale == UNAFFECTED) - scale = ardrec->sql_desc_scale; - if (datetime_interval_precision == UNAFFECTED) - datetime_interval_precision = ardrec->sql_desc_datetime_interval_precision; + datetime_interval_precision = ardrec->sql_desc_datetime_interval_precision; } else { - if (precision == UNAFFECTED) - precision = type == SQL_C_NUMERIC ? 10 : 6; - if (scale == UNAFFECTED) - scale = 0; - if (datetime_interval_precision == UNAFFECTED) + switch (type) { + case SQL_C_INTERVAL_YEAR: + datetime_interval_precision = 4; + break; + case SQL_C_INTERVAL_YEAR_TO_MONTH: + case SQL_C_INTERVAL_MONTH: + datetime_interval_precision = 6; + break; + case SQL_C_INTERVAL_DAY: + case SQL_C_INTERVAL_DAY_TO_HOUR: + case SQL_C_INTERVAL_DAY_TO_MINUTE: + case SQL_C_INTERVAL_DAY_TO_SECOND: + case SQL_C_INTERVAL_HOUR: + case SQL_C_INTERVAL_HOUR_TO_MINUTE: + case SQL_C_INTERVAL_HOUR_TO_SECOND: + case SQL_C_INTERVAL_MINUTE: + case SQL_C_INTERVAL_MINUTE_TO_SECOND: + case SQL_C_INTERVAL_SECOND: + datetime_interval_precision = 9; + break; + default: datetime_interval_precision = 2; + } } } i = datetime_interval_precision; diff --git a/clients/odbc/tests/ODBCtester.c b/clients/odbc/tests/ODBCtester.c --- a/clients/odbc/tests/ODBCtester.c +++ b/clients/odbc/tests/ODBCtester.c @@ -269,7 +269,7 @@ testGetDataGUID(SQLHANDLE stmt) pos += snprintf(outp + pos, outp_len - pos, "NULL\n"); else pos += snprintf(outp + pos, outp_len - pos, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", - (unsigned int) guid_val.Data1, guid_val.Data2, guid_val.Data3, + guid_val.Data1, guid_val.Data2, guid_val.Data3, guid_val.Data4[0], guid_val.Data4[1], guid_val.Data4[2], guid_val.Data4[3], guid_val.Data4[4], guid_val.Data4[5], guid_val.Data4[6], guid_val.Data4[7]); check(ret, SQL_HANDLE_STMT, stmt, "SQLGetData(col)"); } @@ -297,6 +297,118 @@ testGetDataGUID(SQLHANDLE stmt) return ret; } +static SQLRETURN +testGetDataIntervalDay(SQLHANDLE stmt, int sqlquery) +{ + SQLRETURN ret; + SQLLEN RowCount = 0; + SWORD NumResultCols = 0; + + size_t outp_len = 1800; + char * outp = malloc(outp_len); + size_t pos = 0; + + char * sql1 = "select cast(NULL as interval day) as valnil, cast('99' as interval day) as val1, cast('-99' as interval day) as val2;"; + char * sql2 = "select cast(NULL as interval day) as valnil, cast('101' as interval day) as val1, cast('-102' as interval day) as val2;"; /* Interval field overflow */ + ret = SQLExecDirect(stmt, (sqlquery == 1) ? (SQLCHAR *) sql1 : (SQLCHAR *) sql2, SQL_NTS); + pos += snprintf(outp + pos, outp_len - pos, "SQLExecDirect query %d\n", sqlquery); + check(ret, SQL_HANDLE_STMT, stmt, "SQLExecDirect"); + + ret = SQLRowCount(stmt, &RowCount); + pos += snprintf(outp + pos, outp_len - pos, "SQLRowCount is " LLFMT "\n", (int64_t) RowCount); + check(ret, SQL_HANDLE_STMT, stmt, "SQLRowCount"); + + ret = SQLNumResultCols(stmt, &NumResultCols); + pos += snprintf(outp + pos, outp_len - pos, "SQLNumResultCols is %d\n", NumResultCols); + check(ret, SQL_HANDLE_STMT, stmt, "SQLNumResultCols"); + + ret = SQLFetch(stmt); + pos += snprintf(outp + pos, outp_len - pos, "SQLFetch\n"); + check(ret, SQL_HANDLE_STMT, stmt, "SQLFetch"); + + for (SWORD col = 1; col <= NumResultCols; col++) { + char buf[99]; + char str_val[42]; + int int_val; + SQL_INTERVAL_STRUCT itv_val; + SQLLEN vallen = 0; + SQLLEN NumAttr = 0; + + /* retrieve query result column metadata */ + ret = SQLColAttribute(stmt, (UWORD)col, SQL_DESC_CONCISE_TYPE, (PTR)&buf, (SQLLEN)20, NULL, &NumAttr); + pos += snprintf(outp + pos, outp_len - pos, "SQLColAttribute(%d, SQL_DESC_CONCISE_TYPE) returns %d, NumAttr " LLFMT "\n", col, ret, (int64_t) NumAttr); + ret = SQLColAttribute(stmt, (UWORD)col, SQL_DESC_DISPLAY_SIZE, (PTR)&buf, (SQLLEN)20, NULL, &NumAttr); + pos += snprintf(outp + pos, outp_len - pos, "SQLColAttribute(%d, SQL_DESC_DISPLAY_SIZE) returns %d, NumAttr " LLFMT "\n", col, ret, (int64_t) NumAttr); + + /* test SQLGetData(SQL_C_CHAR) */ + ret = SQLGetData(stmt, (UWORD)col, (SWORD)SQL_C_CHAR, (PTR)&str_val, (SQLLEN)41, &vallen); + pos += snprintf(outp + pos, outp_len - pos, "SQLGetData(%d, SQL_C_CHAR, 41) returns %d, vallen " LLFMT ", str_val: '%s'\n", + col, ret, (int64_t) vallen, (vallen == SQL_NULL_DATA) ? "NULL" : str_val); + check(ret, SQL_HANDLE_STMT, stmt, "SQLGetData(col) as str"); + + /* test SQLGetData(SQL_C_SLONG) */ + ret = SQLGetData(stmt, (UWORD)col, (SWORD)SQL_C_SLONG, (PTR)&int_val, (SQLLEN)4, &vallen); + pos += snprintf(outp + pos, outp_len - pos, "SQLGetData(%d, SQL_C_SLONG) returns %d, vallen " LLFMT ", int_val: ", col, ret, (int64_t) vallen); + if (vallen == SQL_NULL_DATA) + pos += snprintf(outp + pos, outp_len - pos, "NULL\n"); + else + pos += snprintf(outp + pos, outp_len - pos, "%d\n", int_val); + check(ret, SQL_HANDLE_STMT, stmt, "SQLGetData(col) as int"); /* SQLstate 07006 Restricted data type attribute violation */ + + /* test SQLGetData(SQL_C_INTERVAL_DAY) */ + ret = SQLGetData(stmt, (UWORD)col, (SWORD)SQL_C_INTERVAL_DAY, (PTR)&itv_val, (SQLLEN)sizeof(SQL_INTERVAL_STRUCT), &vallen); + pos += snprintf(outp + pos, outp_len - pos, "SQLGetData(%d, SQL_C_INTERVAL_DAY) returns %d, vallen " LLFMT ", itv_day_val: ", col, ret, (int64_t) vallen); + if (vallen == SQL_NULL_DATA) + pos += snprintf(outp + pos, outp_len - pos, "NULL\n"); + else + pos += snprintf(outp + pos, outp_len - pos, "%d (type %d, sign %d)\n", itv_val.intval.day_second.day, itv_val.interval_type, itv_val.interval_sign); + check(ret, SQL_HANDLE_STMT, stmt, "SQLGetData(col) as int"); + } + + compareResult("testGetDataIntervalDay()", outp, + (sqlquery == 1) + ? "SQLExecDirect query 1\nSQLRowCount is 1\nSQLNumResultCols is 3\nSQLFetch\n" + "SQLColAttribute(1, SQL_DESC_CONCISE_TYPE) returns 0, NumAttr 103\n" + "SQLColAttribute(1, SQL_DESC_DISPLAY_SIZE) returns 0, NumAttr 21\n" + "SQLGetData(1, SQL_C_CHAR, 41) returns 0, vallen -1, str_val: 'NULL'\n" + "SQLGetData(1, SQL_C_SLONG) returns 0, vallen -1, int_val: NULL\n" + "SQLGetData(1, SQL_C_INTERVAL_DAY) returns 0, vallen -1, itv_day_val: NULL\n" + "SQLColAttribute(2, SQL_DESC_CONCISE_TYPE) returns 0, NumAttr 103\n" + "SQLColAttribute(2, SQL_DESC_DISPLAY_SIZE) returns 0, NumAttr 21\n" + "SQLGetData(2, SQL_C_CHAR, 41) returns 0, vallen 17, str_val: 'INTERVAL '99' DAY'\n" + "SQLGetData(2, SQL_C_SLONG) returns 0, vallen 4, int_val: 99\n" /* SQLstate 07006 Restricted data type attribute violation */ + "SQLGetData(2, SQL_C_INTERVAL_DAY) returns 0, vallen 28, itv_day_val: 99 (type 3, sign 0)\n" + "SQLColAttribute(3, SQL_DESC_CONCISE_TYPE) returns 0, NumAttr 103\n" + "SQLColAttribute(3, SQL_DESC_DISPLAY_SIZE) returns 0, NumAttr 21\n" + "SQLGetData(3, SQL_C_CHAR, 41) returns 0, vallen 18, str_val: 'INTERVAL -'99' DAY'\n" + "SQLGetData(3, SQL_C_SLONG) returns 0, vallen 4, int_val: -99\n" /* SQLstate 07006 Restricted data type attribute violation */ + "SQLGetData(3, SQL_C_INTERVAL_DAY) returns 0, vallen 28, itv_day_val: 99 (type 3, sign 1)\n" + : "SQLExecDirect query 2\nSQLRowCount is 1\nSQLNumResultCols is 3\nSQLFetch\n" + "SQLColAttribute(1, SQL_DESC_CONCISE_TYPE) returns 0, NumAttr 103\n" + "SQLColAttribute(1, SQL_DESC_DISPLAY_SIZE) returns 0, NumAttr 21\n" + "SQLGetData(1, SQL_C_CHAR, 41) returns 0, vallen -1, str_val: 'NULL'\n" + "SQLGetData(1, SQL_C_SLONG) returns 0, vallen -1, int_val: NULL\n" + "SQLGetData(1, SQL_C_INTERVAL_DAY) returns 0, vallen -1, itv_day_val: NULL\n" + "SQLColAttribute(2, SQL_DESC_CONCISE_TYPE) returns 0, NumAttr 103\n" + "SQLColAttribute(2, SQL_DESC_DISPLAY_SIZE) returns 0, NumAttr 21\n" + "SQLGetData(2, SQL_C_CHAR, 41) returns 0, vallen 18, str_val: 'INTERVAL '101' DAY'\n" + "SQLGetData(2, SQL_C_SLONG) returns 0, vallen 4, int_val: 101\n" /* SQLstate 07006 Restricted data type attribute violation */ + "SQLGetData(2, SQL_C_INTERVAL_DAY) returns 0, vallen 28, itv_day_val: 101 (type 3, sign 0)\n" /* SQLstate 22015 Interval field overflow */ + "SQLColAttribute(3, SQL_DESC_CONCISE_TYPE) returns 0, NumAttr 103\n" + "SQLColAttribute(3, SQL_DESC_DISPLAY_SIZE) returns 0, NumAttr 21\n" + "SQLGetData(3, SQL_C_CHAR, 41) returns 0, vallen 19, str_val: 'INTERVAL -'102' DAY'\n" + "SQLGetData(3, SQL_C_SLONG) returns 0, vallen 4, int_val: -102\n" /* SQLstate 07006 Restricted data type attribute violation */ + "SQLGetData(3, SQL_C_INTERVAL_DAY) returns 0, vallen 28, itv_day_val: 102 (type 3, sign 1)\n" /* SQLstate 22015 Interval field overflow */ + ); + + ret = SQLCloseCursor(stmt); + check(ret, SQL_HANDLE_STMT, stmt, "SQLCloseCursor"); + + /* cleanup */ + free(outp); + return ret; +} + int main(int argc, char **argv) { @@ -351,6 +463,12 @@ main(int argc, char **argv) ret = testGetDataGUID(stmt); check(ret, SQL_HANDLE_STMT, stmt, "testGetDataGUID(STMT)"); + ret = testGetDataIntervalDay(stmt, 1); + check(ret, SQL_HANDLE_STMT, stmt, "testGetDataIntervalDay(STMT, 99, -99)"); + + ret = testGetDataIntervalDay(stmt, 2); + check(ret, SQL_HANDLE_STMT, stmt, "testGetDataIntervalDay(STMT, 101, -102)"); + /* cleanup */ ret = SQLFreeHandle(SQL_HANDLE_STMT, stmt); check(ret, SQL_HANDLE_STMT, stmt, "SQLFreeHandle (STMT)"); diff --git a/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test b/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test --- a/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test +++ b/sql/test/proto_loader/odbc/Tests/monetodbc_datatypes.test @@ -137,14 +137,14 @@ 12345678901234567890.123456789 onlyif has-hugeint query I -select cast(-92345678901234567890123456789.123456789 as decimal(38,9)) as dec16_val +select cast(-923456789012345678901234567890.12345678 as decimal(38,8)) as dec16_val ---- --92345678901234567890123456789 +-923456789012345678901234567890 --query T ---select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(-92345678901234567890123456789.123456789 as decimal(38,9)) as dec16_val' +--select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(-923456789012345678901234567890.12345678 as decimal(38,8)) as dec16_val' ---- --- -92345678901234567890123456789.123456789 +-- -923456789012345678901234567890.12345678 ---- REAL ---- @@ -308,6 +308,48 @@ select * from 'odbc:DSN=MonetDB-Test;QUE 99 -99 +query TT +select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(''99'' as interval day) as val1, cast(''-99'' as interval day) as val2' +---- +99 +-99 + +query II +select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(''101'' as interval day) as val1, cast(''-102'' as interval day) as val2' +---- +101 +-102 + +query RR +select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(''101'' as interval day) as val1, cast(''-102'' as interval day) as val2' +---- +101.000 +-102.000 + +query TT +select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(''101'' as interval day) as val1, cast(''-102'' as interval day) as val2' +---- +101 +-102 + +query II +select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(''9101'' as interval day) as val1, cast(''-9102'' as interval day) as val2' +---- +9101 +-9102 + +query RR +select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(''9101'' as interval day) as val1, cast(''-9102'' as interval day) as val2' +---- +9101.000 +-9102.000 + +query TT +select * from 'odbc:DSN=MonetDB-Test;QUERY=select cast(''9101'' as interval day) as val1, cast(''-9102'' as interval day) as val2' +---- +9101 +-9102 + query TTTT select cast('32' as interval hour) as val1, cast('-32' as interval hour) as val2, cast('0' as interval hour) as val0, cast(NULL as interval hour) as valnil _______________________________________________ checkin-list mailing list -- [email protected] To unsubscribe send an email to [email protected]
