MonetDB: Aug2024 - Tweak socket parameters to simulate network a...

2024-10-08 Thread Joeri van Ruth via checkin-list
Changeset: 7a82419603d3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7a82419603d3
Modified Files:
documentation/source/manual_pages/monetdbd.rst.in
tools/merovingian/ChangeLog.Aug2024
tools/merovingian/daemon/client.c
tools/merovingian/daemon/merovingian.c
tools/merovingian/daemon/monetdbd.1.in
Branch: Aug2024
Log Message:

Tweak socket parameters to simulate network activity on client connections


diffs (146 lines):

diff --git a/documentation/source/manual_pages/monetdbd.rst.in 
b/documentation/source/manual_pages/monetdbd.rst.in
--- a/documentation/source/manual_pages/monetdbd.rst.in
+++ b/documentation/source/manual_pages/monetdbd.rst.in
@@ -251,6 +251,17 @@ using the **set** command. The following
use redirects instead of proxies. Changing this property takes effect
immediately at runtime.
 
+**keepalive**
+   Specifies the keepalive interval for incoming connections. If this is
+   set to a positive number, *monetdbd* configures the system to send
+   automatic periodic keepalive probes on all client connections. This
+   can help keep firewalls from killing connections that seem idle but
+   are in fact waiting for a long running query to finish. The default
+   is 60 seconds. When 127 consecutive probes have failed, the
+   connection is closed. With the default setting of 60 seconds this
+   means the connection is closed when the client has been unreachable
+   for more than two hours.
+
 REMOTE DATABASES
 
 
diff --git a/tools/merovingian/ChangeLog.Aug2024 
b/tools/merovingian/ChangeLog.Aug2024
--- a/tools/merovingian/ChangeLog.Aug2024
+++ b/tools/merovingian/ChangeLog.Aug2024
@@ -1,3 +1,8 @@
 # ChangeLog file for sql/src/backends/monet5/merovingian
 # This file is updated with mchangelog
 
+* Mon Oct  7 2024 Joeri van Ruth 
+- Tweak socket parameters to simulate network activity on client connections.
+  This prevents firewalls from killing connections that seem idle but are
+  actually waiting for a long-running query. Can be controlled with a new
+  'keepalive' option to monetdbd.
diff --git a/tools/merovingian/daemon/client.c 
b/tools/merovingian/daemon/client.c
--- a/tools/merovingian/daemon/client.c
+++ b/tools/merovingian/daemon/client.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #ifdef HAVE_POLL_H
 #include 
 #endif
@@ -57,6 +58,8 @@ struct clientdata {
char challenge[32];
 };
 
+static void configureKeepAlive(int sock, int keepalive);
+
 static void *
 handleClient(void *data)
 {
@@ -80,6 +83,7 @@ handleClient(void *data)
int sock;
bool isusock;
struct threads *self;
+   int keepalive;
 
 #ifdef HAVE_PTHREAD_SETNAME_NP
pthread_setname_np(
@@ -94,6 +98,11 @@ handleClient(void *data)
self = ((struct clientdata *) data)->self;
memcpy(chal, ((struct clientdata *) data)->challenge, sizeof(chal));
free(data);
+
+   keepalive = getConfNum(_mero_props, "keepalive");
+   if (keepalive > 0 && !isusock)
+   configureKeepAlive(sock, keepalive);
+
fdin = socket_rstream(sock, "merovingian<-client (read)");
if (fdin == NULL) {
self->dead = true;
@@ -661,3 +670,37 @@ error:
}
return(newErr("accept connection: %s", msg));
 }
+
+static void
+configureKeepAlive(int sock, const int keepalive)
+{
+   // It seems that on MacOS, TCP_KEEPIDLE is called TCP_KEEPALIVE.
+   // (Not to be confused with SO_KEEPALIVE).
+   int flag;
+   #if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE)
+   flag = TCP_KEEPALIVE;
+   #else
+   flag = TCP_KEEPIDLE;
+   #endif
+   if (setsockopt(sock, IPPROTO_TCP, flag, &keepalive, sizeof(keepalive)) 
< 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
TCP_KEEPIDLE on socket: %s\n", strerror(errno));
+   return;
+   }
+
+   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive, 
sizeof(keepalive)) < 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
TCP_KEEPINTVL on socket: %s\n", strerror(errno));
+   return;
+   }
+
+   const int keepcnt = 127; // fixed value, maximum allowed
+   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, 
sizeof(keepcnt)) < 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set TCP_KEEPCNT 
on socket: %s\n", strerror(errno));
+   return;
+   }
+
+   const int enabled = 1;
+   if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enabled, 
sizeof(enabled)) < 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
SO_KEEPALIVE on socket: %s\n", strerror(errno));
+   return;
+   }
+}
diff --git a/tools/merovingian/daemon/merovingian.c 
b/tools/merovingian/daemon/merovingian.c
--- a/

MonetDB: Aug2024 - Revert "Tweak socket parameters to simulate n...

2024-10-07 Thread Joeri van Ruth via checkin-list
Changeset: 6e8087cb5902 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/6e8087cb5902
Modified Files:
documentation/source/manual_pages/monetdbd.rst.in
tools/merovingian/ChangeLog.Aug2024
tools/merovingian/daemon/client.c
tools/merovingian/daemon/merovingian.c
tools/merovingian/daemon/monetdbd.1.in
Branch: Aug2024
Log Message:

Revert "Tweak socket parameters to simulate network activity on client 
connections"


diffs (138 lines):

diff --git a/documentation/source/manual_pages/monetdbd.rst.in 
b/documentation/source/manual_pages/monetdbd.rst.in
--- a/documentation/source/manual_pages/monetdbd.rst.in
+++ b/documentation/source/manual_pages/monetdbd.rst.in
@@ -251,17 +251,6 @@ using the **set** command. The following
use redirects instead of proxies. Changing this property takes effect
immediately at runtime.
 
-**keepalive**
-   Specifies the keepalive interval for incoming connections. If this is
-   set to a positive number, *monetdbd* configures the system to send
-   automatic periodic keepalive probes on all client connections. This
-   can help keep firewalls from killing connections that seem idle but
-   are in fact waiting for a long running query to finish. The default
-   is 60 seconds. When 127 consecutive probes have failed, the
-   connection is closed. With the default setting of 60 seconds this
-   means the connection is closed when the client has been unreachable
-   for more than two hours.
-
 REMOTE DATABASES
 
 
diff --git a/tools/merovingian/ChangeLog.Aug2024 
b/tools/merovingian/ChangeLog.Aug2024
--- a/tools/merovingian/ChangeLog.Aug2024
+++ b/tools/merovingian/ChangeLog.Aug2024
@@ -1,8 +1,3 @@
 # ChangeLog file for sql/src/backends/monet5/merovingian
 # This file is updated with mchangelog
 
-* Mon Oct  7 2024 Joeri van Ruth 
-- Tweak socket parameters to simulate network activity on client connections.
-  This prevents firewalls from killing connections that seem idle but are
-  actually waiting for a long-running query. Can be controlled with a new
-  'keepalive' option to monetdbd.
diff --git a/tools/merovingian/daemon/client.c 
b/tools/merovingian/daemon/client.c
--- a/tools/merovingian/daemon/client.c
+++ b/tools/merovingian/daemon/client.c
@@ -18,7 +18,6 @@
 #include 
 #include 
 #include 
-#include 
 #ifdef HAVE_POLL_H
 #include 
 #endif
@@ -58,8 +57,6 @@ struct clientdata {
char challenge[32];
 };
 
-static void configureKeepAlive(int sock, int keepalive);
-
 static void *
 handleClient(void *data)
 {
@@ -83,7 +80,6 @@ handleClient(void *data)
int sock;
bool isusock;
struct threads *self;
-   int keepalive;
 
 #ifdef HAVE_PTHREAD_SETNAME_NP
pthread_setname_np(
@@ -98,11 +94,6 @@ handleClient(void *data)
self = ((struct clientdata *) data)->self;
memcpy(chal, ((struct clientdata *) data)->challenge, sizeof(chal));
free(data);
-
-   keepalive = getConfNum(_mero_props, "keepalive");
-   if (keepalive > 0)
-   configureKeepAlive(sock, keepalive);
-
fdin = socket_rstream(sock, "merovingian<-client (read)");
if (fdin == NULL) {
self->dead = true;
@@ -670,29 +661,3 @@ error:
}
return(newErr("accept connection: %s", msg));
 }
-
-static void
-configureKeepAlive(int sock, const int keepalive)
-{
-   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, 
sizeof(keepalive)) < 0) {
-   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
TCP_KEEPIDLE on socket: %s", strerror(errno));
-   return;
-   }
-
-   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive, 
sizeof(keepalive)) < 0) {
-   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
TCP_KEEPINTVL on socket: %s", strerror(errno));
-   return;
-   }
-
-   const int keepcnt = 127; // fixed value, maximum allowed
-   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, 
sizeof(keepcnt)) < 0) {
-   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set TCP_KEEPCNT 
on socket: %s", strerror(errno));
-   return;
-   }
-
-   const int enabled = 1;
-   if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enabled, 
sizeof(enabled)) < 0) {
-   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
SO_KEEPALIVE on socket: %s", strerror(errno));
-   return;
-   }
-}
diff --git a/tools/merovingian/daemon/merovingian.c 
b/tools/merovingian/daemon/merovingian.c
--- a/tools/merovingian/daemon/merovingian.c
+++ b/tools/merovingian/daemon/merovingian.c
@@ -461,7 +461,6 @@ main(int argc, char *argv[])
 #else
{"snapshotcompression", strdup(".tar"), 0, 
STR},
 #endif
-   {"keepalive", str

MonetDB: Aug2024 - Tweak socket parameters to simulate network a...

2024-10-07 Thread Joeri van Ruth via checkin-list
Changeset: 7398ed995a3e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7398ed995a3e
Modified Files:
documentation/source/manual_pages/monetdbd.rst.in
tools/merovingian/ChangeLog.Aug2024
tools/merovingian/daemon/client.c
tools/merovingian/daemon/merovingian.c
tools/merovingian/daemon/monetdbd.1.in
Branch: Aug2024
Log Message:

Tweak socket parameters to simulate network activity on client connections


diffs (138 lines):

diff --git a/documentation/source/manual_pages/monetdbd.rst.in 
b/documentation/source/manual_pages/monetdbd.rst.in
--- a/documentation/source/manual_pages/monetdbd.rst.in
+++ b/documentation/source/manual_pages/monetdbd.rst.in
@@ -251,6 +251,17 @@ using the **set** command. The following
use redirects instead of proxies. Changing this property takes effect
immediately at runtime.
 
+**keepalive**
+   Specifies the keepalive interval for incoming connections. If this is
+   set to a positive number, *monetdbd* configures the system to send
+   automatic periodic keepalive probes on all client connections. This
+   can help keep firewalls from killing connections that seem idle but
+   are in fact waiting for a long running query to finish. The default
+   is 60 seconds. When 127 consecutive probes have failed, the
+   connection is closed. With the default setting of 60 seconds this
+   means the connection is closed when the client has been unreachable
+   for more than two hours.
+
 REMOTE DATABASES
 
 
diff --git a/tools/merovingian/ChangeLog.Aug2024 
b/tools/merovingian/ChangeLog.Aug2024
--- a/tools/merovingian/ChangeLog.Aug2024
+++ b/tools/merovingian/ChangeLog.Aug2024
@@ -1,3 +1,8 @@
 # ChangeLog file for sql/src/backends/monet5/merovingian
 # This file is updated with mchangelog
 
+* Mon Oct  7 2024 Joeri van Ruth 
+- Tweak socket parameters to simulate network activity on client connections.
+  This prevents firewalls from killing connections that seem idle but are
+  actually waiting for a long-running query. Can be controlled with a new
+  'keepalive' option to monetdbd.
diff --git a/tools/merovingian/daemon/client.c 
b/tools/merovingian/daemon/client.c
--- a/tools/merovingian/daemon/client.c
+++ b/tools/merovingian/daemon/client.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #ifdef HAVE_POLL_H
 #include 
 #endif
@@ -57,6 +58,8 @@ struct clientdata {
char challenge[32];
 };
 
+static void configureKeepAlive(int sock, int keepalive);
+
 static void *
 handleClient(void *data)
 {
@@ -80,6 +83,7 @@ handleClient(void *data)
int sock;
bool isusock;
struct threads *self;
+   int keepalive;
 
 #ifdef HAVE_PTHREAD_SETNAME_NP
pthread_setname_np(
@@ -94,6 +98,11 @@ handleClient(void *data)
self = ((struct clientdata *) data)->self;
memcpy(chal, ((struct clientdata *) data)->challenge, sizeof(chal));
free(data);
+
+   keepalive = getConfNum(_mero_props, "keepalive");
+   if (keepalive > 0)
+   configureKeepAlive(sock, keepalive);
+
fdin = socket_rstream(sock, "merovingian<-client (read)");
if (fdin == NULL) {
self->dead = true;
@@ -661,3 +670,29 @@ error:
}
return(newErr("accept connection: %s", msg));
 }
+
+static void
+configureKeepAlive(int sock, const int keepalive)
+{
+   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalive, 
sizeof(keepalive)) < 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
TCP_KEEPIDLE on socket: %s", strerror(errno));
+   return;
+   }
+
+   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepalive, 
sizeof(keepalive)) < 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
TCP_KEEPINTVL on socket: %s", strerror(errno));
+   return;
+   }
+
+   const int keepcnt = 127; // fixed value, maximum allowed
+   if (setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, 
sizeof(keepcnt)) < 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set TCP_KEEPCNT 
on socket: %s", strerror(errno));
+   return;
+   }
+
+   const int enabled = 1;
+   if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enabled, 
sizeof(enabled)) < 0) {
+   Mlevelfprintf(WARNING, _mero_ctlerr, "could not set 
SO_KEEPALIVE on socket: %s", strerror(errno));
+   return;
+   }
+}
diff --git a/tools/merovingian/daemon/merovingian.c 
b/tools/merovingian/daemon/merovingian.c
--- a/tools/merovingian/daemon/merovingian.c
+++ b/tools/merovingian/daemon/merovingian.c
@@ -461,6 +461,7 @@ main(int argc, char *argv[])
 #else
{"snapshotcompression", strdup(".tar"), 0, 
STR},
 #endif
