Changeset: 633c63b5ecb7 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=633c63b5ecb7
Modified Files:
        sql/backends/monet5/sql_execute.c
        sql/backends/monet5/sql_scenario.c
        sql/backends/monet5/sql_upgrades.c
        sql/scripts/51_sys_schema_extension.sql
        sql/server/sql_mvc.c
        sql/server/sql_mvc.h
        sql/server/sql_parser.y
        sql/server/sql_qc.c
        sql/server/sql_qc.h
        sql/server/sql_scan.c
Branch: default
Log Message:

Introducing deallocate statements, which allow users to close a prepared 
statement via SQL: DEALLOC[ATE] [PREPARE] { number | ALL }


diffs (truncated from 552 to 300 lines):

diff --git a/sql/backends/monet5/sql_execute.c 
b/sql/backends/monet5/sql_execute.c
--- a/sql/backends/monet5/sql_execute.c
+++ b/sql/backends/monet5/sql_execute.c
@@ -763,7 +763,7 @@ SQLengineIntern(Client c, backend *be)
 
 cleanup_engine:
        if (m->type == Q_SCHEMA && m->qc != NULL)
-               qc_clean(m->qc);
+               qc_clean(m->qc, false);
        if (msg) {
                /* don't print exception decoration, just the message */
 /*
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
@@ -217,7 +217,7 @@ SQLepilogue(void *ret)
 }
 
 #define SQLglobal(name, val, failure)                                          
                                   \
-       if(!stack_push_var(sql, name, &ctype) || !stack_set_var(sql, name, 
VALset(&src, ctype.type->localtype, (char*)(val)))) \
+       if (!stack_push_var(sql, name, &ctype) || !stack_set_var(sql, name, 
VALset(&src, ctype.type->localtype, (char*)(val)))) \
                failure--;
 
 #define NR_GLOBAL_VARS 9
@@ -286,17 +286,17 @@ SQLprepareClient(Client c, int login)
        c->getquery = SQLgetquery;
        if (c->sqlcontext == 0) {
                m = mvc_create(c->idx, 0, SQLdebug, c->fdin, c->fdout);
-               if( m == NULL) {
+               if (m == NULL) {
                        throw(SQL,"sql.initClient",SQLSTATE(HY001) 
MAL_MALLOC_FAIL);
                }
-               if(global_variables(m, "monetdb", "sys") < 0) {
+               if (global_variables(m, "monetdb", "sys") < 0) {
                        mvc_destroy(m);
                        throw(SQL,"sql.initClient",SQLSTATE(HY001) 
MAL_MALLOC_FAIL);
                }
                if (c->scenario && strcmp(c->scenario, "msql") == 0)
                        m->reply_size = -1;
                be = (void *) backend_create(m, c);
-               if( be == NULL) {
+               if ( be == NULL) {
                        mvc_destroy(m);
                        throw(SQL,"sql.initClient", SQLSTATE(HY001) 
MAL_MALLOC_FAIL);
                }
@@ -306,10 +306,10 @@ SQLprepareClient(Client c, int login)
                /* Only reset if there is no active transaction which
                 * can happen when we combine sql.init with msql.
                */
-               if(m->session->tr->active) {
+               if (m->session->tr->active) {
                        return NULL;
                }
-               if(mvc_reset(m, c->fdin, c->fdout, SQLdebug, NR_GLOBAL_VARS) < 
0) {
+               if (mvc_reset(m, c->fdin, c->fdout, SQLdebug, NR_GLOBAL_VARS) < 
0) {
                        throw(SQL,"sql.initClient", SQLSTATE(HY001) 
MAL_MALLOC_FAIL);
                }
                backend_reset(be);
@@ -364,9 +364,9 @@ SQLresetClient(Client c)
                c->sqlcontext = NULL;
        }
        c->state[MAL_SCENARIO_READER] = NULL;
-       if(other && !msg)
+       if (other && !msg)
                msg = other;
-       else if(other && msg)
+       else if (other && msg)
                freeException(other);
        return msg;
 }
@@ -420,7 +420,7 @@ SQLinit(Client c)
                stream *buf;
                bstream *fdin;
 
-               if( b == NULL || cbuf == NULL) {
+               if ( b == NULL || cbuf == NULL) {
                        MT_lock_unset(&sql_contextLock);
                        GDKfree(b);
                        GDKfree(cbuf);
@@ -429,21 +429,21 @@ SQLinit(Client c)
 
                buffer_init(b, cbuf, len);
                buf = buffer_rastream(b, "si");
-               if( buf == NULL) {
+               if ( buf == NULL) {
                        MT_lock_unset(&sql_contextLock);
                        buffer_destroy(b);
                        throw(SQL,"sql.init",SQLSTATE(HY001) MAL_MALLOC_FAIL);
                }
 
                fdin = bstream_create(buf, b->len);
-               if( fdin == NULL) {
+               if ( fdin == NULL) {
                        MT_lock_unset(&sql_contextLock);
                        buffer_destroy(b);
                        throw(SQL,"sql.init",SQLSTATE(HY001) MAL_MALLOC_FAIL);
                }
 
                bstream_next(fdin);
-               if( MCpushClientInput(c, fdin, 0, "") < 0)
+               if ( MCpushClientInput(c, fdin, 0, "") < 0)
                        fprintf(stderr, "SQLinit:Could not switch client input 
stream");
        }
        if ((msg = SQLprepareClient(c, 0)) != NULL) {
@@ -614,7 +614,7 @@ SQLinit(Client c)
                        throw(SQL, "SQLinit", SQLSTATE(42000) "Starting idle 
manager failed");
                }
        }
-       if( wlc_state == WLC_STARTUP)
+       if ( wlc_state == WLC_STARTUP)
                return WLCinit();
        return MAL_SUCCEED;
 }
@@ -629,14 +629,14 @@ handle_error(mvc *m, int pstatus, str ms
        /* transaction already broken */
        if (m->type != Q_TRANS && pstatus < 0) {
                new = createException(SQL,"sql.execute",TRANS_ABORTED);
-       } else if( GDKerrbuf && GDKerrbuf[0]){
+       } else if ( GDKerrbuf && GDKerrbuf[0]){
                new = GDKstrdup(GDKerrbuf);
                GDKerrbuf[0] = 0;
-       } else if( *m->errstr){
+       } else if ( *m->errstr){
                new = GDKstrdup(m->errstr);
                m->errstr[0] = 0;
        }
-       if( new && msg){
+       if ( new && msg){
                newmsg = GDKzalloc( strlen(msg) + strlen(new) + 64);
                if (newmsg == NULL) {
                        newmsg = createException(SQL, "sql.execute", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
@@ -648,10 +648,10 @@ handle_error(mvc *m, int pstatus, str ms
                freeException(new);
                freeException(msg);
        } else
-       if( msg)
+       if ( msg)
                newmsg = msg;
        else
-       if( new)
+       if ( new)
                newmsg = new;
        return newmsg;
 }
@@ -793,7 +793,7 @@ SQLcompile(Client cntxt, MalBlkPtr mb, M
        *ret = NULL;
        if ((msg = SQLstatementIntern(cntxt, expr, "SQLcompile", FALSE, FALSE, 
NULL)) != MAL_SUCCEED)
                return msg;
-       if((*ret = _STRDUP("SQLcompile")) == NULL)
+       if ((*ret = _STRDUP("SQLcompile")) == NULL)
                throw(SQL,"sql.compile",SQLSTATE(HY001) MAL_MALLOC_FAIL);
        return MAL_SUCCEED;
 }
@@ -828,7 +828,7 @@ SQLinclude(Client cntxt, MalBlkPtr mb, M
                close_stream(fd);
                throw(MAL, "sql.include", SQLSTATE(42000) "file %s too large to 
process", fullname);
        }
-       if((bfd = bstream_create(fd, sz == 0 ? (size_t) (128 * BLOCK) : sz)) == 
NULL) {
+       if ((bfd = bstream_create(fd, sz == 0 ? (size_t) (128 * BLOCK) : sz)) 
== NULL) {
                close_stream(fd);
                throw(MAL, "sql.include", SQLSTATE(HY001) MAL_MALLOC_FAIL);
        }
@@ -1031,7 +1031,7 @@ cachable(mvc *m, sql_rel *r)
        if (m->type == Q_TRANS )        /* m->type == Q_SCHEMA || cachable to 
make sure we have trace on alter statements  */
                return 0;
        /* we don't store queries with a large footprint */
-       if(r && sa_size(m->sa) > MAX_QUERY) 
+       if (r && sa_size(m->sa) > MAX_QUERY) 
                return 0;
        return 1;
 }
@@ -1052,7 +1052,7 @@ SQLparser(Client c)
        mvc *m;
        int oldvtop, oldstop;
        int pstatus = 0;
-       int err = 0, opt = 0;
+       int err = 0, opt = 0, preparedid = -1;
        char *q = NULL;
 
        be = (backend *) c->sqlcontext;
@@ -1210,34 +1210,49 @@ SQLparser(Client c)
        if (q == NULL) {
                err = 1;
                msg = createException(PARSE, "SQLparser", SQLSTATE(HY001) 
MAL_MALLOC_FAIL);
-       } else if (m->emode == m_execute) {
-               assert(m->sym->data.lval->h->type == type_int);
-               be->q = qc_find(m->qc, m->sym->data.lval->h->data.i_val);
-               if (!be->q) {
-                       err = -1;
-                       msg = createException(SQL, "EXEC", SQLSTATE(07003) "No 
prepared statement with id: %d\n", m->sym->data.lval->h->data.i_val);
-                       *m->errstr = 0;
-                       msg = handle_error(m, pstatus, msg);
-                       sqlcleanup(m, err);
-                       goto finalize;
-               } else if (!be->q->prepared) {
-                       err = -1;
-                       msg = createException(SQL, "EXEC", SQLSTATE(07005) 
"Given handle id is not for a " "prepared statement: %d\n", 
m->sym->data.lval->h->data.i_val);
-                       *m->errstr = 0;
-                       msg = handle_error(m, pstatus, msg);
-                       sqlcleanup(m, err);
-                       goto finalize;
+       } else if (m->emode == m_execute || m->emode == m_deallocate) {
+               if (m->emode == m_execute) {
+                       assert(m->sym->data.lval->h->type == type_int);
+                       preparedid = m->sym->data.lval->h->data.i_val;
+
+                       assert(preparedid >= 0);
+                       be->q = qc_find(m->qc, preparedid);
+               } else { /* m_deallocate case */
+                       AtomNode *an = (AtomNode *) m->sym;
+                       assert(m->sym->type == type_symbol && an->a->data.vtype 
== TYPE_int);
+                       preparedid = an->a->data.val.ival;
+
+                       if (preparedid > -1) /* The -1 case represents the 
deallocate the entire query cache */
+                               be->q = qc_find(m->qc, preparedid);
                }
-               m->type = be->q->type; 
+
+               if (preparedid > -1) {
+                       const char *mode = (m->emode == m_execute) ? "EXEC" : 
"DEALLOC";
+                       if (!be->q) {
+                               err = -1;
+                               msg = createException(SQL, mode, 
SQLSTATE(07003) "No prepared statement with id: %d\n", preparedid);
+                               *m->errstr = 0;
+                               msg = handle_error(m, pstatus, msg);
+                               sqlcleanup(m, err);
+                               goto finalize;
+                       } else if (!be->q->prepared) {
+                               err = -1;
+                               msg = createException(SQL, mode, 
SQLSTATE(07005) "Given handle id is not for a prepared statement: %d\n", 
preparedid);
+                               *m->errstr = 0;
+                               msg = handle_error(m, pstatus, msg);
+                               sqlcleanup(m, err);
+                               goto finalize;
+                       }
+               }
+
+               m->type = (m->emode == m_execute) ? be->q->type : Q_SCHEMA; /* 
TODO DEALLOCATE statements don't fit for Q_SCHEMA */
                scanner_query_processed(&(m->scanner));
        } else if (caching(m) && cachable(m, NULL) && m->emode != m_prepare && 
(be->q = qc_match(m->qc, m, m->sym, m->args, m->argc, m->scanner.key ^ 
m->session->schema->base.id)) != NULL) {
                /* query template was found in the query cache */
                scanner_query_processed(&(m->scanner));
                m->no_mitosis = be->q->no_mitosis;
        } else {
-               sql_rel *r;
-
-               r = sql_symbol2relation(m, m->sym);
+               sql_rel *r = sql_symbol2relation(m, m->sym);
 
                if (!r || (err = mvc_status(m) && m->type != Q_TRANS && 
*m->errstr)) {
                        if (strlen(m->errstr) > 6 && m->errstr[5] == '!')
@@ -1268,7 +1283,7 @@ SQLparser(Client c)
                        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 (!escaped_q) {
                                err = 1;
                                msg = createException(PARSE, "SQLparser", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
                        } else {
@@ -1283,7 +1298,7 @@ SQLparser(Client c)
                                                  m->no_mitosis,
                                                  m->emode == m_prepare);
                        }
-                       if(!be->q) {
+                       if (!be->q) {
                                err = 1;
                                msg = createException(PARSE, "SQLparser", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
                        }
@@ -1298,7 +1313,7 @@ SQLparser(Client c)
                        m->sym = NULL;
                        /* register name in the namespace */
                        be->q->name = putName(be->q->name);
-                       if(!be->q->name) {
+                       if (!be->q->name) {
                                err = 1;
                                msg = createException(PARSE, "SQLparser", 
SQLSTATE(HY001) MAL_MALLOC_FAIL);
                        }
@@ -1308,12 +1323,21 @@ SQLparser(Client c)
                m->session->status = -10;
        if (err == 0) {
                /* no parsing error encountered, finalize the code of the query 
wrapper */
-               if (be->q) {
-                       if (m->emode == m_prepare){
+               if (m->emode == m_deallocate) {
+                       assert(be->q || preparedid == -1);
+                       if (be->q) {
+                               qc_delete(m->qc, be->q);
+                       } else {
+                               qc_clean(m->qc, true);
+                       }
+                       /* For deallocate statements just export a simple 
output */
+                       err = mvc_export_operation(be, c->fdout, "", 
c->curprg->def->starttime, c->curprg->def->optimize);
+               } else if (be->q) {
+                       if (m->emode == m_prepare) {
                                /* For prepared queries, return a table with 
result set structure*/
                                /* optimize the code block and rename it */
                                err = mvc_export_prepare(m, c->fdout, be->q, 
"");
-                       } else if( m->emode == m_execute || m->emode == 
m_normal || m->emode == m_plan){
+                       } else if (m->emode == m_execute || m->emode == 
m_normal || m->emode == m_plan) {
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to