Changeset: 34ab77de43c5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=34ab77de43c5
Modified Files:
sql/backends/monet5/rel_bin.c
sql/backends/monet5/sql_scenario.c
sql/server/rel_schema.c
sql/server/rel_select.c
sql/server/rel_updates.c
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_semantic.c
sql/server/sql_symbol.c
sql/server/sql_symbol.h
sql/server/sql_tokens.h
sql/test/miscellaneous/Tests/groupby_expressions.sql
sql/test/miscellaneous/Tests/groupby_expressions.stable.err
sql/test/miscellaneous/Tests/groupby_expressions.stable.out
Branch: groupby-expressions
Log Message:
Introducing SQL_IDENT token to distinguish arguments from column references.
This allows a more fined grained symbol comparison.
Also moved symbol_cmp code to sql_mvc to eliminate a circular dependency.
diffs (truncated from 764 to 300 lines):
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -1163,7 +1163,7 @@ rel_parse_value(backend *be, char *query
/* get out the single value as we don't want an enclosing projection! */
if (m->sym->token == SQL_SELECT) {
SelectNode *sn = (SelectNode *)m->sym;
- if (sn->selection->h->data.sym->token == SQL_COLUMN) {
+ if (sn->selection->h->data.sym->token == SQL_COLUMN ||
sn->selection->h->data.sym->token == SQL_IDENT) {
int is_last = 0;
sql_rel *rel = NULL;
sql_exp *e = rel_value_exp2(m, &rel,
sn->selection->h->data.sym->data.lval->h->data.sym, sql_sel, ek, &is_last);
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
@@ -1190,7 +1190,7 @@ SQLparser(Client c)
goto finalize;
}
scanner_query_processed(&(m->scanner));
- } else if (caching(m) && cachable(m, NULL) && m->emode != m_prepare &&
(be->q = qc_match(m->qc, m->sym, m->args, m->argc, m->scanner.key ^
m->session->schema->base.id)) != NULL) {
+ } 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;
diff --git a/sql/server/rel_schema.c b/sql/server/rel_schema.c
--- a/sql/server/rel_schema.c
+++ b/sql/server/rel_schema.c
@@ -430,7 +430,7 @@ column_option(
symbol *sym = s->data.sym;
char *err = NULL, *r;
- if (sym->token == SQL_COLUMN) {
+ if (sym->token == SQL_COLUMN || sym->token == SQL_IDENT) {
sql_exp *e = rel_logical_value_exp(sql, NULL, sym,
sql_sel);
if (e && is_atom(e->type)) {
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
@@ -1051,7 +1051,7 @@ rel_column_ref(mvc *sql, sql_rel **rel,
sql_exp *exp = NULL;
dlist *l = NULL;
- assert(column_r->token == SQL_COLUMN && column_r->type == type_list);
+ assert((column_r->token == SQL_COLUMN || column_r->token == SQL_IDENT)
&& column_r->type == type_list);
l = column_r->data.lval;
if (dlist_length(l) == 1 && l->h->type == type_int) {
@@ -2375,6 +2375,7 @@ rel_logical_value_exp(mvc *sql, sql_rel
return exp_atom(sql->sa, atom_dup(sql->sa, an->a));
}
}
+ case SQL_IDENT:
case SQL_COLUMN:
return rel_column_ref(sql, rel, sc, f);
case SQL_UNION:
@@ -3010,6 +3011,7 @@ rel_logical_exp(mvc *sql, sql_rel *rel,
sql_exp *e = exp_atom(sql->sa, atom_dup(sql->sa, an->a));
return rel_select(sql->sa, rel, e);
}
+ case SQL_IDENT:
case SQL_COLUMN: {
sql_rel *or = rel;
sql_exp *e = rel_column_ref(sql, &rel, sc, f);
@@ -4063,7 +4065,8 @@ rel_selection_ref(mvc *sql, sql_rel **re
name = gl->h->data.sval;
for (n = selection->h; n; n = n->next) {
/* we only look for columns */
- if (n->data.sym->token == SQL_COLUMN) {
+ tokens to = n->data.sym->token;
+ if (to == SQL_COLUMN || to == SQL_IDENT) {
dlist *l = n->data.sym->data.lval;
/* AS name */
if (l->h->next->data.sval &&
@@ -4079,12 +4082,12 @@ rel_selection_ref(mvc *sql, sql_rel **re
*/
dlist_append_string(sql->sa, l,
sa_strdup(sql->sa, name));
- sym = symbol_create_list(sql->sa,
SQL_COLUMN, l);
+ sym = symbol_create_list(sql->sa, to,
l);
l = dlist_create(sql->sa);
dlist_append_symbol(sql->sa, l, sym);
/* no alias */
dlist_append_symbol(sql->sa, l, NULL);
- n->data.sym =
symbol_create_list(sql->sa, SQL_COLUMN, l);
+ n->data.sym =
symbol_create_list(sql->sa, to, l);
}
return ve;
@@ -4140,7 +4143,7 @@ rel_order_by_simple_column_exp(mvc *sql,
if (!r || !is_project(r->op) || column_r->type == type_int)
return NULL;
- assert(column_r->token == SQL_COLUMN && column_r->type == type_list);
+ assert((column_r->token == SQL_COLUMN || column_r->token == SQL_IDENT)
&& column_r->type == type_list);
r = r->l;
if (!r)
@@ -4164,7 +4167,7 @@ rel_order_by_simple_column_exp(mvc *sql,
}
if (e)
return e;
- return NULL;
+ return sql_error(sql, 02, SQLSTATE(42000) "ORDER BY: absolute column
names not supported");
}
static list *
@@ -4378,12 +4381,12 @@ rel_order_by(mvc *sql, sql_rel **R, symb
for (; o; o = o->next) {
symbol *order = o->data.sym;
- if (order->token == SQL_COLUMN) {
+ if (order->token == SQL_COLUMN || order->token == SQL_IDENT) {
symbol *col = order->data.lval->h->data.sym;
int direction = order->data.lval->h->next->data.i_val;
sql_exp *e = NULL;
- if (col->token == SQL_COLUMN || col->token == SQL_ATOM)
{
+ if (col->token == SQL_COLUMN || col->token == SQL_IDENT
|| col->token == SQL_ATOM) {
int is_last = 0;
exp_kind ek = {type_value, card_column, FALSE};
@@ -4413,7 +4416,7 @@ rel_order_by(mvc *sql, sql_rel **R, symb
assert(order->data.lval->h->next->type == type_int);
if (or != rel)
return NULL;
- if (!e && sql->session->status != -ERR_AMBIGUOUS &&
col->token == SQL_COLUMN) {
+ if (!e && sql->session->status != -ERR_AMBIGUOUS &&
(col->token == SQL_COLUMN || col->token == SQL_IDENT)) {
/* reset error */
sql->session->status = 0;
sql->errstr[0] = '\0';
@@ -5093,6 +5096,7 @@ rel_value_exp2(mvc *sql, sql_rel **rel,
return rel_aggr(sql, rel, se, f);
case SQL_RANK:
return rel_rankop(sql, rel, se, f);
+ case SQL_IDENT:
case SQL_COLUMN:
return rel_column_ref(sql, rel, se, f );
case SQL_NAME:
@@ -5328,7 +5332,7 @@ rel_table_exp(mvc *sql, sql_rel **rel, s
sql_exp *
rel_column_exp(mvc *sql, sql_rel **rel, symbol *column_e, int f)
{
- if (column_e->token == SQL_COLUMN) {
+ if (column_e->token == SQL_COLUMN || column_e->token == SQL_IDENT) {
return column_exp(sql, rel, column_e, f);
}
return NULL;
diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c
--- a/sql/server/rel_updates.c
+++ b/sql/server/rel_updates.c
@@ -1847,7 +1847,7 @@ rel_parse_val(mvc *m, char *query, char
/* get out the single value as we don't want an enclosing projection! */
if (m->sym && m->sym->token == SQL_SELECT) {
SelectNode *sn = (SelectNode *)m->sym;
- if (sn->selection->h->data.sym->token == SQL_COLUMN) {
+ if (sn->selection->h->data.sym->token == SQL_COLUMN ||
sn->selection->h->data.sym->token == SQL_IDENT) {
int is_last = 0;
sql_rel *r = from;
symbol* sq =
sn->selection->h->data.sym->data.lval->h->data.sym;
diff --git a/sql/server/sql_mvc.c b/sql/server/sql_mvc.c
--- a/sql/server/sql_mvc.c
+++ b/sql/server/sql_mvc.c
@@ -1648,7 +1648,7 @@ stack_get_groupby_expression(mvc *sql, s
{
if(sql->has_groupby_expressions) {
for (int i = sql->topvars-1; i >= 0; i--) {
- if (!sql->vars[i].frame && sql->vars[i].exp &&
sql->vars[i].exp->token == def->token && symbol_cmp(sql->vars[i].exp->sdef,
def)==0) {
+ if (!sql->vars[i].frame && sql->vars[i].exp &&
sql->vars[i].exp->token == def->token && symbol_cmp(sql,
sql->vars[i].exp->sdef, def)==0) {
return sql->vars[i].exp->exp;
}
}
@@ -2082,3 +2082,159 @@ mvc_find_subexp(mvc *m, const char *rnam
}
return NULL;
}
+
+static inline int dlist_cmp(mvc *sql, dlist *l1, dlist *l2);
+
+static inline int
+dnode_cmp(mvc *sql, dnode *d1, dnode *d2)
+{
+ if (d1 == d2)
+ return 0;
+
+ if (!d1 || !d2)
+ return -1;
+
+ if (d1->type == d2->type) {
+ switch (d1->type) {
+ case type_int:
+ return (d1->data.i_val - d2->data.i_val);
+ case type_lng: {
+ lng c = d1->data.l_val - d2->data.l_val;
+ assert((lng) GDK_int_min <= c && c <= (lng)
GDK_int_max);
+ return (int) c;
+ }
+ case type_string:
+ if (d1->data.sval == d2->data.sval)
+ return 0;
+ if (!d1->data.sval || !d2->data.sval)
+ return -1;
+ return strcmp(d1->data.sval, d2->data.sval);
+ case type_list:
+ return dlist_cmp(sql, d1->data.lval,
d2->data.lval);
+ case type_symbol:
+ return symbol_cmp(sql, d1->data.sym,
d2->data.sym);
+ case type_type:
+ return subtype_cmp(&d1->data.typeval,
&d2->data.typeval);
+ default:
+ assert(0);
+ }
+ }
+ return -1;
+}
+
+static inline int
+dlist_cmp(mvc *sql, dlist *l1, dlist *l2)
+{
+ int res = 0;
+ dnode *d1, *d2;
+
+ if (l1 == l2)
+ return 0;
+
+ if (!l1 || !l2 || dlist_length(l1) != dlist_length(l2))
+ return -1;
+
+ for (d1 = l1->h, d2 = l2->h; !res && d1; d1 = d1->next, d2 = d2->next) {
+ res = dnode_cmp(sql, d1, d2);
+ }
+ return res;
+}
+
+static inline int
+AtomNodeCmp(AtomNode *a1, AtomNode *a2)
+{
+ if (a1 == a2)
+ return 0;
+ if (!a1 || !a2)
+ return -1;
+ if (a1->a && a2->a)
+ return atom_cmp(a1->a, a2->a);
+ return -1;
+}
+
+static inline int
+SelectNodeCmp(mvc *sql, SelectNode *s1, SelectNode *s2)
+{
+ if (s1 == s2)
+ return 0;
+ if (!s1 || !s2)
+ return -1;
+
+ if (symbol_cmp(sql, s1->limit, s2->limit) == 0 &&
+ symbol_cmp(sql, s1->offset, s2->offset) == 0 &&
+ symbol_cmp(sql, s1->sample, s2->sample) == 0 &&
+ s1->distinct == s2->distinct &&
+ s1->lateral == s2->lateral &&
+ symbol_cmp(sql, s1->name, s2->name) == 0 &&
+ symbol_cmp(sql, s1->orderby, s2->orderby) == 0 &&
+ symbol_cmp(sql, s1->having, s2->having) == 0 &&
+ symbol_cmp(sql, s1->groupby, s2->groupby) == 0 &&
+ symbol_cmp(sql, s1->where, s2->where) == 0 &&
+ symbol_cmp(sql, s1->from, s2->from) == 0 &&
+ symbol_cmp(sql, s1->window, s2->window) == 0 &&
+ dlist_cmp(sql, s1->selection, s2->selection) == 0)
+ return 0;
+ return -1;
+}
+
+static inline int
+_symbol_cmp(mvc *sql, symbol *s1, symbol *s2)
+{
+ if (s1 == s2)
+ return 0;
+ if (!s1 || !s2)
+ return -1;
+ if (s1->token != s2->token || s1->type != s2->type)
+ return -1;
+ switch (s1->type) {
+ case type_int:
+ return (s1->data.i_val - s2->data.i_val);
+ case type_lng: {
+ lng c = s1->data.l_val - s2->data.l_val;
+ assert((lng) GDK_int_min <= c && c <= (lng)
GDK_int_max);
+ return (int) c;
+ }
+ case type_string:
+ if (s1->data.sval == s2->data.sval)
+ return 0;
+ if (!s1->data.sval || !s2->data.sval)
+ return -1;
+ return strcmp(s1->data.sval, s2->data.sval);
+ case type_list: {
+ if (s1->token == SQL_IDENT) {
+ atom *at1, *at2;
+
+ if (s2->token != SQL_IDENT)
+ return -1;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list