Changeset: a5a20e4bc813 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a5a20e4bc813
Modified Files:
clients/odbc/tests/ODBCtester.c
Branch: Mar2025
Log Message:
Extend ODBCtester with getting big decimal values: dec(29,9), dec(38,19) and
dec(38,29), both as string and as numeric.
When fetching as string it fails to convert the decimal/numeric value when the
number of digits before or after the decimal separator.
The problem is in ODBCConvert.c code lines 1333 to 1372 where it is trying to
convert the nval.val back to a string, but there is no support for values
larger than 2**64. Needs to be fixed.
diffs (151 lines):
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
@@ -393,12 +393,12 @@ testGetDataIntervalDay(SQLHANDLE stmt, i
"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 */
+ "SQLGetData(2, SQL_C_INTERVAL_DAY) returns 0, vallen
28, itv_day_val: 101 (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 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 */
+ "SQLGetData(3, SQL_C_INTERVAL_DAY) returns 0, vallen
28, itv_day_val: 102 (type 3, sign 1)\n"
);
ret = SQLCloseCursor(stmt);
@@ -409,6 +409,116 @@ testGetDataIntervalDay(SQLHANDLE stmt, i
return ret;
}
+static SQLRETURN
+testGetDataDecimal(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(92345678901234567890.123456789 as
decimal(29,9)) as val1, cast(-92345678901234567890.123456789 as decimal(29,9))
as val2;";
+ char * sql2 = "select cast(92345678901234567890.123456789012345678 as
decimal(38,18)) as val1, cast(-9234567890123456789.1234567890123456789 as
decimal(38,19)) as val2;";
+ char * sql3 = "select cast(987654321.12345678901234567890123456789 as
decimal(38,29)) as val1, cast(-987654321.12345678901234567890123456789 as
decimal(38,29)) as val2;";
+ char * sql = (sqlquery == 1) ? sql1 : (sqlquery == 2) ? sql2 : sql3;
+
+ ret = SQLExecDirect(stmt, (SQLCHAR *) sql, SQL_NTS);
+ pos += snprintf(outp + pos, outp_len - pos, "SQLExecDirect query %d:
%s\n", sqlquery, sql);
+ 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 dec_str_val[42];
+ SQL_NUMERIC_STRUCT dec_num_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)&dec_str_val, (SQLLEN)42, &vallen);
+ pos += snprintf(outp + pos, outp_len - pos, "SQLGetData(%d,
SQL_C_CHAR, 42) returns %d, vallen " LLFMT ", str_val: '%s'\n",
+ col, ret, (int64_t) vallen, (vallen == SQL_NULL_DATA) ?
"NULL" : dec_str_val);
+ check(ret, SQL_HANDLE_STMT, stmt, "SQLGetData(col)");
+
+ /* test SQLGetData(SQL_C_NUMERIC) */
+ ret = SQLGetData(stmt, (UWORD)col, (SWORD)SQL_C_NUMERIC,
(PTR)&dec_num_val, (SQLLEN)sizeof(SQL_NUMERIC_STRUCT), &vallen);
+ pos += snprintf(outp + pos, outp_len - pos, "SQLGetData(%d,
SQL_C_NUMERIC, 19) returns %d, vallen " LLFMT ", data_val: ", col, ret,
(int64_t) vallen);
+ if (ret == SQL_SUCCESS) {
+ if (vallen == SQL_NULL_DATA)
+ pos += snprintf(outp + pos, outp_len - pos,
"NULL\n");
+ else {
+ pos += snprintf(outp + pos, outp_len - pos, "%u
%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\n",
+ (uint8_t)dec_num_val.val[0],
(uint8_t)dec_num_val.val[1], (uint8_t)dec_num_val.val[2],
(uint8_t)dec_num_val.val[3],
+ (uint8_t)dec_num_val.val[4],
(uint8_t)dec_num_val.val[5], (uint8_t)dec_num_val.val[6],
(uint8_t)dec_num_val.val[7],
+ (uint8_t)dec_num_val.val[8],
(uint8_t)dec_num_val.val[9], (uint8_t)dec_num_val.val[10],
(uint8_t)dec_num_val.val[11],
+ (uint8_t)dec_num_val.val[12],
(uint8_t)dec_num_val.val[13], (uint8_t)dec_num_val.val[14],
(uint8_t)dec_num_val.val[15]);
+ }
+ }
+ check(ret, SQL_HANDLE_STMT, stmt, "SQLGetData(col)");
+ }
+
+ compareResult("testGetDataDecimal()", outp,
+ (sqlquery == 1)
+ ? "SQLExecDirect query 1: select
cast(92345678901234567890.123456789 as decimal(29,9)) as val1,
cast(-92345678901234567890.123456789 as decimal(29,9)) as val2;\n"
+ "SQLRowCount is 1\nSQLNumResultCols is 2\nSQLFetch\n"
+ "SQLColAttribute(1, SQL_DESC_CONCISE_TYPE) returns 0,
NumAttr 3\n"
+ "SQLColAttribute(1, SQL_DESC_DISPLAY_SIZE) returns 0,
NumAttr 31\n"
+ "SQLGetData(1, SQL_C_CHAR, 42) returns 0, vallen 30,
str_val: '92345678901234567890.123456789'\n" /* SQLGetData(col): Error:
SQLstate 22003, Numeric value out of range */
+ "SQLGetData(1, SQL_C_NUMERIC, 19) returns 0, vallen 19,
data_val: 0 8 201 240 176 193 141 1 5 0 0 0 0 0 0 0\n"
+ "SQLColAttribute(2, SQL_DESC_CONCISE_TYPE) returns 0,
NumAttr 3\n"
+ "SQLColAttribute(2, SQL_DESC_DISPLAY_SIZE) returns 0,
NumAttr 31\n"
+ "SQLGetData(2, SQL_C_CHAR, 42) returns 0, vallen 31,
str_val: '-92345678901234567890.123456789'\n" /* SQLGetData(col): Error:
SQLstate 22003, Numeric value out of range */
+ "SQLGetData(2, SQL_C_NUMERIC, 19) returns 0, vallen 19,
data_val: 0 8 201 240 176 193 141 1 5 0 0 0 0 0 0 0\n"
+ : (sqlquery == 2)
+ ? "SQLExecDirect query 2: select
cast(92345678901234567890.123456789012345678 as decimal(38,18)) as val1,
cast(-9234567890123456789.1234567890123456789 as decimal(38,19)) as val2;\n"
+ "SQLRowCount is 1\nSQLNumResultCols is 2\nSQLFetch\n"
+ "SQLColAttribute(1, SQL_DESC_CONCISE_TYPE) returns 0,
NumAttr 3\n"
+ "SQLColAttribute(1, SQL_DESC_DISPLAY_SIZE) returns 0,
NumAttr 40\n"
+ "SQLGetData(1, SQL_C_CHAR, 42) returns 0, vallen 39,
str_val: '92345678901234567890.123456789012345678'\n" /* SQLGetData(col):
Error: SQLstate 22003, Numeric value out of range */
+ "SQLGetData(1, SQL_C_NUMERIC, 19) returns 0, vallen 19,
data_val: 0 8 201 240 176 193 141 1 5 0 0 0 0 0 0 0\n"
+ "SQLColAttribute(2, SQL_DESC_CONCISE_TYPE) returns 0,
NumAttr 3\n"
+ "SQLColAttribute(2, SQL_DESC_DISPLAY_SIZE) returns 0,
NumAttr 40\n"
+ "SQLGetData(2, SQL_C_CHAR, 42) returns 0, vallen 40,
str_val: '-9234567890123456789.1234567890123456789'\n"
+ "SQLGetData(2, SQL_C_NUMERIC, 19) returns 0, vallen 19,
data_val: 0 180 173 177 145 198 39 128 0 0 0 0 0 0 0 0\n"
+ : "SQLExecDirect query 3: select
cast(987654321.12345678901234567890123456789 as decimal(38,29)) as val1,
cast(-987654321.12345678901234567890123456789 as decimal(38,29)) as val2;\n"
+ "SQLRowCount is 1\nSQLNumResultCols is 2\nSQLFetch\n"
+ "SQLColAttribute(1, SQL_DESC_CONCISE_TYPE) returns 0,
NumAttr 3\n"
+ "SQLColAttribute(1, SQL_DESC_DISPLAY_SIZE) returns 0,
NumAttr 40\n"
+ "SQLGetData(1, SQL_C_CHAR, 42) returns 0, vallen 39,
str_val: '987654321.12345678901234567890123456789'\n" /* SQLGetData(col): Info:
SQLstate 01004, String data, right truncated */
+ "SQLGetData(1, SQL_C_NUMERIC, 19) returns 0, vallen 19,
data_val: 177 104 222 58 0 0 0 0 0 0 0 0 0 0 0 0\n"
+ "SQLColAttribute(2, SQL_DESC_CONCISE_TYPE) returns 0,
NumAttr 3\n"
+ "SQLColAttribute(2, SQL_DESC_DISPLAY_SIZE) returns 0,
NumAttr 40\n"
+ "SQLGetData(2, SQL_C_CHAR, 42) returns 0, vallen 40,
str_val: '-987654321.12345678901234567890123456789'\n" /* SQLGetData(col):
Info: SQLstate 01004, String data, right truncated */
+ "SQLGetData(2, SQL_C_NUMERIC, 19) returns 0, vallen 19,
data_val: 177 104 222 58 0 0 0 0 0 0 0 0 0 0 0 0\n");
+
+ ret = SQLCloseCursor(stmt);
+ check(ret, SQL_HANDLE_STMT, stmt, "SQLCloseCursor");
+
+ /* cleanup */
+ free(outp);
+ return ret;
+}
+
int
main(int argc, char **argv)
{
@@ -469,6 +579,15 @@ main(int argc, char **argv)
ret = testGetDataIntervalDay(stmt, 2);
check(ret, SQL_HANDLE_STMT, stmt, "testGetDataIntervalDay(STMT, 101,
-102)");
+ ret = testGetDataDecimal(stmt, 1); /* SQLGetData(col): Error: SQLstate
22003, Numeric value out of range */
+ check(ret, SQL_HANDLE_STMT, stmt, "testGetDataDecimal(STMT,
dec(29,9))");
+
+ ret = testGetDataDecimal(stmt, 2); /* SQLGetData(col): Error: SQLstate
22003, Numeric value out of range */
+ check(ret, SQL_HANDLE_STMT, stmt, "testGetDataDecimal(STMT,
dec(38,19))");
+
+ ret = testGetDataDecimal(stmt, 3); /* SQLGetData(col): Info: SQLstate
01004, String data, right truncated */
+ check(ret, SQL_HANDLE_STMT, stmt, "testGetDataDecimal(STMT,
dec(38,29))");
+
/* cleanup */
ret = SQLFreeHandle(SQL_HANDLE_STMT, stmt);
check(ret, SQL_HANDLE_STMT, stmt, "SQLFreeHandle (STMT)");
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]