Changeset: 20d8211f0a2c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/20d8211f0a2c
Modified Files:
        clients/odbc/tests/ODBCtester.c
        sql/storage/store.c
Branch: default
Log Message:

Merge with Mar2025 branch.


diffs (267 lines):

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
@@ -1308,6 +1308,8 @@ ODBCFetch(ODBCStmt *stmt,
                case SQL_INTEGER:
                case SQL_BIGINT:
                case SQL_HUGEINT:
+               case SQL_DECIMAL:
+               case SQL_NUMERIC:
                        sz = snprintf((char *) ptr, buflen, "%s", data);
                        if (sz < 0 || sz >= buflen) {
                                /* Numeric value out of range */
@@ -1320,8 +1322,6 @@ ODBCFetch(ODBCStmt *stmt,
                        if (lenp)
                                *lenp = sz;
                        break;
-               case SQL_DECIMAL:
-               case SQL_NUMERIC:
                case SQL_BIT: {
                        uint64_t f;
                        int n;
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)");
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -318,14 +318,18 @@ sql_trans_add_predicate(sql_trans* tr, s
        p->semantics = semantics;
        p->r = r;
        p->f = f;
+       MT_lock_set(&tr->lock);
        if (!tr->predicates && !(tr->predicates = list_create((fdestroy) 
&predicate_destroy))) {
                predicate_destroy(tr->store, p);
+               MT_lock_unset(&tr->lock);
                return LOG_ERR;
        }
        if (!list_append(tr->predicates, p)) {
                predicate_destroy(tr->store, p);
+               MT_lock_unset(&tr->lock);
                return LOG_ERR;
        }
+       MT_lock_unset(&tr->lock);
        return LOG_OK;
 }
 
@@ -3882,6 +3886,8 @@ sql_trans_destroy(sql_trans *tr)
        MT_lock_destroy(&tr->lock);
        if (!list_empty(tr->dropped))
                list_destroy(tr->dropped);
+       if (!list_empty(tr->predicates))
+               list_destroy(tr->predicates);
        _DELETE(tr);
        return res;
 }
diff --git a/tools/merovingian/ChangeLog.Mar2025 
b/tools/merovingian/ChangeLog.Mar2025
--- a/tools/merovingian/ChangeLog.Mar2025
+++ b/tools/merovingian/ChangeLog.Mar2025
@@ -1,3 +1,11 @@
 # ChangeLog file for sql/src/backends/monet5/merovingian
 # This file is updated with mchangelog
 
+* Thu May 22 2025 Sjoerd Mullender <[email protected]>
+- When mserver5 is started by monetdbd due to an implicit request
+  (application trying to connect to a database), and mserver5 crashes
+  or exits before a connection can be established, monetdbd will stop
+  trying to start the server after a few attempts.  When using an explicit
+  command to start the server (using monetdb start), monetdbd will always
+  attempt to start the server.
+
diff --git a/tools/merovingian/daemon/forkmserver.c 
b/tools/merovingian/daemon/forkmserver.c
--- a/tools/merovingian/daemon/forkmserver.c
+++ b/tools/merovingian/daemon/forkmserver.c
@@ -322,6 +322,14 @@ forkMserver(const char *database, sabdb*
                pthread_mutex_unlock(&dp->fork_lock);
                return(NO_ERR);
        case SABdbCrashed:
+               if (!force && dp->crashcount > 4) {
+                       state = (*stats)->state;
+                       msab_freeStatus(stats);
+                       freeConfFile(ckv);
+                       free(ckv);
+                       pthread_mutex_unlock(&dp->fork_lock);
+                       return newErr("too many startup failures for database 
%s: fix database and try `monetdb start %s'", database, database);
+               }
                t = localtime(&info.lastcrash);
                strftime(tstr, sizeof(tstr), "%Y-%m-%d %H:%M:%S", t);
                secondsToString(upmin, info.minuptime, 1);
@@ -809,6 +817,10 @@ forkMserver(const char *database, sabdb*
                if (dp->pid == -1) {
                        state = (*stats)->state;
 
+                       /* do this while we still have the lock */
+                       if (!force)
+                               dp->crashcount++;
+
                        pthread_mutex_unlock(&_mero_topdp_lock);
                        pthread_mutex_unlock(&dp->fork_lock);
 
@@ -851,6 +863,8 @@ forkMserver(const char *database, sabdb*
                        }
                }
 
+               dp->crashcount = 0;
+
                pthread_mutex_unlock(&_mero_topdp_lock);
                pthread_mutex_unlock(&dp->fork_lock);
 
diff --git a/tools/merovingian/daemon/merovingian.h 
b/tools/merovingian/daemon/merovingian.h
--- a/tools/merovingian/daemon/merovingian.h
+++ b/tools/merovingian/daemon/merovingian.h
@@ -51,6 +51,7 @@ typedef struct _dpair {
        } input[2];
        mtype type;       /* type of process */
        short flag;               /* flag internal to logListener */
+       short crashcount; /* number of crashes during startup */
        pid_t pid;        /* this process' id */
        char *dbname;     /* the database that this server serves */
        pthread_mutex_t fork_lock;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to