MonetDB: Aug2024 - Fix diagnostic in streamcat

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: f20799ff6a30 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f20799ff6a30
Modified Files:
clients/examples/C/streamcat.c
Branch: Aug2024
Log Message:

Fix diagnostic in streamcat


diffs (12 lines):

diff --git a/clients/examples/C/streamcat.c b/clients/examples/C/streamcat.c
--- a/clients/examples/C/streamcat.c
+++ b/clients/examples/C/streamcat.c
@@ -422,7 +422,7 @@ opener_rstream(char *filename)
 {
stream *s = open_rstream(filename);
if (!mnstr_isbinary(s))
-   croak(2, "open_rastream returned binary stream");
+   croak(2, "open_rstream returned text stream");
return s;
 }
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Test non-NUL-terminated arguments

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 55b7f9555245 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/55b7f9555245
Modified Files:
clients/odbc/tests/odbcconnect.c
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Test non-NUL-terminated arguments


diffs (172 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -17,6 +17,7 @@
 #endif
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,6 +34,7 @@ static const char *USAGE =
"-l  List registered drivers and data sources\n"
"-u USER\n"
"-p PASSWORD\n"
+   "-0  use counted strings rather than nul-terminated 
arguments\n"
"-v  Be verbose\n"
"TARGET  DSN or with -d and -b, Connection String\n";
 
@@ -49,10 +51,16 @@ static int do_listdsns(const char *prefi
 
 static void ensure_ok(SQLSMALLINT type, SQLHANDLE handle, const char *message, 
SQLRETURN ret);
 
+#define MARGIN 100
+static SQLCHAR* sqldup_with_margin(const char *str);
+static void fuzz_sql_nts(SQLCHAR **str, SQLSMALLINT *len);
 
 int verbose = 0;
 SQLCHAR *user = NULL;
+SQLSMALLINT user_len = SQL_NTS;
 SQLCHAR *password = NULL;
+SQLSMALLINT password_len = SQL_NTS;
+bool use_counted_strings = false;
 
 SQLHANDLE env = NULL;
 SQLHANDLE conn = NULL;
@@ -89,13 +97,15 @@ main(int argc, char **argv)
else if (strcmp(arg, "-l") == 0)
action = NULL;
else if (strcmp(arg, "-u") == 0 && i + 1 < argc)
-   user = (SQLCHAR*)argv[++i];
+   user = sqldup_with_margin(argv[++i]);
else if (strcmp(arg, "-p") == 0 && i + 1 < argc)
-   password = (SQLCHAR*)argv[++i];
+   password = sqldup_with_margin(argv[++i]);
+   else if (strcmp(arg, "-0") == 0)
+   use_counted_strings = true;
else if (strcmp(arg, "-v") == 0)
verbose += 1;
else if (arg[0] != '-')
-   targets[ntargets++] = (SQLCHAR*)arg;
+   targets[ntargets++] = sqldup_with_margin(arg);
else {
fprintf(stderr, "\nERROR: invalid argument: %s\n%s", 
arg, USAGE);
ret = 1;
@@ -111,6 +121,11 @@ main(int argc, char **argv)
SQL_HANDLE_ENV, env, "set odbc version",
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, 
(SQLPOINTER)SQL_OV_ODBC3, 0));
 
+   if (use_counted_strings) {
+   fuzz_sql_nts(&user, &user_len);
+   fuzz_sql_nts(&password, &password_len);
+   }
+
if (action) {
if (ntargets == 0) {
fprintf(stderr, "\nERROR: pass at least one 
target\n%s", USAGE);
@@ -130,6 +145,10 @@ main(int argc, char **argv)
}
 
 end:
+   free(user);
+   free(password);
+   for (int i = 0; i < ntargets; i++)
+   free(targets[i]);
free(targets);
cleanup();
 
@@ -207,9 +226,13 @@ do_actions(action_t action, int ntargets
 static int
 do_sqlconnect(SQLCHAR *target)
 {
+   SQLSMALLINT target_len = SQL_NTS;
+   if (use_counted_strings)
+   fuzz_sql_nts(&target, &target_len);
+
ensure_ok(
SQL_HANDLE_DBC, conn, "SQLConnect",
-   SQLConnect(conn, target, SQL_NTS, user, SQL_NTS, password, 
SQL_NTS));
+   SQLConnect(conn, target, target_len, user, user_len, password, 
password_len));
printf("OK\n");
 
return 0;
@@ -219,11 +242,15 @@ static int
 do_sqldriverconnect(SQLCHAR *target)
 {
SQLSMALLINT n;
+   SQLSMALLINT target_len = SQL_NTS;
+   if (use_counted_strings)
+   fuzz_sql_nts(&target, &target_len);
+
ensure_ok(
SQL_HANDLE_DBC, conn, "SQLDriverConnect",
SQLDriverConnect(
conn, NULL,
-   target, SQL_NTS,
+   target, target_len,
outbuf, sizeof(outbuf), &n,
SQL_DRIVER_NOPROMPT
));
@@ -236,9 +263,13 @@ static int
 do_sqlbrowseconnect(SQLCHAR *target)
 {
SQLSMALLINT n;
+   SQLSMALLINT target_len = SQL_NTS;
+   if (use_counted_strings)
+   fuzz_sql_nts(&target, &target_len);
+
SQLRETURN ret = SQLBrowseConnect(
conn,
-   target, SQL_NTS,
+   target, target_len,
outbuf, sizeof(outbuf), &n
);
ensure_ok(SQL_HANDLE_DBC, conn, "SQLBrowseConnect", ret);
@@ -302,3 +333,27 @@ do_listdsns(const char *prefix, SQLSMALL
return 0;
 }
 
+
+static SQLCHAR*
+sqldup_with_margin(const char *str)
+{
+   size_t len = strlen(str);
+   char *buf = malloc(len + MARGIN);
+  

MonetDB: Aug2024 - Copy data, not the pointer

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 7177f1898fe2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7177f1898fe2
Modified Files:
clients/odbc/driver/SQLConnect.c
Branch: Aug2024
Log Message:

Copy data, not the pointer


diffs (12 lines):

diff --git a/clients/odbc/driver/SQLConnect.c b/clients/odbc/driver/SQLConnect.c
--- a/clients/odbc/driver/SQLConnect.c
+++ b/clients/odbc/driver/SQLConnect.c
@@ -121,7 +121,7 @@ makeNulTerminated(const SQLCHAR **argume
SQLCHAR *value = malloc(argument_len + 1);
if (value == NULL)
return false;
-   memmove(value, argument, argument_len);
+   memmove(value, *argument, argument_len);
value[argument_len] = '\0';
 
*argument = value;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Test SQLDriverConnect

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 7e379cfaffaf for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7e379cfaffaf
Modified Files:
sql/odbc/tests/Tests/ODBCconnect.py
testing/Mtest.py.in
Branch: Aug2024
Log Message:

Test SQLDriverConnect


diffs (121 lines):

diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -14,9 +14,16 @@
 # sqlstate lines of the form '- STATE: MESSAGE'.
 
 import atexit
+import os
 import subprocess
 import sys
 
+dsn = 'MonetDB-Test'
+dbname = os.environ.get('TSTDB', 'demo')
+user = 'monetdb'
+password = 'monetdb'
+port = os.environ.get('MAPIPORT', 5)
+
 
 class Execution:
 def __init__(self, *odbcconnect_args):
@@ -97,38 +104,35 @@ def show_context():
 print(ex.report(), file=sys.stderr)
 
 
-dbname = 'MonetDB-Test'
-
-
-ex = Execution(dbname)
+ex = Execution(dsn)
 ex.expect('OK')
 ex.end()
 
-ex = Execution(dbname + '-nonexistent')
+ex = Execution(dsn + '-nonexistent')
 ex.expect_fail()
 ex.expect('Error')
 ex.expect('IM002:')  # IM002 not found
 ex.end()
 
-ex = Execution(dbname, '-p', 'wrongpassword')
+ex = Execution(dsn, '-p', 'wrongpassword')
 ex.expect_fail()
 ex.expect('Error')
 ex.expect('28000:')  # 28000 bad credentials
 ex.end()
 
-ex = Execution(dbname, '-u', 'wronguser')
+ex = Execution(dsn, '-u', 'wronguser')
 ex.expect_fail()
 ex.expect('Error')
 ex.expect('28000:')  # 28000 bad credentials
 ex.end()
 
-ex = Execution(dbname, '-p', '')
+ex = Execution(dsn, '-p', '')
 ex.expect_fail()
 ex.expect('Error')
 ex.expect('28000:')  # 28000 bad credentials
 ex.end()
 
-ex = Execution(dbname, '-u', '')
+ex = Execution(dsn, '-u', '')
 ex.expect_fail()
 ex.expect('Error')
 ex.expect('28000:')  # 28000 bad credentials
@@ -136,13 +140,33 @@ ex.end()
 
 # test non-NUL terminated strings
 
-ex = Execution(dbname, '-0')
+ex = Execution(dsn, '-0')
+ex.expect('OK')
+ex.end()
+
+ex = Execution(dsn, '-0', '-u', user, '-p', password)
+ex.expect('OK')
+ex.end()
+
+# test connection strings
+
+ex = Execution('-d', f'DSN={dsn}')
 ex.expect('OK')
 ex.end()
 
-ex = Execution(dbname, '-0', '-u', 'monetdb', '-p', 'monetdb')
+# override things that are already set in the dsn
+ex = Execution('-d', 
f'DSN={dsn}-Wrong;Database={dbname};Uid={user};Pwd={password}')
 ex.expect('OK')
 ex.end()
 
+# .. even if the DSN= comes last
+ex = Execution('-d', 
f'Database={dbname};Uid={user};Pwd={password};DSN={dsn}-Wrong')
+ex.expect('OK')
+ex.end()
+
+# test without DSN= clause
+ex = Execution('-d', 
f'DRIVER={{MonetDB}};Database={dbname};Uid={user};Pwd={password};Port={port}')
+ex.expect('OK')
+ex.end()
 
 ex = None
diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -2227,6 +2227,16 @@ Database = {TSTDB}
 User = {user or "monetdb"}
 Password = {passwd or "monetdb"}
 Debug =
+
+[MonetDB-Test-Wrong]
+Description = Wrong values for Database, Uid and Pwd
+Driver = {env["LIBDIR"]}/libMonetODBC.so
+Setup = {env["LIBDIR"]}/libMonetODBCs.so
+Host = localhost
+Port = {env["MAPIPORT"]}
+Database = {TSTDB}-Wrong
+User = {user or "monetdb"}-Wrong
+Password = {passwd or "monetdb"}-Wrong
 ''')
 f.close()
 os.environ['ODBCINI'] = os.path.join(TSTTRGDIR, 'odbc.ini')
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Mtest: set ODBCSYSINI instead of ODBCINI

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 766bdabd4d7c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/766bdabd4d7c
Modified Files:
testing/Mtest.py.in
Branch: Aug2024
Log Message:

Mtest: set ODBCSYSINI instead of ODBCINI

And split odbc.ini into odbc.ini and odbcinst.ini

This insulates Mtest's odbc setup from whatever else is going on in the system.

odbc.ini can now just set Driver=MonetDB and does not need any file system paths


diffs (64 lines):

diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -2215,12 +2215,18 @@ def RunTest(env, TST, COND, oktests, len
 f.close()
 
 if odbc:
-f = openutf8('odbc.ini', 'w')
-f.write(f'''\
-[MonetDB-Test]
+with openutf8('odbcinst.ini', 'w') as f:
+f.write(f'''\
+[MonetDB]
 Description = Test MonetDB Data Source
 Driver = {env["LIBDIR"]}/libMonetODBC.so
 Setup = {env["LIBDIR"]}/libMonetODBCs.so
+''')
+with openutf8('odbc.ini', 'w') as f:
+f.write(f'''\
+[MonetDB-Test]
+Description = Test MonetDB Data Source
+Driver = MonetDB
 Host = localhost
 Port = {env["MAPIPORT"]}
 Database = {TSTDB}
@@ -2230,16 +2236,17 @@ Debug =
 
 [MonetDB-Test-Wrong]
 Description = Wrong values for Database, Uid and Pwd
-Driver = {env["LIBDIR"]}/libMonetODBC.so
-Setup = {env["LIBDIR"]}/libMonetODBCs.so
+Driver = MonetDB
 Host = localhost
 Port = {env["MAPIPORT"]}
 Database = {TSTDB}-Wrong
 User = {user or "monetdb"}-Wrong
 Password = {passwd or "monetdb"}-Wrong
 ''')
-f.close()
-os.environ['ODBCINI'] = os.path.join(TSTTRGDIR, 'odbc.ini')
+orig_odbcsysini = os.environ.pop('ODBCSYSINI', None)
+orig_odbcini = os.environ.pop('ODBCINI', None)
+orig_odbcinstini = os.environ.pop('ODBCINSTINI', None)
+os.environ['ODBCSYSINI'] = TSTTRGDIR
 
 STABLEout,STABLEerr = 
StableOutErr(env,par,TST,SYST,RELEASE,DIST,VERSION)
 TIMEOUT = par['TIMEOUT']
@@ -2268,7 +2275,15 @@ Password = {passwd or "monetdb"}-Wrong
 print(" %7.3fs " % TX, end='')
 
 if odbc:
-del os.environ['ODBCINI']
+if orig_odbcsysini is not None:
+os.environ['ODBCSYSINI'] = orig_odbcsysini
+else:
+del os.environ['ODBCSYSINI']
+if orig_odbcini is not None:
+os.environ['ODBCINI'] = orig_odbcini
+if orig_odbcinstini is not None:
+os.environ['ODBCINSTINI'] = orig_odbcinstini
+
 
 if tres == 'timeout':
 errcode = F_TIME
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Add tests for SQLBrowseConnect

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: c2718b187150 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c2718b187150
Modified Files:
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Add tests for SQLBrowseConnect


diffs (77 lines):

diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -56,7 +56,10 @@ class Execution:
 if self.checks:
 parts.append('--- test history: ---')
 for wanted, found in self.checks:
-parts.append(f'wanted {wanted!r}, found {found!r}')
+if len(wanted) == 1:
+parts.append(f'wanted {wanted[0]!r}, found {found!r}')
+else:
+parts.append(f'wanted all of {wanted!r}, found {found!r}')
 parts.append('--- end ---')
 if self.remaining:
 parts += [
@@ -66,11 +69,13 @@ class Execution:
 ]
 return '\n'.join(parts)
 
-def expect(self, pattern):
+def expect(self, pattern, *more_patterns):
+patterns = [pattern, *more_patterns]
 line = self.next_line()
-self.checks.append((pattern, line))
-if pattern not in line:
-raise Exception(f'Wanted {pattern!r}, found {line!r}')
+self.checks.append((patterns, line))
+for p in patterns:
+if p not in line:
+raise Exception(f'Wanted {p!r}, found {line!r}')
 
 def next_line(self):
 if not self.remaining:
@@ -169,4 +174,43 @@ ex = Execution('-d', f'DRIVER={{MonetDB}
 ex.expect('OK')
 ex.end()
 
+# non-NUL terminated connection string
+ex = Execution('-0', '-d', 
f'DSN={dsn}-Wrong;Database={dbname};Uid={user};Pwd={password}')
+ex.expect('OK')
+ex.end()
+
+# Test browsing
+
+ex = Execution('-b', 'Driver={MonetDB}')
+ex.expect('Info')
+ex.expect('08001')
+# browse not complete, uid and pwd mandatory, database optional
+ex.expect('BROWSE', 'UID:User=?', 'PWD:Password=?', '*DATABASE')
+ex.end()
+
+# same as above, but with another iteration of browsing
+ex = Execution('-b', 'Driver={MonetDB}', 
f'Driver={{MonetDB}};UID={user};PWD={password};Port={port}')
+# first iteration
+ex.expect('Info')
+ex.expect('08001')
+ex.expect('BROWSE', 'UID:User=?', 'PWD:Password=?', '*DATABASE')
+# second iteration
+ex.expect('OK', ';', 'HOST=')
+ex.end()
+
+# similar to above, but not NUL-terminated
+ex = Execution('-0', '-b', 'Driver={MonetDB}')
+ex.expect('Info')
+ex.expect('08001')
+# browse not complete, uid and pwd mandatory, database optional
+ex.expect('BROWSE', 'UID:User=?', 'PWD:Password=?', '*DATABASE')
+ex.end()
+
+# it should also work when the user and password are in the dsn
+ex = Execution('-b', f'DSN={dsn}')
+ex.expect('OK', ';')
+ex.end()
+
+# clear 'ex', otherwise the atexit handler will write things
+# to stderr
 ex = None
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Close connection handles after use

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 62dcc4c2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/62dcc4c2
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Close connection handles after use


diffs (55 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -71,6 +71,8 @@ SQLCHAR attrbuf[4096];
 static void
 cleanup(void)
 {
+   free(user);
+   free(password);
if (conn) {
SQLDisconnect(conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn);
@@ -145,8 +147,6 @@ main(int argc, char **argv)
}
 
 end:
-   free(user);
-   free(password);
for (int i = 0; i < ntargets; i++)
free(targets[i]);
free(targets);
@@ -235,6 +235,10 @@ do_sqlconnect(SQLCHAR *target)
SQLConnect(conn, target, target_len, user, user_len, password, 
password_len));
printf("OK\n");
 
+   ensure_ok(
+   SQL_HANDLE_DBC, conn, "Banana",
+   SQLDisconnect(conn));
+
return 0;
 }
 
@@ -256,6 +260,11 @@ do_sqldriverconnect(SQLCHAR *target)
));
 
printf("OK %s\n", outbuf);
+
+   ensure_ok(
+   SQL_HANDLE_DBC, conn, "Banana",
+   SQLDisconnect(conn));
+
return 0;
 }
 
@@ -277,6 +286,10 @@ do_sqlbrowseconnect(SQLCHAR *target)
ret == SQL_NEED_DATA ? "BROWSE" : "OK",
outbuf
);
+
+   // Do not call SQLDisconnect, SQLBrowseConnect is intended to
+   // be invoked multiple times without disconnecting inbetween
+
return 0;
 }
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Show errors that do not set any diagnostics

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 3da6dc78a5f8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/3da6dc78a5f8
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Show errors that do not set any diagnostics


diffs (26 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -183,6 +183,7 @@ ensure_ok(SQLSMALLINT type, SQLHANDLE ha
SQLCHAR explanation[256];
SQLSMALLINT len;
 
+   bool printed_something = false;
for (int i = 1; ; i++) {
SQLRETURN diag_ret = SQLGetDiagRec(
type, handle, i,
@@ -194,9 +195,14 @@ ensure_ok(SQLSMALLINT type, SQLHANDLE ha
class = NULL;
}
printf("- %s: %s\n", state, explanation);
+   printed_something = true;
}
 
if (!SQL_SUCCEEDED(ret) && ret != SQL_NEED_DATA) {
+   if (!printed_something) {
+   printf("%s: %s\n", class, message);
+   printf("- failed without explanation\n");
+   }
cleanup();
exit(1);
}
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Add option to execute a sql statement after c...

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: f552db6c983d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f552db6c983d
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Add option to execute a sql statement after connecting


diffs (193 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -34,21 +34,23 @@ static const char *USAGE =
"-l  List registered drivers and data sources\n"
"-u USER\n"
"-p PASSWORD\n"
+   "-q SQL  Execute SQL statement when connection 
succeeds\n"
"-0  use counted strings rather than nul-terminated 
arguments\n"
"-v  Be verbose\n"
"TARGET  DSN or with -d and -b, Connection String\n";
 
 typedef int (action_t)(SQLCHAR *);
 
-static int do_actions(action_t action, int ntargets, SQLCHAR **targets);
-
 static action_t do_sqlconnect;
 static action_t do_sqldriverconnect;
 static action_t do_sqlbrowseconnect;
 
+static int do_actions(action_t action, int ntargets, SQLCHAR **targets);
+
 static int do_listdrivers(void);
 static int do_listdsns(const char *prefix, SQLSMALLINT dir);
 
+static int do_execute_stmt(void);
 static void ensure_ok(SQLSMALLINT type, SQLHANDLE handle, const char *message, 
SQLRETURN ret);
 
 #define MARGIN 100
@@ -60,10 +62,13 @@ SQLCHAR *user = NULL;
 SQLSMALLINT user_len = SQL_NTS;
 SQLCHAR *password = NULL;
 SQLSMALLINT password_len = SQL_NTS;
+SQLCHAR *query = NULL;
+SQLSMALLINT query_len = SQL_NTS;
 bool use_counted_strings = false;
 
 SQLHANDLE env = NULL;
 SQLHANDLE conn = NULL;
+SQLHANDLE stmt = NULL;
 
 SQLCHAR outbuf[4096];
 SQLCHAR attrbuf[4096];
@@ -73,6 +78,9 @@ cleanup(void)
 {
free(user);
free(password);
+   free(query);
+   if (stmt)
+   SQLFreeHandle(SQL_HANDLE_STMT, stmt);
if (conn) {
SQLDisconnect(conn);
SQLFreeHandle(SQL_HANDLE_DBC, conn);
@@ -102,6 +110,8 @@ main(int argc, char **argv)
user = sqldup_with_margin(argv[++i]);
else if (strcmp(arg, "-p") == 0 && i + 1 < argc)
password = sqldup_with_margin(argv[++i]);
+   else if (strcmp(arg, "-q") == 0 && i + 1 < argc)
+   query = sqldup_with_margin(argv[++i]);
else if (strcmp(arg, "-0") == 0)
use_counted_strings = true;
else if (strcmp(arg, "-v") == 0)
@@ -159,7 +169,6 @@ end:
 static void
 ensure_ok(SQLSMALLINT type, SQLHANDLE handle, const char *message, SQLRETURN 
ret)
 {
-
char *class = "Info";
switch (ret) {
case SQL_SUCCESS:
@@ -241,11 +250,13 @@ do_sqlconnect(SQLCHAR *target)
SQLConnect(conn, target, target_len, user, user_len, password, 
password_len));
printf("OK\n");
 
+   int exitcode = do_execute_stmt();
+
ensure_ok(
-   SQL_HANDLE_DBC, conn, "Banana",
+   SQL_HANDLE_DBC, conn, "SQLDisconnect",
SQLDisconnect(conn));
 
-   return 0;
+   return exitcode;
 }
 
 static int
@@ -267,11 +278,13 @@ do_sqldriverconnect(SQLCHAR *target)
 
printf("OK %s\n", outbuf);
 
+   int exitcode = do_execute_stmt();
+
ensure_ok(
-   SQL_HANDLE_DBC, conn, "Banana",
+   SQL_HANDLE_DBC, conn, "SQLDisconnect",
SQLDisconnect(conn));
 
-   return 0;
+   return exitcode;
 }
 
 static int
@@ -293,10 +306,15 @@ do_sqlbrowseconnect(SQLCHAR *target)
outbuf
);
 
+   int exitcode = 0;
+   if (ret != SQL_NEED_DATA)
+   exitcode = do_execute_stmt();
+
+
// Do not call SQLDisconnect, SQLBrowseConnect is intended to
// be invoked multiple times without disconnecting inbetween
 
-   return 0;
+   return exitcode;
 }
 
 static int
@@ -353,6 +371,64 @@ do_listdsns(const char *prefix, SQLSMALL
 }
 
 
+static int
+do_execute_stmt(void)
+{
+   if (query == NULL)
+   return 0;
+
+   if (verbose)
+   printf("Statement: %s\n", query);
+
+   if (use_counted_strings)
+   fuzz_sql_nts(&query, &query_len);
+
+   ensure_ok(
+   SQL_HANDLE_ENV, conn, "allocate stmt handle",
+   SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt));
+
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLExecDirect",
+   SQLExecDirect(stmt, query, query_len));
+
+   do {
+   SQLLEN rowcount = -1;
+   SQLSMALLINT colcount = -1;
+
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLRowCount",
+   SQLRowCount(stmt, &rowcount));
+
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLNumResultCols",
+   SQL

MonetDB: Aug2024 - Include line numbers in -v output

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 2cc634740180 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2cc634740180
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Include line numbers in -v output


diffs (59 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -51,7 +51,10 @@ static int do_listdrivers(void);
 static int do_listdsns(const char *prefix, SQLSMALLINT dir);
 
 static int do_execute_stmt(void);
-static void ensure_ok(SQLSMALLINT type, SQLHANDLE handle, const char *message, 
SQLRETURN ret);
+
+static void ensure_ok_impl(SQLSMALLINT type, SQLHANDLE handle, const char 
*message, SQLRETURN ret, int lineno);
+
+#define ensure_ok(type, handle, message, ret)ensure_ok_impl(type, handle, 
message, ret, __LINE__)
 
 #define MARGIN 100
 static SQLCHAR* sqldup_with_margin(const char *str);
@@ -167,14 +170,23 @@ end:
 
 
 static void
-ensure_ok(SQLSMALLINT type, SQLHANDLE handle, const char *message, SQLRETURN 
ret)
+ensure_ok_impl(SQLSMALLINT type, SQLHANDLE handle, const char *message, 
SQLRETURN ret, int lineno)
 {
+   static const char *filename = NULL;
+   if (!filename) {
+   filename = __FILE__;
+   for (const char *p = filename; *p; p++) {
+   if (*p == '/' || *p == '\\')
+   filename = p + 1;
+   }
+   }
+
char *class = "Info";
switch (ret) {
case SQL_SUCCESS:
case SQL_NEED_DATA:
if (verbose)
-   printf("Succeeded: %s\n", message);
+   printf(" Succeeded: %s (%s:%d)\n", message, 
filename, lineno);
break;
case SQL_SUCCESS_WITH_INFO:
class = "Warning";
@@ -183,7 +195,7 @@ ensure_ok(SQLSMALLINT type, SQLHANDLE ha
class = "Error";
break;
default:
-   printf("Internal error: %s: unknown SQLRETURN %d", 
message, ret);
+   printf("Internal error: %s (%s:%d): unknown SQLRETURN 
%d", message, filename, lineno, ret);
break;
}
 
@@ -200,7 +212,7 @@ ensure_ok(SQLSMALLINT type, SQLHANDLE ha
if (!SQL_SUCCEEDED(diag_ret))
break;
if (class) {
-   printf("%s: %s\n", class, message);
+   printf("%s: %s (%s:%d)\n", class, message, filename, 
lineno);
class = NULL;
}
printf("- %s: %s\n", state, explanation);
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Get rid of sql_attr_autocommit

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: e48d017e9a10 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e48d017e9a10
Modified Files:
clients/odbc/driver/ODBCDbc.c
clients/odbc/driver/ODBCDbc.h
clients/odbc/driver/SQLConnect.c
clients/odbc/driver/SQLEndTran.c
clients/odbc/driver/SQLGetConnectAttr.c
clients/odbc/driver/SQLSetConnectAttr.c
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Get rid of sql_attr_autocommit

It's part of the msettings now and shouldn't blindly override those.


diffs (111 lines):

diff --git a/clients/odbc/driver/ODBCDbc.c b/clients/odbc/driver/ODBCDbc.c
--- a/clients/odbc/driver/ODBCDbc.c
+++ b/clients/odbc/driver/ODBCDbc.c
@@ -80,7 +80,6 @@ newODBCDbc(ODBCEnv *env)
*dbc = (ODBCDbc) {
.Env = env,
.settings = settings,
-   .sql_attr_autocommit = SQL_AUTOCOMMIT_ON,   /* default is 
autocommit */
.sql_attr_metadata_id = SQL_FALSE,
/* add this dbc to start of the administrative linked dbc list 
*/
.next = env->FirstDbc,
diff --git a/clients/odbc/driver/ODBCDbc.h b/clients/odbc/driver/ODBCDbc.h
--- a/clients/odbc/driver/ODBCDbc.h
+++ b/clients/odbc/driver/ODBCDbc.h
@@ -59,7 +59,6 @@ typedef struct tODBCDRIVERDBC {
bool allow_hugeint; /* whether the application deals with HUGEINT */
bool raw_strings;   /* server uses raw strings */
int mapToLongVarchar;   /* when > 0 we map WVARCHAR to WLONGVARCHAR, 
default 0 */
-   SQLUINTEGER sql_attr_autocommit;
SQLUINTEGER sql_attr_metadata_id;
 
/* MonetDB connection handle & status information */
diff --git a/clients/odbc/driver/SQLConnect.c b/clients/odbc/driver/SQLConnect.c
--- a/clients/odbc/driver/SQLConnect.c
+++ b/clients/odbc/driver/SQLConnect.c
@@ -482,7 +482,6 @@ MNDBConnectSettings(ODBCDbc *dbc, const 
if (mid) {
settings = NULL; // will be free'd as part of 'mid' now
mapi_setclientprefix(mid, "ODBC " MONETDB_VERSION);
-   mapi_setAutocommit(mid, dbc->sql_attr_autocommit == 
SQL_AUTOCOMMIT_ON);
mapi_set_size_header(mid, true);
mapi_reconnect(mid);
}
diff --git a/clients/odbc/driver/SQLEndTran.c b/clients/odbc/driver/SQLEndTran.c
--- a/clients/odbc/driver/SQLEndTran.c
+++ b/clients/odbc/driver/SQLEndTran.c
@@ -119,7 +119,7 @@ MNDBEndTran(SQLSMALLINT HandleType,
 
assert(HandleType == SQL_HANDLE_DBC);
 
-   if (dbc->sql_attr_autocommit == SQL_AUTOCOMMIT_ON) {
+   if (msetting_bool(dbc->settings, MP_AUTOCOMMIT)) {
/* nothing to do if in autocommit mode */
return SQL_SUCCESS;
}
diff --git a/clients/odbc/driver/SQLGetConnectAttr.c 
b/clients/odbc/driver/SQLGetConnectAttr.c
--- a/clients/odbc/driver/SQLGetConnectAttr.c
+++ b/clients/odbc/driver/SQLGetConnectAttr.c
@@ -64,7 +64,8 @@ MNDBGetConnectAttr(ODBCDbc *dbc,
break;
case SQL_ATTR_AUTOCOMMIT:   /* SQLUINTEGER */
/* SQL_AUTOCOMMIT */
-   WriteData(ValuePtr, dbc->sql_attr_autocommit, SQLUINTEGER);
+   bool autocommit = msetting_bool(dbc->settings, MP_AUTOCOMMIT);
+   WriteData(ValuePtr, autocommit, SQLUINTEGER);
break;
case SQL_ATTR_CONNECTION_DEAD:  /* SQLUINTEGER */
WriteData(ValuePtr, dbc->mid && mapi_is_connected(dbc->mid) ? 
SQL_CD_FALSE : SQL_CD_TRUE, SQLUINTEGER);
diff --git a/clients/odbc/driver/SQLSetConnectAttr.c 
b/clients/odbc/driver/SQLSetConnectAttr.c
--- a/clients/odbc/driver/SQLSetConnectAttr.c
+++ b/clients/odbc/driver/SQLSetConnectAttr.c
@@ -47,13 +47,12 @@ MNDBSetConnectAttr(ODBCDbc *dbc,
switch ((SQLUINTEGER) (uintptr_t) ValuePtr) {
case SQL_AUTOCOMMIT_ON:
case SQL_AUTOCOMMIT_OFF:
-   dbc->sql_attr_autocommit = (SQLUINTEGER) (uintptr_t) 
ValuePtr;
+   bool autocommit = (bool) (SQLUINTEGER) (uintptr_t) 
ValuePtr;
 #ifdef ODBCDEBUG
-   ODBCLOG("SQLSetConnectAttr set autocommit %s\n",
-   dbc->sql_attr_autocommit == SQL_AUTOCOMMIT_ON ? 
"on" : "off");
+   ODBCLOG("SQLSetConnectAttr set autocommit %s\n", 
autocommit ? "on" : "off");
 #endif
if (dbc->mid)
-   mapi_setAutocommit(dbc->mid, 
dbc->sql_attr_autocommit == SQL_AUTOCOMMIT_ON);
+   mapi_setAutocommit(dbc->mid, autocommit);
break;
default:
/* Invalid attribute value */
diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -179,6 +179,29 @@ ex = Execution('-0', '-d', f'DSN={dsn}-W
 ex.expect('OK')
 ex.end()
 
+# test autocommit

MonetDB: Aug2024 - Test that settings do not leak into next conn...

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: f8838596f8c9 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f8838596f8c9
Modified Files:
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Test that settings do not leak into next connection when a handle is reused


diffs (41 lines):

diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -15,6 +15,7 @@
 
 import atexit
 import os
+import shlex
 import subprocess
 import sys
 
@@ -37,7 +38,7 @@ class Execution:
 self.checks = []
 
 def report(self):
-parts = [f'COMMAND: {self.cmd}',
+parts = [f'COMMAND: {shlex.join(self.cmd)}',
  f'EXIT CODE: {self.proc.returncode}', '']
 if self.proc.stdout:
 parts += [
@@ -201,6 +202,20 @@ ex.expect('OK') # connect succee
 ex.expect('RESULT') # rollback succeeds
 ex.end()
 
+# test that configuration does not leak to next connection when handle is 
reused
+ex = Execution('-d',
+'-q', 'select remark from sys.sessions where sessionid = 
current_sessionid()',
+f'DSN={dsn};Client Remark=banana',
+f'DSN={dsn}'
+)
+ex.expect('OK')
+ex.expect('RESULT')
+ex.expect('- banana;')   # as set by Client Remark property
+ex.expect('OK')
+ex.expect('RESULT')
+ex.expect('- ;')   # this connection did not have a Client Remark
+ex.end()
+
 
 # Test browsing
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Comment

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 0b8f54cd8c3f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0b8f54cd8c3f
Modified Files:
clients/odbc/driver/SQLBrowseConnect.c
Branch: Aug2024
Log Message:

Comment


diffs (11 lines):

diff --git a/clients/odbc/driver/SQLBrowseConnect.c 
b/clients/odbc/driver/SQLBrowseConnect.c
--- a/clients/odbc/driver/SQLBrowseConnect.c
+++ b/clients/odbc/driver/SQLBrowseConnect.c
@@ -116,6 +116,7 @@ MNDBBrowseConnect(ODBCDbc *dbc,
size_t cap = 0;
suggest_settings(dbc, &buf, &pos, &cap, 2, "");// mandatory first
suggest_settings(dbc, &buf, &pos, &cap, 0, "*");   // then optional
+   // note that we leave out level 1, they have already been provided
 
if (buf && pos) {
size_t n = strcpy_len((char*)OutConnectionString, buf, 
BufferLength);
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Test SQLConnect user/pass parameters take pre...

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 3f6bfb98715f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/3f6bfb98715f
Modified Files:
sql/odbc/tests/Tests/ODBCconnect.py
testing/Mtest.py.in
Branch: Aug2024
Log Message:

Test SQLConnect user/pass parameters take precedence

Modify MonetDB-Test-Wrong dsn in Mtest.py to not set
DATABASE wrong as there is no way we can override it in
with SQLConnect.


diffs (41 lines):

diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -144,6 +144,16 @@ ex.expect('Error')
 ex.expect('28000:')  # 28000 bad credentials
 ex.end()
 
+# parameters passed directly to SQLConnect override those from the dsn
+ex = Execution(dsn + '-Wrong')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('28000:')# this dsn uses the wrong user name and password
+ex.end()
+ex = Execution(dsn + '-Wrong', '-u', user, '-p', password)
+ex.expect('OK')# but those passes as arguments take precedence
+ex.end()
+
 # test non-NUL terminated strings
 
 ex = Execution(dsn, '-0')
@@ -213,7 +223,7 @@ ex.expect('RESULT')
 ex.expect('- banana;')   # as set by Client Remark property
 ex.expect('OK')
 ex.expect('RESULT')
-ex.expect('- ;')   # this connection did not have a Client Remark
+ex.expect('- ;')   # the second connection does not have a Client Remark
 ex.end()
 
 
diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -2239,7 +2239,7 @@ Description = Wrong values for Database,
 Driver = MonetDB
 Host = localhost
 Port = {env["MAPIPORT"]}
-Database = {TSTDB}-Wrong
+Database = {TSTDB}
 User = {user or "monetdb"}-Wrong
 Password = {passwd or "monetdb"}-Wrong
 ''')
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - ODBCConnectionString is no longer used

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 4b59dd0861ce for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/4b59dd0861ce
Modified Files:
clients/odbc/driver/ODBCDbc.h
clients/odbc/driver/SQLDriverConnect.c
Branch: Aug2024
Log Message:

ODBCConnectionString is no longer used

instead we have buildConnectionString which takes all msettings into account


diffs (199 lines):

diff --git a/clients/odbc/driver/ODBCDbc.h b/clients/odbc/driver/ODBCDbc.h
--- a/clients/odbc/driver/ODBCDbc.h
+++ b/clients/odbc/driver/ODBCDbc.h
@@ -141,14 +141,6 @@ ODBCError *getDbcError(ODBCDbc *dbc);
 void destroyODBCDbc(ODBCDbc *dbc);
 
 int ODBCGetKeyAttr(const SQLCHAR **conn, SQLSMALLINT *nconn, char **key, char 
**attr);
-SQLRETURN ODBCConnectionString(SQLRETURN rc, ODBCDbc *dbc,
-  SQLCHAR *OutConnectionString,
-  SQLSMALLINT BufferLength,
-  SQLSMALLINT *StringLength2Ptr,
-  const char *dsn, const char *uid,
-  const char *pwd, const char *host,
-  int port, const char *database,
-  int mapToLongVarchar);
 SQLRETURN MNDBAllocStmt(ODBCDbc *dbc, SQLHANDLE *pnOutputHandle);
 SQLRETURN MNDBConnect(ODBCDbc *dbc, const SQLCHAR *szDataSource, SQLSMALLINT 
nDataSourceLength,
const SQLCHAR *szUID, SQLSMALLINT nUIDLength,
diff --git a/clients/odbc/driver/SQLDriverConnect.c 
b/clients/odbc/driver/SQLDriverConnect.c
--- a/clients/odbc/driver/SQLDriverConnect.c
+++ b/clients/odbc/driver/SQLDriverConnect.c
@@ -105,177 +105,6 @@ ODBCGetKeyAttr(const SQLCHAR **conn, SQL
return 1;
 }
 
-SQLRETURN
-ODBCConnectionString(SQLRETURN rc,
-ODBCDbc *dbc,
-SQLCHAR *OutConnectionString,
-SQLSMALLINT BufferLength,
-SQLSMALLINT *StringLength2Ptr,
-const char *dsn,
-const char *uid,
-const char *pwd,
-const char *host,
-int port,
-const char *database,
-int mapToLongVarchar)
-{
-   int n;
-#ifdef ODBCDEBUG
-   SQLCHAR *buf = OutConnectionString;
-   int buflen = BufferLength;
-#endif
-
-   if (OutConnectionString == NULL)
-   BufferLength = -1;
-   if (BufferLength > 0) {
-   n = snprintf((char *) OutConnectionString, BufferLength,
-"DSN=%s;", dsn ? dsn : "DEFAULT");
-   /* some snprintf's return -1 if buffer too small */
-   if (n < 0)
-   n = BufferLength + 1;   /* make sure it becomes < 0 */
-   BufferLength -= n;
-   OutConnectionString += n;
-   } else {
-   BufferLength = -1;
-   }
-   if (uid) {
-   if (BufferLength > 0) {
-   n = snprintf((char *) OutConnectionString,
-BufferLength, "UID=%s;", uid);
-   if (n < 0)
-   n = BufferLength + 1;
-   BufferLength -= n;
-   OutConnectionString += n;
-   } else {
-   BufferLength = -1;
-   }
-   }
-   if (pwd) {
-   if (BufferLength > 0) {
-   n = snprintf((char *) OutConnectionString,
-BufferLength, "PWD=%s;", pwd);
-   if (n < 0)
-   n = BufferLength + 1;
-   BufferLength -= n;
-   OutConnectionString += n;
-   } else {
-   BufferLength = -1;
-   }
-   }
-   if (host) {
-   if (BufferLength > 0) {
-   n = snprintf((char *) OutConnectionString,
-BufferLength, "HOST=%s;", host);
-   if (n < 0)
-   n = BufferLength + 1;
-   BufferLength -= n;
-   OutConnectionString += n;
-   } else {
-   BufferLength = -1;
-   }
-   }
-   if (port) {
-   char portbuf[10];
-
-   if (BufferLength > 0) {
-   n = snprintf((char *) OutConnectionString,
-BufferLength, "PORT=%d;", port);
-   if (n < 0)
-   n = BufferLength + 1;
-   BufferLength -= n;
-   OutConnectionString += n;
-   } else {
-   BufferLength = -1;
-   }
-   port = snprintf(portbuf, sizeof(portbuf), "%d", port);
-   }
-   if (database) {
-   if (BufferLength > 0) {
-   n = snprintf((char *) OutConnectionS

MonetDB: Aug2024 - Last four parameters of MNDBConnect are now u...

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 28ad5b5a for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/28ad5b5a
Modified Files:
clients/odbc/driver/ODBCDbc.h
clients/odbc/driver/SQLConnect.c
Branch: Aug2024
Log Message:

Last four parameters of MNDBConnect are now unused


diffs (88 lines):

diff --git a/clients/odbc/driver/ODBCDbc.h b/clients/odbc/driver/ODBCDbc.h
--- a/clients/odbc/driver/ODBCDbc.h
+++ b/clients/odbc/driver/ODBCDbc.h
@@ -144,8 +144,7 @@ int ODBCGetKeyAttr(const SQLCHAR **conn,
 SQLRETURN MNDBAllocStmt(ODBCDbc *dbc, SQLHANDLE *pnOutputHandle);
 SQLRETURN MNDBConnect(ODBCDbc *dbc, const SQLCHAR *szDataSource, SQLSMALLINT 
nDataSourceLength,
const SQLCHAR *szUID, SQLSMALLINT nUIDLength,
-   const SQLCHAR *szPWD, SQLSMALLINT nPWDLength,
-   const char *host, int port, const char *dbname, int 
mapToLongVarchar);
+   const SQLCHAR *szPWD, SQLSMALLINT nPWDLength);
 SQLRETURN MNDBGetConnectAttr(ODBCDbc *dbc, SQLINTEGER Attribute, SQLPOINTER 
ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLength);
 SQLRETURN MNDBSetConnectAttr(ODBCDbc *dbc, SQLINTEGER Attribute, SQLPOINTER 
ValuePtr, SQLINTEGER StringLength);
 
diff --git a/clients/odbc/driver/SQLConnect.c b/clients/odbc/driver/SQLConnect.c
--- a/clients/odbc/driver/SQLConnect.c
+++ b/clients/odbc/driver/SQLConnect.c
@@ -311,17 +311,14 @@ end:
 
 
 SQLRETURN
+
 MNDBConnect(ODBCDbc *dbc,
const SQLCHAR *ServerName,
SQLSMALLINT NameLength1,
const SQLCHAR *UserName,
SQLSMALLINT NameLength2,
const SQLCHAR *Authentication,
-   SQLSMALLINT NameLength3,
-   const char *host,
-   int port,
-   const char *dbname,
-   int mapToLongVarchar)
+   SQLSMALLINT NameLength3)
 {
// These will be passed to addDbcError if you 'goto failure'.
// If unset, 'goto failure' will assume an allocation error.
@@ -402,30 +399,12 @@ MNDBConnect(ODBCDbc *dbc,
goto failure;
}
 
-   if (host != NULL) {
-   error_explanation = msetting_set_string(settings, MP_HOST, 
host);
-   if (error_explanation != NULL)
-   goto failure;
-   }
-
mapiport_env = getenv("MAPIPORT");
-   if (port > 0)
-   error_explanation = msetting_set_long(settings, MP_PORT, port);
-   else if (mapiport_env != NULL)
+   if (mapiport_env != NULL)
error_explanation = msetting_parse(settings, MP_PORT, 
mapiport_env);
if (error_explanation != NULL)
goto failure;
 
-   if (dbname != NULL) {
-   error_explanation = msetting_set_string(settings, MP_DATABASE, 
dbname);
-   if (error_explanation != NULL)
-   goto failure;
-   }
-
-   error_explanation = msetting_set_long(settings, MP_MAPTOLONGVARCHAR, 
mapToLongVarchar);
-   if (error_explanation)
-   goto failure;
-
 #ifdef ODBCDEBUG
{
free(scratch);
@@ -545,8 +524,7 @@ SQLConnect(SQLHDBC ConnectionHandle,
return MNDBConnect((ODBCDbc *) ConnectionHandle,
   ServerName, NameLength1,
   UserName, NameLength2,
-  Authentication, NameLength3,
-  NULL, 0, NULL, 0);
+  Authentication, NameLength3);
 }
 
 SQLRETURN SQL_API
@@ -596,8 +574,7 @@ SQLConnectW(SQLHDBC ConnectionHandle,
rc = MNDBConnect(dbc,
 ds, SQL_NTS,
 uid, SQL_NTS,
-pwd, SQL_NTS,
-NULL, 0, NULL, 0);
+pwd, SQL_NTS);
 
   bailout:
if (ds)
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Write SQLConnectA, etc in odbcconnect.c

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 0fe29b9b9760 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0fe29b9b9760
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Write SQLConnectA, etc in odbcconnect.c


diffs (74 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static const char *USAGE =
"Usage:\n"
@@ -206,7 +207,7 @@ ensure_ok_impl(SQLSMALLINT type, SQLHAND
 
bool printed_something = false;
for (int i = 1; ; i++) {
-   SQLRETURN diag_ret = SQLGetDiagRec(
+   SQLRETURN diag_ret = SQLGetDiagRecA(
type, handle, i,
state, &error, explanation, sizeof(explanation), &len);
if (!SQL_SUCCEEDED(diag_ret))
@@ -259,7 +260,7 @@ do_sqlconnect(SQLCHAR *target)
 
ensure_ok(
SQL_HANDLE_DBC, conn, "SQLConnect",
-   SQLConnect(conn, target, target_len, user, user_len, password, 
password_len));
+   SQLConnectA(conn, target, target_len, user, user_len, password, 
password_len));
printf("OK\n");
 
int exitcode = do_execute_stmt();
@@ -281,7 +282,7 @@ do_sqldriverconnect(SQLCHAR *target)
 
ensure_ok(
SQL_HANDLE_DBC, conn, "SQLDriverConnect",
-   SQLDriverConnect(
+   SQLDriverConnectA(
conn, NULL,
target, target_len,
outbuf, sizeof(outbuf), &n,
@@ -307,7 +308,7 @@ do_sqlbrowseconnect(SQLCHAR *target)
if (use_counted_strings)
fuzz_sql_nts(&target, &target_len);
 
-   SQLRETURN ret = SQLBrowseConnect(
+   SQLRETURN ret = SQLBrowseConnectA(
conn,
target, target_len,
outbuf, sizeof(outbuf), &n
@@ -338,7 +339,7 @@ do_listdrivers(void)
 
while (1) {
outbuf[0] = attrbuf[0] = '\0';
-   SQLRETURN ret = SQLDrivers(
+   SQLRETURN ret = SQLDriversA(
env, dir,
outbuf, sizeof(outbuf), &len1,
attrbuf, sizeof(attrbuf), &len2
@@ -367,7 +368,7 @@ do_listdsns(const char *prefix, SQLSMALL
 
while (1) {
outbuf[0] = attrbuf[0] = '\0';
-   SQLRETURN ret = SQLDataSources(
+   SQLRETURN ret = SQLDataSourcesA(
env, dir,
outbuf, sizeof(outbuf), &len1,
attrbuf, sizeof(attrbuf), &len2
@@ -401,7 +402,7 @@ do_execute_stmt(void)
 
ensure_ok(
SQL_HANDLE_STMT, stmt, "SQLExecDirect",
-   SQLExecDirect(stmt, query, query_len));
+   SQLExecDirectA(stmt, query, query_len));
 
do {
SQLLEN rowcount = -1;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Mark user DNS's as such

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 327a94079349 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/327a94079349
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Mark user DNS's as such


diffs (12 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -157,7 +157,7 @@ main(int argc, char **argv)
}
ret = do_listdrivers();
ret |= do_listdsns("SYSTEM", SQL_FETCH_FIRST_SYSTEM);
-   ret |= do_listdsns("SYSTEM", SQL_FETCH_FIRST_USER);
+   ret |= do_listdsns("USER", SQL_FETCH_FIRST_USER);
}
 
 end:
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Simplify memory management in odbcconnect.c

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: dd08c6628fb2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/dd08c6628fb2
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Simplify memory management in odbcconnect.c


diffs (truncated from 316 to 300 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -40,13 +40,13 @@ static const char *USAGE =
"-v  Be verbose\n"
"TARGET  DSN or with -d and -b, Connection String\n";
 
-typedef int (action_t)(SQLCHAR *);
+typedef int (action_t)(const char *);
 
 static action_t do_sqlconnect;
 static action_t do_sqldriverconnect;
 static action_t do_sqlbrowseconnect;
 
-static int do_actions(action_t action, int ntargets, SQLCHAR **targets);
+static int do_actions(action_t action, int ntargets, char **targets);
 
 static int do_listdrivers(void);
 static int do_listdsns(const char *prefix, SQLSMALLINT dir);
@@ -57,17 +57,13 @@ static void ensure_ok_impl(SQLSMALLINT t
 
 #define ensure_ok(type, handle, message, ret)ensure_ok_impl(type, handle, 
message, ret, __LINE__)
 
-#define MARGIN 100
-static SQLCHAR* sqldup_with_margin(const char *str);
-static void fuzz_sql_nts(SQLCHAR **str, SQLSMALLINT *len);
+static void make_arg(const char *arg, SQLCHAR**bufp, SQLSMALLINT *buflen);
+
 
 int verbose = 0;
-SQLCHAR *user = NULL;
-SQLSMALLINT user_len = SQL_NTS;
-SQLCHAR *password = NULL;
-SQLSMALLINT password_len = SQL_NTS;
-SQLCHAR *query = NULL;
-SQLSMALLINT query_len = SQL_NTS;
+char *user = NULL;
+char *password = NULL;
+char *query = NULL;
 bool use_counted_strings = false;
 
 SQLHANDLE env = NULL;
@@ -77,12 +73,25 @@ SQLHANDLE stmt = NULL;
 SQLCHAR outbuf[4096];
 SQLCHAR attrbuf[4096];
 
+// This free-list will be processed by cleanup().
+// It is added to by alloc()
+unsigned int ngarbage = 0;
+void *garbage[100] = { NULL };
+
+
+static void*
+alloc(size_t size)
+{
+   void *p = calloc(size, 1);
+   assert(p);
+   if (ngarbage < sizeof(garbage) / sizeof(garbage[0]))
+   garbage[ngarbage++] = p;
+   return p;
+}
+
 static void
 cleanup(void)
 {
-   free(user);
-   free(password);
-   free(query);
if (stmt)
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
if (conn) {
@@ -91,14 +100,18 @@ cleanup(void)
}
if (env)
SQLFreeHandle(SQL_HANDLE_DBC, env);
+
+   while (ngarbage > 0) {
+   free(garbage[--ngarbage]);
+   }
 }
 
 int
 main(int argc, char **argv)
 {
-   int (*action)(SQLCHAR *);
+   int (*action)(const char*);
action = do_sqlconnect;
-   SQLCHAR **targets = calloc(argc, sizeof(argv[0]));
+   char **targets = alloc(argc * sizeof(argv[0]));
int ntargets = 0;
int ret;
 
@@ -111,17 +124,17 @@ main(int argc, char **argv)
else if (strcmp(arg, "-l") == 0)
action = NULL;
else if (strcmp(arg, "-u") == 0 && i + 1 < argc)
-   user = sqldup_with_margin(argv[++i]);
+   user = argv[++i];
else if (strcmp(arg, "-p") == 0 && i + 1 < argc)
-   password = sqldup_with_margin(argv[++i]);
+   password = argv[++i];
else if (strcmp(arg, "-q") == 0 && i + 1 < argc)
-   query = sqldup_with_margin(argv[++i]);
+   query = argv[++i];
else if (strcmp(arg, "-0") == 0)
use_counted_strings = true;
else if (strcmp(arg, "-v") == 0)
verbose += 1;
else if (arg[0] != '-')
-   targets[ntargets++] = sqldup_with_margin(arg);
+   targets[ntargets++] = arg;
else {
fprintf(stderr, "\nERROR: invalid argument: %s\n%s", 
arg, USAGE);
ret = 1;
@@ -137,11 +150,6 @@ main(int argc, char **argv)
SQL_HANDLE_ENV, env, "set odbc version",
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, 
(SQLPOINTER)SQL_OV_ODBC3, 0));
 
-   if (use_counted_strings) {
-   fuzz_sql_nts(&user, &user_len);
-   fuzz_sql_nts(&password, &password_len);
-   }
-
if (action) {
if (ntargets == 0) {
fprintf(stderr, "\nERROR: pass at least one 
target\n%s", USAGE);
@@ -161,9 +169,6 @@ main(int argc, char **argv)
}
 
 end:
-   for (int i = 0; i < ntargets; i++)
-   free(targets[i]);
-   free(targets);
cleanup();
 
return ret;
@@ -232,14 +237,14 @@ ensure_ok_impl(SQLSMALLINT type, SQLHAND
 
 
 static int
-do_actions(action_t action, int ntargets, SQLCHAR **targets)
+do_actions(action_t action, int ntargets, char **targets)
 {
ensure_ok(
SQL_HANDLE_ENV, env, "al

MonetDB: Aug2024 - Extend odbcconnect with -w to test the Wide API

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: e37e83b564b7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e37e83b564b7
Modified Files:
clients/odbc/tests/CMakeLists.txt
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Extend odbcconnect with -w to test the Wide API


diffs (truncated from 400 to 300 lines):

diff --git a/clients/odbc/tests/CMakeLists.txt 
b/clients/odbc/tests/CMakeLists.txt
--- a/clients/odbc/tests/CMakeLists.txt
+++ b/clients/odbc/tests/CMakeLists.txt
@@ -44,6 +44,7 @@ add_executable(odbcconnect
 
 target_link_libraries(odbcconnect
   PRIVATE
+  mutf8
   ODBC::ODBC)
 
 install(TARGETS
diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -26,6 +26,8 @@
 #include 
 #include 
 
+#include "mutf8.h"
+
 static const char *USAGE =
"Usage:\n"
"odbcconnect [-d | -c | -b ] [-v] [-u USER] [-p PASSWORD] 
TARGET..\n"
@@ -37,6 +39,7 @@ static const char *USAGE =
"-p PASSWORD\n"
"-q SQL  Execute SQL statement when connection 
succeeds\n"
"-0  use counted strings rather than nul-terminated 
arguments\n"
+   "-w  use the wide-char (unicode) interface\n"
"-v  Be verbose\n"
"TARGET  DSN or with -d and -b, Connection String\n";
 
@@ -57,7 +60,13 @@ static void ensure_ok_impl(SQLSMALLINT t
 
 #define ensure_ok(type, handle, message, ret)ensure_ok_impl(type, handle, 
message, ret, __LINE__)
 
-static void make_arg(const char *arg, SQLCHAR**bufp, SQLSMALLINT *buflen);
+static void make_arg(bool wide, const char *arg, void **bufp, SQLSMALLINT 
*buflen);
+static void make_arga(const char *arg, void **bufp, SQLSMALLINT *buflen);
+static void make_argw(const char *arg, void **bufp, SQLSMALLINT *buflen, bool 
bytes_not_chars);
+
+
+static SQLWCHAR *gen_utf16(SQLWCHAR *dest, const char *src, size_t len);
+static void convert_outw_outa(size_t n);
 
 
 int verbose = 0;
@@ -65,13 +74,17 @@ char *user = NULL;
 char *password = NULL;
 char *query = NULL;
 bool use_counted_strings = false;
+bool use_wide = false;
 
 SQLHANDLE env = NULL;
 SQLHANDLE conn = NULL;
 SQLHANDLE stmt = NULL;
 
-SQLCHAR outbuf[4096];
+#define OUTBUF_SIZE 4096
 SQLCHAR attrbuf[4096];
+SQLCHAR outabuf[OUTBUF_SIZE];
+SQLWCHAR outwbuf[OUTBUF_SIZE];
+
 
 // This free-list will be processed by cleanup().
 // It is added to by alloc()
@@ -131,6 +144,8 @@ main(int argc, char **argv)
query = argv[++i];
else if (strcmp(arg, "-0") == 0)
use_counted_strings = true;
+   else if (strcmp(arg, "-w") == 0)
+   use_wide = true;
else if (strcmp(arg, "-v") == 0)
verbose += 1;
else if (arg[0] != '-')
@@ -247,7 +262,8 @@ do_actions(action_t action, int ntargets
char *t = targets[i];
if (verbose)
printf("\nTarget: %s\n", t);
-   outbuf[0] = '\0';
+   outabuf[0] = '\0';
+   outwbuf[0] = 0;
int ret = action(t);
if (ret)
return ret;
@@ -259,21 +275,24 @@ do_actions(action_t action, int ntargets
 static int
 do_sqlconnect(const char *target)
 {
-   SQLCHAR *target_buf;
+   void *target_buf;
SQLSMALLINT target_len = SQL_NTS;
-   make_arg(target, &target_buf, &target_len);
+   make_arg(use_wide, target, &target_buf, &target_len);
 
-   SQLCHAR *user_buf;
+   void *user_buf;
SQLSMALLINT user_len = SQL_NTS;
-   make_arg(user, &user_buf, &user_len);
+   make_arg(use_wide, user, &user_buf, &user_len);
 
-   SQLCHAR *password_buf;
+   void *password_buf;
SQLSMALLINT password_len = SQL_NTS;
-   make_arg(password, &password_buf, &password_len);
+   make_arg(use_wide, password, &password_buf, &password_len);
 
ensure_ok(
SQL_HANDLE_DBC, conn, "SQLConnect",
-   SQLConnectA(conn, target_buf, target_len, user_buf, user_len, 
password_buf, password_len));
+   use_wide
+   ? SQLConnectW(conn, target_buf, target_len, user_buf, 
user_len, password_buf, password_len)
+   : SQLConnectA(conn, target_buf, target_len, user_buf, 
user_len, password_buf, password_len)
+   );
printf("OK\n");
 
int exitcode = do_execute_stmt();
@@ -288,22 +307,22 @@ do_sqlconnect(const char *target)
 static int
 do_sqldriverconnect(const char *target)
 {
-   SQLCHAR *target_buf;
+   void *target_buf;
SQLSMALLINT target_len = SQL_NTS;
-   make_arg(target, &target_buf, &target_len);
+   make_arg(use_wide, target, &target_buf, &target_len);
 
SQLSMALLINT n;
 
ensure_ok(
SQL_HANDLE_DBC, conn, "SQLDriverConnect",
- 

MonetDB: Aug2024 - SQLDriverConnect: build connection string eve...

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 89396b04faf9 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/89396b04faf9
Modified Files:
clients/odbc/driver/SQLDriverConnect.c
Branch: Aug2024
Log Message:

SQLDriverConnect: build connection string even with tryOnly

It's the only reason tryOnly exists!


diffs (56 lines):

diff --git a/clients/odbc/driver/SQLDriverConnect.c 
b/clients/odbc/driver/SQLDriverConnect.c
--- a/clients/odbc/driver/SQLDriverConnect.c
+++ b/clients/odbc/driver/SQLDriverConnect.c
@@ -189,6 +189,18 @@ MNDBDriverConnect(ODBCDbc *dbc,
goto end;
}
 
+   // Build a connect string for the current connection and put it in the 
out buffer.
+   scratch_alloc = buildConnectionString(dsn ? dsn : "DEFAULT", settings);
+   if (!scratch_alloc)
+   goto failure;
+   out_len = strcpy_len((char*)OutConnectionString, scratch_alloc, 
BufferLength);
+   if (StringLength2Ptr)
+   *StringLength2Ptr = (SQLSMALLINT)out_len;
+   if (out_len + 1 > (size_t)BufferLength) {
+   addDbcError(dbc, "01004", NULL, 0);
+   rc = SQL_SUCCESS_WITH_INFO;
+   }
+
if (tryOnly) {
assert(sqlstate == NULL);
goto end;
@@ -200,23 +212,8 @@ MNDBDriverConnect(ODBCDbc *dbc,
 
rc = MNDBConnectSettings(dbc, dsn, settings);
settings = NULL; // do not free now
-   if (!SQL_SUCCEEDED(rc))
-   goto end; // not to 'failure', all errors have already been 
logged
 
-
-   // Build a connect string for the current connection
-   // and put it in the buffer.
-   scratch_alloc = buildConnectionString(dsn ? dsn : "DEFAULT", 
dbc->settings);
-   if (!scratch_alloc)
-   goto failure;
-   out_len = strcpy_len((char*)OutConnectionString, scratch_alloc, 
BufferLength);
-   if (StringLength2Ptr)
-   *StringLength2Ptr = (SQLSMALLINT)out_len;
-   if (out_len + 1 > (size_t)BufferLength) {
-   addDbcError(dbc, "01004", NULL, 0);
-   rc = SQL_SUCCESS_WITH_INFO;
-   }
-
+   // always go to end, MNDBConnectSettings has already logged any failures
goto end;
 
 failure:
@@ -313,7 +310,7 @@ SQLDriverConnectW(SQLHDBC ConnectionHand
   addDbcError, dbc, return SQL_ERROR);
 
rc = MNDBDriverConnect(dbc, WindowHandle, in, SQL_NTS, NULL, 0, &n,
-  DriverCompletion, 1);  // Try Only
+  DriverCompletion, 1);  // 1 = Try Only
if (!SQL_SUCCEEDED(rc))
return rc;
clearDbcErrors(dbc);
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Make odbcconnect handle full utf-16, not just...

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: d0a155c796b6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d0a155c796b6
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Make odbcconnect handle full utf-16, not just ascii-16


diffs (90 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -338,7 +338,7 @@ do_sqlbrowseconnect(const char *target)
 {
void *target_buf;
SQLSMALLINT target_len = SQL_NTS;
-   make_arg(false, target, &target_buf, &target_len);
+   make_arg(use_wide, target, &target_buf, &target_len);
 
 
SQLSMALLINT n;
@@ -462,9 +462,13 @@ do_execute_stmt(void)
for (int i = 1; i <= colcount; i++) {
SQLLEN n;
outabuf[0] = '\0';
-   SQLRETURN ret = SQLGetData(stmt, i, SQL_C_CHAR, 
outabuf, OUTBUF_SIZE, &n);
+   SQLRETURN ret = use_wide
+   ? SQLGetData(stmt, i, SQL_C_WCHAR, 
outwbuf, OUTBUF_SIZE * sizeof(SQLWCHAR), &n)
+   : SQLGetData(stmt, i, SQL_C_CHAR, 
outabuf, OUTBUF_SIZE, &n);
if (!SQL_SUCCEEDED(ret))
ensure_ok(SQL_HANDLE_STMT, stmt, 
"SQLGetData", ret);
+   if (use_wide)
+   convert_outw_outa(n);
printf("%s;", outabuf);
}
printf("\n");
@@ -584,17 +588,54 @@ gen_utf16(SQLWCHAR *dest, const char *sr
return p;
 }
 
+static inline SQLCHAR
+continuation_byte(uint32_t val, int n)
+{
+   val >>= 6 * n; // chop off right hand bits
+   val &= 0x3F;   // chop off left hand bits
+   val |= 0x80;   // add continuation marker bit
+   return val;
+}
+
 static void
 convert_outw_outa(size_t n)
 {
-   // outw mostly holds connection strings and those are mostly ascii
-   for (size_t i = 0; i < n; i++) {
-   SQLWCHAR w = outwbuf[i];
-   if (w > 127) {
-   fprintf(stderr, "Sorry, this test is lazy and should be 
extended to non-ascii utf-16\n");
-   exit(1);
+   SQLWCHAR *end = &outwbuf[n];
+   SQLWCHAR *in = &outwbuf[0];
+   SQLCHAR *out = &outabuf[0];
+
+   while (in < end) {
+   SQLWCHAR w = *in++;
+   uint32_t codepoint;
+   if (w < 0xD800 || w >= 0xE000) {
+   codepoint = w;
+   } else if (w < 0xDC00 && in < end && *in >= 0xDC00 && *in < 
0xE000) {
+   uint32_t hi = w - 0xD800;
+   uint32_t lo = *in++ - 0xDC00;
+   codepoint = 0x1 + (hi << 10) + lo;
+   } else {
+   strcpy((char*)out, "!!INVALID UTF-16 OR A BUG IN THE 
TEST ITSELF!!");
+   break;
}
-   outabuf[i] = (SQLCHAR)w;
+   if (codepoint == 0xFEFF && out == &outabuf[0]) {
+   // skip the BOM
+   } else if (codepoint < 0x80) {
+   *out++ = codepoint;
+   } else if (codepoint < 0x800) {
+   *out++ = 0xC0 | (codepoint >> 6);
+   *out++ = continuation_byte(codepoint, 0);
+   } else if (codepoint < 0x1) {
+   *out++ = 0xE0 | (codepoint >> 12);
+   *out++ = continuation_byte(codepoint, 1);
+   *out++ = continuation_byte(codepoint, 0);
+   } else {
+   assert(codepoint < 0x11);
+   *out++ = 0xF0 | (codepoint >> 18);
+   *out++ = continuation_byte(codepoint, 2);
+   *out++ = continuation_byte(codepoint, 1);
+   *out++ = continuation_byte(codepoint, 0);
+   }
}
-   outabuf[n] = '\0';
+
+   *out = '\0';
 }
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Include wide character tests in sql/odbc/test...

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: c85461b96b69 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c85461b96b69
Modified Files:
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Include wide character tests in sql/odbc/tests/ODBCconnect


diffs (109 lines):

diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -25,6 +25,10 @@ user = 'monetdb'
 password = 'monetdb'
 port = os.environ.get('MAPIPORT', 5)
 
+# \u{E1} is LATIN SMALL LETTER A WITH ACUTE
+unicode_text = 'R\u00E1inbow'
+# \u{1F308} is RAINBOW EMOJI
+#unicode_text += '\U0001F308'
 
 class Execution:
 def __init__(self, *odbcconnect_args):
@@ -110,6 +114,10 @@ def show_context():
 print(ex.report(), file=sys.stderr)
 
 
+###
+# Test SQLConnect
+###
+
 ex = Execution(dsn)
 ex.expect('OK')
 ex.end()
@@ -164,7 +172,21 @@ ex = Execution(dsn, '-0', '-u', user, '-
 ex.expect('OK')
 ex.end()
 
-# test connection strings
+# test wide characters
+ex = Execution('-w', dsn + '-Wrong', '-u', user, '-p', password)
+ex.expect('OK')
+ex.end()
+
+# test wide characters in combination with non-NUL
+ex = Execution('-0', '-w', dsn + '-Wrong', '-u', user, '-p', password)
+ex.expect('OK')
+ex.end()
+
+
+
+###
+# Test SQLDriverConnect
+###
 
 ex = Execution('-d', f'DSN={dsn}')
 ex.expect('OK')
@@ -226,8 +248,15 @@ ex.expect('RESULT')
 ex.expect('- ;')   # the second connection does not have a Client Remark
 ex.end()
 
+# test wide characters
+ex = Execution('-w', '-d', f'DSN={dsn};Client Remark={unicode_text}')
+# expect OK followed by connection string containing the rainbow
+ex.expect('OK', f'CLIENTREMARK={unicode_text}')
+ex.end()
 
-# Test browsing
+###
+# Test SQLBrowseConnect
+###
 
 ex = Execution('-b', 'Driver={MonetDB}')
 ex.expect('Info')
@@ -259,6 +288,41 @@ ex = Execution('-b', f'DSN={dsn}')
 ex.expect('OK', ';')
 ex.end()
 
-# clear 'ex', otherwise the atexit handler will write things
-# to stderr
+# test wide characters
+ex = Execution('-w', '-b', f'DSN={dsn}')
+ex.expect('OK', ';')
+ex.end()
+
+ex = Execution('-w', '-b', f'DSN={dsn};Client Remark={unicode_text}')
+ex.expect('OK', f';CLIENTREMARK={unicode_text}')
+ex.expect
+ex.end()
+
+# also with non-NUL terminated strings
+ex = Execution('-0', '-w', '-b', f'DSN={dsn}')
+ex.expect('OK', ';')
+ex.end()
+
+ex = Execution('-0', '-w', '-b', f'DSN={dsn};Client Remark={unicode_text}')
+ex.expect('OK', f';CLIENTREMARK={unicode_text}')
+ex.expect
+ex.end()
+
+# Also test that queries return unicode ok
+ex = Execution(
+'-w',
+'-b', f'DSN={dsn};Client Remark={unicode_text}',
+'-q', 'select remark from sys.sessions where sessionid = 
current_sessionid()',
+)
+ex.expect('OK', f';CLIENTREMARK={unicode_text}')
+ex.expect('RESULT')
+ex.expect(unicode_text)
+ex.end()
+
+
+###
+#
+# clear 'ex', otherwise the atexit handler will write things to stderr
+#
+###
 ex = None
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Show output of odbcconnect -l when test fails

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 1f00aade5a18 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/1f00aade5a18
Modified Files:
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Show output of odbcconnect -l when test fails


diffs (23 lines):

diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -101,6 +101,10 @@ class Execution:
 raise Exception(
 f'Process exited with code {code!r}, expected {expected!r}')
 
+# Grab the output of 'odbcconnect -l' so we can show it if a test fails
+list_output = None
+ex = Execution('-l')
+list_output = ex.proc.stdout
 
 ex = None
 
@@ -112,6 +116,8 @@ def show_context():
 # ex.end()
 print(file=sys.stderr)
 print(ex.report(), file=sys.stderr)
+if list_output:
+print(f'\n--- output of odbcconnect -l ---\n{list_output}--- end 
---', file=sys.stderr)
 
 
 ###
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Fix SQLErrorW: odbc errors start at 1, not 0

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 1962142fc6d2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/1962142fc6d2
Modified Files:
clients/odbc/driver/SQLError.c
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Fix SQLErrorW: odbc errors start at 1, not 0


diffs (51 lines):

diff --git a/clients/odbc/driver/SQLError.c b/clients/odbc/driver/SQLError.c
--- a/clients/odbc/driver/SQLError.c
+++ b/clients/odbc/driver/SQLError.c
@@ -125,19 +125,19 @@ SQLErrorW(SQLHENV EnvironmentHandle,
if (StatementHandle)
rc = MNDBGetDiagRec(SQL_HANDLE_STMT,
StatementHandle,
-   ((ODBCStmt *) 
StatementHandle)->RetrievedErrors,
+   ++((ODBCStmt *) 
StatementHandle)->RetrievedErrors,
state, NativeErrorPtr,
errmsg, (SQLSMALLINT) sizeof(errmsg), &n);
else if (ConnectionHandle)
rc = MNDBGetDiagRec(SQL_HANDLE_DBC,
ConnectionHandle,
-   ((ODBCDbc *) 
ConnectionHandle)->RetrievedErrors,
+   ++((ODBCDbc *) 
ConnectionHandle)->RetrievedErrors,
state, NativeErrorPtr,
errmsg, (SQLSMALLINT) sizeof(errmsg), &n);
else if (EnvironmentHandle)
rc = MNDBGetDiagRec(SQL_HANDLE_ENV,
EnvironmentHandle,
-   ((ODBCEnv *) 
EnvironmentHandle)->RetrievedErrors,
+   ++((ODBCEnv *) 
EnvironmentHandle)->RetrievedErrors,
state, NativeErrorPtr,
errmsg, (SQLSMALLINT) sizeof(errmsg), &n);
else
diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -254,6 +254,21 @@ ex.expect('RESULT')
 ex.expect('- ;')   # the second connection does not have a Client Remark
 ex.end()
 
+# test error handling when -w is given
+
+# first without the -w to demonstrate the expected behavior
+ex = Execution('-d', 
f'Driver={{MonetDB}};User={user};Password={password};Database={dbname + 
"-Wrong"}')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('08001')  # something wrong with the database
+ex.end()
+# then with the -w
+ex = Execution('-w', '-d', 
f'Driver={{MonetDB}};User={user};Password={password};Database={dbname + 
"-Wrong"}')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('08001')  # something wrong with the database
+ex.end()
+
 # test wide characters
 ex = Execution('-w', '-d', f'DSN={dsn};Client Remark={unicode_text}')
 # expect OK followed by connection string containing the rainbow
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Fix uninitialized use

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 3b49dad3d4f7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/3b49dad3d4f7
Modified Files:
clients/odbc/tests/odbcconnect.c
Branch: Aug2024
Log Message:

Fix uninitialized use

Hadn't realized mutf8 decode() reads the *codepoint without writing it first


diffs (14 lines):

diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -559,9 +559,9 @@ gen_utf16(SQLWCHAR *dest, const char *sr
 {
SQLWCHAR *p = dest;
uint32_t state = UTF8_ACCEPT;
+   uint32_t codepoint = UTF8_ACCEPT;
for (size_t i = 0; i < len; i++) {
unsigned char byte = (unsigned char)src[i];
-   uint32_t codepoint;
switch (decode(&state, &codepoint, byte)) {
case UTF8_ACCEPT:
if (codepoint <= 0x) {
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Print more info when ODBCconnect.py fails

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: b87fb6cce3e5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/b87fb6cce3e5
Modified Files:
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Print more info when ODBCconnect.py fails


diffs (19 lines):

diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
--- a/sql/odbc/tests/Tests/ODBCconnect.py
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -118,6 +118,15 @@ def show_context():
 print(ex.report(), file=sys.stderr)
 if list_output:
 print(f'\n--- output of odbcconnect -l ---\n{list_output}--- end 
---', file=sys.stderr)
+odbcini = os.getenv('ODBCINI', 'odbc.ini')
+sysini = os.getenv('ODBCSYSINI', os.getenv('TSTTRGDIR'))
+fullpath = os.path.join(sysini, odbcini)
+try:
+with open(fullpath) as f:
+content = f.read()
+print(f'\n--- content of {fullpath} ---\n{content}\n--- end 
---', file=sys.stderr)
+except FileNotFoundError:
+pass
 
 
 ###
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Restore mapToLongVarchar setting

2024-07-05 Thread Joeri van Ruth via checkin-list
Changeset: 90b3c951a5ec for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/90b3c951a5ec
Modified Files:
clients/odbc/driver/ODBCAttrs.c
clients/odbc/driver/SQLBrowseConnect.c
clients/odbc/tests/odbcconnect.c
sql/odbc/tests/Tests/ODBCconnect.py
Branch: Aug2024
Log Message:

Restore mapToLongVarchar setting

It was available on the URL but not in ODBC


diffs (109 lines):

diff --git a/clients/odbc/driver/ODBCAttrs.c b/clients/odbc/driver/ODBCAttrs.c
--- a/clients/odbc/driver/ODBCAttrs.c
+++ b/clients/odbc/driver/ODBCAttrs.c
@@ -50,6 +50,7 @@ const struct attr_setting attr_settings[
{ "CLIENTINFO", "Send Client Info", MP_CLIENT_INFO },
{ "APPNAME", "Application Name", MP_CLIENT_APPLICATION },
{ "CLIENTREMARK", "Client Remark", MP_CLIENT_REMARK },
+   { "MAPTOLONGVARCHAR", NULL, MP_MAPTOLONGVARCHAR },
 };
 
 const int attr_setting_count = sizeof(attr_settings) / 
sizeof(attr_settings[0]);
diff --git a/clients/odbc/driver/SQLBrowseConnect.c 
b/clients/odbc/driver/SQLBrowseConnect.c
--- a/clients/odbc/driver/SQLBrowseConnect.c
+++ b/clients/odbc/driver/SQLBrowseConnect.c
@@ -53,7 +53,12 @@ suggest_settings(ODBCDbc *dbc, char **bu
mparm parm = entry->parm;
if (dbc->setting_touched[(int)parm] == touched_as) {
const char *sep = *pos > 0 ? ";" : "";
-   reallocprintf(buf, pos, cap, "%s%s%s:%s=?", sep, 
prefix, entry->name, entry->alt_name);
+   reallocprintf(
+   buf, pos, cap,
+   "%s%s%s%s%s=?",
+   sep, prefix, entry->name,
+   entry->alt_name ? ":" : "",
+   entry->alt_name ? entry->alt_name : "");
if (entry->is_enum) {
assert(entry->values != NULL);
*pos -= 1;  // eat the '?'
diff --git a/clients/odbc/tests/odbcconnect.c b/clients/odbc/tests/odbcconnect.c
--- a/clients/odbc/tests/odbcconnect.c
+++ b/clients/odbc/tests/odbcconnect.c
@@ -455,7 +455,45 @@ do_execute_stmt(void)
SQL_HANDLE_STMT, stmt, "SQLNumResultCols",
SQLNumResultCols(stmt, &colcount));
 
-   printf("RESULT rows=%ld cols=%d \n", rowcount, colcount);
+   printf("RESULT rows=%ld: ", rowcount);
+   char *sep = "";
+   for (int i = 1; i <= colcount; i++) {
+   printf("%s", sep);
+   sep = "; ";
+   SQLSMALLINT n;
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLColAttributeW 
SQL_DESC_NAME",
+   SQLColAttributeW(stmt, i, SQL_DESC_NAME, 
outwbuf, sizeof(outwbuf) /* in bytes! */, &n, NULL));
+   convert_outw_outa(n);
+   printf("%s", outabuf);
+   SQLLEN typenr;
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLColAttributeW 
SQL_DESC_TYPE",
+   SQLColAttributeW(stmt, i, 
SQL_DESC_CONCISE_TYPE, NULL, 0, NULL, &typenr));
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLColAttributeW 
SQL_DESC_TYPE_NAME",
+   SQLColAttributeW(stmt, i, SQL_DESC_TYPE_NAME, 
outwbuf, sizeof(outwbuf) /* in bytes! */, &n, NULL));
+   convert_outw_outa(n);
+   char *marker = typenr == SQL_LONGVARCHAR || typenr == 
SQL_WLONGVARCHAR ? "*" : "";
+   printf(":%s%s", marker, outabuf);
+   SQLLEN fixed, len, scale;
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLColAttributeW 
SQL_DESC_LENGTH",
+   SQLColAttributeW(stmt, i, 
SQL_DESC_FIXED_PREC_SCALE, NULL, 0, NULL, &fixed));
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLColAttributeW 
SQL_DESC_LENGTH",
+   SQLColAttributeW(stmt, i, SQL_DESC_LENGTH, 
NULL, 0, NULL, &len));
+   ensure_ok(
+   SQL_HANDLE_STMT, stmt, "SQLColAttributeW 
SQL_DESC_SCALE",
+   SQLColAttributeW(stmt, i, SQL_DESC_SCALE, NULL, 
0, NULL, &scale));
+   if (!fixed || scale) {
+   if (scale > 0)
+   printf("(%ld,%ld)", len, scale);
+   else
+   printf("(%ld)", len);
+   }
+   }
+   printf("\n");
 
while (colcount > 0 && SQL_SUCCEEDED(SQLFetch(stmt))) {
printf("- ");
diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/od