+   {"keepalive", strdup("60&quo

MonetDB: default - Add system function sys.unclosed_result_sets()

2024-09-27 Thread Joeri van Ruth via checkin-list
Changeset: 3812616d921c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/3812616d921c
Modified Files:
sql/backends/monet5/sql.c
sql/backends/monet5/sql_upgrades.c
sql/scripts/22_clients.sql
Branch: default
Log Message:

Add system function sys.unclosed_result_sets()

Returns a tuple (query_id, res_id) for every unclosed result set.
This is useful for checking for resource leaks in client libraries.


diffs (94 lines):

diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -3542,6 +3542,47 @@ dump_trace(Client cntxt, MalBlkPtr mb, M
 }
 
 static str
+sql_unclosed_result_sets(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci)
+{
+   (void)mb;
+   bat *ret_query_id = getArgReference_bat(stk, pci, 0);
+   bat *ret_res_id = getArgReference_bat(stk, pci, 1);
+   backend *be = cntxt->sqlcontext;
+
+   BUN count = 0;
+   for (res_table *p = be->results; p != NULL; p = p->next)
+   count++;
+
+   BAT *query_ids = COLnew(0, TYPE_oid, count, TRANSIENT);
+   BAT *res_ids = COLnew(0, TYPE_int, count, TRANSIENT);
+
+   if (query_ids == NULL || res_ids == NULL) {
+   BBPreclaim(query_ids);
+   BBPreclaim(res_ids);
+   throw(SQL, "sql.sql_unclosed_result_sets", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+   }
+
+   for (res_table *p = be->results; p != NULL; p = p->next) {
+   if (BUNappend(query_ids, &p->query_id, false) != GDK_SUCCEED)
+   goto bailout;
+   if (BUNappend(res_ids, &p->id, false) != GDK_SUCCEED)
+   goto bailout;
+   }
+
+   *ret_query_id = query_ids->batCacheid;
+   BBPkeepref(query_ids);
+   *ret_res_id = res_ids->batCacheid;
+   BBPkeepref(res_ids);
+
+   return MAL_SUCCEED;
+
+bailout:
+   BBPunfix(query_ids->batCacheid);
+   BBPunfix(res_ids->batCacheid);
+   throw(SQL, "sql.sql_unclosed_result_sets", SQLSTATE(42000)"failed to 
retrieve result tables");
+}
+
+static str
 sql_sessions_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
BAT *id = NULL, *user = NULL, *login = NULL, *sessiontimeout = NULL,
@@ -5629,6 +5670,7 @@ static mel_func sql_init_funcs[] = {
  pattern("sql", "argRecord", SQLargRecord, false, "Glue together the calling 
sequence", args(1,2, arg("",str),varargany("a",0))),
  pattern("sql", "sql_variables", sql_variables, false, "return the table with 
session variables", args(4,4, 
batarg("sname",str),batarg("name",str),batarg("type",str),batarg("value",str))),
  pattern("sql", "sessions", sql_sessions_wrap, false, "SQL export table of 
active sessions, their timeouts and idle 
status",args(16,16,batarg("id",int),batarg("user",str),batarg("start",timestamp),batarg("idle",timestamp),batarg("optimizer",str),batarg("stimeout",int),batarg("qtimeout",int),batarg("wlimit",int),batarg("mlimit",int),batarg("language",
 str),batarg("peer", str),batarg("hostname", str),batarg("application", 
str),batarg("client", str),batarg("clientpid", lng),batarg("remark", str),)),
+ pattern("sql", "unclosed_result_sets", sql_unclosed_result_sets, false, 
"return query_id/res_id of unclosed result sets", args(2,2, 
batarg("query_id",oid),batarg("res_id", int))),
  pattern("sql", "password", SQLuser_password, false, "Return password hash of 
user", args(1,2, arg("",str),arg("user",str))),
  pattern("sql", "decypher", SQLdecypher, false, "Return decyphered password", 
args(1,2, arg("",str),arg("hash",str))),
  pattern("sql", "dump_cache", dump_cache, false, "dump the content of the 
query cache", args(2,2, batarg("query",str),batarg("count",int))),
diff --git a/sql/backends/monet5/sql_upgrades.c 
b/sql/backends/monet5/sql_upgrades.c
--- a/sql/backends/monet5/sql_upgrades.c
+++ b/sql/backends/monet5/sql_upgrades.c
@@ -4384,6 +4384,13 @@ sql_update_default(Client c, mvc *sql, s
"external name sql.vacuum;\n"
"create procedure sys.stop_vacuum(sname string, tname 
string)\n"
"external name sql.stop_vacuum;\n"
+   "create function sys.unclosed_result_sets()\n"
+   "returns table(\n"
+   "   \"query_id\" oid,\n"
+   "   \"res_id\" int\n"
+   ")\n"
+   "external name sql.unclosed_result_sets;\n"
+   "grant execute on function sys.unclosed_result_sets() 
to public;\n"
"update sys.functions set system = true where system <> 
true and schema_id = 2000 and name in ('vacuum', 'stop_vacuum');\n";
printf("Running database upgrade commands:\n%s\n", 
query);
fflush(stdout);
diff --git a/sql/scripts/22_clients.sql b/sql/scripts/22_clients.sql
--- a/sql/scripts/22_clients.sql
+++ b/sql/scripts/22_clients.sql
@@ -41,6 +41,14 

MonetDB: default - tlstester: listen on both AF_INET and AF_INET6

2024-09-18 Thread Joeri van Ruth via checkin-list
Changeset: ed17ccf72c48 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ed17ccf72c48
Modified Files:
testing/tlstester.py
Branch: default
Log Message:

tlstester: listen on both AF_INET and AF_INET6

This should speed up the tlssecurity test on Windows.


diffs (91 lines):

diff --git a/testing/tlstester.py b/testing/tlstester.py
--- a/testing/tlstester.py
+++ b/testing/tlstester.py
@@ -416,6 +416,32 @@ class TLSTester:
 for t in threads:
 t.join()
 
+def spawn_server(self, name, server_class, addr, port, handler):
+fam = server_class.address_family.name
+try:
+server = server_class((addr, port), handler)
+except Exception as e:
+log.debug(f"Could not bind {name} to {fam} = {addr} port {port}: 
{e}")
+raise
+bound_addr, bound_port = server.server_address[:2]
+log.debug(f"Bound {name}: {fam} = {bound_addr} port {bound_port}")
+self.portmap[name] = bound_port
+self.workers.append(server.serve_forever)
+return bound_port
+
+def spawn_servers(self, name, server_classes, addr, port, handler):
+exceptions = []
+for server_class in server_classes:
+try:
+# update 'port' so all servers use the same port number
+port = self.spawn_server(name, server_class, addr, port, 
handler)
+except OSError as e:
+exceptions.append(e)
+if len(exceptions) == len(server_classes):
+e = exceptions[0]
+log.error(f"Could not spawn any listener for {name} on {addr}: 
{e}")
+raise e
+
 def spawn_http(self, name: str, only_preassigned: bool):
 if only_preassigned and name not in self.preassigned:
 return
@@ -425,11 +451,7 @@ class TLSTester:
 handler = lambda req, addr, server: WebHandler(
 req, addr, server, self.certs, self.portmap
 )
-server = http.server.HTTPServer((self.listen_addr, port), handler)
-port = server.server_address[1]
-log.debug(f"Bound port {name} to {port}")
-self.portmap[name] = port
-self.workers.append(server.serve_forever)
+self.spawn_servers(name, [MyHTTPServer, MyHTTP6Server], 
self.listen_addr, port, handler)
 
 def spawn_mapi(self, name: str, only_preassigned, ctx: SSLContext, 
check_alpn=None, redirect_to=None):
 if only_preassigned and name not in self.preassigned:
@@ -438,11 +460,7 @@ class TLSTester:
 return
 port = self.allocate_port(name)
 handler = lambda req, addr, server: MapiHandler(req, addr, server, 
self, name, ctx, check_alpn, redirect_to)
-server = MyTCPServer((self.listen_addr, port), handler)
-port = server.server_address[1]
-log.debug(f"Bound port {name} to {port}")
-self.portmap[name] = port
-self.workers.append(server.serve_forever)
+self.spawn_servers(name, [MyTCPServer, MyTCP6Server], 
self.listen_addr, port, handler)
 
 def spawn_forward(self, name, ctx: SSLContext):
 if name in self.portmap:
@@ -451,11 +469,8 @@ class TLSTester:
 handler = lambda req, addr, server: ForwardHandler(
 req, addr, server, name, ctx, self.forward_to
 )
-server = MyTCPServer((self.listen_addr, local_port), handler)
-port = server.server_address[1]
-log.debug(f"Bound port {name} to {port}")
-self.portmap[name] = port
-self.workers.append(server.serve_forever)
+self.spawn_servers(name, [MyTCPServer, MyTCP6Server], 
self.listen_addr, local_port, handler)
+
 
 def allocate_port(self, name):
 if name in self.preassigned:
@@ -551,6 +566,14 @@ class MyTCPServer(socketserver.Threading
 allow_reuse_address = True
 pass
 
+class MyTCP6Server(MyTCPServer):
+address_family = socket.AF_INET6
+
+class MyHTTPServer(http.server.HTTPServer):
+pass
+
+class MyHTTP6Server(MyHTTPServer):
+address_family = socket.AF_INET6
 
 class MapiHandler(socketserver.BaseRequestHandler):
 tlstester: TLSTester
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - Support hot snapshotting huge bats and log files

2024-09-16 Thread Joeri van Ruth via checkin-list
Changeset: 25d775cb23fc for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/25d775cb23fc
Added Files:
sql/test/Tests/hot_snapshot_huge_file.py
sql/test/Tests/hot_snapshot_huge_file.timeout
Modified Files:
ChangeLog
sql/storage/store.c
sql/test/Tests/All
tools/merovingian/daemon/snapshot.c
Branch: default
Log Message:

Support hot snapshotting huge bats and log files

The regular tar format does not allow member files >8GiB because the
size field in the per-member header is 11 octal digits plus a NUL byte.
However, because we and most tar implementations don't need the NUL
byte, it actually worked up to 64GiB.

This patch adds support for binary size headers as originally introduced
by GNU tar. The new limit is 8 exabyte which is sufficient for the
foreseeable future.


diffs (truncated from 347 to 300 lines):

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
 # ChangeLog file for devel
 # This file is updated with Maddlog
 
+* Mon Sep 16 2024 Joeri van Ruth 
+- Hot snapshot: allow member files larger than 64 GiB. By member files we mean
+  the files inside the resulting .tar file, not the tar file itself. Huge 
member
+  files are written using a GNU tar extension to the original tar format, which
+  doesn't support more than 8 GiB.
+
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -2561,13 +2561,8 @@ tar_write_header(stream *tarfile, const 
 {
char buf[TAR_BLOCK_SIZE] = {0};
char *cursor = buf;
-   char *chksum;
-
-   if (size > 0777) { // 0_777__
-   // doesn't fit header field
-   GDKerror("error writing tar file: member %s too large", path);
-   return GDK_FAIL;
-   }
+   char *size_field;
+   char *chksum_field;
 
// We set the uid/gid fields to 0 and the uname/gname fields to "".
// When unpacking as a normal user, they are ignored and the files are
@@ -2580,9 +2575,10 @@ tar_write_header(stream *tarfile, const 
tar_write_header_field(&cursor, 8, "644");  // mode[8]
tar_write_header_field(&cursor, 8, "%07o", 0U);  // uid[8]
tar_write_header_field(&cursor, 8, "%07o", 0U);  // gid[8]
-   tar_write_header_field(&cursor, 12, "%011"PRIo64, size);  // 
size[12]
+   size_field = cursor;
+   cursor += 12;  // size[12]
tar_write_header_field(&cursor, 12, "%011lo", (unsigned long)mtime); // 
mtime[12]
-   chksum = cursor; // use this later to set the computed checksum
+   chksum_field = cursor; // use this later to set the computed checksum
tar_write_header_field(&cursor, 8, "%8s", ""); // chksum[8]
*cursor++ = '0'; // typeflag REGTYPE
tar_write_header_field(&cursor, 100, "%s", "");  // linkname[100]
@@ -2593,14 +2589,27 @@ tar_write_header(stream *tarfile, const 
tar_write_header_field(&cursor, 8, "%07o", 0U); // devmajor[8]
tar_write_header_field(&cursor, 8, "%07o", 0U); // devminor[8]
tar_write_header_field(&cursor, 155, "%s", ""); // prefix[155]
-
assert(cursor - buf == 500);
 
+   int64_t max_oct_size = 0777;// 0_777__, 11 octal 
digits
+   // max_oct_size = 077; // for testing
+   if (size <= max_oct_size) {
+   tar_write_header_field(&size_field, 12, "%011"PRIo64, size);
  // size[12]
+   } else {
+   uint8_t *field = (uint8_t *)size_field;
+   field[0] = 0x80;
+   for (int i = 11; i >= 4; i--) {
+   field[i] = size & 0xFF;
+   size >>= 8;
+   }
+   }
+
+   // checksum
unsigned sum = 0;
for (int i = 0; i < TAR_BLOCK_SIZE; i++)
sum += (unsigned char) buf[i];
 
-   tar_write_header_field(&chksum, 8, "%06o", sum);
+   tar_write_header_field(&chksum_field, 8, "%06o", sum);
 
if (mnstr_write(tarfile, buf, TAR_BLOCK_SIZE, 1) != 1) {
GDKerror("error writing tar header %s: %s", path, 
mnstr_peek_error(tarfile));
@@ -2688,7 +2697,7 @@ tar_copy_stream(stream *tarfile, const c
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
-hot_snapshot_write_tar(stream *out, const char *prefix, char *plan)
+hot_snapshot_write_tar(stream *out, const char *prefix, const char *plan)
 {
if (plan == NULL)
return GDK_FAIL;
@@ -2729,6 +2738,11 @@ hot_snapshot_write_tar(stream *out, cons
src_name = abs_src_path + len - 1; // - 1 because len includes the 
trailing newline
*sr

MonetDB: default - Test tlssecurity: leave logging permanently e...

2024-09-16 Thread Joeri van Ruth via checkin-list
Changeset: bb5de91bf7dc for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/bb5de91bf7dc
Modified Files:
clients/mapilib/Tests/tlssecurity.py
Branch: default
Log Message:

Test tlssecurity: leave logging permanently enabled

Prefix levels DEBUG and INFO with a # so Mtest does not consider them a failure.


diffs (46 lines):

diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -20,11 +20,10 @@ from MonetDBtesting.tlstester import TLS
 log_level = logging.WARNING
 log_format = '%(levelname)s:t=%(relativeCreated)d:%(name)s:%(message)s'# if 
sys.platform == 'win32':
 
-if sys.platform == 'win32':
-log_level=logging.DEBUG
-if '-v' in sys.argv:
-log_level = logging.DEBUG
-# log_level = logging.DEBUG
+# Be verbose but make Mtest ignore it
+log_level = logging.DEBUG
+logging.addLevelName(logging.DEBUG, '#DEBUG')
+logging.addLevelName(logging.INFO, '#INFO')
 
 logging.basicConfig(level=log_level,format=log_format)
 
@@ -47,13 +46,13 @@ def attempt(experiment: str, portname: s
 if params:
 # should be percent-escaped
 url += '?' + '&'.join(f"{k}={v}" for k, v in params.items())
-logging.debug(f" START TEST {experiment}")
-logging.debug(f"Connecting to {url}, 
expected_error={expected_error_regex}")
+logging.info(f" START TEST {experiment}")
+logging.info(f"Connecting to {url}, expected_error={expected_error_regex}")
 test_log_file = os.path.join(scratchdir, portname + '.log')
 cmd = ['mclient', '-d', url, '-L', test_log_file]
-logging.debug(f"cmd={cmd}")
+logging.info(f"cmd={cmd}")
 proc = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
-logging.debug(f"mclient exited with code {proc.returncode}, 
err={proc.stderr}")
+logging.info(f"mclient exited with code {proc.returncode}, 
err={proc.stderr}")
 with open(test_log_file, 'r') as f:
 for line in f:
 logging.debug(f'mclient log: {line.rstrip()}')
@@ -70,7 +69,7 @@ def attempt(experiment: str, portname: s
 elif  expected_error_regex is not None and actual_error is not None and 
re.search(expected_error_regex, actual_error):
 ok = True
 if ok:
-logging.debug(f" END SUCCESSFUL TEST {experiment} ")
+logging.info(f" END SUCCESSFUL TEST {experiment} ")
 return
 logging.error(f"Unexpected result for test {experiment}")
 logging.error(f"When connecting to port '{portname}' using URL {url}")
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - Do not use non-ascii characters in mapi log file

2024-09-09 Thread Joeri van Ruth via checkin-list
Changeset: ab6f5e3f15f3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ab6f5e3f15f3
Modified Files:
clients/mapilib/mapi.c
Branch: default
Log Message:

Do not use non-ascii characters in mapi log file

\u25B6 right pointing triangle looked pretty but caused problems on Windows


diffs (12 lines):

diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -1217,7 +1217,7 @@ mapi_log_header(Mapi mid, const char *fu
if (firstcall == 0)
firstcall = now;
double seconds = (double)(now - firstcall) / 1e6;
-   mnstr_printf(mid->tracelog, "\342\226\266 [%u] t=%.3fs %s%s %s(), line 
%ld\n", mid->index, seconds, mark1, mark2, funcname, line); /* U+25B6: 
right-pointing triangle */
+   mnstr_printf(mid->tracelog, "\n** [%u] t=%.3fs %s%s %s(), line %ld\n", 
mid->index, seconds, mark1, mark2, funcname, line);
 }
 
 void
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - Remove spurious else-clause

2024-09-06 Thread Joeri van Ruth via checkin-list
Changeset: ace959bab520 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ace959bab520
Modified Files:
clients/mapilib/msettings.c
Branch: default
Log Message:

Remove spurious else-clause

Not sure what was intended to be there.


diffs (11 lines):

diff --git a/clients/mapilib/msettings.c b/clients/mapilib/msettings.c
--- a/clients/mapilib/msettings.c
+++ b/clients/mapilib/msettings.c
@@ -477,7 +477,6 @@ msetting_set_string(msettings *mp, mparm
mp->lang_is_mal = true;
else if (strstr(value, "sql") == value)
mp->lang_is_sql = true;
-   else if (strcmp(value, "`"))
break;
default:
break;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - In test tlssecurity: temporarily enable mclie...

2024-08-30 Thread Joeri van Ruth via checkin-list
Changeset: 36618f6168bd for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/36618f6168bd
Modified Files:
clients/mapilib/Tests/tlssecurity.py
testing/Mtest.py.in
Branch: default
Log Message:

In test tlssecurity: temporarily enable mclient verbosity

Still debugging Windows slowness


diffs (56 lines):

diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -24,7 +24,7 @@ if sys.platform == 'win32':
 log_level=logging.DEBUG
 if '-v' in sys.argv:
 log_level = logging.DEBUG
-#level = logging.DEBUG
+# log_level = logging.DEBUG
 
 logging.basicConfig(level=log_level,format=log_format)
 
@@ -34,13 +34,13 @@ assert os.path.isdir(tgtdir)
 scratchdir = os.path.join(tgtdir, "scratch")
 logging.debug(f"scratchdir={scratchdir}")
 
-tlstester = TLSTesterClient(scratchdir, host='127.0.0.1')
+tlstester = TLSTesterClient(scratchdir)
 
 
 def certpath(name):
 return tlstester.download(name)
 
-def attempt(experiment: str, portname: str, expected_error_regex: str, 
tls=True, host='127.0.0.1', **params):
+def attempt(experiment: str, portname: str, expected_error_regex: str, 
tls=True, host='localhost', **params):
 port = tlstester.get_port(portname)
 scheme = 'monetdbs' if tls else 'monetdb'
 url = f"{scheme}://{host}:{port}/demo"
@@ -49,10 +49,14 @@ def attempt(experiment: str, portname: s
 url += '?' + '&'.join(f"{k}={v}" for k, v in params.items())
 logging.debug(f" START TEST {experiment}")
 logging.debug(f"Connecting to {url}, 
expected_error={expected_error_regex}")
-cmd = ['mclient', '-d', url]
+test_log_file = os.path.join(scratchdir, portname + '.log')
+cmd = ['mclient', '-d', url, '-L', test_log_file]
 logging.debug(f"cmd={cmd}")
 proc = subprocess.run(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
 logging.debug(f"mclient exited with code {proc.returncode}, 
err={proc.stderr}")
+with open(test_log_file, 'r') as f:
+for line in f:
+logging.debug(f'mclient log: {line.rstrip()}')
 if proc.returncode != 2:
 msg = str(proc.stderr, 'utf-8')
 print(f"mclient is supposed to exit with status 2, not 
{proc.returncode}.\n--- stderr ---\n{msg}\n---end stderr ---", file=sys.stderr)
diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -3299,7 +3299,7 @@ def StartTlsTester():
 # Start a dummy server that only returns errors.
 return DummyTlsTester()
 from MonetDBtesting import tlstester
-hostnames = ['localhost', '127.0.0.1']  # make certificates also valid for 
127.0.0.1
+hostnames = ['localhost']
 certs = tlstester.Certs(hostnames)
 server = tlstester.TLSTester(
 certs = certs,
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - In test tlssecurity: access tlstester on 127....

2024-08-30 Thread Joeri van Ruth via checkin-list
Changeset: f3c6d48acaca for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f3c6d48acaca
Modified Files:
clients/mapilib/Tests/tlssecurity.py
testing/Mtest.py.in
Branch: default
Log Message:

In test tlssecurity: access tlstester on 127.0.0.1 instead of localhost

Still debugging Windows slowness. If the delay is in host resolution,
it should disappear now. If it's because the Python TCPServer code
is trying to do a reverse lookup, the delay will remain.
If it's something else, all bets are still off.


diffs (31 lines):

diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -34,13 +34,13 @@ assert os.path.isdir(tgtdir)
 scratchdir = os.path.join(tgtdir, "scratch")
 logging.debug(f"scratchdir={scratchdir}")
 
-tlstester = TLSTesterClient(scratchdir)
+tlstester = TLSTesterClient(scratchdir, host='127.0.0.1')
 
 
 def certpath(name):
 return tlstester.download(name)
 
-def attempt(experiment: str, portname: str, expected_error_regex: str, 
tls=True, host='localhost', **params):
+def attempt(experiment: str, portname: str, expected_error_regex: str, 
tls=True, host='127.0.0.1', **params):
 port = tlstester.get_port(portname)
 scheme = 'monetdbs' if tls else 'monetdb'
 url = f"{scheme}://{host}:{port}/demo"
diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -3299,7 +3299,7 @@ def StartTlsTester():
 # Start a dummy server that only returns errors.
 return DummyTlsTester()
 from MonetDBtesting import tlstester
-hostnames = ['localhost']
+hostnames = ['localhost', '127.0.0.1']  # make certificates also valid for 
127.0.0.1
 certs = tlstester.Certs(hostnames)
 server = tlstester.TLSTester(
 certs = certs,
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - Try to figure out why test 'tlssecurity' take...

2024-08-23 Thread Joeri van Ruth via checkin-list
Changeset: 0458139ac3f7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0458139ac3f7
Modified Files:
clients/mapilib/Tests/tlssecurity.py
Branch: default
Log Message:

Try to figure out why test 'tlssecurity' takes so long on Windows

Enable DEBUG on Windows only, with timestamps.  The stderr output will
make the test fail but that's not a big deal on the default branch.


diffs (25 lines):

diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -17,13 +17,16 @@ import sys
 
 from MonetDBtesting.tlstester import TLSTesterClient
 
-level = logging.WARNING
-# if sys.platform == 'win32':
-# level=logging.DEBUG
+log_level = logging.WARNING
+log_format = '%(levelname)s:t=%(relativeCreated)d:%(name)s:%(message)s'# if 
sys.platform == 'win32':
+
+if sys.platform == 'win32':
+level=logging.DEBUG
 if '-v' in sys.argv:
-level = logging.DEBUG
+log_level = logging.DEBUG
 #level = logging.DEBUG
-logging.basicConfig(level=level)
+
+logging.basicConfig(level=log_level,format=log_format)
 
 # A tmpdir to write certificates to
 tgtdir = os.environ['TSTTRGDIR']
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - In snapshot code, use int64_t to represent fi...

2024-08-23 Thread Joeri van Ruth via checkin-list
Changeset: cde28737021c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/cde28737021c
Modified Files:
sql/storage/store.c
Branch: default
Log Message:

In snapshot code, use int64_t to represent file sizes


diffs (164 lines):

diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -2557,12 +2557,18 @@ tar_write_header_field(char **cursor_ptr
 
 // Write a tar header to the given stream.
 static gdk_return __attribute__((__warn_unused_result__))
-tar_write_header(stream *tarfile, const char *path, time_t mtime, size_t size)
+tar_write_header(stream *tarfile, const char *path, time_t mtime, int64_t size)
 {
char buf[TAR_BLOCK_SIZE] = {0};
char *cursor = buf;
char *chksum;
 
+   if (size > 0777) { // 0_777__
+   // doesn't fit header field
+   GDKerror("error writing tar file: member %s too large", path);
+   return GDK_FAIL;
+   }
+
// We set the uid/gid fields to 0 and the uname/gname fields to "".
// When unpacking as a normal user, they are ignored and the files are
// owned by that user. When unpacking as root it is reasonable that
@@ -2574,7 +2580,7 @@ tar_write_header(stream *tarfile, const 
tar_write_header_field(&cursor, 8, "644");  // mode[8]
tar_write_header_field(&cursor, 8, "%07o", 0U);  // uid[8]
tar_write_header_field(&cursor, 8, "%07o", 0U);  // gid[8]
-   tar_write_header_field(&cursor, 12, "%011zo", size);  // size[12]
+   tar_write_header_field(&cursor, 12, "%011"PRIo64, size);  // 
size[12]
tar_write_header_field(&cursor, 12, "%011lo", (unsigned long)mtime); // 
mtime[12]
chksum = cursor; // use this later to set the computed checksum
tar_write_header_field(&cursor, 8, "%8s", ""); // chksum[8]
@@ -2609,7 +2615,7 @@ tar_write_header(stream *tarfile, const 
  * of TAR_BLOCK_SIZE.
  */
 static gdk_return __attribute__((__warn_unused_result__))
-tar_write(stream *outfile, const char *data, size_t size)
+tar_write(stream *outfile, const char *path,  const char *data, size_t size)
 {
const size_t tail = size % TAR_BLOCK_SIZE;
const size_t bulk = size - tail;
@@ -2617,7 +2623,7 @@ tar_write(stream *outfile, const char *d
if (bulk) {
size_t written = mnstr_write(outfile, data, 1, bulk);
if (written != bulk) {
-   GDKerror("Wrote only %zu bytes instead of first %zu", 
written, bulk);
+   GDKerror("Wrote only %zu bytes of %s instead of first 
%zu", written, path, bulk);
return GDK_FAIL;
}
}
@@ -2627,7 +2633,7 @@ tar_write(stream *outfile, const char *d
memcpy(buf, data + bulk, tail);
size_t written = mnstr_write(outfile, buf, 1, TAR_BLOCK_SIZE);
if (written != TAR_BLOCK_SIZE) {
-   GDKerror("Wrote only %zu tail bytes instead of %d", 
written, TAR_BLOCK_SIZE);
+   GDKerror("Wrote only %zu tail bytes of %s instead of 
%d", written, path, TAR_BLOCK_SIZE);
return GDK_FAIL;
}
}
@@ -2644,40 +2650,38 @@ tar_write_data(stream *tarfile, const ch
if (res != GDK_SUCCEED)
return res;
 
-   return tar_write(tarfile, data, size);
+   return tar_write(tarfile, path, data, size);
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
-tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, size_t size, char *buf, size_t bufsize)
-{
-   size_t file_size;
-   size_t to_read;
-
-   file_size = getFileSize(contents);
-   if (file_size < size) {
-   GDKerror("Have to copy %zd bytes but only %zd exist in %s", 
size, file_size, path);
-   return GDK_FAIL;
-   }
-
+tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, int64_t size, char *buf, size_t bufsize)
+{
assert( (bufsize % TAR_BLOCK_SIZE) == 0);
assert(bufsize >= TAR_BLOCK_SIZE);
 
-
if (tar_write_header(tarfile, path, mtime, size) != GDK_SUCCEED)
return GDK_FAIL;
 
-   to_read = size;
-
-   while (to_read > 0) {
-   size_t chunk = (to_read <= bufsize) ? to_read : bufsize;
+   int64_t to_do = size;
+   while (to_do > 0) {
+   size_t chunk = (to_do <= (int64_t)bufsize) ? (size_t)to_do : 
bufsize;
ssize_t nbytes = mnstr_read(contents, buf, 1, chunk);
-   if (nbytes != (ssize_t)chunk) {
-   GDKerror("Read only %zd/%zd bytes of component %s: %s", 
nbytes, chunk, path, mnstr_peek_error(contents));
+   if (nbytes > 0) {
+   if (tar_write(tarfile, path, buf, nbytes) != 
GDK_SUCCEED)
+   return GDK_FAIL;
+   

MonetDB: default - Merge branch 'branches/Aug2024' into branches...

2024-08-23 Thread Joeri van Ruth via checkin-list
Changeset: f4087ca49840 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f4087ca49840
Branch: default
Log Message:

Merge branch 'branches/Aug2024' into branches/default


diffs (11 lines):

diff --git a/sql/ChangeLog.Aug2024 b/sql/ChangeLog.Aug2024
--- a/sql/ChangeLog.Aug2024
+++ b/sql/ChangeLog.Aug2024
@@ -1,3 +1,7 @@
 # ChangeLog file for sql
 # This file is updated with Maddlog
 
+* Fri Aug 23 2024 Joeri van Ruth 
+- Increase the buffer size used by hot snapshot from 64kiB to 1MiB,
+  and make it configurable through setting 'hot_snapshot_buffer_size'.
+  It must be a multiple of 512.
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Merge with Dec2023

2024-08-23 Thread Joeri van Ruth via checkin-list
Changeset: 9175965842f6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9175965842f6
Modified Files:
sql/ChangeLog.Aug2024
sql/storage/store.c
Branch: Aug2024
Log Message:

Merge with Dec2023


diffs (118 lines):

diff --git a/sql/ChangeLog.Aug2024 b/sql/ChangeLog.Aug2024
--- a/sql/ChangeLog.Aug2024
+++ b/sql/ChangeLog.Aug2024
@@ -1,3 +1,7 @@
 # ChangeLog file for sql
 # This file is updated with Maddlog
 
+* Fri Aug 23 2024 Joeri van Ruth 
+- Increase the buffer size used by hot snapshot from 64kiB to 1MiB,
+  and make it configurable through setting 'hot_snapshot_buffer_size'.
+  It must be a multiple of 512.
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -2648,52 +2648,39 @@ tar_write_data(stream *tarfile, const ch
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
-tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, ssize_t size)
-{
-   const ssize_t bufsize = 64 * 1024;
-   gdk_return ret = GDK_FAIL;
-   ssize_t file_size;
-   char *buf = NULL;
-   ssize_t to_read;
+tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, size_t size, char *buf, size_t bufsize)
+{
+   size_t file_size;
+   size_t to_read;
 
file_size = getFileSize(contents);
if (file_size < size) {
GDKerror("Have to copy %zd bytes but only %zd exist in %s", 
size, file_size, path);
-   goto end;
+   return GDK_FAIL;
}
 
assert( (bufsize % TAR_BLOCK_SIZE) == 0);
assert(bufsize >= TAR_BLOCK_SIZE);
 
-   buf = GDKmalloc(bufsize);
-   if (!buf) {
-   GDKerror("could not allocate buffer");
-   goto end;
-   }
 
if (tar_write_header(tarfile, path, mtime, size) != GDK_SUCCEED)
-   goto end;
+   return GDK_FAIL;
 
to_read = size;
 
while (to_read > 0) {
-   ssize_t chunk = (to_read <= bufsize) ? to_read : bufsize;
+   size_t chunk = (to_read <= bufsize) ? to_read : bufsize;
ssize_t nbytes = mnstr_read(contents, buf, 1, chunk);
-   if (nbytes != chunk) {
+   if (nbytes != (ssize_t)chunk) {
GDKerror("Read only %zd/%zd bytes of component %s: %s", 
nbytes, chunk, path, mnstr_peek_error(contents));
-   goto end;
-   }
-   ret = tar_write(tarfile, buf, chunk);
-   if (ret != GDK_SUCCEED)
-   goto end;
+   return GDK_FAIL;
+   }
+   if (tar_write(tarfile, buf, chunk) != GDK_SUCCEED)
+   return GDK_FAIL;
to_read -= chunk;
}
 
-   ret = GDK_SUCCEED;
-end:
-   if (buf)
-   GDKfree(buf);
-   return ret;
+   return GDK_SUCCEED;
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
@@ -2712,6 +2699,20 @@ hot_snapshot_write_tar(stream *out, cons
char dest_path[100]; // size imposed by tar format.
char *dest_name = dest_path + snprintf(dest_path, sizeof(dest_path), 
"%s/", prefix);
stream *infile = NULL;
+   const char *bufsize_env_var = "hot_snapshot_buffer_size";
+   int bufsize = GDKgetenv_int(bufsize_env_var, 1024 * 1024);
+   char *buffer = NULL;
+
+   if (bufsize < TAR_BLOCK_SIZE || (bufsize % TAR_BLOCK_SIZE) != 0) {
+   GDKerror("invalid value for setting %s=%d: must be a multiple 
of %d",
+   bufsize_env_var, bufsize, TAR_BLOCK_SIZE);
+   goto end;
+   }
+   buffer = GDKmalloc(bufsize);
+   if (!buffer) {
+   GDKerror("could not allocate buffer");
+   goto end;
+   }
 
QryCtx *qry_ctx = MT_thread_get_qry_ctx();
 
@@ -2741,7 +2742,7 @@ hot_snapshot_write_tar(stream *out, cons
GDKerror("%s", mnstr_peek_error(NULL));
goto end;
}
-   if (tar_copy_stream(out, dest_path, timestamp, 
infile, size) != GDK_SUCCEED)
+   if (tar_copy_stream(out, dest_path, timestamp, 
infile, size, buffer, (size_t)bufsize) != GDK_SUCCEED)
goto end;
close_stream(infile);
infile = NULL;
@@ -2767,6 +2768,7 @@ hot_snapshot_write_tar(stream *out, cons
 
 end:
free(plan);
+   GDKfree(buffer);
if (infile)
close_stream(infile);
return ret;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Dec2023 - ChangeLog for hot snapshot change

2024-08-23 Thread Joeri van Ruth via checkin-list
Changeset: 5483eaecec98 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/5483eaecec98
Modified Files:
sql/ChangeLog.Dec2023
Branch: Dec2023
Log Message:

ChangeLog for hot snapshot change


diffs (11 lines):

diff --git a/sql/ChangeLog.Dec2023 b/sql/ChangeLog.Dec2023
--- a/sql/ChangeLog.Dec2023
+++ b/sql/ChangeLog.Dec2023
@@ -1,3 +1,7 @@
 # ChangeLog file for sql
 # This file is updated with Maddlog
 
+* Fri Aug 23 2024 Joeri van Ruth 
+- Increase the buffer size used by hot snapshot from 64kiB to 1MiB,
+  and make it configurable through setting 'hot_snapshot_buffer_size'.
+  It must be a multiple of 512.
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Dec2023 - Make hot snapshot buffer size configurable, i...

2024-08-23 Thread Joeri van Ruth via checkin-list
Changeset: 0c0746a5f0b9 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0c0746a5f0b9
Modified Files:
sql/storage/store.c
Branch: Dec2023
Log Message:

Make hot snapshot buffer size configurable, increase the default

The buffer size is configurable with setting 'hot_snapshot_buffer_size'.
The value is in bytes. It must be a multiple of 512.
The default has been increased from 65536 to 1048576.

For example,

mserver5 --set hot_snapshot_buffer_size=2097152


diffs (107 lines):

diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -2615,52 +2615,39 @@ tar_write_data(stream *tarfile, const ch
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
-tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, ssize_t size)
-{
-   const ssize_t bufsize = 64 * 1024;
-   gdk_return ret = GDK_FAIL;
-   ssize_t file_size;
-   char *buf = NULL;
-   ssize_t to_read;
+tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, size_t size, char *buf, size_t bufsize)
+{
+   size_t file_size;
+   size_t to_read;
 
file_size = getFileSize(contents);
if (file_size < size) {
GDKerror("Have to copy %zd bytes but only %zd exist in %s", 
size, file_size, path);
-   goto end;
+   return GDK_FAIL;
}
 
assert( (bufsize % TAR_BLOCK_SIZE) == 0);
assert(bufsize >= TAR_BLOCK_SIZE);
 
-   buf = GDKmalloc(bufsize);
-   if (!buf) {
-   GDKerror("could not allocate buffer");
-   goto end;
-   }
 
if (tar_write_header(tarfile, path, mtime, size) != GDK_SUCCEED)
-   goto end;
+   return GDK_FAIL;
 
to_read = size;
 
while (to_read > 0) {
-   ssize_t chunk = (to_read <= bufsize) ? to_read : bufsize;
+   size_t chunk = (to_read <= bufsize) ? to_read : bufsize;
ssize_t nbytes = mnstr_read(contents, buf, 1, chunk);
-   if (nbytes != chunk) {
+   if (nbytes != (ssize_t)chunk) {
GDKerror("Read only %zd/%zd bytes of component %s: %s", 
nbytes, chunk, path, mnstr_peek_error(contents));
-   goto end;
-   }
-   ret = tar_write(tarfile, buf, chunk);
-   if (ret != GDK_SUCCEED)
-   goto end;
+   return GDK_FAIL;
+   }
+   if (tar_write(tarfile, buf, chunk) != GDK_SUCCEED)
+   return GDK_FAIL;
to_read -= chunk;
}
 
-   ret = GDK_SUCCEED;
-end:
-   if (buf)
-   GDKfree(buf);
-   return ret;
+   return GDK_SUCCEED;
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
@@ -2679,6 +2666,20 @@ hot_snapshot_write_tar(stream *out, cons
char dest_path[100]; // size imposed by tar format.
char *dest_name = dest_path + snprintf(dest_path, sizeof(dest_path), 
"%s/", prefix);
stream *infile = NULL;
+   const char *bufsize_env_var = "hot_snapshot_buffer_size";
+   int bufsize = GDKgetenv_int(bufsize_env_var, 1024 * 1024);
+   char *buffer = NULL;
+
+   if (bufsize < TAR_BLOCK_SIZE || (bufsize % TAR_BLOCK_SIZE) != 0) {
+   GDKerror("invalid value for setting %s=%d: must be a multiple 
of %d",
+   bufsize_env_var, bufsize, TAR_BLOCK_SIZE);
+   goto end;
+   }
+   buffer = GDKmalloc(bufsize);
+   if (!buffer) {
+   GDKerror("could not allocate buffer");
+   goto end;
+   }
 
lng timeoffset = 0;
QryCtx *qry_ctx = MT_thread_get_qry_ctx();
@@ -2712,7 +2713,7 @@ hot_snapshot_write_tar(stream *out, cons
GDKerror("%s", mnstr_peek_error(NULL));
goto end;
}
-   if (tar_copy_stream(out, dest_path, timestamp, 
infile, size) != GDK_SUCCEED)
+   if (tar_copy_stream(out, dest_path, timestamp, 
infile, size, buffer, (size_t)bufsize) != GDK_SUCCEED)
goto end;
close_stream(infile);
infile = NULL;
@@ -2738,6 +2739,7 @@ hot_snapshot_write_tar(stream *out, cons
 
 end:
free(plan);
+   GDKfree(buffer);
if (infile)
close_stream(infile);
return ret;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - Make hot snapshot buffer size configurable, i...

2024-08-21 Thread Joeri van Ruth via checkin-list
Changeset: dab11424c673 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/dab11424c673
Modified Files:
sql/storage/store.c
Branch: default
Log Message:

Make hot snapshot buffer size configurable, increase the default

The buffer size is configurable with setting 'hot_snapshot_buffer_size'.
The value is in bytes. It must be a multiple of 512.
The default has been increased from 65536 to 1048576.

For example,

mserver5 --set hot_snapshot_buffer_size=2097152


diffs (107 lines):

diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -2648,52 +2648,39 @@ tar_write_data(stream *tarfile, const ch
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
-tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, ssize_t size)
-{
-   const ssize_t bufsize = 64 * 1024;
-   gdk_return ret = GDK_FAIL;
-   ssize_t file_size;
-   char *buf = NULL;
-   ssize_t to_read;
+tar_copy_stream(stream *tarfile, const char *path, time_t mtime, stream 
*contents, size_t size, char *buf, size_t bufsize)
+{
+   size_t file_size;
+   size_t to_read;
 
file_size = getFileSize(contents);
if (file_size < size) {
GDKerror("Have to copy %zd bytes but only %zd exist in %s", 
size, file_size, path);
-   goto end;
+   return GDK_FAIL;
}
 
assert( (bufsize % TAR_BLOCK_SIZE) == 0);
assert(bufsize >= TAR_BLOCK_SIZE);
 
-   buf = GDKmalloc(bufsize);
-   if (!buf) {
-   GDKerror("could not allocate buffer");
-   goto end;
-   }
 
if (tar_write_header(tarfile, path, mtime, size) != GDK_SUCCEED)
-   goto end;
+   return GDK_FAIL;
 
to_read = size;
 
while (to_read > 0) {
-   ssize_t chunk = (to_read <= bufsize) ? to_read : bufsize;
+   size_t chunk = (to_read <= bufsize) ? to_read : bufsize;
ssize_t nbytes = mnstr_read(contents, buf, 1, chunk);
-   if (nbytes != chunk) {
+   if (nbytes != (ssize_t)chunk) {
GDKerror("Read only %zd/%zd bytes of component %s: %s", 
nbytes, chunk, path, mnstr_peek_error(contents));
-   goto end;
-   }
-   ret = tar_write(tarfile, buf, chunk);
-   if (ret != GDK_SUCCEED)
-   goto end;
+   return GDK_FAIL;
+   }
+   if (tar_write(tarfile, buf, chunk) != GDK_SUCCEED)
+   return GDK_FAIL;
to_read -= chunk;
}
 
-   ret = GDK_SUCCEED;
-end:
-   if (buf)
-   GDKfree(buf);
-   return ret;
+   return GDK_SUCCEED;
 }
 
 static gdk_return __attribute__((__warn_unused_result__))
@@ -2712,6 +2699,20 @@ hot_snapshot_write_tar(stream *out, cons
char dest_path[100]; // size imposed by tar format.
char *dest_name = dest_path + snprintf(dest_path, sizeof(dest_path), 
"%s/", prefix);
stream *infile = NULL;
+   const char *bufsize_env_var = "hot_snapshot_buffer_size";
+   int bufsize = GDKgetenv_int(bufsize_env_var, 1024 * 1024);
+   char *buffer = NULL;
+
+   if (bufsize < TAR_BLOCK_SIZE || (bufsize % TAR_BLOCK_SIZE) != 0) {
+   GDKerror("invalid value for setting %s=%d: must be a multiple 
of %d",
+   bufsize_env_var, bufsize, TAR_BLOCK_SIZE);
+   goto end;
+   }
+   buffer = GDKmalloc(bufsize);
+   if (!buffer) {
+   GDKerror("could not allocate buffer");
+   goto end;
+   }
 
QryCtx *qry_ctx = MT_thread_get_qry_ctx();
 
@@ -2741,7 +2742,7 @@ hot_snapshot_write_tar(stream *out, cons
GDKerror("%s", mnstr_peek_error(NULL));
goto end;
}
-   if (tar_copy_stream(out, dest_path, timestamp, 
infile, size) != GDK_SUCCEED)
+   if (tar_copy_stream(out, dest_path, timestamp, 
infile, size, buffer, (size_t)bufsize) != GDK_SUCCEED)
goto end;
close_stream(infile);
infile = NULL;
@@ -2767,6 +2768,7 @@ hot_snapshot_write_tar(stream *out, cons
 
 end:
free(plan);
+   GDKfree(buffer);
if (infile)
close_stream(infile);
return ret;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


monetdb-java: default - ChangeLog

2024-08-14 Thread Joeri van Ruth via checkin-list
Changeset: 0ce63f3686fe for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/0ce63f3686fe
Modified Files:
ChangeLog
Branch: default
Log Message:

ChangeLog


diffs (15 lines):

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
 # ChangeLog file for monetdb-java
 # This file is updated with Maddlog
 
+* Wed Jun 19 2024 Joeri van Ruth 
+- Implemented Connection#set/getClientInfo, and send sensible default info
+  at connect time. This can be controlled with the properties 
'client_info=on/off',
+  'client_application=ApplicationName' and 'client_remark=Other Useful Info'.
+
 * Thu Apr  4 2024 Martin van Dinther 
 - Corrected ResultSetMetaData methods getColumnTypeName(), getPrecision(),
   getColumnDisplaySize() and ParameterMetaData methods getParameterTypeName()
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Test sys.sessions row permissions interaction...

2024-07-12 Thread Joeri van Ruth via checkin-list
Changeset: a4c6641aaeac for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a4c6641aaeac
Modified Files:
sql/test/mapi/Tests/clientinfo-nonadmin.test
Branch: Aug2024
Log Message:

Test sys.sessions row permissions interaction with SET ROLE


diffs (33 lines):

diff --git a/sql/test/mapi/Tests/clientinfo-nonadmin.test 
b/sql/test/mapi/Tests/clientinfo-nonadmin.test
--- a/sql/test/mapi/Tests/clientinfo-nonadmin.test
+++ b/sql/test/mapi/Tests/clientinfo-nonadmin.test
@@ -60,3 +60,29 @@ 3
 user 2b
 
 
+# Having the same role does not mean you can see each others details
+
+statement ok
+CREATE ROLE common
+
+statement ok
+GRANT common TO user1
+
+statement ok
+GRANT common TO user2
+
+@connection(id=user1)
+statement ok
+SET ROLE common
+
+@connection(id=user2a)
+statement ok
+SET ROLE common
+
+# no user2!
+@connection(id=user1)
+query IT rowsort
+SELECT sessionid, remark FROM sys.sessions
+
+1
+user 1
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Use proper sqlid to decide which sessions row...

2024-07-12 Thread Joeri van Ruth via checkin-list
Changeset: f6c052f76604 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f6c052f76604
Modified Files:
sql/backends/monet5/sql.c
Branch: Aug2024
Log Message:

Use proper sqlid to decide which sessions rows to show


diffs (45 lines):

diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -37,6 +37,7 @@
 #include "mal_resolve.h"
 #include "mal_client.h"
 #include "mal_interpreter.h"
+#include "mal_scenario.h"
 #include "mal_profiler.h"
 #include "bat5.h"
 #include "opt_pipes.h"
@@ -3563,6 +3564,9 @@ sql_sessions_wrap(Client cntxt, MalBlkPt
bat *clientpidId = getArgReference_bat(stk, pci, 14);
bat *remarkId = getArgReference_bat(stk, pci, 15);
Client c;
+   backend *be;
+   sqlid user_id;
+   sqlid role_id;
bool admin;
timestamp ts;
lng pid;
@@ -3615,14 +3619,21 @@ sql_sessions_wrap(Client cntxt, MalBlkPt
throw(SQL, "sql.sessions", SQLSTATE(HY013) MAL_MALLOC_FAIL);
}
 
-   admin = strcmp(cntxt->username, "monetdb") == 0;
+   be = cntxt->sqlcontext;
+   user_id = be->mvc->user_id;
+   role_id = be->mvc->role_id;
+   admin = user_id == USER_MONETDB || role_id == ROLE_SYSADMIN;
 
MT_lock_set(&mal_contextLock);
for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) {
if (c->mode != RUNCLIENT)
continue;
 
-   bool allowed_to_see = admin || c == cntxt || 
strcmp(c->username, cntxt->username) == 0;
+   backend *their_be = c->sqlcontext;
+   bool allowed_to_see = admin || c == cntxt ||  
their_be->mvc->user_id == user_id;
+   // Note that their role_id is not checked. Just because we have
+   // both been granted a ROLE does not mean you are allowed to see
+   // my private details.
if (!allowed_to_see)
continue;
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Inline CLTsessions into sql_sessions_wrap

2024-07-12 Thread Joeri van Ruth via checkin-list
Changeset: 6e71ccb990b3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/6e71ccb990b3
Modified Files:
clients/Tests/exports.stable.out
monetdb5/modules/mal/clients.c
monetdb5/modules/mal/clients.h
sql/backends/monet5/sql.c
Branch: Aug2024
Log Message:

Inline CLTsessions into sql_sessions_wrap

Because in the clients module we don't have access to the be->mvc


diffs (truncated from 454 to 300 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -790,7 +790,6 @@ str AUTHunlockVault(const char *password
 str AUTHverifyPassword(const char *passwd);
 str BKCmirror(bat *ret, const bat *bid);
 str BKCnewBAT(bat *res, const int *tt, const BUN *cap, role_t role);
-str CLTsessions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
 str CLTshutdown(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
 str COPYrejects(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
 str COPYrejects_clear(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);
diff --git a/monetdb5/modules/mal/clients.c b/monetdb5/modules/mal/clients.c
--- a/monetdb5/modules/mal/clients.c
+++ b/monetdb5/modules/mal/clients.c
@@ -773,214 +773,6 @@ CLTshutdown(Client cntxt, MalBlkPtr mb, 
return MAL_SUCCEED;
 }
 
-str
-CLTsessions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
-{
-   BAT *id = NULL, *user = NULL, *login = NULL, *sessiontimeout = NULL,
-   *querytimeout = NULL, *idle = NULL;
-   BAT *opt = NULL, *wlimit = NULL, *mlimit = NULL;
-   BAT *language = NULL, *peer = NULL, *hostname = NULL, *application = 
NULL, *client = NULL, *clientpid = NULL, *remark = NULL;
-   bat *idId = getArgReference_bat(stk, pci, 0);
-   bat *userId = getArgReference_bat(stk, pci, 1);
-   bat *loginId = getArgReference_bat(stk, pci, 2);
-   bat *idleId = getArgReference_bat(stk, pci, 3);
-   bat *optId = getArgReference_bat(stk, pci, 4);
-   bat *sessiontimeoutId = getArgReference_bat(stk, pci, 5);
-   bat *querytimeoutId = getArgReference_bat(stk, pci, 6);
-   bat *wlimitId = getArgReference_bat(stk, pci, 7);
-   bat *mlimitId = getArgReference_bat(stk, pci, 8);
-   bat *languageId = getArgReference_bat(stk, pci, 9);
-   bat *peerId = getArgReference_bat(stk, pci, 10);
-   bat *hostnameId = getArgReference_bat(stk, pci, 11);
-   bat *applicationId = getArgReference_bat(stk, pci, 12);
-   bat *clientId = getArgReference_bat(stk, pci, 13);
-   bat *clientpidId = getArgReference_bat(stk, pci, 14);
-   bat *remarkId = getArgReference_bat(stk, pci, 15);
-   Client c;
-   bool admin;
-   timestamp ts;
-   lng pid;
-   const char *s;
-   int timeout;
-   str msg = NULL;
-
-   (void) cntxt;
-   (void) mb;
-
-   id = COLnew(0, TYPE_int, 0, TRANSIENT);
-   user = COLnew(0, TYPE_str, 0, TRANSIENT);
-   login = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
-   opt = COLnew(0, TYPE_str, 0, TRANSIENT);
-   sessiontimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
-   querytimeout = COLnew(0, TYPE_int, 0, TRANSIENT);
-   wlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
-   mlimit = COLnew(0, TYPE_int, 0, TRANSIENT);
-   idle = COLnew(0, TYPE_timestamp, 0, TRANSIENT);
-   language = COLnew(0, TYPE_str, 0, TRANSIENT);
-   peer = COLnew(0, TYPE_str, 0, TRANSIENT);
-   hostname = COLnew(0, TYPE_str, 0, TRANSIENT);
-   application = COLnew(0, TYPE_str, 0, TRANSIENT);
-   client = COLnew(0, TYPE_str, 0, TRANSIENT);
-   clientpid = COLnew(0, TYPE_lng, 0, TRANSIENT);
-   remark = COLnew(0, TYPE_str, 0, TRANSIENT);
-
-   if (id == NULL || user == NULL || login == NULL || sessiontimeout == 
NULL
-   || idle == NULL || querytimeout == NULL || opt == NULL || 
wlimit == NULL
-   || mlimit == NULL || language == NULL || peer == NULL || 
hostname == NULL
-   || application == NULL || client == NULL || clientpid == NULL
-   || remark == NULL) {
-   BBPreclaim(id);
-   BBPreclaim(user);
-   BBPreclaim(login);
-   BBPreclaim(sessiontimeout);
-   BBPreclaim(querytimeout);
-   BBPreclaim(idle);
-   BBPreclaim(opt);
-   BBPreclaim(wlimit);
-   BBPreclaim(mlimit);
-   BBPreclaim(language);
-   BBPreclaim(peer);
-   BBPreclaim(hostname);
-   BBPreclaim(application);
-   BBPreclaim(client);
-   BBPreclaim(clientpid);
-   BBPreclaim(remark);
-
-   throw(SQL, "sql.sessions", SQLSTATE(HY013) MAL_MALLOC_FAIL);
-   }
-
-   admin = strcmp(cntxt->username, "monetdb") == 0;
-
-   MT_lock_set(&mal_contextLock);
-   for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) {
-   

MonetDB: Aug2024 - Export getScenarioLanguage

2024-07-12 Thread Joeri van Ruth via checkin-list
Changeset: ec523f3b884f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ec523f3b884f
Modified Files:
clients/Tests/exports.stable.out
monetdb5/mal/mal_scenario.h
Branch: Aug2024
Log Message:

Export getScenarioLanguage

so the sql backend can use it


diffs (27 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -1022,6 +1022,7 @@ int getOidConstant(MalBlkPtr mb, oid val
 int getPC(MalBlkPtr mb, InstrPtr p);
 str getPipeCatalog(bat *nme, bat *def, bat *stat);
 const char *getRef;
+str getScenarioLanguage(Client c);
 int getShtConstant(MalBlkPtr mb, sht val);
 int getStrConstant(MalBlkPtr mb, str val);
 const char *getTraceRef;
diff --git a/monetdb5/mal/mal_scenario.h b/monetdb5/mal/mal_scenario.h
--- a/monetdb5/mal/mal_scenario.h
+++ b/monetdb5/mal/mal_scenario.h
@@ -37,11 +37,11 @@ typedef struct SCENARIO {
 
 mal_export Scenario getFreeScenario(void);
 mal_export Scenario findScenario(const char *nme);
+mal_export str getScenarioLanguage(Client c);
 
 #ifdef LIBMONETDB5
 extern str setScenario(Client c, const char *nme);
 extern str runScenario(Client c);
-extern str getScenarioLanguage(Client c);
 
 extern void showCurrentScenario(void);
 extern void showScenarioByName(stream *f, const char *s);
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Convert sql/test/clientinfo-nonadmin into a s...

2024-07-12 Thread Joeri van Ruth via checkin-list
Changeset: c9475f5c9773 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c9475f5c9773
Added Files:
sql/test/mapi/Tests/clientinfo-nonadmin.test
Removed Files:
sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py
Branch: Aug2024
Log Message:

Convert sql/test/clientinfo-nonadmin into a sqllogictest

(I wasn't aware of @connection before)


diffs (133 lines):

diff --git a/sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py 
b/sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py
deleted file mode 100644
--- a/sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py
+++ /dev/null
@@ -1,61 +0,0 @@
-
-import os
-import sys
-from typing import List, Tuple
-import pymonetdb
-
-
-def connect(remark: str, **args) -> pymonetdb.Connection:
-dbname = os.environ['TSTDB']
-mapiport = os.environ['MAPIPORT']
-conn = pymonetdb.connect(dbname, port=mapiport, autocommit=True,  **args)
-with conn.cursor() as c:
-c.execute("CALL sys.setclientinfo('ClientRemark', %s)", [remark])
-return conn
-
-def get_remarks(conn: pymonetdb.Connection) -> List[Tuple[int,str]]:
-with conn.cursor() as c:
-c.execute("SELECT sessionid, remark FROM sys.sessions ORDER BY 
sessionid")
-return c.fetchall()
-
-def assert_equal(left, right):
-if left != right:
-print(f'LEFT:  {left!r}\nRIGHT: {right!r}\n', file=sys.stderr)
-assert left == right
-
-
-###
-# Connect as admin
-
-conn0 = connect('admin 0')
-assert_equal(get_remarks(conn0), [(0, 'admin 0')])
-
-
-###
-# Create a user
-
-c0 = conn0.cursor()
-# try:
-# c0.execute('DROP USER nonadmin')# convenientduring interactive 
testing
-# except pymonetdb.Error:
-# pass
-c0.execute("CREATE USER nonadmin WITH PASSWORD 'na' NAME 'Not Admin' SCHEMA 
sys")
-
-
-###
-# Connect as that user, twice
-
-conn1 = connect('user 1', user='nonadmin', password='na')
-conn2 = connect('user 2', user='nonadmin', password='na')
-
-
-###
-# Check who can see what
-
-# admin can see both
-assert_equal(get_remarks(conn0), [(0, 'admin 0'), (1, 'user 1'), (2, 'user 
2')])
-
-# users can only see themselves
-assert_equal(get_remarks(conn1), [(1, 'user 1'), (2, 'user 2')])
-assert_equal(get_remarks(conn2), [(1, 'user 1'), (2, 'user 2')])
-
diff --git a/sql/test/mapi/Tests/clientinfo-nonadmin.test 
b/sql/test/mapi/Tests/clientinfo-nonadmin.test
new file mode 100644
--- /dev/null
+++ b/sql/test/mapi/Tests/clientinfo-nonadmin.test
@@ -0,0 +1,62 @@
+
+# admin logs in with ClientRemark and creates users
+
+statement ok
+CALL sys.setclientinfo('ClientRemark', 'admin')
+
+statement ok
+CREATE USER user1 WITH PASSWORD 'bla' NAME 'User 1' SCHEMA sys;
+
+statement ok
+CREATE USER user2 WITH PASSWORD 'bla' NAME 'User 2' SCHEMA sys;
+
+
+# user1 logs in with ClientRemark
+
+@connection(id=user1, username=user1, password=bla)
+statement ok
+CALL sys.setclientinfo('ClientRemark', 'user 1')
+
+
+# user2 logs in twice, with different ClientRemarks
+
+@connection(id=user2a, username=user2, password=bla)
+statement ok
+CALL sys.setclientinfo('ClientRemark', 'user 2a')
+
+@connection(id=user2b, username=user2, password=bla)
+statement ok
+CALL sys.setclientinfo('ClientRemark', 'user 2b')
+
+
+# Now verify what everybody sees
+
+query IT rowsort
+SELECT sessionid, remark FROM sys.sessions
+
+0
+admin
+1
+user 1
+2
+user 2a
+3
+user 2b
+
+@connection(id=user1)
+query IT rowsort
+SELECT sessionid, remark FROM sys.sessions
+
+1
+user 1
+
+@connection(id=user2a)
+query IT rowsort
+SELECT sessionid, remark FROM sys.sessions
+
+2
+user 2a
+3
+user 2b
+
+
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Mention public select privilege on sys.sessio...

2024-07-09 Thread Joeri van Ruth via checkin-list
Changeset: 08cc537c4877 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/08cc537c4877
Modified Files:
sql/ChangeLog.Aug2024
Branch: Aug2024
Log Message:

Mention public select privilege on sys.sessions in client info ChangeLog entry

See #7549


diffs (12 lines):

diff --git a/sql/ChangeLog.Aug2024 b/sql/ChangeLog.Aug2024
--- a/sql/ChangeLog.Aug2024
+++ b/sql/ChangeLog.Aug2024
@@ -8,6 +8,8 @@
 * Wed May 29 2024 Joeri van Ruth 
 - Extended view sys.sessions and function sys.sessions() with new columns:
   language, peer, hostname, application, client, clientpid and remark.
+- All users now have SELECT privilege on view sys.sessions, but non-admin
+  users only see their own sessions.
 - Added procedure sys.setclientinfo(property string, value string)
   to allow the client application to set a specific client info property.
 - Added system table sys.clientinfo_properties that lists the supported
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Allow every user to see their own rows in sys...

2024-07-08 Thread Joeri van Ruth via checkin-list
Changeset: 79294808aa31 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/79294808aa31
Added Files:
sql/test/mapi/Tests/clientinfo-nonadmin.SQL.py
Modified Files:
monetdb5/modules/mal/clients.c
sql/backends/monet5/sql_upgrades.c
sql/scripts/22_clients.sql
sql/test/mapi/Tests/All
Branch: Aug2024
Log Message:

Allow every user to see their own rows in sys.sessions

This fixes #7549


diffs (246 lines):

diff --git a/monetdb5/modules/mal/clients.c b/monetdb5/modules/mal/clients.c
--- a/monetdb5/modules/mal/clients.c
+++ b/monetdb5/modules/mal/clients.c
@@ -797,6 +797,7 @@ CLTsessions(Client cntxt, MalBlkPtr mb, 
bat *clientpidId = getArgReference_bat(stk, pci, 14);
bat *remarkId = getArgReference_bat(stk, pci, 15);
Client c;
+   bool admin;
timestamp ts;
lng pid;
const char *s;
@@ -848,73 +849,80 @@ CLTsessions(Client cntxt, MalBlkPtr mb, 
throw(SQL, "sql.sessions", SQLSTATE(HY013) MAL_MALLOC_FAIL);
}
 
+   admin = strcmp(cntxt->username, "monetdb") == 0;
+
MT_lock_set(&mal_contextLock);
-
for (c = mal_clients; c < mal_clients + MAL_MAXCLIENTS; c++) {
-   if (c->mode == RUNCLIENT) {
-   const char *username = c->username;
-   if (!username)
-   username = str_nil;
-   if (BUNappend(user, username, false) != GDK_SUCCEED)
+   if (c->mode != RUNCLIENT)
+   continue;
+
+   bool allowed_to_see = admin || c == cntxt || 
strcmp(c->username, cntxt->username) == 0;
+   if (!allowed_to_see)
+   continue;
+
+   const char *username = c->username;
+   if (!username)
+   username = str_nil;
+   if (BUNappend(user, username, false) != GDK_SUCCEED)
+   goto bailout;
+   ts = timestamp_fromtime(c->login);
+   if (is_timestamp_nil(ts)) {
+   msg = createException(SQL, "sql.sessions",
+   
SQLSTATE(22003)
+   "Failed 
to convert user logged time");
+   goto bailout;
+   }
+   if (BUNappend(id, &c->idx, false) != GDK_SUCCEED)
goto bailout;
-   ts = timestamp_fromtime(c->login);
+   if (BUNappend(login, &ts, false) != GDK_SUCCEED)
+   goto bailout;
+   timeout = (int) (c->logical_sessiontimeout);
+   if (BUNappend(sessiontimeout, &timeout, false) != GDK_SUCCEED)
+   goto bailout;
+   timeout = (int) (c->querytimeout / 100);
+   if (BUNappend(querytimeout, &timeout, false) != GDK_SUCCEED)
+   goto bailout;
+   if (c->idle) {
+   ts = timestamp_fromtime(c->idle);
if (is_timestamp_nil(ts)) {
msg = createException(SQL, "sql.sessions",
- 
SQLSTATE(22003)
- 
"Failed to convert user logged time");
+   
SQLSTATE(22003)
+   
"Failed to convert user logged time");
goto bailout;
}
-   if (BUNappend(id, &c->idx, false) != GDK_SUCCEED)
-goto bailout;
-   if (BUNappend(login, &ts, false) != GDK_SUCCEED)
-   goto bailout;
-   timeout = (int) (c->logical_sessiontimeout);
-   if (BUNappend(sessiontimeout, &timeout, false) != 
GDK_SUCCEED)
-   goto bailout;
-   timeout = (int) (c->querytimeout / 100);
-   if (BUNappend(querytimeout, &timeout, false) != 
GDK_SUCCEED)
-   goto bailout;
-   if (c->idle) {
-   ts = timestamp_fromtime(c->idle);
-   if (is_timestamp_nil(ts)) {
-   msg = createException(SQL, 
"sql.sessions",
-   
  SQLSTATE(22003)
-   
  "Failed to convert user logged time");
-   goto bailout;
-   }
-   } else
-   ts = tim

MonetDB: Aug2024 - streamline unicode usage in ODBCconnect.py

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

streamline unicode usage in ODBCconnect.py


diffs (81 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,10 +25,17 @@ user = 'monetdb'
 password = 'monetdb'
 port = os.environ.get('MAPIPORT', 5)
 
-# \u{E1} is LATIN SMALL LETTER A WITH ACUTE
-unicode_text = 'R\u00E1inbow'
+
+# UnixODBC turns out to be broken when it comes to Unicode in connection
+# strings. In SQLBrowseConnectW it basically converts the 16-bit connection
+# string to an 8-bit connection string by dropping the upper bytes and keeping
+# only the lower bytes. The character sequence below has been chosen with this
+# in mind.
+
+# \u{E1} is LATIN SMALL LETTER A WITH ACUTE.
+basic_unicode_text = 'R\u00E1inbow'
 # \u{1F308} is RAINBOW EMOJI
-#unicode_text += '\U0001F308'
+full_unicode_text = basic_unicode_text + '\U0001F308'
 
 class Execution:
 def __init__(self, *odbcconnect_args):
@@ -279,9 +286,11 @@ ex.expect('08001')  # something wrong wi
 ex.end()
 
 # test wide characters
-ex = Execution('-w', '-d', f'DSN={dsn};Client Remark={unicode_text}')
+# we can use the full character set because UnixODBC's SQLDriverConnect
+# passes the connection string on without looking at it
+ex = Execution('-w', '-d', f'DSN={dsn};Client Remark={full_unicode_text}')
 # expect OK followed by connection string containing the rainbow
-ex.expect('OK', f'CLIENTREMARK={unicode_text}')
+ex.expect('OK', f'CLIENTREMARK={full_unicode_text}')
 ex.end()
 
 # test maptolongvarchar
@@ -340,12 +349,14 @@ ex.expect('OK', ';')
 ex.end()
 
 # test wide characters
+# we use the limited character set because UnixODBC's SQLBrowserConnect
+# messes up code points > 255
 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 = Execution('-w', '-b', f'DSN={dsn};Client Remark={basic_unicode_text}')
+ex.expect('OK', f';CLIENTREMARK={basic_unicode_text}')
 ex.expect
 ex.end()
 
@@ -354,20 +365,20 @@ ex = Execution('-0', '-w', '-b', f'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 = Execution('-0', '-w', '-b', f'DSN={dsn};Client 
Remark={basic_unicode_text}')
+ex.expect('OK', f';CLIENTREMARK={basic_unicode_text}')
 ex.expect
 ex.end()
 
 # Also test that queries return unicode ok
 ex = Execution(
 '-w',
-'-b', f'DSN={dsn};Client Remark={unicode_text}',
+'-b', f'DSN={dsn};Client Remark={basic_unicode_text}',
 '-q', 'select remark from sys.sessions where sessionid = 
current_sessionid()',
 )
-ex.expect('OK', f';CLIENTREMARK={unicode_text}')
+ex.expect('OK', f';CLIENTREMARK={basic_unicode_text}')
 ex.expect('RESULT')
-ex.expect(unicode_text)
+ex.expect(basic_unicode_text)
 ex.end()
 
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Let odbcconnect -l print some Driver Manager ...

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

Let odbcconnect -l print some Driver Manager info


diffs (34 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
@@ -368,10 +368,30 @@ do_sqlbrowseconnect(const char *target)
 static int
 do_listdrivers(void)
 {
+   SQLRETURN ret;
SQLSMALLINT dir = SQL_FETCH_FIRST;
SQLSMALLINT len1, len2;
int count = 0;
 
+   // unixodbc defines these in sqlext.h:
+   // #define SQL_ATTR_UNIXODBC_SYSPATH   65001
+   // #define SQL_ATTR_UNIXODBC_VERSION   65002
+   ret = SQLGetEnvAttr(env, 65002, outabuf, OUTBUF_SIZE, NULL);
+   if (SQL_SUCCEEDED(ret))
+   printf("SQL_ATTR_UNIXODBC_VERSION=%s\n", outabuf);
+   ret = SQLGetEnvAttr(env, 65001, outabuf, OUTBUF_SIZE, NULL);
+   if (SQL_SUCCEEDED(ret))
+   printf("SQL_ATTR_UNIXODBC_SYSPATH=%s\n", outabuf);
+
+   // SQLGetInfo needs a DBC handle. It does not need to be connected to 
anything
+   ensure_ok(
+   SQL_HANDLE_ENV, env, "allocate conn handle",
+   SQLAllocHandle(SQL_HANDLE_DBC, env, &conn));
+
+   ret = SQLGetInfoA(conn, SQL_DM_VER, outabuf, OUTBUF_SIZE, NULL);
+   if (SQL_SUCCEEDED(ret))
+   printf("SQL_DM_VER=%s\n", outabuf);
+
while (1) {
outabuf[0] = attrbuf[0] = '\0';
SQLRETURN ret = SQLDriversA(
___
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

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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 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 - 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 - Merge with 'Dec2023'

2024-06-26 Thread Joeri van Ruth via checkin-list
Changeset: a9ca51334e01 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a9ca51334e01
Modified Files:
sql/backends/monet5/vaults/csv/csv.c
sql/test/BugTracker-2024/Tests/All
sql/test/copy/Tests/All
Branch: Aug2024
Log Message:

Merge with 'Dec2023'


diffs (118 lines):

diff --git a/sql/backends/monet5/vaults/csv/csv.c 
b/sql/backends/monet5/vaults/csv/csv.c
--- a/sql/backends/monet5/vaults/csv/csv.c
+++ b/sql/backends/monet5/vaults/csv/csv.c
@@ -45,6 +45,7 @@ next_delim(const char *s, const char *e,
return s;
}
if (s <= e)
+   if (s <= e)
return s;
return NULL;
 }
diff --git a/sql/test/BugTracker-2024/Tests/7542-column-name-resolution.test 
b/sql/test/BugTracker-2024/Tests/7542-column-name-resolution.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2024/Tests/7542-column-name-resolution.test
@@ -0,0 +1,13 @@
+
+-- https://github.com/MonetDB/MonetDB/issues/7542
+
+query I nosort
+WITH "E" AS ( SELECT 2 AS "F" )
+  SELECT 3 AS "Z" FROM (
+SELECT "B"."X" FROM ( SELECT 2 AS "Y" FROM "E" ) AS "A" 
+LEFT OUTER JOIN ( SELECT 2 AS "X" ) AS "B" ON 1 = 1
+  ) AS "C"
+  ORDER BY "Z" DESC LIMIT 1
+
+3
+
diff --git a/sql/test/BugTracker-2024/Tests/All 
b/sql/test/BugTracker-2024/Tests/All
--- a/sql/test/BugTracker-2024/Tests/All
+++ b/sql/test/BugTracker-2024/Tests/All
@@ -68,3 +68,4 @@ 7539-is-distinct-from
 7537-prepare_stmt_with_dropped_table
 7536-mclient-forgets-to-flush
 7541-levenshtein
+7542-column-name-resolution
diff --git a/sql/test/copy/Tests/All b/sql/test/copy/Tests/All
--- a/sql/test/copy/Tests/All
+++ b/sql/test/copy/Tests/All
@@ -17,3 +17,4 @@ columns
 no_escape
 no_escape2
 crlf_normalization
+select-from-file
diff --git a/sql/test/copy/Tests/aapnootmies.csv 
b/sql/test/copy/Tests/aapnootmies.csv
new file mode 100644
--- /dev/null
+++ b/sql/test/copy/Tests/aapnootmies.csv
@@ -0,0 +1,3 @@
+1|aap
+2|noot
+3|mies
diff --git a/sql/test/copy/Tests/select-from-file.test.in 
b/sql/test/copy/Tests/select-from-file.test.in
new file mode 100644
--- /dev/null
+++ b/sql/test/copy/Tests/select-from-file.test.in
@@ -0,0 +1,60 @@
+query IT rowsort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv';
+
+1
+aap
+2
+noot
+3
+mies
+
+statement ok
+DROP TABLE IF EXISTS foo;
+
+statement ok
+CREATE TABLE foo(i INT, t TEXT);
+
+statement ok
+INSERT INTO foo SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv';
+
+query IT rowsort
+SELECT * FROM foo;
+
+1
+aap
+2
+noot
+3
+mies
+
+query IT nosort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' ORDER BY name_1;
+
+1
+aap
+3
+mies
+2
+noot
+
+query IT nosort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' WHERE name_1 = 'aap';
+
+1
+aap
+
+query IT rowsort
+SELECT count(name_0), name_1 FROM R'$TSTSRCDIR/aapnootmies.csv' GROUP BY 
name_1;
+
+1
+aap
+1
+mies
+1
+noot
+
+query IT nosort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' a WHERE a.name_1 = 'aap';
+
+1
+aap
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Dec2023 - Fix broken test

2024-06-26 Thread Joeri van Ruth via checkin-list
Changeset: 0eb9a0f779bd for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0eb9a0f779bd
Modified Files:
sql/test/copy/Tests/select-from-file.test.in
Branch: Dec2023
Log Message:

Fix broken test


diffs (20 lines):

diff --git a/sql/test/copy/Tests/select-from-file.test.in 
b/sql/test/copy/Tests/select-from-file.test.in
--- a/sql/test/copy/Tests/select-from-file.test.in
+++ b/sql/test/copy/Tests/select-from-file.test.in
@@ -44,13 +44,13 @@ 1
 aap
 
 query IT rowsort
-SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' GROUP BY name_1;
+SELECT count(name_0), name_1 FROM R'$TSTSRCDIR/aapnootmies.csv' GROUP BY 
name_1;
 
 1
 aap
-3
+1
 mies
-2
+1
 noot
 
 query IT nosort
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Dec2023 - Add some tests for SELECT FROM file

2024-06-26 Thread Joeri van Ruth via checkin-list
Changeset: a66e4659af96 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/a66e4659af96
Added Files:
sql/test/copy/Tests/aapnootmies.csv
sql/test/copy/Tests/select-from-file.test.in
Modified Files:
sql/test/copy/Tests/All
Branch: Dec2023
Log Message:

Add some tests for SELECT FROM file


diffs (81 lines):

diff --git a/sql/test/copy/Tests/All b/sql/test/copy/Tests/All
--- a/sql/test/copy/Tests/All
+++ b/sql/test/copy/Tests/All
@@ -16,3 +16,4 @@ columns
 no_escape
 no_escape2
 crlf_normalization
+select-from-file
diff --git a/sql/test/copy/Tests/aapnootmies.csv 
b/sql/test/copy/Tests/aapnootmies.csv
new file mode 100644
--- /dev/null
+++ b/sql/test/copy/Tests/aapnootmies.csv
@@ -0,0 +1,3 @@
+1|aap
+2|noot
+3|mies
diff --git a/sql/test/copy/Tests/select-from-file.test.in 
b/sql/test/copy/Tests/select-from-file.test.in
new file mode 100644
--- /dev/null
+++ b/sql/test/copy/Tests/select-from-file.test.in
@@ -0,0 +1,60 @@
+query IT rowsort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv';
+
+1
+aap
+2
+noot
+3
+mies
+
+statement ok
+DROP TABLE IF EXISTS foo;
+
+statement ok
+CREATE TABLE foo(i INT, t TEXT);
+
+statement ok
+INSERT INTO foo SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv';
+
+query IT rowsort
+SELECT * FROM foo;
+
+1
+aap
+2
+noot
+3
+mies
+
+query IT nosort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' ORDER BY name_1;
+
+1
+aap
+3
+mies
+2
+noot
+
+query IT nosort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' WHERE name_1 = 'aap';
+
+1
+aap
+
+query IT rowsort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' GROUP BY name_1;
+
+1
+aap
+3
+mies
+2
+noot
+
+query IT nosort
+SELECT * FROM R'$TSTSRCDIR/aapnootmies.csv' a WHERE a.name_1 = 'aap';
+
+1
+aap
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Dec2023 - Add test for #7542

2024-06-26 Thread Joeri van Ruth via checkin-list
Changeset: 20a2cc3713af for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/20a2cc3713af
Added Files:
sql/test/BugTracker-2024/Tests/7542-column-name-resolution.test
Modified Files:
sql/test/BugTracker-2024/Tests/All
Branch: Dec2023
Log Message:

Add test for #7542


diffs (26 lines):

diff --git a/sql/test/BugTracker-2024/Tests/7542-column-name-resolution.test 
b/sql/test/BugTracker-2024/Tests/7542-column-name-resolution.test
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2024/Tests/7542-column-name-resolution.test
@@ -0,0 +1,13 @@
+
+-- https://github.com/MonetDB/MonetDB/issues/7542
+
+query I nosort
+WITH "E" AS ( SELECT 2 AS "F" )
+  SELECT 3 AS "Z" FROM (
+SELECT "B"."X" FROM ( SELECT 2 AS "Y" FROM "E" ) AS "A" 
+LEFT OUTER JOIN ( SELECT 2 AS "X" ) AS "B" ON 1 = 1
+  ) AS "C"
+  ORDER BY "Z" DESC LIMIT 1
+
+3
+
diff --git a/sql/test/BugTracker-2024/Tests/All 
b/sql/test/BugTracker-2024/Tests/All
--- a/sql/test/BugTracker-2024/Tests/All
+++ b/sql/test/BugTracker-2024/Tests/All
@@ -59,3 +59,4 @@ 7528-jarowinkler-null
 7537-prepare_stmt_with_dropped_table
 7536-mclient-forgets-to-flush
 7541-levenshtein
+7542-column-name-resolution
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Remove duplicate test from All-file

2024-06-19 Thread Joeri van Ruth via checkin-list
Changeset: 2eebb9b68c36 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2eebb9b68c36
Modified Files:
sql/test/BugTracker-2024/Tests/All
Branch: Aug2024
Log Message:

Remove duplicate test from All-file


diffs (11 lines):

diff --git a/sql/test/BugTracker-2024/Tests/All 
b/sql/test/BugTracker-2024/Tests/All
--- a/sql/test/BugTracker-2024/Tests/All
+++ b/sql/test/BugTracker-2024/Tests/All
@@ -63,7 +63,6 @@ 7524-right-outer-join
 7528-jarowinkler-null
 7534-is-distinct-from
 7535-create-view-groupby-func
-7536-mclient-forgets-to-flush
 7538-reduce-cast
 7539-is-distinct-from
 7537-prepare_stmt_with_dropped_table
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Add ChangeLog for ClientInfo

2024-06-19 Thread Joeri van Ruth via checkin-list
Changeset: c0d93ccdd32f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/c0d93ccdd32f
Modified Files:
clients/mapilib/ChangeLog.Aug2024
Branch: Aug2024
Log Message:

Add ChangeLog for ClientInfo


diffs (14 lines):

diff --git a/clients/mapilib/ChangeLog.Aug2024 
b/clients/mapilib/ChangeLog.Aug2024
--- a/clients/mapilib/ChangeLog.Aug2024
+++ b/clients/mapilib/ChangeLog.Aug2024
@@ -1,3 +1,10 @@
 # ChangeLog file for mapilib
 # This file is updated with Maddlog
 
+* Wed Jun 19 2024 Joeri van Ruth 
+- Add new columns to sys.sessions. Column 'language' is usually 'sql'.
+  Column 'peer' is the network address of the client (something like
+  '[::1]:46558' or ''). Columns 'hostname', 'application',
+  'client', 'clientpid' and 'remark' can be set by the client.
+  Libmapi/mclient, pymonetdb and monetdb-java have been modified to fill
+  in sensible default values.
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


monetdb-java: default - Add ClientInfo tests

2024-06-19 Thread Joeri van Ruth via checkin-list
Changeset: 4a5fb9ddee45 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/4a5fb9ddee45
Modified Files:
tests/JDBC_API_Tester.java
Branch: default
Log Message:

Add ClientInfo tests


diffs (163 lines):

diff --git a/tests/JDBC_API_Tester.java b/tests/JDBC_API_Tester.java
--- a/tests/JDBC_API_Tester.java
+++ b/tests/JDBC_API_Tester.java
@@ -118,6 +118,8 @@ final public class JDBC_API_Tester {
jt.Test_SgeneratedKeys();
jt.Test_Smoreresults();
jt.Test_Wrapper();
+   if (jt.isPostDec2023)
+   jt.Test_ClientInfo(con_URL);
jt.bogus_auto_generated_keys();
jt.BugConcurrent_clients_SF_1504657(con_URL);
jt.BugConcurrent_sequences(con_URL);
@@ -1480,10 +1482,12 @@ final public class JDBC_API_Tester {
"TABLE_CAT  TABLE_SCHEM TABLE_NAME  
COLUMN_NAME GRANTOR GRANTEE PRIVILEGE   IS_GRANTABLE\n" +
"char(1)varchar(1024)   varchar(1024)   
varchar(1024)   varchar(1024)   varchar(1024)   varchar(40) varchar(3)\n");
 
-   compareResultSet(dbmd.getClientInfoProperties(), 
"getClientInfoProperties()",
-   "Resultset with 4 columns\n" +
-   "NAME   MAX_LEN DEFAULT_VALUE   DESCRIPTION\n" +
-   "varchar(64)int varchar(128)
varchar(128)\n");
+   if (!isPostDec2023) {
+   
compareResultSet(dbmd.getClientInfoProperties(), "getClientInfoProperties()",
+   "Resultset with 4 columns\n" +
+   "NAME   MAX_LEN DEFAULT_VALUE   DESCRIPTION\n" +
+   "varchar(64)int varchar(128)
varchar(128)\n");
+   }
 
compareResultSet(dbmd.getSuperTables(null, "jdbctst", 
"pk_uc"), "getSuperTables(null, jdbctst, pk_uc)",
"Resultset with 4 columns\n" +
@@ -7135,6 +7139,133 @@ final public class JDBC_API_Tester {
"\n");
}
 
+   private void Test_ClientInfo(String con_URL) {
+   if (!isPostDec2023)
+   return;
+
+   sb.setLength(0);
+
+   final String[] known = {
+   "ApplicationName", "ClientHostname", 
"ClientLibrary",  "ClientPid", "ClientRemark"
+   };
+
+   try {
+   sb.append("Connecting\n");
+   try (Connection conn = 
DriverManager.getConnection(con_URL)) {
+
+   // Server metadata includes list of supported 
clientinfo properties
+   sb.append("Fetching supported clientinfo 
properties\n");
+   DatabaseMetaData md = conn.getMetaData();
+   try (ResultSet rs = 
md.getClientInfoProperties()) {
+   HashSet seen = new HashSet<>();
+   while (rs.next()) {
+   String name = rs.getString(1);
+   if (name == null || 
name.isEmpty()) {
+   sb.append("NAME column 
contains empty string\n");
+   }
+   seen.add(name);
+   int width = rs.getInt(2);
+   if (width <= 0) {
+   sb.append("MAX_LEN for 
" + name + " is " + width + "\n");
+   }
+   String description = 
rs.getString(4);
+   if (description == null || 
description.isEmpty()) {
+   sb.append("DESCRIPTION 
for " + name + " is empty\n");
+   }
+   }
+   for (String name: known) {
+   boolean found = 
seen.contains(name);
+   sb.append("- " + name + (found 
? " was " : " was not ") + "found\n");
+   }
+   }
+
+   // I cannot think of a way to check the default 
values that doesn't
+   // essentially duplicate the code that came up 
with the default values.
+   // The best we can do is verify they're not 
empty.
+   sb.append("Check initial values.\n");
+   Properties initi

monetdb-java: default - Implement DatabaseMetaData.getClientInfo...

2024-06-19 Thread Joeri van Ruth via checkin-list
Changeset: cc6425e98017 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/cc6425e98017
Modified Files:
src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java
src/main/java/org/monetdb/mcl/net/ClientInfo.java
Branch: default
Log Message:

Implement DatabaseMetaData.getClientInfoProperties


diffs (76 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java 
b/src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java
--- a/src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java
+++ b/src/main/java/org/monetdb/jdbc/MonetDatabaseMetaData.java
@@ -12,6 +12,8 @@
 
 package org.monetdb.jdbc;
 
+import org.monetdb.mcl.net.ClientInfo;
+
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.Statement;
@@ -3917,17 +3919,36 @@ public final class MonetDatabaseMetaData
 */
@Override
public ResultSet getClientInfoProperties() throws SQLException {
-   // MonetDB currently does not support any client properties, so 
return an empty ResultSet
+   // This query combines the properties we know about with any 
additional properties that
+   // may have been added to sys.clientinfo_properties in the mean 
time.
final String query =
-   "SELECT cast(null as varchar(64)) AS \"NAME\", " +
-   "cast(0 as int) AS \"MAX_LEN\", " +
-   "cast(null as varchar(128)) AS \"DEFAULT_VALUE\", " +
-   "cast(null as varchar(128)) AS \"DESCRIPTION\" " +
-   "WHERE 1=0";
+   "WITH jdbc_info AS (\n" +
+   "SELECT 'ApplicationName' AS \"NAME\", NULL 
AS \"MAX_LEN\", " + stringEscape(ClientInfo.defaultApplicationName) + " AS 
\"DEFAULT_VALUE\", 'Name of the application' AS \"DESCRIPTION\", 0 AS i\n" +
+   "UNION ALL\n" +
+   "SELECT 'ClientHostname' AS \"NAME\", NULL 
AS \"MAX_LEN\", " + stringEscape(ClientInfo.defaultHostname) + " AS 
\"DEFAULT_VALUE\", 'Host the application is running on' AS \"DESCRIPTION\", 1 
AS i\n" +
+   "UNION ALL\n" +
+   "SELECT 'ClientRemark' AS \"NAME\", 256 AS 
\"MAX_LEN\", R'' AS \"DEFAULT_VALUE\", 'Additional information' AS 
\"DESCRIPTION\", 2 AS i\n" +
+   "UNION ALL\n" +
+   "SELECT 'ClientLibrary' AS \"NAME\", NULL 
AS \"MAX_LEN\", " + stringEscape(ClientInfo.defaultClientLibrary) + " AS 
\"DEFAULT_VALUE\", 'Name and version of the driver' AS \"DESCRIPTION\", 3 AS 
i\n" +
+   "UNION ALL\n" +
+   "SELECT 'ClientPid' AS \"NAME\", 10 AS 
\"MAX_LEN\", " + stringEscape(ClientInfo.defaultPid) + " AS \"DEFAULT_VALUE\", 
'Process id of the application' AS \"DESCRIPTION\", 4 AS i\n" +
+   ")\n" +
+   "SELECT\n" +
+   "prop AS \"NAME\",\n" +
+   "COALESCE(\"MAX_LEN\", 24) AS 
\"MAX_LEN\",\n" +
+   "\"DEFAULT_VALUE\",\n" +
+   "\"DESCRIPTION\"\n" +
+   "FROM sys.clientinfo_properties AS sys_info 
LEFT OUTER JOIN jdbc_info ON prop = \"NAME\"\n" +
+   "ORDER BY COALESCE(i, 1000), \"NAME\"\n"
+   ;
 
return executeMetaDataQuery(query);
}
 
+   private static String stringEscape(String s) {
+   return "R'" + s.replaceAll("'", "''") + "'";
+   }
+
/**
 * Retrieves a description of the system and user functions
 * available in the given catalog.
diff --git a/src/main/java/org/monetdb/mcl/net/ClientInfo.java 
b/src/main/java/org/monetdb/mcl/net/ClientInfo.java
--- a/src/main/java/org/monetdb/mcl/net/ClientInfo.java
+++ b/src/main/java/org/monetdb/mcl/net/ClientInfo.java
@@ -21,13 +21,13 @@ import java.util.Set;
  * @{link SQLClientInfoException} if there is a failure
  */
 public class ClientInfo {
-   private static final String defaultHostname = findHostname();
+   public static final String defaultHostname = findHostname();
 
-   private static final String defaultClientLibrary = findClientLibrary();
+   public static final String defaultClientLibrary = findClientLibrary();
 
-   private static final String defaultApplicationName = 
findApplicationName();
+   public static final String defaultApplicationName = 
findApplicationName();
 
-   private static final String defaultPid = findPid();
+   public static final String defaultPid = findPid();
 
private final Properties props;
private HashMap problems = null;
___
checkin-list mailing list -- checkin-list@m

monetdb-java: default - Minor changes to JDBC_API_Tester

2024-06-19 Thread Joeri van Ruth via checkin-list
Changeset: 9c9a6c0a85f6 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/9c9a6c0a85f6
Modified Files:
tests/JDBC_API_Tester.java
Branch: default
Log Message:

Minor changes to JDBC_API_Tester


diffs (96 lines):

diff --git a/tests/JDBC_API_Tester.java b/tests/JDBC_API_Tester.java
--- a/tests/JDBC_API_Tester.java
+++ b/tests/JDBC_API_Tester.java
@@ -42,9 +42,9 @@ import org.monetdb.jdbc.types.URL;
 final public class JDBC_API_Tester {
private StringBuilder sb;   // buffer to collect the test output
private Connection con; // main connection shared by all tests
-   private int dbmsMajorVersion;
-   private int dbmsMinorVersion;
-   private boolean isPostDec2023;  // flag to support version specific 
output
+   final private int dbmsMajorVersion;
+   final private int dbmsMinorVersion;
+   final private boolean isPostDec2023;// flag to support version 
specific output
private boolean foundDifferences = false;
 
final private static int sbInitLen = 5468;
@@ -52,8 +52,16 @@ final public class JDBC_API_Tester {
/**
 * constructor
 */
-   JDBC_API_Tester() {
+   JDBC_API_Tester(Connection con_) throws SQLException {
+   this.con = con_;
sb = new StringBuilder(sbInitLen);
+
+   DatabaseMetaData dbmd = con_.getMetaData();
+   dbmsMajorVersion = dbmd.getDatabaseMajorVersion();
+   dbmsMinorVersion = dbmd.getDatabaseMinorVersion();
+   // from version 11.50 on, the MonetDB server returns different 
metadata for
+   // integer digits (1 less) and for clob and char columns (now 
return varchar).
+   isPostDec2023 = versionIsAtLeast(11, 50);
}
 
/**
@@ -67,15 +75,9 @@ final public class JDBC_API_Tester {
// Test this before trying to connect
UrlTester.runAllTests();
 
-   JDBC_API_Tester jt = new JDBC_API_Tester();
-   jt.con = DriverManager.getConnection(con_URL);
-   // we are now connected
-   DatabaseMetaData dbmd = jt.con.getMetaData();
-   jt.dbmsMajorVersion = dbmd.getDatabaseMajorVersion();
-   jt.dbmsMinorVersion = dbmd.getDatabaseMinorVersion();
-   // from version 11.50 the MonetDB server returns different 
metadata for
-   // integer digits (1 less) and for clob and char columns (now 
return varchar).
-   jt.isPostDec2023 = !(jt.dbmsMajorVersion == 11 && 
jt.dbmsMinorVersion <= 49);
+   Connection conn = DriverManager.getConnection(con_URL);
+   JDBC_API_Tester jt = new JDBC_API_Tester(conn);
+
 
// run the tests
jt.Test_Cautocommit(con_URL);
@@ -145,7 +147,7 @@ final public class JDBC_API_Tester {
ConnectionTests.runTests(con_URL);
 
// invoke running OnClientTester only on Oct2020 (11.39) or 
older servers
-   if (jt.dbmsMajorVersion == 11 && jt.dbmsMinorVersion <= 39) {
+   if (!jt.versionIsAtLeast(11,40)) {
OnClientTester oct = new OnClientTester(con_URL, 0);
int failures = oct.runTests();
if (failures > 0)
@@ -153,6 +155,10 @@ final public class JDBC_API_Tester {
}
}
 
+   private boolean versionIsAtLeast(int major, int minor) {
+   return (dbmsMajorVersion > major || (dbmsMajorVersion == major 
&& dbmsMinorVersion >= minor));
+   }
+
private void Test_Cautocommit(String arg0) {
sb.setLength(0);// clear the output log buffer
 
@@ -7242,16 +7248,18 @@ final public class JDBC_API_Tester {
prodLen = pos + 40;
System.err.println("Difference 
found at line " + line + " position " + rowpos
+ ". Expected:\n\"" + 
expected.substring(pos < expLen ? pos : expLen-1, expLen-1)
-   + "\"\nbut gotten:\n\"" 
+ produced.substring(pos < prodLen ? pos : prodLen-1, prodLen-1) + "\"");
+   + "\"\nFound:\n\"" + 
produced.substring(pos < prodLen ? pos : prodLen-1, prodLen-1) + "\"");
pos = max_pos;
}
}
}
System.err.println();
-   System.err.println("Expected:");
+   System.err.println(" Full Output: 
---");
+   System.err.println(sb);
+   System.err.println(" END 
--");
+   System.err.println(" Expe

monetdb-java: default - Older servers don't have clientinfo_prop...

2024-06-19 Thread Joeri van Ruth via checkin-list
Changeset: 8c8c423dc619 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/8c8c423dc619
Modified Files:
src/main/java/org/monetdb/jdbc/MonetConnection.java
Branch: default
Log Message:

Older servers don't have clientinfo_properties yet


diffs (22 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetConnection.java 
b/src/main/java/org/monetdb/jdbc/MonetConnection.java
--- a/src/main/java/org/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/org/monetdb/jdbc/MonetConnection.java
@@ -1348,11 +1348,13 @@ public class MonetConnection
private HashMap getClientInfoAttributeNames() throws 
SQLException {
if (clientInfoAttributeNames == null) {
HashMap map = new HashMap<>();
-   try (Statement st = createStatement(); ResultSet rs = 
st.executeQuery("SELECT prop, session_attr FROM sys.clientinfo_properties")) {
-   while (rs.next()) {
-   String jdbcName = rs.getString(1);
-   String attrName = rs.getString(2);
-   map.put(jdbcName, attrName);
+   if (server.canClientInfo()) {
+   try (Statement st = createStatement(); 
ResultSet rs = st.executeQuery("SELECT prop, session_attr FROM 
sys.clientinfo_properties")) {
+   while (rs.next()) {
+   String jdbcName = 
rs.getString(1);
+   String attrName = 
rs.getString(2);
+   map.put(jdbcName, attrName);
+   }
}
}
clientInfoAttributeNames = map;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


monetdb-java: default - Implement ClientInfo API

2024-06-19 Thread Joeri van Ruth via checkin-list
Changeset: a52bc2dcdb8c for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/a52bc2dcdb8c
Modified Files:
src/main/java/org/monetdb/jdbc/MonetConnection.java
src/main/java/org/monetdb/mcl/net/ClientInfo.java
src/main/java/org/monetdb/mcl/net/MapiSocket.java
src/main/java/org/monetdb/mcl/net/Target.java
Branch: default
Log Message:

Implement ClientInfo API

And move ClientInfo out out MapiSocket


diffs (truncated from 390 to 300 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetConnection.java 
b/src/main/java/org/monetdb/jdbc/MonetConnection.java
--- a/src/main/java/org/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/org/monetdb/jdbc/MonetConnection.java
@@ -21,6 +21,7 @@ import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
 import java.sql.SQLClientInfoException;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
@@ -35,6 +36,7 @@ import java.util.concurrent.Executor;
 import org.monetdb.mcl.io.BufferedMCLReader;
 import org.monetdb.mcl.io.BufferedMCLWriter;
 import org.monetdb.mcl.io.LineType;
+import org.monetdb.mcl.net.ClientInfo;
 import org.monetdb.mcl.net.MapiSocket;
 import org.monetdb.mcl.net.Target;
 import org.monetdb.mcl.parser.HeaderLineParser;
@@ -118,6 +120,11 @@ public class MonetConnection
/** A template to apply to each command (like pre and post fixes), 
filled in constructor */
private final String[] commandTempl = new String[2]; // pre, post
 
+   /** A mapping of ClientInfo property names such as 'ClientHostname' to 
columns of the
+* sessions table, such as 'hostname'.
+*/
+   private HashMap clientInfoAttributeNames = null;
+
/** the SQL language */
private static final int LANG_SQL = 0;
/** the MAL language (officially *NOT* supported) */
@@ -224,9 +231,16 @@ public class MonetConnection
throw sqle;
}
 
-   // send any clientinfo
-   if (server.hasClientInfo()) {
-   sendControlCommand("clientinfo " + 
server.getClientInfo().format());
+   if (server.canClientInfo() && target.sendClientInfo()) {
+   ClientInfo info = new ClientInfo();
+   info.setDefaults();
+   String clientApplication = 
target.getClientApplication();
+   String clientRemark = target.getClientRemark();
+   if (!clientApplication.isEmpty())
+   info.set("ApplicationName", clientApplication);
+   if (!clientRemark.isEmpty())
+   info.set("ClientRemark", clientRemark);
+   sendClientInfo(info);
}
 
// Now take care of any options not handled during the handshake
@@ -1270,8 +1284,16 @@ public class MonetConnection
 */
@Override
public String getClientInfo(final String name) throws SQLException {
-   // MonetDB doesn't support any Client Info Properties yet
-   return null;
+   String attrName = getClientInfoAttributeNames().get(name);
+   if (attrName == null)
+   return null;
+   String query = "SELECT " + attrName + " FROM sys.sessions WHERE 
sessionid = current_sessionid()";
+   try (Statement st = createStatement(); ResultSet rs = 
st.executeQuery(query)) {
+   if (rs.next())
+   return rs.getString(1);
+   else
+   return null;
+   }
}
 
/**
@@ -1289,7 +1311,53 @@ public class MonetConnection
@Override
public Properties getClientInfo() throws SQLException {
// MonetDB doesn't support any Client Info Properties yet
-   return new Properties();
+   Properties props = new Properties();
+
+   if (server.canClientInfo()) {
+   StringBuilder builder = new StringBuilder("SELECT ");
+   String sep = "";
+   for (Entry entry: 
getClientInfoAttributeNames().entrySet()) {
+   String jdbcName = entry.getKey();
+   String attrName = entry.getValue();
+   builder.append(sep);
+   sep = ", ";
+   builder.append(attrName);
+   builder.append(" AS \"");
+   builder.append(jdbcName);
+   builder.append("\"");
+   }
+   builder.append(" FROM sys.sessions WHERE sessionid = 
current_sessionid()");
+
+   try (
+ 

MonetDB: Aug2024 - Add column 'session_attr' to sys.clientinfo_p...

2024-06-18 Thread Joeri van Ruth via checkin-list
Changeset: bbc110e2e56a for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/bbc110e2e56a
Modified Files:
sql/backends/monet5/sql_upgrades.c
sql/scripts/22_clients.sql

sql/test/emptydb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.int128
sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out
sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.int128
sql/test/emptydb-previous-upgrade-hge/Tests/upgrade.stable.out.int128
sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out
sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out.int128
sql/test/emptydb-upgrade-chain-hge/Tests/upgrade.stable.out.int128
sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out
sql/test/emptydb-upgrade-chain/Tests/upgrade.stable.out.int128
sql/test/emptydb-upgrade-hge/Tests/upgrade.stable.out.int128
sql/test/emptydb-upgrade/Tests/upgrade.stable.out
sql/test/emptydb-upgrade/Tests/upgrade.stable.out.int128

sql/test/testdb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.int128
sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out
sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out.int128
sql/test/testdb-previous-upgrade-hge/Tests/upgrade.stable.out.int128
sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out
sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out.int128
sql/test/testdb-upgrade-chain-hge/Tests/upgrade.stable.out.int128
sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out
sql/test/testdb-upgrade-chain/Tests/upgrade.stable.out.int128
sql/test/testdb-upgrade-hge/Tests/upgrade.stable.out.int128
sql/test/testdb-upgrade/Tests/upgrade.stable.out
sql/test/testdb-upgrade/Tests/upgrade.stable.out.int128
Branch: Aug2024
Log Message:

Add column 'session_attr' to sys.clientinfo_properties

So clients can figure out the relationship between the JDBC-style
ClientInfo property names used in the MAPI protocol and the
corresponding columns of the sessions table.


diffs (truncated from 598 to 300 lines):

diff --git a/sql/backends/monet5/sql_upgrades.c 
b/sql/backends/monet5/sql_upgrades.c
--- a/sql/backends/monet5/sql_upgrades.c
+++ b/sql/backends/monet5/sql_upgrades.c
@@ -7101,13 +7101,13 @@ sql_update_aug2024(Client c, mvc *sql, s
"create procedure 
sys.setclientinfo(property string, value string)\n"
" external name 
clients.setinfo;\n"
"grant execute on procedure 
sys.setclientinfo(string, string) to public;\n"
-   "create table 
sys.clientinfo_properties(prop string);\n"
+   "create table 
sys.clientinfo_properties(prop string, session_attr string);\n"
"insert into 
sys.clientinfo_properties values\n"
-   " ('ClientHostname'),\n"
-   " ('ApplicationName'),\n"
-   " ('ClientLibrary'),\n"
-   " ('ClientRemark'),\n"
-   " ('ClientPid');\n"
+   " ('ClientHostname', 
'hostname'),\n"
+   " ('ApplicationName', 
'application'),\n"
+   " ('ClientLibrary', 
'client'),\n"
+   " ('ClientRemark', 'remark'),\n"
+   " ('ClientPid', 'clientpid');\n"
"update sys.functions set 
system = true where schema_id = 2000 and name in ('setclientinfo', 
'sessions');\n"
"update sys._tables set system 
= true where schema_id = 2000 and name in ('clientinfo_properties', 
'sessions');\n";
 
diff --git a/sql/scripts/22_clients.sql b/sql/scripts/22_clients.sql
--- a/sql/scripts/22_clients.sql
+++ b/sql/scripts/22_clients.sql
@@ -44,13 +44,13 @@ create view sys.sessions as select * fro
 create procedure sys.setclientinfo(property string, value string)
external name clients.setinfo;
 grant execute on procedure sys.setclientinfo(string, string) to public;
-create table sys.clientinfo_properties(prop string);
+create table sys.clientinfo_properties(prop string, session_attr string);
 insert into sys.clientinfo_properties values
-   ('ClientHostname'),
-   ('ApplicationName'),
-   ('ClientLibrary'),
-   ('ClientRemark'),
-   ('ClientPid');
+   ('ClientHostname', 'hostname'),
+   ('ApplicationName', 'application'),
+   ('ClientLibrary', 'client'),
+ 

MonetDB: Aug2024 - Write 'ClientHostname', not 'ClientHostName'

2024-06-18 Thread Joeri van Ruth via checkin-list
Changeset: e0abc7044ed5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e0abc7044ed5
Modified Files:
clients/mapilib/connect.c
Branch: Aug2024
Log Message:

Write 'ClientHostname', not 'ClientHostName'


diffs (12 lines):

diff --git a/clients/mapilib/connect.c b/clients/mapilib/connect.c
--- a/clients/mapilib/connect.c
+++ b/clients/mapilib/connect.c
@@ -429,7 +429,7 @@ send_all_clientinfo(Mapi mid)
size_t pos = 0, cap = 200;
 
if (hostname[0])
-   reallocprintf(&buf, &pos, &cap, "ClientHostName=%s\n", 
hostname);
+   reallocprintf(&buf, &pos, &cap, "ClientHostname=%s\n", 
hostname);
if (application_name[0])
reallocprintf(&buf, &pos, &cap, "ApplicationName=%s\n", 
application_name);
reallocprintf(&buf, &pos, &cap, "ClientLibrary=");
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Dec2023 - mclient: close redirected output stream befor...

2024-06-18 Thread Joeri van Ruth via checkin-list
Changeset: ed39e0bf9e67 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ed39e0bf9e67
Added Files:
sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
Modified Files:
clients/mapiclient/mclient.c
sql/test/BugTracker-2024/Tests/All
Branch: Dec2023
Log Message:

mclient: close redirected output stream before exiting

Fixes #7536


diffs (56 lines):

diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -3763,6 +3763,8 @@ main(int argc, char **argv)
}
 
mapi_destroy(mid);
+   if (toConsole != stdout_stream && toConsole != stderr_stream)
+   close_stream(toConsole);
mnstr_destroy(stdout_stream);
mnstr_destroy(stderr_stream);
if (priv.buf != NULL)
diff --git 
a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py 
b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
@@ -0,0 +1,31 @@
+import gzip
+import os
+import tempfile
+import subprocess
+
+
+# This SQL script redirects the output to a file (the %s).
+# We will check that all output arrives there, even if it's a gzipped file.
+SCRIPT = r"""
+\>%s
+SELECT 'Donald Knuth';
+"""
+
+
+with tempfile.TemporaryDirectory('mtest') as dir:
+outputfile = os.path.join(dir, 'output.txt.gz')
+inputfile = os.path.join(dir, 'input.sql')
+
+with open(inputfile, 'w') as f:
+f.write(SCRIPT % outputfile)
+
+subprocess.check_call([
+'mclient', '-i',
+'-p', os.environ['MAPIPORT'],
+inputfile,
+])
+
+with gzip.open(outputfile, 'rt', encoding='utf-8') as f:
+content = f.read()
+
+assert 'Donald Knuth' in content
diff --git a/sql/test/BugTracker-2024/Tests/All 
b/sql/test/BugTracker-2024/Tests/All
--- a/sql/test/BugTracker-2024/Tests/All
+++ b/sql/test/BugTracker-2024/Tests/All
@@ -57,3 +57,4 @@ 7512-concurrent-globaltmp-instantiate-cr
 7513-uri-authority-parse-issue
 7528-jarowinkler-null
 7537-prepare_stmt_with_dropped_table
+7536-mclient-forgets-to-flush
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


monetdb-java: default - Try to use reasonable defaults for Clien...

2024-06-14 Thread Joeri van Ruth via checkin-list
Changeset: 2d880f90be2a for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/2d880f90be2a
Modified Files:
src/main/java/org/monetdb/mcl/net/ClientInfo.java
src/main/java/org/monetdb/mcl/net/MapiSocket.java
Branch: default
Log Message:

Try to use reasonable defaults for ClientInfo


diffs (97 lines):

diff --git a/src/main/java/org/monetdb/mcl/net/ClientInfo.java 
b/src/main/java/org/monetdb/mcl/net/ClientInfo.java
--- a/src/main/java/org/monetdb/mcl/net/ClientInfo.java
+++ b/src/main/java/org/monetdb/mcl/net/ClientInfo.java
@@ -2,6 +2,11 @@ package org.monetdb.mcl.net;
 
 import org.monetdb.jdbc.MonetDriver;
 
+import java.io.File;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.sql.ClientInfoStatus;
 import java.sql.SQLClientInfoException;
 import java.util.Collections;
@@ -13,7 +18,9 @@ public class ClientInfo {
 
private static final String defaultClientLibrary = findClientLibrary();
 
-   private static final int defaultPid = findPid();
+   private static final String defaultApplicationName = 
findApplicationName();
+
+   private static final String defaultPid = findPid();
 
private final Properties props;
 
@@ -21,17 +28,47 @@ public class ClientInfo {
props = new Properties();
props.setProperty("ClientHostname", defaultHostname);
props.setProperty("ClientLibrary", defaultClientLibrary);
-   props.setProperty("ClientPid", "" + defaultPid);
-   props.setProperty("ApplicationName", "");
+   props.setProperty("ClientPid", defaultPid);
+   props.setProperty("ApplicationName", defaultApplicationName);
props.setProperty("ClientRemark", "");
}
 
private static String findHostname() {
-   return "my host";
+   try {
+   return InetAddress.getLocalHost().getHostName();
+   } catch (UnknownHostException e) {
+   return "";
+   }
}
 
-   private static int findPid() {
-   return 42;
+   private static String findApplicationName() {
+   String appName = "";
+   try {
+   String prop = System.getProperty("sun.java.command");
+   if (prop != null) {
+   // we want only the command, and not the 
arguments
+   prop = prop.split("\\s", 2)[0];
+   // keep only the basename5
+   int idx = prop.lastIndexOf(File.separatorChar);
+   if (idx >= 0)
+   prop = prop.substring(idx + 1);
+   appName = prop;
+   }
+   } catch (SecurityException e) {
+   // ignore
+   }
+
+   return appName;
+   }
+
+   private static String findPid() {
+   try {
+   RuntimeMXBean mxbean = 
ManagementFactory.getRuntimeMXBean();
+   String pidAtHostname = mxbean.getName();
+   return pidAtHostname.split("@", 2)[0];
+   } catch (RuntimeException e) {
+   return "";
+   }
}
 
private static String findClientLibrary() {
diff --git a/src/main/java/org/monetdb/mcl/net/MapiSocket.java 
b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
--- a/src/main/java/org/monetdb/mcl/net/MapiSocket.java
+++ b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
@@ -502,8 +502,12 @@ public final class MapiSocket {
if (parts.length > 9 && target.isClientInfo()) {
clientInfo = new ClientInfo();
try {
-   clientInfo.set("ApplicationName", 
target.getClientApplication());
-   clientInfo.set("ClientRemark", 
target.getClientRemark());
+   String clientApplication = 
target.getClientApplication();
+   String clientRemark = target.getClientRemark();
+   if (!clientApplication.isEmpty())
+   clientInfo.set("ApplicationName", 
clientApplication);
+   if (!clientRemark.isEmpty())
+   clientInfo.set("ClientRemark", 
clientRemark);
} catch (SQLClientInfoException e) {
String keys = String.join(", ", 
e.getFailedProperties().keySet());
throw new MCLException("Could not set 
ClientInfo properties: " + keys, e);
___
checkin-list mailing list -- checkin-list@monet

monetdb-java: default - Send ClientInfo on startup

2024-06-14 Thread Joeri van Ruth via checkin-list
Changeset: 778959b2e0a4 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/778959b2e0a4
Added Files:
src/main/java/org/monetdb/mcl/net/ClientInfo.java
Modified Files:
src/main/java/org/monetdb/jdbc/MonetConnection.java
src/main/java/org/monetdb/mcl/net/MapiSocket.java
src/main/java/org/monetdb/mcl/net/Parameter.java
src/main/java/org/monetdb/mcl/net/Target.java
tests/javaspecific.md
Branch: default
Log Message:

Send ClientInfo on startup

Configurable through the client_info=bool, client_application=NAME,
client_remark=MESSAGE properties.


diffs (271 lines):

diff --git a/src/main/java/org/monetdb/jdbc/MonetConnection.java 
b/src/main/java/org/monetdb/jdbc/MonetConnection.java
--- a/src/main/java/org/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/org/monetdb/jdbc/MonetConnection.java
@@ -224,6 +224,11 @@ public class MonetConnection
throw sqle;
}
 
+   // send any clientinfo
+   if (server.hasClientInfo()) {
+   sendControlCommand("clientinfo " + 
server.getClientInfo().format());
+   }
+
// Now take care of any options not handled during the handshake
curReplySize = defaultFetchSize;
if (lang == LANG_SQL) {
diff --git a/src/main/java/org/monetdb/mcl/net/ClientInfo.java 
b/src/main/java/org/monetdb/mcl/net/ClientInfo.java
new file mode 100644
--- /dev/null
+++ b/src/main/java/org/monetdb/mcl/net/ClientInfo.java
@@ -0,0 +1,74 @@
+package org.monetdb.mcl.net;
+
+import org.monetdb.jdbc.MonetDriver;
+
+import java.sql.ClientInfoStatus;
+import java.sql.SQLClientInfoException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+
+public class ClientInfo {
+   private static final String defaultHostname = findHostname();
+
+   private static final String defaultClientLibrary = findClientLibrary();
+
+   private static final int defaultPid = findPid();
+
+   private final Properties props;
+
+   public ClientInfo() {
+   props = new Properties();
+   props.setProperty("ClientHostname", defaultHostname);
+   props.setProperty("ClientLibrary", defaultClientLibrary);
+   props.setProperty("ClientPid", "" + defaultPid);
+   props.setProperty("ApplicationName", "");
+   props.setProperty("ClientRemark", "");
+   }
+
+   private static String findHostname() {
+   return "my host";
+   }
+
+   private static int findPid() {
+   return 42;
+   }
+
+   private static String findClientLibrary() {
+   return "monetdb-java " + MonetDriver.getDriverVersion();
+   }
+
+   public String format() {
+   StringBuilder builder = new StringBuilder(200);
+   for (String name : props.stringPropertyNames()) {
+   String value = props.getProperty(name);
+   builder.append(name);
+   builder.append('=');
+   builder.append(value);
+   builder.append('\n');
+   }
+   return builder.toString();
+   }
+
+   public Properties get() {
+   Properties ret = new Properties();
+   ret.putAll(props);
+   return ret;
+   }
+
+   public boolean set(String name, String value) throws 
SQLClientInfoException {
+   if (value == null)
+   value = "";
+   if (value.contains("\n")) {
+   Map map = 
Collections.singletonMap(name, ClientInfoStatus.REASON_VALUE_INVALID);
+   throw new SQLClientInfoException(map);
+   }
+   if (props.containsKey(name)) {
+   props.setProperty(name, value);
+   return true;
+   } else {
+   return false;
+   }
+   }
+
+}
diff --git a/src/main/java/org/monetdb/mcl/net/MapiSocket.java 
b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
--- a/src/main/java/org/monetdb/mcl/net/MapiSocket.java
+++ b/src/main/java/org/monetdb/mcl/net/MapiSocket.java
@@ -25,6 +25,7 @@ import java.net.*;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.sql.SQLClientInfoException;
 import java.util.*;
 
 import javax.net.ssl.SSLException;
@@ -117,6 +118,7 @@ public final class MapiSocket {
private BufferedMCLWriter writer;
/** protocol version of the connection */
private int version;
+   private ClientInfo clientInfo;
 
/** Whether we should follow redirects.
 * Not sure why this needs to be separate
@@ -497,6 +499,17 @@ public final class MapiSocket {
String optionsPart = parts.length > 6 ? parts[6] : null;
 //

MonetDB: Aug2024 - Extend MAX_MEMORY to accept strings of the fo...

2024-06-14 Thread Joeri van Ruth via checkin-list
Changeset: 5d0aa8898992 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/5d0aa8898992
Modified Files:
clients/mapiclient/mhelp.c
sql/ChangeLog.Aug2024
sql/server/sql_parser.y
sql/test/Users/Tests/create_user_options.test
Branch: Aug2024
Log Message:

Extend MAX_MEMORY to accept strings of the form '10MiB', '10G', etc.


diffs (185 lines):

diff --git a/clients/mapiclient/mhelp.c b/clients/mapiclient/mhelp.c
--- a/clients/mapiclient/mhelp.c
+++ b/clients/mapiclient/mhelp.c
@@ -88,7 +88,7 @@ SQLhelp sqlhelp1[] = {
 "ALTER USER ident\n"
 "[WITH [ENCRYPTED | UNENCRYPTED] PASSWORD string]\n"
 "[SET SCHEMA ident] [SCHEMA PATH string] [DEFAULT ROLE ident]\n"
-"[MAX_MEMORY posbytes | NO MAX_MEMORY] [MAX_WORKERS poscount | NO 
MAX_WORKERS]",
+"[MAX_MEMORY posbytes | MAX_MEMORY sizestr | NO MAX_MEMORY] 
[MAX_WORKERS poscount | NO MAX_WORKERS]",
 "ident",
 "See also 
https://www.monetdb.org/documentation/user-guide/sql-manual/data-definition/privileges/"},
{"ANALYZE",
@@ -252,7 +252,7 @@ SQLhelp sqlhelp1[] = {
{"CREATE USER",
 "Create a new database user",
 "CREATE USER ident WITH [ENCRYPTED | UNENCRYPTED] PASSWORD string NAME 
string [SCHEMA ident] [SCHEMA PATH string]\n"
-"[MAX_MEMORY posbytes | NO MAX_MEMORY] [MAX_WORKERS poscount | NO 
MAX_WORKERS]\n"
+"[MAX_MEMORY posbytes | MAX_MEMORY sizestr | NO MAX_MEMORY] 
[MAX_WORKERS poscount | NO MAX_WORKERS]\n"
 "[OPTIMIZER string] [DEFAULT ROLE ident]",
 "ident",
 "See also 
https://www.monetdb.org/documentation/user-guide/sql-manual/data-definition/privileges/"},
diff --git a/sql/ChangeLog.Aug2024 b/sql/ChangeLog.Aug2024
--- a/sql/ChangeLog.Aug2024
+++ b/sql/ChangeLog.Aug2024
@@ -1,6 +1,10 @@
 # ChangeLog file for sql
 # This file is updated with Maddlog
 
+* Fri Jun 14 2024 Joeri van Ruth 
+- Extend CREATE USER MAX_MEMORY and ALTER USER MAX_MEMORY to accept
+  strings of the form '10MiB', '10G', etc.
+
 * Mon May 13 2024 Niels Nes 
 - Extended sys.generate_series() to generate dates. Added 2 new functions:
   sys.generate_series(first date, "limit" date, stepsize interval month) and
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -165,6 +165,27 @@ uescape_xform(char *restrict s, const ch
return s;
 }
 
+static lng
+size_unit(const char *suffix)
+{
+   if (suffix[0] == '\0')
+   return 1;
+   else if (strcasecmp("k", suffix) == 0)
+   return 1000L;
+   else if (strcasecmp("kib", suffix) == 0)
+   return 1024L;
+   else if (strcasecmp("m", suffix) == 0)
+   return 1000L * 1000L;
+   else if (strcasecmp("mib", suffix) == 0)
+   return 1024L * 1024L;
+   else if (strcasecmp("g", suffix) == 0)
+   return 1000L * 1000L * 1000L;
+   else if (strcasecmp("gib", suffix) == 0)
+   return 1024L * 1024L * 1024L;
+   else
+   return -1;
+}
+
 %}
 /* KNOWN NOT DONE OF sql'99
  *
@@ -1619,6 +1640,17 @@ opt_max_memory:
 /* empty */ { $$ = -1; }
  |  NO MAX_MEMORY   { $$ = 0; }
  |  MAX_MEMORY poslng   { $$ = $2; }
+ |  MAX_MEMORY string   {
+   char *end = NULL;
+   lng size = strtoll($2, &end, 10);
+   lng unit = size_unit(end);
+   if (unit < 0 || size < 0) {
+   $$ = -1;
+   yyerror(m, "Invalid size");
+   YYABORT;
+   }
+   $$ = size * unit;
+   }
  ;
 
 opt_max_workers:
diff --git a/sql/test/Users/Tests/create_user_options.test 
b/sql/test/Users/Tests/create_user_options.test
--- a/sql/test/Users/Tests/create_user_options.test
+++ b/sql/test/Users/Tests/create_user_options.test
@@ -259,3 +259,97 @@ query TTITIITI rowsort
 select name, fullname, default_schema > 2000, schema_path, max_memory, 
max_workers, optimizer, default_role > 2000 from sys.users where name like 
'test%' order by name
 
 
+
+statement ok
+create user testmaxmem10 with password 'foo' name 'testmaxmem' max_memory '10';
+
+statement ok
+create user testmaxmem10g with password 'foo' name 'testmaxmem' max_memory 
'10G';
+
+statement ok
+create user testmaxmem10g_lower with password 'foo' name 'testmaxmem' 
max_memory '10g';
+
+statement ok
+create user testmaxmem10gib with password 'foo' name 'testmaxmem' max_memory 
'10GiB';
+
+state

MonetDB: Aug2024 - Python 3.6 doesn't support subprocess.Popen(c...

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

Python 3.6 doesn't support subprocess.Popen(capture_output=)


diffs (14 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
@@ -22,7 +22,9 @@ class Execution:
 def __init__(self, *odbcconnect_args):
 cmd = self.cmd = ['odbcconnect', *odbcconnect_args]
 proc = self.proc = subprocess.run(
-cmd, capture_output=True, encoding='utf-8')
+cmd,
+stderr=subprocess.PIPE, stdout=subprocess.PIPE,
+encoding='utf-8')
 self.expected_exitcode = 0
 self.remaining = proc.stdout.splitlines()
 self.checks = []
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Remove fancy type signature

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: f66c54d25182 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f66c54d25182
Modified Files:
testing/tlstester.py
Branch: Aug2024
Log Message:

Remove fancy type signature

Old Python versions don't support it


diffs (12 lines):

diff --git a/testing/tlstester.py b/testing/tlstester.py
--- a/testing/tlstester.py
+++ b/testing/tlstester.py
@@ -542,7 +542,7 @@ class WebHandler(http.server.BaseHTTPReq
 self.end_headers()
 self.wfile.write(content)
 
-def log_request(self, code: int | str = "-", size: int | str = "-") -> 
None:
+def log_request(self, code = "-", size = "-"):
 # be silent
 pass
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Add list drivers and list dns's to odbcconnect

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: 230778a77ea1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/230778a77ea1
Modified Files:
clients/odbc/samples/odbcconnect.c
Branch: Aug2024
Log Message:

Add list drivers and list dns's to odbcconnect

Fix a small memory leak in the process


diffs (204 lines):

diff --git a/clients/odbc/samples/odbcconnect.c 
b/clients/odbc/samples/odbcconnect.c
--- a/clients/odbc/samples/odbcconnect.c
+++ b/clients/odbc/samples/odbcconnect.c
@@ -15,6 +15,8 @@
 
 #include 
 #endif
+
+#include 
 #include 
 #include 
 #include 
@@ -29,14 +31,22 @@ static const char *USAGE =
"-d  Target is DSN, call SQLConnect()\n"
"-c  Target is connection string, call 
SQLDriverConnect()\n"
"-b  Target is connection string, call 
SQLBrowseConnect()\n"
+   "-l  List registered drivers and data sources\n"
"-u USER\n"
"-p PASSWORD\n"
"-v  Be verbose\n"
"TARGET  Connection String or DSN\n";
 
-static int do_sqlconnect(SQLCHAR *target);
-static int do_sqldriverconnect(SQLCHAR *target);
-static int do_sqlbrowseconnect(SQLCHAR *target);
+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_listdrivers(void);
+static int do_listdsns(const char *prefix, SQLSMALLINT dir);
 
 static void ensure_ok(SQLSMALLINT type, SQLHANDLE handle, const char *message, 
SQLRETURN ret);
 
@@ -49,6 +59,7 @@ SQLHANDLE env = NULL;
 SQLHANDLE conn = NULL;
 
 SQLCHAR outbuf[4096];
+SQLCHAR attrbuf[4096];
 
 static void
 cleanup(void)
@@ -68,7 +79,7 @@ main(int argc, char **argv)
action = do_sqlconnect;
SQLCHAR **targets = calloc(argc, sizeof(argv[0]));
int ntargets = 0;
-   int ret = 0;
+   int ret;
 
for (int i = 1; i < argc; i++) {
char *arg = argv[i];
@@ -78,6 +89,8 @@ main(int argc, char **argv)
action = do_sqldriverconnect;
else if (strcmp(arg, "-b") == 0)
action = do_sqlbrowseconnect;
+   else if (strcmp(arg, "-l") == 0)
+   action = NULL;
else if (strcmp(arg, "-u") == 0 && i + 1 < argc)
user = (SQLCHAR*)argv[++i];
else if (strcmp(arg, "-p") == 0 && i + 1 < argc)
@@ -88,15 +101,11 @@ main(int argc, char **argv)
targets[ntargets++] = (SQLCHAR*)arg;
else {
fprintf(stderr, "\nERROR: invalid argument: %s\n%s", 
arg, USAGE);
-   return 1;
+   ret = 1;
+   goto end;
}
}
 
-   if (ntargets == 0) {
-   fprintf(stderr, "\nERROR: pass at least one target\n%s", USAGE);
-   return 1;
-   }
-
ensure_ok(
SQL_HANDLE_ENV, NULL, "allocate env handle",
SQLAllocHandle(SQL_HANDLE_ENV, NULL, &env));
@@ -105,20 +114,25 @@ main(int argc, char **argv)
SQL_HANDLE_ENV, env, "set odbc version",
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, 
(SQLPOINTER)SQL_OV_ODBC3, 0));
 
-   ensure_ok(
-   SQL_HANDLE_ENV, env, "allocate conn handle",
-   SQLAllocHandle(SQL_HANDLE_DBC, env, &conn));
-
-   for (int i = 0; i < ntargets; i++) {
-   SQLCHAR *t = targets[i];
-   if (verbose)
-   printf("\nTarget: %s\n", t);
-   outbuf[0] = '\0';
-   int ret = action(t);
-   if (ret)
-   break;
+   if (action) {
+   if (ntargets == 0) {
+   fprintf(stderr, "\nERROR: pass at least one 
target\n%s", USAGE);
+   ret = 1;
+   goto end;
+   }
+   ret = do_actions(action, ntargets, targets);
+   } else {
+   if (ntargets != 0) {
+   fprintf(stderr, "\nERROR: -l does not take 
arguments\n%s", USAGE);
+   ret = 1;
+   goto end;
+   }
+   ret = do_listdrivers();
+   ret |= do_listdsns("SYSTEM", SQL_FETCH_FIRST_SYSTEM);
+   ret |= do_listdsns("SYSTEM", SQL_FETCH_FIRST_USER);
}
 
+end:
free(targets);
cleanup();
 
@@ -174,6 +188,26 @@ ensure_ok(SQLSMALLINT type, SQLHANDLE ha
 
 
 static int
+do_actions(action_t action, int ntargets, SQLCHAR **targets)
+{
+   ensure_ok(
+   SQL_HANDLE_ENV, env, "allocate conn handle",
+   SQLAllocHandle(SQL_HANDLE_DBC, env, &conn));
+
+   for (int i = 0; i < ntargets; i++) {
+   SQLCHAR *t = targets[i];
+   if (verbose)
+

MonetDB: Aug2024 - Don't write certs to TSTTRGDIR, it may not ex...

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

Don't write certs to TSTTRGDIR, it may not exist yet


diffs (26 lines):

diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -3250,14 +3250,6 @@ def StartTlsTester(tsttrgdir):
 from MonetDBtesting import tlstester
 hostnames = ['localhost']
 certs = tlstester.Certs(hostnames)
-certsdir = os.path.join(tsttrgdir, "certs")
-try:
-os.mkdir(certsdir)
-except FileExistsError:
-pass
-for name, content in certs.all().items():
-with open(os.path.join(certsdir, name), "wb") as f:
-f.write(content)
 server = tlstester.TLSTester(
 certs = certs,
 listen_addr='localhost',
@@ -3267,7 +3259,6 @@ def StartTlsTester(tsttrgdir):
 server_thread = threading.Thread(target=server.serve_forever, daemon=True)
 server_thread.start()
 return server.get_port('base')
-
 ### StartTlsTester() #
 
 #
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Use Mtest's TLSTester to test JDBC TLS

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: e0c0dbd3e852 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e0c0dbd3e852
Added Files:
sql/jdbc/tests/Tests/TLSTester.py
Modified Files:
sql/jdbc/tests/Tests/All
Branch: Aug2024
Log Message:

Use Mtest's TLSTester to test JDBC TLS


diffs (32 lines):

diff --git a/sql/jdbc/tests/Tests/All b/sql/jdbc/tests/Tests/All
--- a/sql/jdbc/tests/Tests/All
+++ b/sql/jdbc/tests/Tests/All
@@ -1,4 +1,5 @@
 HAVE_JDBCTESTS?JDBC_API_Tester
+HAVE_JDBCTESTS?TLSTester
 HAVE_JDBCTESTS?OnClientTester
 HAVE_JDBCCLIENT_JAR?Test_JdbcClient
 # next test should be done AFTER all the other tests have completed
diff --git a/sql/jdbc/tests/Tests/TLSTester.py 
b/sql/jdbc/tests/Tests/TLSTester.py
new file mode 100644
--- /dev/null
+++ b/sql/jdbc/tests/Tests/TLSTester.py
@@ -0,0 +1,18 @@
+import os, sys
+from subprocess import run, PIPE, CalledProcessError
+
+PORT=os.environ['TST_TLSTESTERPORT']
+
+cmd = [
+'java', 'TLSTester',
+# '-v',
+f'localhost:{PORT}',
+'-a', 'localhost.localdomain'
+]
+try:
+p = run(cmd, stdout=PIPE, stderr=PIPE, check=True, encoding='utf-8')
+sys.stderr.write(p.stdout)
+sys.stderr.write(p.stderr)
+except CalledProcessError as e:
+raise SystemExit(e.stderr)
+
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Move tlstester to testing/ directory

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: d3c75b4b83c6 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d3c75b4b83c6
Added Files:
testing/tlstester.py
Removed Files:
clients/mapilib/Tests/tlstester.py
Modified Files:
clients/mapilib/Tests/tlssecurity.py
testing/CMakeLists.txt
Branch: Aug2024
Log Message:

Move tlstester to testing/ directory


diffs (27 lines):

diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -16,8 +16,7 @@ import subprocess
 import sys
 import threading
 
-sys.path.append(os.environ.get('TSTSRCDIR','.'))
-import tlstester
+from MonetDBtesting import tlstester
 
 level = logging.WARNING
 # if sys.platform == 'win32':
diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt
--- a/testing/CMakeLists.txt
+++ b/testing/CMakeLists.txt
@@ -147,6 +147,7 @@ if(PYTHON3_LIBDIR)
 malmapi.py
 helpers.py
 sqltest.py
+tlstester.py
 utils.py
 DESTINATION ${PYTHON3_LIBDIR}/MonetDBtesting
 COMPONENT pytesting)
diff --git a/clients/mapilib/Tests/tlstester.py b/testing/tlstester.py
rename from clients/mapilib/Tests/tlstester.py
rename to testing/tlstester.py
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Move TLSTesterClient from tlssecurity,py to t...

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: 61f71d59ed8d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/61f71d59ed8d
Modified Files:
clients/mapilib/Tests/tlssecurity.py
testing/tlstester.py
Branch: Aug2024
Log Message:

Move TLSTesterClient from tlssecurity,py to testing/tlstester.py

So we can use it from other tests as well


diffs (129 lines):

diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -14,9 +14,8 @@ import os
 import re
 import subprocess
 import sys
-import urllib.request
 
-from MonetDBtesting import tlstester
+from MonetDBtesting.tlstester import TLSTesterClient
 
 level = logging.WARNING
 # if sys.platform == 'win32':
@@ -32,50 +31,6 @@ assert os.path.isdir(tgtdir)
 scratchdir = os.path.join(tgtdir, "scratch")
 logging.debug(f"scratchdir={scratchdir}")
 
-class TLSTesterClient:
-"""Connect to TLSTester to figure out port numbers and download 
certificates"""
-def __init__(self, scratchdir, base_port=None, host='localhost'):
-if not base_port:
-base_port = os.environ['TST_TLSTESTERPORT']
-self.url = f'http://{host}:{base_port}/'
-self.scratch = scratchdir
-try:
-os.mkdir(scratchdir)
-except FileExistsError:
-pass
-self.filenames = dict()
-self.contents = dict()
-self.portmap = dict()
-for line in self.fetch('').splitlines():
-name, port = str(line, 'ascii').split(':', 1)
-self.portmap[name] = int(port)
-logging.debug(f'port {name} = {port}')
-
-def get_port(self, name):
-return self.portmap[name]
-
-def fetch(self, name):
-cached = self.contents.get(name)
-if cached is not None:
-return cached
-url = self.url + name
-logging.debug(f'fetch {url}')
-with urllib.request.urlopen(url) as response:
-content = response.read()
-self.contents[name] = content
-return content
-
-def download(self, name):
-cached = self.filenames.get(name)
-if cached:
-return cached
-content = self.fetch(name)
-path = os.path.join(self.scratch, name)
-with open(path, 'wb') as f:
-f.write(content)
-self.filenames[name] = path
-return path
-
 tlstester = TLSTesterClient(scratchdir)
 
 
diff --git a/testing/tlstester.py b/testing/tlstester.py
--- a/testing/tlstester.py
+++ b/testing/tlstester.py
@@ -27,6 +27,7 @@ import tempfile
 from threading import Thread
 import threading
 from typing import Any, Callable, Dict, List, Optional, Tuple, Union
+import urllib.request
 
 # Our TLS implementation never uses anything less than TLSv1.3.
 assert ssl.HAS_TLSv1_3
@@ -98,6 +99,52 @@ argparser.add_argument(
 )
 
 
+
+class TLSTesterClient:
+"""Connect to TLSTester to figure out port numbers and download 
certificates"""
+def __init__(self, scratchdir, base_port=None, host='localhost'):
+if not base_port:
+base_port = os.environ['TST_TLSTESTERPORT']
+self.url = f'http://{host}:{base_port}/'
+self.scratch = scratchdir
+try:
+os.mkdir(scratchdir)
+except FileExistsError:
+pass
+self.filenames = dict()
+self.contents = dict()
+self.portmap = dict()
+for line in self.fetch('').splitlines():
+name, port = str(line, 'ascii').split(':', 1)
+self.portmap[name] = int(port)
+logging.debug(f'port {name} = {port}')
+
+def get_port(self, name):
+return self.portmap[name]
+
+def fetch(self, name):
+cached = self.contents.get(name)
+if cached is not None:
+return cached
+url = self.url + name
+logging.debug(f'fetch {url}')
+with urllib.request.urlopen(url) as response:
+content = response.read()
+self.contents[name] = content
+return content
+
+def download(self, name):
+cached = self.filenames.get(name)
+if cached:
+return cached
+content = self.fetch(name)
+path = os.path.join(self.scratch, name)
+with open(path, 'wb') as f:
+f.write(content)
+self.filenames[name] = path
+return path
+
+
 class Certs:
 hostnames: str
 _files: Dict[str, bytes]
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Add test for SQLConnect/DriverConnect/BrowseC...

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: 0ad8b1cc201d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0ad8b1cc201d
Added Files:
sql/odbc/tests/Tests/ODBCconnect.py
Modified Files:
sql/odbc/tests/Tests/All
Branch: Aug2024
Log Message:

Add test for SQLConnect/DriverConnect/BrowseConnect

still incomplete


diffs (149 lines):

diff --git a/sql/odbc/tests/Tests/All b/sql/odbc/tests/Tests/All
--- a/sql/odbc/tests/Tests/All
+++ b/sql/odbc/tests/Tests/All
@@ -2,4 +2,5 @@ HAVE_ODBC?ODBCgetInfo
 HAVE_ODBC?ODBCmetadata
 HAVE_ODBC?ODBCStmtAttr
 HAVE_ODBC?ODBCtester
+HAVE_ODBC?ODBCconnect
 HAVE_PYODBC&!SANITIZER?pyodbc-test
diff --git a/sql/odbc/tests/Tests/ODBCconnect.py 
b/sql/odbc/tests/Tests/ODBCconnect.py
new file mode 100755
--- /dev/null
+++ b/sql/odbc/tests/Tests/ODBCconnect.py
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# Copyright 2024 MonetDB Foundation;
+# Copyright August 2008 - 2023 MonetDB B.V.;
+# Copyright 1997 - July 2008 CWI.
+
+
+# For each target, odbcconnect first prints a status line,
+# either 'OK' or 'Error FUNCNAME', followed by zero or more
+# sqlstate lines of the form '- STATE: MESSAGE'.
+
+import atexit
+import subprocess
+import sys
+
+
+class Execution:
+def __init__(self, *odbcconnect_args):
+cmd = self.cmd = ['odbcconnect', *odbcconnect_args]
+proc = self.proc = subprocess.run(
+cmd, capture_output=True, encoding='utf-8')
+self.expected_exitcode = 0
+self.remaining = proc.stdout.splitlines()
+self.checks = []
+
+def report(self):
+parts = [f'COMMAND: {self.cmd}',
+ f'EXIT CODE: {self.proc.returncode}', '']
+if self.proc.stdout:
+parts += [
+'--- stdout: ---',
+self.proc.stdout.rstrip(),
+'--- end ---',
+''
+]
+if self.proc.stderr:
+parts += [
+'--- stderr: ---',
+self.proc.stderr.rstrip(),
+'--- end ---',
+''
+]
+if self.checks:
+parts.append('--- test history: ---')
+for wanted, found in self.checks:
+parts.append(f'wanted {wanted!r}, found {found!r}')
+parts.append('--- end ---')
+if self.remaining:
+parts += [
+'--- remaining output: ---',
+*self.remaining,
+'--- end ---'
+]
+return '\n'.join(parts)
+
+def expect(self, pattern):
+line = self.next_line()
+self.checks.append((pattern, line))
+if pattern not in line:
+raise Exception(f'Wanted {pattern!r}, found {line!r}')
+
+def next_line(self):
+if not self.remaining:
+raise Exception(f"Unexpected end of output")
+line = self.remaining[0]
+del self.remaining[0]
+return line
+
+def expect_fail(self, exitcode=1):
+self.expected_exitcode = exitcode
+
+def end(self):
+if self.remaining:
+raise Exception(f'Unexpected output remaining: {self.remaining}')
+code = self.proc.returncode
+expected = self.expected_exitcode
+if code != expected:
+raise Exception(
+f'Process exited with code {code!r}, expected {expected!r}')
+
+
+ex = None
+
+
+@atexit.register
+def show_context():
+global ex
+if ex:
+# ex.end()
+print(file=sys.stderr)
+print(ex.report(), file=sys.stderr)
+
+
+dbname = 'MonetDB-Test'
+
+
+ex = Execution(dbname)
+ex.expect('OK')
+ex.end()
+
+ex = Execution(dbname + '-nonexistent')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('IM002:')  # IM002 not found
+ex.end()
+
+ex = Execution(dbname, '-p', 'wrongpassword')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('28000:')  # 28000 bad credentials
+ex.end()
+
+ex = Execution(dbname, '-u', 'wronguser')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('28000:')  # 28000 bad credentials
+ex.end()
+
+ex = Execution(dbname, '-p', '')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('28000:')  # 28000 bad credentials
+ex.end()
+
+ex = Execution(dbname, '-u', '')
+ex.expect_fail()
+ex.expect('Error')
+ex.expect('28000:')  # 28000 bad credentials
+ex.end()
+
+ex = None
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Add tests for client_{info,application,remark...

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: f17ab4c9405d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f17ab4c9405d
Modified Files:
sql/test/mapi/Tests/clientinfo-mclient.SQL.py
Branch: Aug2024
Log Message:

Add tests for client_{info,application,remark} properties


diffs (116 lines):

diff --git a/sql/test/mapi/Tests/clientinfo-mclient.SQL.py 
b/sql/test/mapi/Tests/clientinfo-mclient.SQL.py
--- a/sql/test/mapi/Tests/clientinfo-mclient.SQL.py
+++ b/sql/test/mapi/Tests/clientinfo-mclient.SQL.py
@@ -1,5 +1,6 @@
 import os
 import subprocess
+import urllib.parse
 
 TSTDB = os.environ['TSTDB']
 MAPIPORT = os.environ['MAPIPORT']
@@ -10,26 +11,27 @@ FROM sys.sessions
 WHERE sessionid = current_sessionid()
 """
 
-cmd = [
-'mclient',
-'-d', TSTDB,
-'-p', MAPIPORT,
-'-fexpanded',
-'-s', QUERY,
-]
-
-out = subprocess.check_output(cmd, encoding='latin1')
+def run_mclient(**extra_args):
+url = f'monetdb://localhost:{MAPIPORT}/{TSTDB}'
+if extra_args:
+url += '?' + urllib.parse.urlencode(extra_args)
+cmd = [ 'mclient', '-d', url, '-fexpanded', '-s', QUERY ]
+out = subprocess.check_output(cmd, encoding='latin1')
+fields = dict()
+for line in out.splitlines()[1:]:
+line = line.strip()
+if line:
+k, v = line.split('|', 1)
+k = k.strip()
+v = v.strip()
+fields[k] = v
+return fields
 
-# print(out)
 
-fields = dict()
-for line in out.splitlines()[1:]:
-line = line.strip()
-if line:
-k, v = line.split('|', 1)
-k = k.strip()
-v = v.strip()
-fields[k] = v
+###
+# By default, most fields get filled in
+
+fields = run_mclient()
 
 assert fields['language'] == 'sql',\
 f'Found {fields["language"]!r}'
@@ -52,3 +54,59 @@ assert fields['clientpid'] != 'null' and
 
 assert fields['remark'] == 'null',\
 f'Found {fields["remark"]!r}'
+
+
+###
+# client_info=off suppresses everything sent by the client.
+# Server still fills in language and peer
+
+fields = run_mclient(client_info='off')
+
+assert fields['language'] == 'sql',\
+f'Found {fields["language"]!r}'
+
+assert fields['peer'] == '' or ']:' in fields['peer'],\
+f'Found {fields["peer"]!r}'
+
+assert fields['hostname'] == 'null',\
+f'Found {fields["hostname"]!r}'
+
+# could be mclient-11.51.0, mclient.exe, or whatever
+assert fields['application'] == 'null',\
+f'Found {fields["application"]!r}'
+
+assert fields['client'] == 'null',\
+f'Found {fields["client"]!r}'
+
+assert fields['clientpid'] == 'null',\
+f'Found {fields["clientpid"]!r}'
+
+assert fields['remark'] == 'null',\
+f'Found {fields["remark"]!r}'
+
+###
+# We can override application and remark
+
+fields = run_mclient(client_application='app', client_remark='mark')
+
+# could be mclient-11.51.0, mclient.exe, or whatever
+assert fields['application'] == 'app',\
+f'Found {fields["application"]!r}'
+
+assert fields['remark'] == 'mark',\
+f'Found {fields["remark"]!r}'
+
+
+###
+# We can override application and remark, but client_info=off
+# suppresses that.
+
+fields = run_mclient(client_application='app', client_remark='mark', 
client_info='off')
+
+# could be mclient-11.51.0, mclient.exe, or whatever
+assert fields['application'] == 'null',\
+f'Found {fields["application"]!r}'
+
+assert fields['remark'] == 'null',\
+f'Found {fields["remark"]!r}'
+
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Use raw string to suppress Python warning

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: 750de1fa87e2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/750de1fa87e2
Modified Files:
sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
Branch: Aug2024
Log Message:

Use raw string to suppress Python warning


diffs (12 lines):

diff --git 
a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py 
b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
--- a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
+++ b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
@@ -6,7 +6,7 @@ import subprocess
 
 # This SQL script redirects the output to a file (the %s).
 # We will check that all output arrives there, even if it's a gzipped file.
-SCRIPT = """\
+SCRIPT = r"""
 \>%s
 SELECT 'Donald Knuth';
 """
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - odbc: Map InvalidCredentialsException to SQLS...

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

odbc: Map InvalidCredentialsException to SQLSTATE 28000


diffs (17 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
@@ -487,8 +487,12 @@ MNDBConnectSettings(ODBCDbc *dbc, const 
mapi_reconnect(mid);
}
if (mid == NULL || mapi_error(mid)) {
-   const char *error_state = "08001";
+   const char *error_state;
const char *error_explanation = mid ? mapi_error_str(mid) : 
NULL;
+   if (error_explanation && strncmp(error_explanation, 
"InvalidCredentialsException:", 28) == 0)
+   error_state = "28000";
+   else
+   error_state = "08001";
addDbcError(dbc, error_state, error_explanation, 0);
if (mid)
mapi_destroy(mid);
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Make odbcconnect flags more straightforward

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

Make odbcconnect flags more straightforward

-d for driver, -b for browse


diffs (29 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
@@ -28,14 +28,13 @@ static const char *USAGE =
"Usage:\n"
"odbcconnect [-d | -c | -b ] [-v] [-u USER] [-p PASSWORD] 
TARGET..\n"
"Options:\n"
-   "-d  Target is DSN, call SQLConnect()\n"
-   "-c  Target is connection string, call 
SQLDriverConnect()\n"
+   "-d  Target is connection string, call 
SQLDriverConnect()\n"
"-b  Target is connection string, call 
SQLBrowseConnect()\n"
"-l  List registered drivers and data sources\n"
"-u USER\n"
"-p PASSWORD\n"
"-v  Be verbose\n"
-   "TARGET  Connection String or DSN\n";
+   "TARGET  DSN or with -d and -b, Connection String\n";
 
 typedef int (action_t)(SQLCHAR *);
 
@@ -84,8 +83,6 @@ main(int argc, char **argv)
for (int i = 1; i < argc; i++) {
char *arg = argv[i];
if (strcmp(arg, "-d") == 0)
-   action = do_sqlconnect;
-   else if (strcmp(arg, "-c") == 0)
action = do_sqldriverconnect;
else if (strcmp(arg, "-b") == 0)
action = do_sqlbrowseconnect;
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - ODBCtester.SQL.sh does not need to create odb...

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: e88194ba7d08 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e88194ba7d08
Modified Files:
sql/odbc/tests/Tests/ODBCtester.SQL.sh
Branch: Aug2024
Log Message:

ODBCtester.SQL.sh does not need to create odbc.ini

Mtest takes care of that


diffs (23 lines):

diff --git a/sql/odbc/tests/Tests/ODBCtester.SQL.sh 
b/sql/odbc/tests/Tests/ODBCtester.SQL.sh
--- a/sql/odbc/tests/Tests/ODBCtester.SQL.sh
+++ b/sql/odbc/tests/Tests/ODBCtester.SQL.sh
@@ -1,19 +1,3 @@
 #!/bin/sh
 
-ODBCINI=$PWD/odbc.ini
-trap "rm $ODBCINI" 0 15
-cat > $ODBCINI <

MonetDB: Aug2024 - Run a dummy server if the cryptography module...

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

Run a dummy server if the cryptography module cannot be found


diffs (52 lines):

diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -35,6 +35,8 @@ import socket
 import struct
 import signal
 import fnmatch
+import http
+import http.server
 import glob
 import pymonetdb # check for pymonetdb early: it is essential for our work
 
@@ -3240,13 +3242,26 @@ def SetExecEnv(exe,port,verbose) :
 print(end='', flush=True)
 ### SetExecEnv(exe,port,procdebug) #
 
-def StartTlsTester(tsttrgdir):
+def DummyTlsTester():
+class DummyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
+def handle(self):
+self.requestline = ''
+self.request_version = ''
+self.command = ''
+self.send_error(http.HTTPStatus.INTERNAL_SERVER_ERROR, 
f"{sys.argv[0]} is not running TLSTestter because the 'cryptography' module is 
not present")
+server = http.server.HTTPServer(('localhost', 0), DummyHTTPRequestHandler)
+port = server.server_address[1]
+server_thread = threading.Thread(target=server.serve_forever, daemon=True)
+server_thread.start()
+return port
+### DummyTlsTester(exe,port,procdebug) #
+
+def StartTlsTester():
 try:
 import cryptography
 except:
-# continue without so we can at least run the other tests
-print("cryptography not found!", file=sys.stderr)
-return None
+# Start a dummy server that only returns errors.
+return DummyTlsTester()
 from MonetDBtesting import tlstester
 hostnames = ['localhost']
 certs = tlstester.Certs(hostnames)
@@ -3808,7 +3823,7 @@ def main(argv) :
 
 # start tlstester
 if not env.get('TST_TLSTESTERPORT'):
-tlstester_port = StartTlsTester(os.path.join(TSTTRGBASE, TSTPREF))
+tlstester_port = StartTlsTester()
 if tlstester_port:
 env['TST_TLSTESTERPORT'] = str(tlstester_port)
 if env.get('TST_TLSTESTERPORT'):
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Move odbcconnect from clients/odbc/samples to...

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: e8186ee84c8e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e8186ee84c8e
Added Files:
clients/odbc/tests/odbcconnect.c
Removed Files:
clients/odbc/samples/odbcconnect.c
Modified Files:
clients/odbc/samples/CMakeLists.txt
clients/odbc/tests/CMakeLists.txt
Branch: Aug2024
Log Message:

Move odbcconnect from clients/odbc/samples to clients/odbc/tests


diffs (63 lines):

diff --git a/clients/odbc/samples/CMakeLists.txt 
b/clients/odbc/samples/CMakeLists.txt
--- a/clients/odbc/samples/CMakeLists.txt
+++ b/clients/odbc/samples/CMakeLists.txt
@@ -26,17 +26,9 @@ target_link_libraries(arraytest
   PRIVATE
   ODBC::ODBC)
 
-add_executable(odbcconnect
-  odbcconnect.c)
-
-target_link_libraries(odbcconnect
-  PRIVATE
-  ODBC::ODBC)
-
 install(TARGETS
   odbcsample1
   arraytest
-  odbcconnect
   RUNTIME
   DESTINATION
   ${CMAKE_INSTALL_BINDIR}
@@ -46,7 +38,6 @@ if(WIN32)
   install(FILES
 $
 $
-$
 DESTINATION ${CMAKE_INSTALL_BINDIR}
 OPTIONAL)
 endif()
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
@@ -39,11 +39,19 @@ target_link_libraries(ODBCtester
   PRIVATE
   ODBC::ODBC)
 
+add_executable(odbcconnect
+  odbcconnect.c)
+
+target_link_libraries(odbcconnect
+  PRIVATE
+  ODBC::ODBC)
+
 install(TARGETS
   ODBCgetInfo
   ODBCStmtAttr
   ODBCmetadata
   ODBCtester
+  odbcconnect
   RUNTIME
   DESTINATION
   ${CMAKE_INSTALL_BINDIR}
@@ -55,6 +63,7 @@ if(WIN32)
 $
 $
 $
+$
 DESTINATION ${CMAKE_INSTALL_BINDIR}
 OPTIONAL)
 endif()
diff --git a/clients/odbc/samples/odbcconnect.c 
b/clients/odbc/tests/odbcconnect.c
rename from clients/odbc/samples/odbcconnect.c
rename to clients/odbc/tests/odbcconnect.c
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Incorporate TLSTester in Mtest.py

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: 9b8c0e6feeb5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9b8c0e6feeb5
Modified Files:
clients/mapilib/Tests/tlssecurity.py
testing/Mtest.py.in
testing/tlstester.py
Branch: Aug2024
Log Message:

Incorporate TLSTester in Mtest.py


diffs (196 lines):

diff --git a/clients/mapilib/Tests/tlssecurity.py 
b/clients/mapilib/Tests/tlssecurity.py
--- a/clients/mapilib/Tests/tlssecurity.py
+++ b/clients/mapilib/Tests/tlssecurity.py
@@ -14,7 +14,7 @@ import os
 import re
 import subprocess
 import sys
-import threading
+import urllib.request
 
 from MonetDBtesting import tlstester
 
@@ -26,45 +26,64 @@ if '-v' in sys.argv:
 #level = logging.DEBUG
 logging.basicConfig(level=level)
 
+# A tmpdir to write certificates to
 tgtdir = os.environ['TSTTRGDIR']
 assert os.path.isdir(tgtdir)
+scratchdir = os.path.join(tgtdir, "scratch")
+logging.debug(f"scratchdir={scratchdir}")
 
-hostnames = ['localhost']
-# Generate certificates and write them to the scratch dir
-# Write them to the scratch dir for inspection by the user.
-certs = tlstester.Certs(hostnames)
-certsdir = os.path.join(tgtdir, "certs")
-try:
-os.mkdir(certsdir)
-except FileExistsError:
-pass
-count = 0
-for name, content in certs.all().items():
-with open(os.path.join(certsdir, name), "wb") as a:
-a.write(content)
-count += 1
-logging.debug(f"Wrote {count} files to {certsdir}")
+class TLSTesterClient:
+"""Connect to TLSTester to figure out port numbers and download 
certificates"""
+def __init__(self, scratchdir, base_port=None, host='localhost'):
+if not base_port:
+base_port = os.environ['TST_TLSTESTERPORT']
+self.url = f'http://{host}:{base_port}/'
+self.scratch = scratchdir
+try:
+os.mkdir(scratchdir)
+except FileExistsError:
+pass
+self.filenames = dict()
+self.contents = dict()
+self.portmap = dict()
+for line in self.fetch('').splitlines():
+name, port = str(line, 'ascii').split(':', 1)
+self.portmap[name] = int(port)
+logging.debug(f'port {name} = {port}')
+
+def get_port(self, name):
+return self.portmap[name]
+
+def fetch(self, name):
+cached = self.contents.get(name)
+if cached is not None:
+return cached
+url = self.url + name
+logging.debug(f'fetch {url}')
+with urllib.request.urlopen(url) as response:
+content = response.read()
+self.contents[name] = content
+return content
+
+def download(self, name):
+cached = self.filenames.get(name)
+if cached:
+return cached
+content = self.fetch(name)
+path = os.path.join(self.scratch, name)
+with open(path, 'wb') as f:
+f.write(content)
+self.filenames[name] = path
+return path
+
+tlstester = TLSTesterClient(scratchdir)
+
 
 def certpath(name):
-return os.path.join(certsdir, name)
-def certbytes(name):
-filename = certpath(name)
-with open(filename, 'rb') as f:
-return f.read()
-
-# Start the worker threads
-
-server = tlstester.TLSTester(
-certs=certs,
-listen_addr='127.0.0.1',
-preassigned=dict(),
-sequential=False,
-hostnames=hostnames)
-server_thread = threading.Thread(target=server.serve_forever, daemon=True)
-server_thread.start()
+return tlstester.download(name)
 
 def attempt(experiment: str, portname: str, expected_error_regex: str, 
tls=True, host='localhost', **params):
-port = server.get_port(portname)
+port = tlstester.get_port(portname)
 scheme = 'monetdbs' if tls else 'monetdb'
 url = f"{scheme}://{host}:{port}/demo"
 if params:
@@ -196,7 +215,7 @@ attempt('connect_server_name', 'sni', No
 # Connect to port 'server1' over TLS, with certhash set to a prefix of the hash
 # of the server certificate in DER form. Have a succesful MAPI exchange.
 
-server1hash = sha256(certs.get_file('server1.der')).hexdigest()
+server1hash = sha256(tlstester.fetch('server1.der')).hexdigest()
 attempt('connect_right_hash', 'server1', None, certhash='sha256:' + 
server1hash[:6])
 
 # connect_wrong_hash
@@ -217,7 +236,7 @@ attempt('connect_wrong_hash', 'server1',
 # Connect to port 'server1' over TLS, with certhash set to a prefix of the hash
 # of the CA1 certificate in DER form. This should fail.
 
-ca1hash = sha256(certs.get_file('ca1.der')).hexdigest()
+ca1hash = sha256(tlstester.fetch('ca1.der')).hexdigest()
 attempt('connect_ca_hash', 'server1', "does not match certhash", 
certhash='sha256:' + ca1hash[:6])
 
 
diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -3240,6 +3240,36 @@ def SetExecEnv(exe,port,verbose) :
 print(end='', flush=True)
 ### SetExecEnv(exe,port,procdebug) #
 
+def StartTlsTester(tsttrgdir):
+try:
+import cryptography
+except:
+# co

MonetDB: Aug2024 - Add test for clientinfo

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: 42d6226ac18f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/42d6226ac18f
Added Files:
sql/test/mapi/Tests/clientinfo-mclient.SQL.py
Modified Files:
sql/test/mapi/Tests/All
Branch: Aug2024
Log Message:

Add test for clientinfo

It uses mclient so it doesn't require pymonetdb updates


diffs (67 lines):

diff --git a/sql/test/mapi/Tests/All b/sql/test/mapi/Tests/All
--- a/sql/test/mapi/Tests/All
+++ b/sql/test/mapi/Tests/All
@@ -9,3 +9,4 @@ HAVE_HGE?sql_int128
 HAVE_HGE?python3_int128
 HAVE_HGE?sql_dec38
 HAVE_HGE?python3_dec38
+clientinfo-mclient
diff --git a/sql/test/mapi/Tests/clientinfo-mclient.SQL.py 
b/sql/test/mapi/Tests/clientinfo-mclient.SQL.py
new file mode 100644
--- /dev/null
+++ b/sql/test/mapi/Tests/clientinfo-mclient.SQL.py
@@ -0,0 +1,54 @@
+import os
+import subprocess
+
+TSTDB = os.environ['TSTDB']
+MAPIPORT = os.environ['MAPIPORT']
+
+QUERY = """\
+SELECT *
+FROM sys.sessions
+WHERE sessionid = current_sessionid()
+"""
+
+cmd = [
+'mclient',
+'-d', TSTDB,
+'-p', MAPIPORT,
+'-fexpanded',
+'-s', QUERY,
+]
+
+out = subprocess.check_output(cmd, encoding='latin1')
+
+# print(out)
+
+fields = dict()
+for line in out.splitlines()[1:]:
+line = line.strip()
+if line:
+k, v = line.split('|', 1)
+k = k.strip()
+v = v.strip()
+fields[k] = v
+
+assert fields['language'] == 'sql',\
+f'Found {fields["language"]!r}'
+
+assert fields['peer'] == '' or ']:' in fields['peer'],\
+f'Found {fields["peer"]!r}'
+
+assert fields['hostname'] != 'null',\
+f'Found {fields["hostname"]!r}'
+
+# could be mclient-11.51.0, mclient.exe, or whatever
+assert fields['application'].startswith('mclient'),\
+f'Found {fields["application"]!r}'
+
+assert fields['client'].startswith('libmapi '),\
+f'Found {fields["client"]!r}'
+
+assert fields['clientpid'] != 'null' and int(fields['clientpid']) > 0,\
+f'Found {fields["clientpid"]!r}'
+
+assert fields['remark'] == 'null',\
+f'Found {fields["remark"]!r}'
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Simplify mclient flush test

2024-06-13 Thread Joeri van Ruth via checkin-list
Changeset: e55267399f84 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/e55267399f84
Modified Files:
sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
Branch: Aug2024
Log Message:

Simplify mclient flush test


diffs (34 lines):

diff --git 
a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py 
b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
--- a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
+++ b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
@@ -6,7 +6,7 @@ import subprocess
 
 # This SQL script redirects the output to a file (the %s).
 # We will check that all output arrives there, even if it's a gzipped file.
-SCRIPT = f"""\
+SCRIPT = """\
 \>%s
 SELECT 'Donald Knuth';
 """
@@ -19,16 +19,13 @@ with tempfile.TemporaryDirectory('mtest'
 with open(inputfile, 'w') as f:
 f.write(SCRIPT % outputfile)
 
-with open(inputfile) as f:
-subprocess.check_call([
-'mclient', '-i',
-inputfile,
-'-p', os.environ['MAPIPORT'],
-])
+subprocess.check_call([
+'mclient', '-i',
+'-p', os.environ['MAPIPORT'],
+inputfile,
+])
 
 with gzip.open(outputfile, 'rt', encoding='utf-8') as f:
 content = f.read()
 
-# print(content)
-
 assert 'Donald Knuth' in content
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - Remove debugging leftover

2024-06-12 Thread Joeri van Ruth via checkin-list
Changeset: bc602abd10b2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/bc602abd10b2
Modified Files:
sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
Branch: Aug2024
Log Message:

Remove debugging leftover


diffs (11 lines):

diff --git 
a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py 
b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
--- a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
+++ b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
@@ -13,7 +13,6 @@ SELECT 'Donald Knuth';
 
 
 with tempfile.TemporaryDirectory('mtest') as dir:
-dir = '/tmp/jvr'
 outputfile = os.path.join(dir, 'output.txt.gz')
 inputfile = os.path.join(dir, 'input.sql')
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: Aug2024 - mclient: close redirected output stream befor...

2024-06-12 Thread Joeri van Ruth via checkin-list
Changeset: 75970a2bc94e for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/75970a2bc94e
Added Files:
sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
Modified Files:
clients/mapiclient/mclient.c
sql/test/BugTracker-2024/Tests/All
Branch: Aug2024
Log Message:

mclient: close redirected output stream before exiting

Fixes #7536


diffs (60 lines):

diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -3879,6 +3879,8 @@ main(int argc, char **argv)
}
 
mapi_destroy(mid);
+   if (toConsole != stdout_stream && toConsole != stderr_stream)
+   close_stream(toConsole);
mnstr_destroy(stdout_stream);
mnstr_destroy(stderr_stream);
if (priv.buf != NULL)
diff --git 
a/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py 
b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
new file mode 100644
--- /dev/null
+++ b/sql/test/BugTracker-2024/Tests/7536-mclient-forgets-to-flush.SQL.py
@@ -0,0 +1,35 @@
+import gzip
+import os
+import tempfile
+import subprocess
+
+
+# This SQL script redirects the output to a file (the %s).
+# We will check that all output arrives there, even if it's a gzipped file.
+SCRIPT = f"""\
+\>%s
+SELECT 'Donald Knuth';
+"""
+
+
+with tempfile.TemporaryDirectory('mtest') as dir:
+dir = '/tmp/jvr'
+outputfile = os.path.join(dir, 'output.txt.gz')
+inputfile = os.path.join(dir, 'input.sql')
+
+with open(inputfile, 'w') as f:
+f.write(SCRIPT % outputfile)
+
+with open(inputfile) as f:
+subprocess.check_call([
+'mclient', '-i',
+inputfile,
+'-p', os.environ['MAPIPORT'],
+])
+
+with gzip.open(outputfile, 'rt', encoding='utf-8') as f:
+content = f.read()
+
+# print(content)
+
+assert 'Donald Knuth' in content
diff --git a/sql/test/BugTracker-2024/Tests/All 
b/sql/test/BugTracker-2024/Tests/All
--- a/sql/test/BugTracker-2024/Tests/All
+++ b/sql/test/BugTracker-2024/Tests/All
@@ -63,3 +63,4 @@ 7524-right-outer-join
 7528-jarowinkler-null
 7534-is-distinct-from
 7535-create-view-groupby-func
+7536-mclient-forgets-to-flush
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


monetdb-java: default - Add TLSTester.java to jdbctests.jar

2024-06-10 Thread Joeri van Ruth via checkin-list
Changeset: 65d42db0c831 for monetdb-java
URL: https://dev.monetdb.org/hg/monetdb-java/rev/65d42db0c831
Modified Files:
tests/build.xml
Branch: default
Log Message:

Add TLSTester.java to jdbctests.jar

So we can test it from Mtest, which now has TLSTester.py built in.


diffs (12 lines):

diff --git a/tests/build.xml b/tests/build.xml
--- a/tests/build.xml
+++ b/tests/build.xml
@@ -82,6 +82,8 @@ Copyright 1997 - July 2008 CWI.
 
 
 
+
+
   
   
 
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - More efficient implementation of text_pump_in()

2024-05-31 Thread Joeri van Ruth via checkin-list
Changeset: 064ab92cd39d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/064ab92cd39d
Modified Files:
common/stream/text_stream.c
Branch: default
Log Message:

More efficient implementation of text_pump_in()


diffs (105 lines):

diff --git a/common/stream/text_stream.c b/common/stream/text_stream.c
--- a/common/stream/text_stream.c
+++ b/common/stream/text_stream.c
@@ -89,42 +89,69 @@ take_byte(inner_state_t *ist)
 static pump_result
 text_pump_in(inner_state_t *ist, pump_action action)
 {
-   bool crlf_pending = ist->crlf_pending;
+   assert(ist->dst_win.count > 0);
+   assert(ist->src_win.count > 0 || action == PUMP_FINISH);
 
-   while (ist->src_win.count > 0 && ist->dst_win.count > 0) {
-   char c = take_byte(ist);
-   switch (c) {
-   case '\r':
-   if (crlf_pending) {
-   // put the previous one, which is 
clearly not followed by an \n
-   put_byte(ist, '\r');
-   }
-   crlf_pending = true;
-   continue;
-   case '\n':
-   put_byte(ist, c);
-   crlf_pending = false;
-   continue;
-   default:
-   if (crlf_pending) {
-   put_byte(ist, '\r');
-   crlf_pending = false;
-   // if dst_win.count was 1, there is no 
room for another put_byte().
-   if (ist->dst_win.count > 0) {
-   put_byte(ist, c);
-   } else {
-   // no room anymore for char c, 
put it back!
-   ist->src_win.start--;
-   ist->src_win.count++;
-   }
-   } else {
-   put_byte(ist, c);
-   }
-   continue;
+   if (ist->crlf_pending) {
+   if (ist->src_win.count > 0) {
+   if (ist->src_win.start[0] != '\n') {
+   // CR not followed by a LF, emit it
+   put_byte(ist, '\r');
+   }
+   } else {
+   assert(action == PUMP_FINISH);
+   // CR followed by end of file, not LF, so emit it
+   put_byte(ist, '\r');
}
+   // in any case, the CR is no longer pending
+   ist->crlf_pending = false;
}
 
-   ist->crlf_pending = crlf_pending;
+   while (1) {
+   size_t span = ist->src_win.count < ist->dst_win.count
+   ? ist->src_win.count
+   : ist->dst_win.count;
+   if (span == 0)
+   break;
+
+   if (ist->src_win.start[0] == '\r') {
+   // Looking at a CR. We'll handle just that, then make 
another round of the while loop
+   if (ist->src_win.count == 1) {
+   // Don't know what will follow, move it to the 
flag.
+   // Then stop, as all available input has been 
consumed
+   take_byte(ist);
+   ist->crlf_pending = true;
+   break;
+   }
+   assert(ist->src_win.count > 1); // We can safely look 
ahead
+   if (ist->src_win.start[1] == '\n') {
+   // Drop the CR, move the LF
+   take_byte(ist);
+   put_byte(ist, take_byte(ist));
+   } else {
+   // Move the CR
+   put_byte(ist, take_byte(ist));
+   }
+   // progress has been made, consider the situation anew
+   continue;
+   } else {
+   // The remaining input data does not start with a CR.
+   // Move all non-CR data to the output buffer
+   char *cr = memchr(ist->src_win.start, '\r', span);
+   if (cr != NULL) {
+   span = cr - ist->src_win.start;
+   }
+   assert(span > 0);
+   memcpy(ist->dst_win.start, ist->src_win.start, span);
+   ist->src_win.start += span;
+   ist->s

MonetDB: default - Use of text_pump_in_with_putback is supposed ...

2024-05-31 Thread Joeri van Ruth via checkin-list
Changeset: 9ff9f083b319 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9ff9f083b319
Modified Files:
common/stream/text_stream.c
Branch: default
Log Message:

Use of text_pump_in_with_putback is supposed to be temporary


diffs (49 lines):

diff --git a/common/stream/text_stream.c b/common/stream/text_stream.c
--- a/common/stream/text_stream.c
+++ b/common/stream/text_stream.c
@@ -30,6 +30,7 @@ struct inner_state {
pump_buffer src_win;
pump_buffer dst_win;
pump_buffer putback_win;
+   pump_state *outer_state;
char putback_buf[UTF8BOMLENGTH];
bool crlf_pending;
char buffer[BUFFER_SIZE];
@@ -150,16 +151,20 @@ text_pump_in(inner_state_t *ist, pump_ac
 static pump_result
 text_pump_in_with_putback(inner_state_t *ist, pump_action action)
 {
-   if (ist->putback_win.count > 0) {
-   pump_buffer tmp = ist->src_win;
-   ist->src_win = ist->putback_win;
-   pump_result ret = text_pump_in(ist, PUMP_NO_FLUSH);
-   ist->putback_win = ist->src_win;
-   ist->src_win = tmp;
-   if (ret == PUMP_ERROR)
-   return PUMP_ERROR;
+   if (ist->putback_win.count == 0) {
+   // no need for this function anymore
+   assert(ist->outer_state->worker == text_pump_in_with_putback);
+   ist->outer_state->worker = text_pump_in;
+   return text_pump_in(ist, action);
}
-   return text_pump_in(ist, action);
+
+   // first empty the putback buffer
+   pump_buffer tmp = ist->src_win;
+   ist->src_win = ist->putback_win;
+   pump_result ret = text_pump_in(ist, PUMP_NO_FLUSH);
+   ist->putback_win = ist->src_win;
+   ist->src_win = tmp;
+   return ret;
 }
 
 
@@ -295,6 +300,7 @@ create_text_stream(stream *inner)
state->finalizer = text_end;
state->get_error = get_error;
 
+   inner_state->outer_state = state;
inner_state->putback_win.start = inner_state->putback_buf;
inner_state->putback_win.count = 0;
if (inner->readonly) {
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - Mention 'ODBC' in ClientLibrary if connecting...

2024-05-30 Thread Joeri van Ruth via checkin-list
Changeset: 21bd5080c348 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/21bd5080c348
Modified Files:
clients/Tests/exports.stable.out
clients/mapilib/connect.c
clients/mapilib/mapi.c
clients/mapilib/mapi.h
clients/mapilib/mapi_intern.h
clients/odbc/driver/SQLConnect.c
Branch: default
Log Message:

Mention 'ODBC' in ClientLibrary if connecting through ODBC


diffs (96 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -721,6 +721,7 @@ MapiMsg mapi_set_columnar_protocol(Mapi 
 MapiMsg mapi_set_size_header(Mapi mid, bool value) 
__attribute__((__nonnull__(1)));
 MapiMsg mapi_set_time_zone(Mapi mid, int seconds_east_of_utc) 
__attribute__((__nonnull__(1)));
 MapiMsg mapi_set_timeout(Mapi mid, unsigned int timeout, bool (*callback)(void 
*), void *callback_data) __attribute__((__nonnull__(1)));
+void mapi_setclientprefix(Mapi mid, const char *prefix);
 void mapi_setfilecallback(Mapi mid, char *(*getfunc)(void *priv, const char 
*filename, bool binary, uint64_t offset, size_t *size), char *(*putfunc)(void 
*priv, const char *filename, const void *data, size_t size), void *priv) 
__attribute__((__nonnull__(1)));
 void mapi_setfilecallback2(Mapi mid, char *(*getfunc)(void *priv, const char 
*filename, bool binary, uint64_t offset, size_t *size), char *(*putfunc)(void 
*priv, const char *filename, bool binary, const void *data, size_t size), void 
*priv) __attribute__((__nonnull__(1)));
 Mapi mapi_settings(msettings *settings) __attribute__((__nonnull__(1)));
diff --git a/clients/mapilib/connect.c b/clients/mapilib/connect.c
--- a/clients/mapilib/connect.c
+++ b/clients/mapilib/connect.c
@@ -406,7 +406,6 @@ send_all_clientinfo(Mapi mid)
application_name = (const char*) 
basename((char*)application_name);
}
}
-   const char *client_library = "libmapi " MONETDB_VERSION;
const char *client_remark = msetting_string(mp, MP_CLIENT_REMARK);
long pid = getpid();
 
@@ -417,7 +416,10 @@ send_all_clientinfo(Mapi mid)
reallocprintf(&buf, &pos, &cap, "ClientHostName=%s\n", 
hostname);
if (application_name[0])
reallocprintf(&buf, &pos, &cap, "ApplicationName=%s\n", 
application_name);
-   reallocprintf(&buf, &pos, &cap, "ClientLibrary=%s\n", client_library);
+   reallocprintf(&buf, &pos, &cap, "ClientLibrary=");
+   if (mid->clientprefix)
+   reallocprintf(&buf, &pos, &cap, "%s / ", mid->clientprefix);
+   reallocprintf(&buf, &pos, &cap, "libmapi %s\n", MONETDB_VERSION);
if (client_remark[0])
reallocprintf(&buf, &pos, &cap, "ClientRemark=%s\n", 
client_remark);
if (pid > 0)
diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -2021,6 +2021,7 @@ mapi_destroy(Mapi mid)
free(mid->noexplain);
if (mid->errorstr && mid->errorstr != mapi_nomem)
free(mid->errorstr);
+   free(mid->clientprefix);
 
msettings_destroy(mid->settings);
 
@@ -2246,6 +2247,17 @@ mapi_setfilecallback(Mapi mid,
mid->filecontentprivate_old = filecontentprivate;
 }
 
+void
+mapi_setclientprefix(Mapi mid, const char *prefix)
+{
+   free(mid->clientprefix);
+   if (prefix == NULL)
+   mid->clientprefix = NULL;
+   else
+   mid->clientprefix = strdup(prefix);
+
+}
+
 #define testBinding(hdl,fnr)   \
do {\
mapi_hdl_check(hdl);\
diff --git a/clients/mapilib/mapi.h b/clients/mapilib/mapi.h
--- a/clients/mapilib/mapi.h
+++ b/clients/mapilib/mapi.h
@@ -105,6 +105,7 @@ mapi_export void mapi_setfilecallback(
 const void *data, size_t size),
void *priv)
__attribute__((__nonnull__(1)));
+mapi_export void mapi_setclientprefix(Mapi mid, const char *prefix);
 
 mapi_export MapiMsg mapi_error(Mapi mid)
__attribute__((__nonnull__(1)));
diff --git a/clients/mapilib/mapi_intern.h b/clients/mapilib/mapi_intern.h
--- a/clients/mapilib/mapi_intern.h
+++ b/clients/mapilib/mapi_intern.h
@@ -238,6 +238,7 @@ struct MapiStruct {
MapiMsg error;  /* Error occurred */
char *errorstr; /* error from server */
const char *action; /* pointer to constant string */
+   char *clientprefix; /* prefix for 'client' clientinfo; NULL or 
allocated string */
 
struct BlockCache blk;
bool connected;
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
@@ -481,6 +481,7 @@ MNDBConnectSettings(ODBCDbc *dbc, const 
Mapi mid = mapi_setting

MonetDB: default - Support clientinfo msettings from odbc

2024-05-30 Thread Joeri van Ruth via checkin-list
Changeset: f218fe31ac43 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f218fe31ac43
Modified Files:
clients/odbc/driver/ODBCAttrs.c
Branch: default
Log Message:

Support clientinfo msettings from odbc


diffs (13 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
@@ -47,6 +47,9 @@ const struct attr_setting attr_settings[
{ "LOGFILE", "Log File", MP_LOGFILE },
{ "LOGINTIMEOUT", "Login Timeout", MP_CONNECT_TIMEOUT},
{ "CONNECTIONTIMEOUT", "Connection Timeout", MP_REPLY_TIMEOUT},
+   { "CLIENTINFO", "Send Client Info", MP_CLIENT_INFO },
+   { "APPNAME", "Application Name", MP_CLIENT_APPLICATION },
+   { "CLIENTREMARK", "Client Remark", MP_CLIENT_REMARK },
 };
 
 const int attr_setting_count = sizeof(attr_settings) / 
sizeof(attr_settings[0]);
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


MonetDB: default - Replace mapi_set_application_name() with a ca...

2024-05-30 Thread Joeri van Ruth via checkin-list
Changeset: adafe325ac29 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/adafe325ac29
Modified Files:
clients/Tests/exports.stable.out
clients/mapiclient/mclient.c
clients/mapiclient/msqldump.c
clients/mapilib/connect.c
clients/mapilib/mapi.c
clients/mapilib/mapi.h
clients/mapilib/mapi_intern.h
tools/merovingian/daemon/snapshot.c
Branch: default
Log Message:

Replace mapi_set_application_name() with a call to get_bin_path()


diffs (134 lines):

diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -717,7 +717,6 @@ int64_t mapi_rows_affected(MapiHdl hdl) 
 MapiMsg mapi_seek_row(MapiHdl hdl, int64_t rowne, int whence) 
__attribute__((__nonnull__(1)));
 MapiHdl mapi_send(Mapi mid, const char *cmd) __attribute__((__nonnull__(1)));
 MapiMsg mapi_setAutocommit(Mapi mid, bool autocommit) 
__attribute__((__nonnull__(1)));
-void mapi_set_application_name(const char *name);
 MapiMsg mapi_set_columnar_protocol(Mapi mid, bool columnar_protocol) 
__attribute__((__nonnull__(1)));
 MapiMsg mapi_set_size_header(Mapi mid, bool value) 
__attribute__((__nonnull__(1)));
 MapiMsg mapi_set_time_zone(Mapi mid, int seconds_east_of_utc) 
__attribute__((__nonnull__(1)));
diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -3682,7 +3682,6 @@ main(int argc, char **argv)
} else {
mid = mapi_mapi(host, port, user, passwd, language, dbname);
}
-   mapi_set_application_name("mclient");
free(user_allocated);
user_allocated = NULL;
free(passwd_allocated);
diff --git a/clients/mapiclient/msqldump.c b/clients/mapiclient/msqldump.c
--- a/clients/mapiclient/msqldump.c
+++ b/clients/mapiclient/msqldump.c
@@ -237,7 +237,6 @@ main(int argc, char **argv)
} else {
mid = mapi_mapi(host, port, user, passwd, "sql", dbname);
}
-   mapi_set_application_name("msqldump");
free(user_allocated);
user_allocated = NULL;
free(passwd_allocated);
diff --git a/clients/mapilib/connect.c b/clients/mapilib/connect.c
--- a/clients/mapilib/connect.c
+++ b/clients/mapilib/connect.c
@@ -385,6 +385,7 @@ static void
 send_all_clientinfo(Mapi mid)
 {
msettings *mp = mid->settings;
+   void *free_this = NULL;
if (!mid->clientinfo_supported)
return;
if (!msetting_bool(mp, MP_CLIENT_INFO))
@@ -398,8 +399,13 @@ send_all_clientinfo(Mapi mid)
hostname[sizeof(hostname) - 1] = '\0';
}
const char *application_name = msetting_string(mp, 
MP_CLIENT_APPLICATION);
-   if (!application_name[0])
-   application_name = mapi_application_name;
+   if (!application_name[0]) {
+   application_name = get_bin_path();
+   if (application_name) {
+   free_this = strdup(application_name);
+   application_name = (const char*) 
basename((char*)application_name);
+   }
+   }
const char *client_library = "libmapi " MONETDB_VERSION;
const char *client_remark = msetting_string(mp, MP_CLIENT_REMARK);
long pid = getpid();
@@ -425,7 +431,9 @@ send_all_clientinfo(Mapi mid)
 
if (pos <= cap)
mapi_Xcommand(mid, "clientinfo", buf);
+
free(buf);
+   free(free_this);
 }
 
 static MapiMsg
diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -794,8 +794,6 @@ static void mapi_store_bind(struct MapiR
 
 static ATOMIC_FLAG mapi_initialized = ATOMIC_FLAG_INIT;
 
-char mapi_application_name[256] = { 0 };
-
 /*
  * Blocking
  * 
@@ -2121,15 +2119,6 @@ mapi_disconnect(Mapi mid)
return MOK;
 }
 
-void
-mapi_set_application_name(const char *name)
-{
-   if (name)
-   strncpy(mapi_application_name, name, 
sizeof(mapi_application_name)-1);
-   else
-   mapi_application_name[0] = '\0';
-}
-
 /* Set callback function to retrieve or send file content for COPY
  * INTO queries.
  *
diff --git a/clients/mapilib/mapi.h b/clients/mapilib/mapi.h
--- a/clients/mapilib/mapi.h
+++ b/clients/mapilib/mapi.h
@@ -76,9 +76,6 @@ extern "C" {
 # endif
 #endif
 
-/* global state */
-mapi_export void mapi_set_application_name(const char *name);
-
 /* connection-oriented functions */
 mapi_export Mapi mapi_mapi(const char *host, int port, const char *username, 
const char *password, const char *lang, const char *dbname);
 mapi_export Mapi mapi_mapiuri(const char *url, const char *user, const char 
*pass, const char *lang);
diff --git a/clients/mapilib/mapi_intern.h b/clients/mapilib/mapi_intern.h
--- a/clients/mapilib/mapi_intern.h
+++ b/clients/mapilib/mapi_intern.h
@@ -310,8 +310,6 @@ MapiMsg mapi_Xcommand(Mapi

MonetDB: clientinfo - Add mapi_set_application_name and call it ...

2024-05-29 Thread Joeri van Ruth via checkin-list
Changeset: 7d6f6753c8f3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7d6f6753c8f3
Modified Files:
clients/mapiclient/mclient.c
clients/mapiclient/msqldump.c
clients/mapilib/connect.c
clients/mapilib/mapi.c
clients/mapilib/mapi.h
clients/mapilib/mapi_intern.h
tools/merovingian/daemon/snapshot.c
Branch: clientinfo
Log Message:

Add mapi_set_application_name and call it in mclient etc.


diffs (99 lines):

diff --git a/clients/mapiclient/mclient.c b/clients/mapiclient/mclient.c
--- a/clients/mapiclient/mclient.c
+++ b/clients/mapiclient/mclient.c
@@ -3682,6 +3682,7 @@ main(int argc, char **argv)
} else {
mid = mapi_mapi(host, port, user, passwd, language, dbname);
}
+   mapi_set_application_name("mclient");
free(user_allocated);
user_allocated = NULL;
free(passwd_allocated);
diff --git a/clients/mapiclient/msqldump.c b/clients/mapiclient/msqldump.c
--- a/clients/mapiclient/msqldump.c
+++ b/clients/mapiclient/msqldump.c
@@ -237,6 +237,7 @@ main(int argc, char **argv)
} else {
mid = mapi_mapi(host, port, user, passwd, "sql", dbname);
}
+   mapi_set_application_name("msqldump");
free(user_allocated);
user_allocated = NULL;
free(passwd_allocated);
diff --git a/clients/mapilib/connect.c b/clients/mapilib/connect.c
--- a/clients/mapilib/connect.c
+++ b/clients/mapilib/connect.c
@@ -398,6 +398,8 @@ send_all_clientinfo(Mapi mid)
hostname[sizeof(hostname) - 1] = '\0';
}
const char *application_name = msetting_string(mp, 
MP_CLIENT_APPLICATION);
+   if (!application_name[0])
+   application_name = mapi_application_name;
const char *client_library = "libmapi " MONETDB_VERSION;
const char *client_remark = msetting_string(mp, MP_CLIENT_REMARK);
long pid = getpid();
diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -793,6 +793,9 @@ static int mapi_slice_row(struct MapiRes
 static void mapi_store_bind(struct MapiResultSet *result, int cr);
 
 static ATOMIC_FLAG mapi_initialized = ATOMIC_FLAG_INIT;
+
+char mapi_application_name[256] = { 0 };
+
 /*
  * Blocking
  * 
@@ -2118,6 +2121,15 @@ mapi_disconnect(Mapi mid)
return MOK;
 }
 
+void
+mapi_set_application_name(const char *name)
+{
+   if (name)
+   strncpy(mapi_application_name, name, 
sizeof(mapi_application_name));
+   else
+   mapi_application_name[0] = '\0';
+}
+
 /* Set callback function to retrieve or send file content for COPY
  * INTO queries.
  *
diff --git a/clients/mapilib/mapi.h b/clients/mapilib/mapi.h
--- a/clients/mapilib/mapi.h
+++ b/clients/mapilib/mapi.h
@@ -76,6 +76,9 @@ extern "C" {
 # endif
 #endif
 
+/* global state */
+mapi_export void mapi_set_application_name(const char *name);
+
 /* connection-oriented functions */
 mapi_export Mapi mapi_mapi(const char *host, int port, const char *username, 
const char *password, const char *lang, const char *dbname);
 mapi_export Mapi mapi_mapiuri(const char *url, const char *user, const char 
*pass, const char *lang);
diff --git a/clients/mapilib/mapi_intern.h b/clients/mapilib/mapi_intern.h
--- a/clients/mapilib/mapi_intern.h
+++ b/clients/mapilib/mapi_intern.h
@@ -310,6 +310,8 @@ MapiMsg mapi_Xcommand(Mapi mid, const ch
 
 extern const struct MapiStruct MapiStructDefaults;
 
+extern char mapi_application_name[];
+
 // 'settings' will be newly allocated if NULL
 Mapi mapi_new(msettings *settings);
 
diff --git a/tools/merovingian/daemon/snapshot.c 
b/tools/merovingian/daemon/snapshot.c
--- a/tools/merovingian/daemon/snapshot.c
+++ b/tools/merovingian/daemon/snapshot.c
@@ -114,6 +114,7 @@ snapshot_database_stream(char *dbname, s
e = newErr("connection error: %s", mapi_error_str(conn));
goto bailout;
}
+   mapi_set_application_name("monetdbd");
mapi_reconnect(conn);
if (mapi_error(conn) != MOK) {
e = newErr("connection error: %s", mapi_error_str(conn));
___
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org


  1   2   3   4   5   6   7   8   9   10   >