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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list