Changeset: 9691fc43fc4f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9691fc43fc4f
Modified Files:
        sql/backends/monet5/sql_execute.c
        sql/server/rel_rel.c
        sql/server/sql_mvc.h
        sql/server/sql_var.c
Branch: default
Log Message:

Fixes for variables on multiple frame levels

I will commit the test soon.


diffs (249 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
@@ -820,10 +820,35 @@ parseIdent(char *in, char *out)
        return in;
 }
 
+struct local_var_entry {
+       char *vname;
+       sql_subtype tpe;
+} local_var_entry;
+
+struct global_var_entry {
+       char *vname;
+       sql_schema *s;
+} global_var_entry;
+
+static str
+RAstatement2_return(backend *be, mvc *m, int nlevels, struct global_var_entry 
*gvars, int gentries, str msg)
+{
+       while (nlevels) { /* clean added frames */
+               stack_pop_frame(m);
+               nlevels--;
+       }
+       for (int i = 0 ; i < gentries ; i++) { /* clean any added global 
variables */
+               struct global_var_entry gv = gvars[i];
+               (void) remove_global_var(m, gv.s, gv.vname);
+       }
+       sa_reset(m->ta);
+       return RAcommit_statement(be, msg);
+}
+
 str
 RAstatement2(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
-       int pos = 0;
+       int pos = 0, nlevels = 0, *lkeys = NULL, lcap = 0, lentries = 0, gcap = 
0, gentries = 0;
        str mod = *getArgReference_str(stk, pci, 1);
        str nme = *getArgReference_str(stk, pci, 2);
        str expr = *getArgReference_str(stk, pci, 3);
@@ -834,6 +859,8 @@ RAstatement2(Client cntxt, MalBlkPtr mb,
        str msg = MAL_SUCCEED;
        sql_rel *rel;
        list *refs, *ops;
+       struct local_var_entry *lvars = NULL;
+       struct global_var_entry *gvars = NULL;
 
        if ((msg = getSQLContext(cntxt, mb, &m, &be)) != NULL)
                return msg;
@@ -844,10 +871,8 @@ RAstatement2(Client cntxt, MalBlkPtr mb,
        if (!m->sa)
                m->sa = sa_create(m->pa);
        if (!m->sa)
-               return RAcommit_statement(be, 
createException(SQL,"RAstatement2",SQLSTATE(HY013) MAL_MALLOC_FAIL));
+               return RAstatement2_return(be, m, nlevels, gvars, gentries, 
createException(SQL,"RAstatement2",SQLSTATE(HY013) MAL_MALLOC_FAIL));
 
-       if (!stack_push_frame(m, NULL))
-               return RAcommit_statement(be, 
createException(SQL,"RAstatement2",SQLSTATE(HY013) MAL_MALLOC_FAIL));
        ops = sa_list(m->sa);
        while (sig && *sig) {
                sql_schema *sh = NULL;
@@ -859,13 +884,11 @@ RAstatement2(Client cntxt, MalBlkPtr mb,
                var = p+1;
                assert(*p == '"');
                p = parseIdent(p+1, var);
-               assert(*p == '\0');
                p++;
                if (*p == '"') { /* global variable, parse schema and name */
                        sch = var;
                        var = p+1;
                        p = parseIdent(p+1, var);
-                       assert(*p == '\0');
                        p++;
                }
 
@@ -883,37 +906,72 @@ RAstatement2(Client cntxt, MalBlkPtr mb,
                sig = p;
 
                if (!sql_find_subtype(&tpe, vtype, d, s)) {
-                       if (!(t = mvc_bind_type(m, vtype))) { /* try an 
external type */
-                               stack_pop_frame(m);
-                               return RAcommit_statement(be, 
createException(SQL,"RAstatement2",SQLSTATE(42000) "SQL type %s(%d, %d) not 
found\n", vtype, d, s));
-                       }
+                       if (!(t = mvc_bind_type(m, vtype))) /* try an external 
type */
+                               return RAstatement2_return(be, m, nlevels, 
gvars, gentries, createException(SQL,"RAstatement2",SQLSTATE(42000) "SQL type 
%s(%d, %d) not found\n", vtype, d, s));
                        sql_init_subtype(&tpe, t, d, s);
                }
 
                if (sch) {
                        assert(level == 0);
-                       if (!(sh = mvc_bind_schema(m, sch))) {
-                               stack_pop_frame(m);
-                               return RAcommit_statement(be, 
createException(SQL,"RAstatement2",SQLSTATE(3F000) "No such schema '%s'", sch));
-                       }
-                       if (!find_global_var(m, sh, var) && !push_global_var(m, 
sch, var, &tpe)) {
-                               stack_pop_frame(m);
-                               return RAcommit_statement(be, 
createException(SQL,"RAstatement2",SQLSTATE(HY013) MAL_MALLOC_FAIL));
+                       if (!(sh = mvc_bind_schema(m, sch)))
+                               return RAstatement2_return(be, m, nlevels, 
gvars, gentries, createException(SQL,"RAstatement2",SQLSTATE(3F000) "No such 
schema '%s'", sch));
+                       if (!find_global_var(m, sh, var)) { /* don't add the 
same global variable again */
+                               if (!push_global_var(m, sch, var, &tpe)) /* if 
doesn't exist, add it, then remove it before returning */
+                                       return RAstatement2_return(be, m, 
nlevels, gvars, gentries, createException(SQL,"RAstatement2",SQLSTATE(HY013) 
MAL_MALLOC_FAIL));
+                               if (gentries == gcap) {
+                                       if (gcap == 0) {
+                                               gcap = 8;
+                                               gvars = SA_NEW_ARRAY(m->ta, 
struct global_var_entry, gcap);
+                                       } else {
+                                               int ngcap = gcap * 4;
+                                               gvars = SA_RENEW_ARRAY(m->ta, 
struct global_var_entry, gvars, ngcap, gcap);
+                                               gcap = ngcap;
+                                       }
+                                       gvars[gentries++] = (struct 
global_var_entry) {.s = sh, .vname = var,};
+                               }
                        }
                        list_append(ops, exp_var(m->sa, sa_strdup(m->sa, sch), 
sa_strdup(m->sa, var), &tpe, 0));
                } else {
                        char opname[BUFSIZ];
 
-                       level = 1; /* TODO multiple levels */
-                       if (!frame_push_var(m, var, &tpe)) {
-                               stack_pop_frame(m);
-                               return RAcommit_statement(be, 
createException(SQL,"RAstatement2",SQLSTATE(HY013) MAL_MALLOC_FAIL));
+                       if (lentries == lcap) {
+                               if (lcap == 0) {
+                                       lcap = 8;
+                                       lkeys = SA_NEW_ARRAY(m->ta, int, lcap);
+                                       lvars = SA_NEW_ARRAY(m->ta, struct 
local_var_entry, lcap);
+                               } else {
+                                       int nlcap = lcap * 4;
+                                       lkeys = SA_RENEW_ARRAY(m->ta, int, 
lkeys, nlcap, lcap);
+                                       lvars = SA_RENEW_ARRAY(m->ta, struct 
local_var_entry, lvars, nlcap, lcap);
+                                       lcap = nlcap;
+                               }
                        }
+                       lkeys[lentries] = level;
+                       lvars[lentries] = (struct local_var_entry) {.tpe = tpe, 
.vname = var,};
+                       lentries++;
 
                        snprintf(opname, BUFSIZ, "%d%%%s", level, var); /* 
engineering trick */
                        list_append(ops, exp_var(m->sa, NULL, sa_strdup(m->sa, 
opname), &tpe, level));
                }
        }
+       if (lentries) {
+               GDKqsort(lkeys, lvars, NULL, lentries, sizeof(int), 
sizeof(struct local_var_entry), TYPE_int, false, false);
+
+               for (int i = 0 ; i < lentries ; i++) {
+                       int next_level = lkeys[i];
+                       struct local_var_entry next_val = lvars[i];
+
+                       assert(next_level != 0); /* no global variables here */
+                       while (nlevels < next_level) { /* add gap levels */
+                               if (!stack_push_frame(m, NULL))
+                                       return RAstatement2_return(be, m, 
nlevels, gvars, gentries, createException(SQL,"RAstatement2",SQLSTATE(HY013) 
MAL_MALLOC_FAIL));
+                               nlevels++;
+                       }
+                       if (!frame_push_var(m, next_val.vname, &next_val.tpe))
+                               return RAstatement2_return(be, m, nlevels, 
gvars, gentries, createException(SQL,"RAstatement2",SQLSTATE(HY013) 
MAL_MALLOC_FAIL));
+               }
+       }
+
        refs = sa_list(m->sa);
        rel = rel_read(m, expr, &pos, refs);
        if (rel)
@@ -951,8 +1009,7 @@ RAstatement2(Client cntxt, MalBlkPtr mb,
        if (!msg && monet5_create_relational_function(m, mod, nme, rel, NULL, 
ops, 0) < 0)
                msg = createException(SQL, "RAstatement2", "%s", m->errstr);
        rel_destroy(rel);
-       stack_pop_frame(m);
-       return RAcommit_statement(be, msg);
+       return RAstatement2_return(be, m, nlevels, gvars, gentries, msg);
 }
 
 str
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -1524,7 +1524,7 @@ lastexp(sql_rel *rel)
        if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
                rel = rel_parent(rel);
        assert(list_length(rel->exps));
-       assert(is_project(rel->op));
+       assert(is_project(rel->op) || rel->op == op_table);
        return rel->exps->t->data;
 }
 
diff --git a/sql/server/sql_mvc.h b/sql/server/sql_mvc.h
--- a/sql/server/sql_mvc.h
+++ b/sql/server/sql_mvc.h
@@ -245,6 +245,7 @@ extern int mvc_check_dependency(mvc *m, 
 extern int init_global_variables(mvc *sql);
 extern sql_var *find_global_var(mvc *sql, sql_schema *s, const char *name);
 extern sql_var *push_global_var(mvc *sql, const char *sname, const char *name, 
sql_subtype *type);
+extern int remove_global_var(mvc *sql, sql_schema *s, const char *name);
 
 extern sql_var* frame_push_var(mvc *sql, const char *name, sql_subtype *type);
 extern sql_local_table* frame_push_table(mvc *sql, sql_table *t);
diff --git a/sql/server/sql_var.c b/sql/server/sql_var.c
--- a/sql/server/sql_var.c
+++ b/sql/server/sql_var.c
@@ -49,6 +49,9 @@ init_global_variables(mvc *sql)
 
        if (!(sql->global_vars = list_create(destroy_sql_var)))
                return -1;
+       /* Use hash lookup for global variables */
+       if (!(sql->global_vars->ht = hash_new(NULL, 16, (fkeyvalue)&var_key)))
+               return -1;
 
        sql_find_subtype(&ctype, "int", 0, 0);
        SQLglobal(sname, "debug", &sql->debug);
@@ -70,19 +73,6 @@ init_global_variables(mvc *sql)
        sql_find_subtype(&ctype, "bigint", 0, 0);
        SQLglobal(sname, "last_id", &sec);
        SQLglobal(sname, "rowcnt", &sec);
-
-       /* Use hash lookup for global variables. With 9 variables in total it's 
worth to hash instead of */
-       if (!(sql->global_vars->ht = hash_new(NULL, 
list_length(sql->global_vars), (fkeyvalue)&var_key)))
-               return -1;
-
-       for (node *n = sql->global_vars->h; n; n = n->next) {
-               sql_var *v = n->data;
-               int key = var_key(v);
-
-               if (!hash_add(sql->global_vars->ht, key, v))
-                       return -1;
-       }
-
        return 0;
 }
 
@@ -117,6 +107,19 @@ push_global_var(mvc *sql, const char *sn
        return svar;
 }
 
+int
+remove_global_var(mvc *sql, sql_schema *s, const char *name)
+{
+       sql_var *v = find_global_var(sql, s, name);
+
+       if (v) {
+               list_remove_data(sql->global_vars, NULL, v);
+               return 0;
+       } else {
+               return -1;
+       }
+}
+
 sql_var*
 frame_push_var(mvc *sql, const char *name, sql_subtype *type)
 {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to