Changeset: 4c321453d17c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4c321453d17c
Modified Files:
sql/server/rel_psm.c
sql/server/rel_select.c
sql/server/sql_semantic.c
sql/server/sql_semantic.h
Branch: scoping2
Log Message:
Scoping search on variables
diffs (248 lines):
diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c
--- a/sql/server/rel_psm.c
+++ b/sql/server/rel_psm.c
@@ -57,27 +57,6 @@ rel_psm_stmt(sql_allocator *sa, sql_exp
return NULL;
}
-/* vname can be
- - 'parameter of the function' (ie in the param list)
- - local variable, declared earlier
- - global variable, also declared earlier
-*/
-static void*
-resolve_variable_on_scope(mvc *sql, sql_schema *s, const char *sname, const
char *vname, sql_var **var, sql_arg **a, sql_subtype **tpe, int *level, const
char *action)
-{
- if (!sname && (*var = stack_find_var_frame(sql, vname, level))) { /*
check if variable is known from the stack */
- *tpe = &((*var)->var.tpe);
- } else if (!sname && (*a = sql_bind_param(sql, vname))) { /* then if it
is a parameter */
- *tpe = &((*a)->type);
- *level = 1;
- } else if ((*var = find_global_var(sql, s, vname))) { /* then if it is
a global var */
- *tpe = &((*var)->var.tpe);
- *level = 0;
- } else
- return sql_error(sql, 01, SQLSTATE(42000) "%s: Variable
'%s%s%s' unknown", action, sname ? sname : "", sname ? "." : "", vname);
- return level;
-}
-
/* SET [ schema '.' ] variable = value and set ( [ schema1 '.' ] variable1,
.., [ schemaN '.' ] variableN) = (query) */
static sql_exp *
psm_set_exp(sql_query *query, dnode *n)
@@ -94,14 +73,11 @@ psm_set_exp(sql_query *query, dnode *n)
exp_kind ek = {type_value, card_value, FALSE};
const char *sname = qname_schema(qname);
const char *vname = qname_schema_object(qname);
- sql_schema *s = cur_schema(sql);
+ sql_schema *s = NULL;
sql_var *var = NULL;
sql_arg *a = NULL;
- if (sname && !(s = mvc_bind_schema(sql, sname)))
- return sql_error(sql, 02, SQLSTATE(3F000) "SET: No such
schema '%s'", sname);
-
- if (!resolve_variable_on_scope(sql, s, sname, vname, &var, &a,
&tpe, &level, "SET"))
+ if (!find_variable_on_scope(sql, &s, sname, vname, &var, &a,
&tpe, &level, "SET"))
return NULL;
if (!(e = rel_value_exp2(query, &rel, val, sql_sel | sql_psm,
ek)))
return NULL;
@@ -134,14 +110,11 @@ psm_set_exp(sql_query *query, dnode *n)
const char *sname = qname_schema(nqname);
const char *vname = qname_schema_object(nqname);
sql_exp *v = n->data;
- sql_schema *s = cur_schema(sql);
+ sql_schema *s = NULL;
sql_var *var = NULL;
sql_arg *a = NULL;
- if (sname && !(s = mvc_bind_schema(sql, sname)))
- return sql_error(sql, 02, SQLSTATE(3F000) "SET:
No such schema '%s'", sname);
-
- if (!resolve_variable_on_scope(sql, s, sname, vname,
&var, &a, &tpe, &level, "SET"))
+ if (!find_variable_on_scope(sql, &s, sname, vname,
&var, &a, &tpe, &level, "SET"))
return NULL;
v = exp_ref(sql, v);
@@ -181,7 +154,6 @@ rel_psm_declare(mvc *sql, dnode *n)
dlist *qname = ids->data.lval;
const char *sname = qname_schema(qname);
const char *tname = qname_schema_object(qname);
- sql_schema *s = cur_schema(sql);
sql_exp *r = NULL;
sql_arg *a;
@@ -192,7 +164,7 @@ rel_psm_declare(mvc *sql, dnode *n)
return sql_error(sql, 01, SQLSTATE(42000)
"DECLARE: Variable '%s' declared as a parameter", tname);
/* check if we overwrite a scope local variable declare
x; declare x; */
if (frame_find_var(sql, tname))
- return sql_error(sql, 01, SQLSTATE(42000)
"DECLARE: Variable '%s.%s' already declared", s->base.name, tname);
+ return sql_error(sql, 01, SQLSTATE(42000)
"DECLARE: Variable '%s' already declared", tname);
/* variables are put on stack, globals on a separate
list */
if (!frame_push_var(sql, tname, ctype))
return sql_error(sql, 02, SQLSTATE(HY013)
MAL_MALLOC_FAIL);
@@ -589,17 +561,14 @@ rel_select_into( sql_query *query, symbo
dlist *qname = n->data.lval;
const char *sname = qname_schema(qname);
const char *vname = qname_schema_object(qname);
- sql_schema *s = cur_schema(sql);
+ sql_schema *s = NULL;
sql_exp *v = m->data;
int level;
sql_var *var;
sql_subtype *tpe;
sql_arg *a = NULL;
- if (sname && !(s = mvc_bind_schema(sql, sname)))
- return sql_error(sql, 02, SQLSTATE(3F000) "SELECT INTO:
No such schema '%s'", sname);
-
- if (!resolve_variable_on_scope(sql, s, sname, vname, &var, &a,
&tpe, &level, "SELECT INTO"))
+ if (!find_variable_on_scope(sql, &s, sname, vname, &var, &a,
&tpe, &level, "SELECT INTO"))
return NULL;
v = exp_ref(sql, v);
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -973,36 +973,26 @@ table_ref(sql_query *query, sql_rel *rel
}
}
-static inline sql_exp *
-rel_exp_variable_on_scope(mvc *sql, sql_schema *s, const char *sname, const
char *vname)
+static sql_exp *
+rel_exp_variable_on_scope(mvc *sql, const char *sname, const char *vname)
{
+ sql_schema *s = NULL;
+ sql_subtype *tpe;
sql_var *var = NULL;
sql_arg *a = NULL;
int level = 1;
- if (!sname && (var = stack_find_var_frame(sql, vname, &level))) /*
check if variable is known from the stack */
- return exp_param_or_declared(sql->sa, NULL, sa_strdup(sql->sa,
var->name), &(var->var.tpe), level);
- if (!sname && (a = sql_bind_param(sql, vname))) /* then if it is a
parameter */
- return exp_param_or_declared(sql->sa, NULL, sa_strdup(sql->sa,
vname), &(a->type), 1);
- if ((var = find_global_var(sql, s, vname))) /* then if it is a global
var */
- return exp_param_or_declared(sql->sa, sa_strdup(sql->sa,
var->sname), sa_strdup(sql->sa, var->name), &(var->var.tpe), 0);
+ (void) tpe;
+ if (find_variable_on_scope(sql, &s, sname, vname, &var, &a, &tpe,
&level, "SELECT")) {
+ if (var) /* if variable is known from the stack or a global var
*/
+ return exp_param_or_declared(sql->sa, var->sname ?
sa_strdup(sql->sa, var->sname) : NULL, sa_strdup(sql->sa, var->name),
&(var->var.tpe), level);
+ if (a) /* if variable is a parameter */
+ return exp_param_or_declared(sql->sa, NULL,
sa_strdup(sql->sa, vname), &(a->type), level);
+ }
return NULL;
}
static sql_exp *
-rel_var_ref(mvc *sql, const char *sname, const char *vname)
-{
- sql_schema *s = cur_schema(sql);
- sql_exp *res = NULL;
-
- if (sname && !(s = mvc_bind_schema(sql, sname)))
- return sql_error(sql, 02, SQLSTATE(3F000) "SELECT: no such
schema '%s'", sname);
- if (!(res = rel_exp_variable_on_scope(sql, s, sname, vname)))
- return sql_error(sql, 02, SQLSTATE(42000) "SELECT: identifier
'%s%s%s' unknown", sname ? sname : "", sname ? "." : "", vname);
- return res;
-}
-
-static sql_exp *
exps_get_exp(list *exps, int nth)
{
node *n = NULL;
@@ -1126,7 +1116,7 @@ rel_column_ref(sql_query *query, sql_rel
}
}
if (!exp) /* If no column was found, try a variable or
parameter */
- exp = rel_exp_variable_on_scope(sql, cur_schema(sql),
NULL, name);
+ exp = rel_exp_variable_on_scope(sql, NULL, name);
if (!exp)
return sql_error(sql, 02, SQLSTATE(42000) "SELECT:
identifier '%s' unknown", name);
@@ -4968,7 +4958,7 @@ rel_value_exp2(sql_query *query, sql_rel
dlist *l = se->data.lval;
const char *sname = qname_schema(l);
const char *vname = qname_schema_object(l);
- return rel_var_ref(sql, sname, vname);
+ return rel_exp_variable_on_scope(sql, sname, vname);
}
case SQL_VALUES:
case SQL_WITH:
diff --git a/sql/server/sql_semantic.c b/sql/server/sql_semantic.c
--- a/sql/server/sql_semantic.c
+++ b/sql/server/sql_semantic.c
@@ -118,7 +118,7 @@ tmp_schema(mvc *sql)
CALL; \
} \
EXTRA; \
- if (!sql->search_path_has_tmp) { /* if 'tmp' is not in
the search path, search it before all others */ \
+ if (!res && !sql->search_path_has_tmp) { /* if 'tmp' is
not in the search path, search it before all others */ \
found = mvc_bind_schema(sql, "tmp"); \
CALL; \
} \
@@ -149,7 +149,7 @@ tmp_schema(mvc *sql)
#define table_extra \
do { \
- if (strcmp(objstr, "table") == 0 && (res =
stack_find_table(sql, name))) /* for tables, first try a declared table from
the stack */ \
+ if (!res && strcmp(objstr, "table") == 0 && (res =
stack_find_table(sql, name))) /* for tables, first try a declared table from
the stack */ \
return res; \
} while (0)
@@ -203,6 +203,44 @@ find_trigger_on_scope(mvc *sql, sql_sche
return res;
}
+/* A variable can be any of the following, from the innermost to the outermost:
+ - 'parameter of the function' (ie in the param list)
+ - local variable, declared earlier
+ - global variable, also declared earlier
+*/
+#define variable_extra \
+ do { \
+ if (!res) { \
+ if ((*var = stack_find_var_frame(sql, name, level))) {
/* check if variable is known from the stack */ \
+ *tpe = &((*var)->var.tpe); \
+ res = true; \
+ } else if ((*a = sql_bind_param(sql, name))) { /* then
if it is a parameter */ \
+ *tpe = &((*a)->type); \
+ *level = 1; \
+ res = true; \
+ } \
+ } \
+ } while (0)
+
+#define var_find_on_global \
+ do { \
+ if ((*var = find_global_var(sql, found, name))) { /* then if it
is a global var */ \
+ *tpe = &((*var)->var.tpe); \
+ *level = 0; \
+ res = true; \
+ } \
+ } while (0)
+
+bool
+find_variable_on_scope(mvc *sql, sql_schema **s, const char *sname, const char
*name, sql_var **var, sql_arg **a, sql_subtype **tpe, int *level, const char
*error)
+{
+ const char *objstr = "variable";
+ bool res = false;
+
+ search_object_on_path(var_find_on_global, variable_extra,
SQLSTATE(42000));
+ return res;
+}
+
char *
qname_schema(dlist *qname)
{
diff --git a/sql/server/sql_semantic.h b/sql/server/sql_semantic.h
--- a/sql/server/sql_semantic.h
+++ b/sql/server/sql_semantic.h
@@ -27,6 +27,7 @@ extern sql_sequence *find_sequence_on_sc
extern sql_idx *find_idx_on_scope(mvc *sql, sql_schema **s, const char *sname,
const char *name, const char *error);
extern sql_type *find_type_on_scope(mvc *sql, sql_schema **s, const char
*sname, const char *name, const char *error);
extern sql_trigger *find_trigger_on_scope(mvc *sql, sql_schema **s, const char
*sname, const char *name, const char *error);
+extern bool find_variable_on_scope(mvc *sql, sql_schema **s, const char
*sname, const char *name, sql_var **var, sql_arg **a, sql_subtype **tpe, int
*level, const char *error);
extern char *qname_schema(dlist *qname);
extern char *qname_schema_object(dlist *qname);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list