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