Changeset: fb5890189fc7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=fb5890189fc7
Modified Files:
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql.h
        sql/backends/monet5/sql.mal
        sql/backends/monet5/sql_gencode.c
        sql/backends/monet5/sql_scenario.c
        sql/backends/monet5/sql_session.mal
        sql/backends/monet5/sql_upgrades.c
        sql/scripts/22_clients.sql
        sql/server/sql_qc.c
        sql/server/sql_qc.h
Branch: default
Log Message:

Added table returning function and view "prepared_statements", which depicts 
the available session's prepared statements.

Some minor notes:
- Added "created" field to the query cache struct with the timestamp of the 
query's creation.
- The "codestring" field is no longer escaped, so the prepared statement query 
can be viewed as raw at the "prepared_statements" view.
- Later we can the possibility for the monetdb user to view all the server's 
prepared statements. However this requires to add authentication to the query 
cache and a global lock I think.


diffs (truncated from 371 to 300 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
@@ -5277,3 +5277,85 @@ SQLhot_snapshot(void *ret, const str *ta
        else
                throw(SQL, "sql.hot_snapshot", GDK_EXCEPTION);
 }
+
+str
+SQLsession_prepared_statements(Client cntxt, MalBlkPtr mb, MalStkPtr stk, 
InstrPtr pci)
+{
+       BAT *sessionid, *user, *statementid, *statement, *created;
+       bat *sid = getArgReference_bat(stk,pci,0);
+       bat *u = getArgReference_bat(stk,pci,1);
+       bat *i = getArgReference_bat(stk,pci,2);
+       bat *s = getArgReference_bat(stk,pci,3);
+       bat *c = getArgReference_bat(stk,pci,4);
+       str msg = MAL_SUCCEED, usr;
+       mvc *sql = NULL;
+       cq *q = NULL;
+
+       (void) stk;
+       (void) pci;
+       if ((msg = getSQLContext(cntxt, mb, &sql, NULL)) != NULL)
+               return msg;
+       if ((msg = checkSQLContext(cntxt)) != NULL)
+               return msg;
+
+       assert(sql->qc);
+
+       sessionid = COLnew(0, TYPE_int, 256, TRANSIENT);
+       user = COLnew(0, TYPE_str, 256, TRANSIENT);
+       statementid = COLnew(0, TYPE_int, 256, TRANSIENT);
+       statement = COLnew(0, TYPE_str, 256, TRANSIENT);
+       created = COLnew(0, TYPE_timestamp, 256, TRANSIENT);
+       if (sessionid == NULL || user == NULL || statementid == NULL || 
statement == NULL || created == NULL) {
+               msg = createException(SQL, "sql.session_prepared_statements", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
+               goto bailout;
+       }
+
+       for (q = sql->qc->q; q; q = q->next) {
+               if (q->prepared) {
+                       gdk_return bun_res;
+                       if (BUNappend(sessionid, &(cntxt->idx), false) != 
GDK_SUCCEED) {
+                               msg = createException(SQL, 
"sql.session_prepared_statements", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+                               goto bailout;
+                       }
+
+                       msg = AUTHgetUsername(&usr, cntxt);
+                       if (msg != MAL_SUCCEED)
+                               goto bailout;
+                       bun_res = BUNappend(user, usr, false);
+                       GDKfree(usr);
+                       if (bun_res != GDK_SUCCEED) {
+                               msg = createException(SQL, 
"sql.session_prepared_statements", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+                               goto bailout;
+                       }
+
+                       if (BUNappend(statementid, &(q->id), false) != 
GDK_SUCCEED) {
+                               msg = createException(SQL, 
"sql.session_prepared_statements", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+                               goto bailout;
+                       }
+                       if (BUNappend(statement, q->codestring, false) != 
GDK_SUCCEED) {
+                               msg = createException(SQL, 
"sql.session_prepared_statements", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+                               goto bailout;
+                       }
+                       if (BUNappend(created, &(q->created), false) != 
GDK_SUCCEED) {
+                               msg = createException(SQL, 
"sql.session_prepared_statements", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+                               goto bailout;
+                       }
+               }
+       }
+
+bailout:
+       if (msg) {
+               BBPreclaim(sessionid);
+               BBPreclaim(user);
+               BBPreclaim(statementid);
+               BBPreclaim(statement);
+               BBPreclaim(created);
+       } else {
+               BBPkeepref(*sid = sessionid->batCacheid);
+               BBPkeepref(*u = user->batCacheid);
+               BBPkeepref(*i = statementid->batCacheid);
+               BBPkeepref(*s = statement->batCacheid);
+               BBPkeepref(*c = created->batCacheid);
+       }
+       return msg;
+}
diff --git a/sql/backends/monet5/sql.h b/sql/backends/monet5/sql.h
--- a/sql/backends/monet5/sql.h
+++ b/sql/backends/monet5/sql.h
@@ -312,4 +312,6 @@ sql5_export str SQLsuspend_log_flushing(
 sql5_export str SQLresume_log_flushing(void *ret);
 sql5_export str SQLhot_snapshot(void *ret, const str *tarfile);
 
+sql5_export str SQLsession_prepared_statements(Client cntxt, MalBlkPtr mb, 
MalStkPtr stk, InstrPtr pci);
+
 #endif /* _SQL_H */
diff --git a/sql/backends/monet5/sql.mal b/sql/backends/monet5/sql.mal
--- a/sql/backends/monet5/sql.mal
+++ b/sql/backends/monet5/sql.mal
@@ -603,6 +603,10 @@ address SYSMONstop;
 pattern sysmon_stop(tag:lng)
 address SYSMONstop;
 
+pattern prepared_statements()(sessionid:bat[:int], user:bat[:str], 
statementid:bat[:int], statementt:bat[:str], createdd:bat[:timestamp])
+address SQLsession_prepared_statements
+comment "Available prepared statements in the current session";
+
 pattern copy_rejects() (rowid:bat[:lng], fldid:bat[:int], msg:bat[:str], 
inp:bat[:str])
 address COPYrejects;
 pattern copy_rejects_clear()
diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -742,8 +742,8 @@ backend_dumpproc(backend *be, Client c, 
        MalBlkPtr mb = 0;
        Symbol curPrg = 0, backup = NULL;
        InstrPtr curInstr = 0;
-       int argc = 0;
-       char arg[IDLENGTH];
+       int argc = 0, res;
+       char arg[IDLENGTH], *escaped_q = NULL;
        node *n;
 
        backup = c->curprg;
@@ -806,7 +806,15 @@ backend_dumpproc(backend *be, Client c, 
                }
        }
 
-       if (backend_dumpstmt(be, mb, r, 1, 1, be->q?be->q->codestring:NULL) < 
0) 
+       if (be->q) {
+               if (!(escaped_q = sql_escape_str(be->q->codestring))) {
+                       sql_error(m, 001, SQLSTATE(HY013) MAL_MALLOC_FAIL);
+                       goto cleanup;
+               }
+       }
+       res = backend_dumpstmt(be, mb, r, 1, 1, escaped_q);
+       GDKfree(escaped_q);
+       if (res < 0)
                goto cleanup;
 
        if (cq) {
diff --git a/sql/backends/monet5/sql_scenario.c 
b/sql/backends/monet5/sql_scenario.c
--- a/sql/backends/monet5/sql_scenario.c
+++ b/sql/backends/monet5/sql_scenario.c
@@ -1276,25 +1276,23 @@ SQLparser(Client c)
                        else opt = 1;
                } else {
                        /* Add the query tree to the SQL query cache
-                        * and bake a MAL program for it.
-                        */
-                       char *escaped_q;
-                       char qname[IDLENGTH];
+                        * and bake a MAL program for it. */
+                       char *q_copy = GDKstrdup(q), qname[IDLENGTH];
+
                        be->q = NULL;
                        (void) snprintf(qname, IDLENGTH, "%c%d_%d", (m->emode 
== m_prepare?'p':'s'), m->qc->id++, m->qc->clientid);
-                       escaped_q = sql_escape_str(q);
-                       if (!escaped_q) {
+                       if (!q_copy) {
                                err = 1;
                                msg = createException(PARSE, "SQLparser", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
                        } else {
                                be->q = qc_insert(m->qc, m->sa, /* the 
allocator */
                                                  r,    /* keep relational 
query */
-                                                 qname, /* its MAL name) */
+                                                 qname, /* its MAL name */
                                                  m->sym,       /* the sql 
symbol tree */
                                                  m->args,      /* the argument 
list */
                                                  m->argc, m->scanner.key ^ 
m->session->schema->base.id,        /* the statement hash key */
                                                  m->type,      /* the type of 
the statement */
-                                                 escaped_q,
+                                                 q_copy,
                                                  m->no_mitosis,
                                                  m->emode == m_prepare);
                        }
diff --git a/sql/backends/monet5/sql_session.mal 
b/sql/backends/monet5/sql_session.mal
--- a/sql/backends/monet5/sql_session.mal
+++ b/sql/backends/monet5/sql_session.mal
@@ -1,40 +1,39 @@
 module sql;
-pattern  sql.setquerytimeout(n:int):void
+
+pattern sql.setquerytimeout(n:int):void
 address SQLqueryTimeout;
-pattern  sql.setquerytimeout(sid:bte, n:int):void
+pattern sql.setquerytimeout(sid:bte, n:int):void
 address SQLqueryTimeout;
-pattern  sql.setquerytimeout(sid:sht, n:int):void
+pattern sql.setquerytimeout(sid:sht, n:int):void
 address SQLqueryTimeout;
-pattern  sql.setquerytimeout(sid:int, n:int):void
+pattern sql.setquerytimeout(sid:int, n:int):void
 address SQLqueryTimeout
 comment "A query is aborted after q seconds (q=0 means run undisturbed).";
-        
-pattern  sql.setsessiontimeout(n:int):void
+
+pattern sql.setsessiontimeout(n:int):void
 address SQLsessionTimeout;
-pattern  sql.setsessiontimeout(sid:bte, n:int):void
+pattern sql.setsessiontimeout(sid:bte, n:int):void
 address SQLsessionTimeout;
-pattern  sql.setsessiontimeout(sid:sht, n:int):void
+pattern sql.setsessiontimeout(sid:sht, n:int):void
 address SQLsessionTimeout;
-pattern  sql.setsessiontimeout(sid:int, n:int):void
+pattern sql.setsessiontimeout(sid:int, n:int):void
 address SQLsessionTimeout
 comment "Set the session timeout for a particulat session id";
 
-pattern  sql.setoptimizer(opt:str):void
+pattern sql.setoptimizer(opt:str):void
 address SQLsetoptimizer;
-pattern  sql.setoptimizer(sid:int, opt:str):void
+pattern sql.setoptimizer(sid:int, opt:str):void
 address SQLsetoptimizer
 comment "Set the session optimizer";
-        
-pattern  sql.setworkerlimit(n:int):void
+
+pattern sql.setworkerlimit(n:int):void
 address SQLsetworkerlimit;
-pattern  sql.setworkerlimit(sid:int, n:int):void
+pattern sql.setworkerlimit(sid:int, n:int):void
 address SQLsetworkerlimit
 comment "Limit the number of worker threads per query";
 
-pattern  sql.setmemorylimit(n:int):void
+pattern sql.setmemorylimit(n:int):void
 address SQLsetmemorylimit;
-pattern  sql.setmemorylimit(sid:sht, n:int):void
+pattern sql.setmemorylimit(sid:sht, n:int):void
 address SQLsetmemorylimit
 comment "Limit the memory claim in MB per query";
-
-
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
@@ -2440,11 +2440,22 @@ sql_update_default(Client c, mvc *sql, c
                        " external name clients.stopsession;\n");
 
        pos += snprintf(buf + pos, bufsize - pos,
+                       "create function sys.prepared_statements()\n"
+                       "returns table(\n"
+                       "\"sessionid\" int,\n"
+                       "\"user\" string,\n"
+                       "\"statementid\" int,\n"
+                       "\"statement\" string,\n"
+                       "\"created\" timestamp)\n"
+                       " external name sql.prepared_statements;\n"
+                       "create view sys.prepared_statements as select * from 
sys.prepared_statements();\n");
+
+       pos += snprintf(buf + pos, bufsize - pos,
                        "update sys.functions set system = true where schema_id 
= (select id from sys.schemas where name = 'sys')"
-                       " and name = 'sessions' and type = %d;\n", (int) 
F_UNION);
+                       " and name in ('sessions', 'prepared_statements') and 
type = %d;\n", (int) F_UNION);
        pos += snprintf(buf + pos, bufsize - pos,
                        "update sys._tables set system = true where schema_id = 
(select id from sys.schemas where name = 'sys')"
-                       " and name = 'sessions';\n");
+                       " and name in ('sessions', 'prepared_statements');\n");
        pos += snprintf(buf + pos, bufsize - pos,
                        "update sys.functions set system = true where schema_id 
= (select id from sys.schemas where name = 'sys')"
                        " and name in ('setoptimizer', 'setquerytimeout', 
'setsessiontimeout', 'setworkerlimit', 'setmemorylimit', 'setoptimizer', 
'stopsession') and type = %d;\n", (int) F_PROC);
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
@@ -81,3 +81,18 @@ create procedure sys.stopsession("sessio
 
 create procedure sys.setprinttimeout("timeout" integer)
        external name clients.setprinttimeout;
+
+-- session's prepared statements
+create function sys.prepared_statements()
+returns table(
+       "sessionid" int,
+       "user" string,
+       "statementid" int,
+       "statement" string,
+       "created" timestamp
+)
+external name sql.prepared_statements;
+grant execute on function sys.prepared_statements to public;
+
+create view sys.prepared_statements as select * from sys.prepared_statements();
+grant select on sys.prepared_statements to public;
diff --git a/sql/server/sql_qc.c b/sql/server/sql_qc.c
--- a/sql/server/sql_qc.c
+++ b/sql/server/sql_qc.c
@@ -41,6 +41,7 @@
 #include "sql_qc.h"
 #include "sql_mvc.h"
 #include "sql_atom.h"
+#include "mtime.h"
 
 qc *
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to