Changeset: 7a0a5759557d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7a0a5759557d
Modified Files:
cmake/os_release_info.cmake
sql/server/rel_rel.h
sql/server/rel_select.c
sql/server/sql_parser.y
sql/server/sql_scan.c
sql/server/sql_symbol.c
sql/server/sql_symbol.h
sql/test/Tests/window_functions.test
sql/test/analytics/Tests/analytics18.test
Branch: default
Log Message:
initial support for qualify
diffs (truncated from 558 to 300 lines):
diff --git a/cmake/os_release_info.cmake b/cmake/os_release_info.cmake
--- a/cmake/os_release_info.cmake
+++ b/cmake/os_release_info.cmake
@@ -29,7 +29,7 @@ set(_os_release_info TRUE)
# of the local cmake environment.
# Set cmake policies for at least this level:
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
# Function get_os_release_info - Determine and return OS name and version
diff --git a/sql/server/rel_rel.h b/sql/server/rel_rel.h
--- a/sql/server/rel_rel.h
+++ b/sql/server/rel_rel.h
@@ -36,6 +36,7 @@
#define sql_or (1 << 16) //ORed
#define sql_merge (1 << 17) //ORed
#define sql_no_subquery (1 << 18) //ORed
+#define sql_qualify (1 << 19) //ORed
#define is_sql_from(X) ((X & sql_from) == sql_from)
#define is_sql_where(X) ((X & sql_where) == sql_where)
@@ -56,6 +57,7 @@
#define is_sql_or(X) ((X & sql_or) == sql_or)
#define is_sql_merge(X) ((X & sql_merge) == sql_merge)
#define is_sql_no_subquery(X) ((X & sql_no_subquery) == sql_no_subquery)
+#define is_sql_qualify(X) ((X & sql_qualify) == sql_qualify)
#define is_anyequal_func(sf) (strcmp((sf)->func->base.name, "sql_anyequal") ==
0 || strcmp((sf)->func->base.name, "sql_not_anyequal") == 0)
#define is_anyequal(sf) (strcmp((sf)->func->base.name, "sql_anyequal") == 0)
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
@@ -1508,10 +1508,6 @@ rel_column_ref(sql_query *query, sql_rel
else
exp->card = CARD_ATOM;
set_freevar(exp, i);
- /*
- if (exp->alias.label == exp->nid)
- exp->alias.label = -(sql->nid++);
- */
if (!is_sql_where(of) && !is_sql_aggr(of) &&
!is_sql_aggr(f) && !outer->grouped)
set_outer(outer);
}
@@ -1610,10 +1606,6 @@ rel_column_ref(sql_query *query, sql_rel
else
exp->card = CARD_ATOM;
set_freevar(exp, i);
- /*
- if (exp->alias.label == exp->nid)
- exp->alias.label = -(sql->nid++);
- */
if (!is_sql_where(of) && !is_sql_aggr(of) &&
!is_sql_aggr(f) && !outer->grouped)
set_outer(outer);
}
@@ -2356,115 +2348,6 @@ rel_in_exp(sql_query *query, sql_rel *re
return rel_select_add_exp(sql->sa, rel, e);
}
-static bool
-not_symbol_can_be_propagated(mvc *sql, symbol *sc)
-{
- switch (sc->token) {
- case SQL_IN:
- case SQL_NOT_IN:
- case SQL_EXISTS:
- case SQL_NOT_EXISTS:
- case SQL_LIKE:
- case SQL_NOT_LIKE:
- case SQL_BETWEEN:
- case SQL_NOT_BETWEEN:
- case SQL_IS_NULL:
- case SQL_IS_NOT_NULL:
- case SQL_NOT:
- case SQL_COMPARE:
- return true;
- case SQL_AND:
- case SQL_OR: {
- symbol *lo = sc->data.lval->h->data.sym;
- symbol *ro = sc->data.lval->h->next->data.sym;
- return not_symbol_can_be_propagated(sql, lo) &&
not_symbol_can_be_propagated(sql, ro);
- }
- default:
- return false;
- }
-}
-
-/* Warning, this function assumes the entire bison tree can be negated, so
call it after 'not_symbol_can_be_propagated' */
-static symbol *
-negate_symbol_tree(mvc *sql, symbol *sc)
-{
- switch (sc->token) {
- case SQL_IN:
- sc->token = SQL_NOT_IN;
- break;
- case SQL_NOT_IN:
- sc->token = SQL_IN;
- break;
- case SQL_EXISTS:
- sc->token = SQL_NOT_EXISTS;
- break;
- case SQL_NOT_EXISTS:
- sc->token = SQL_EXISTS;
- break;
- case SQL_LIKE:
- sc->token = SQL_NOT_LIKE;
- break;
- case SQL_NOT_LIKE:
- sc->token = SQL_LIKE;
- break;
- case SQL_BETWEEN:
- sc->token = SQL_NOT_BETWEEN;
- break;
- case SQL_NOT_BETWEEN:
- sc->token = SQL_BETWEEN;
- break;
- case SQL_IS_NULL:
- sc->token = SQL_IS_NOT_NULL;
- break;
- case SQL_IS_NOT_NULL:
- sc->token = SQL_IS_NULL;
- break;
- case SQL_NOT: { /* nested NOTs eliminate each other */
- if (sc->data.sym->token == SQL_ATOM) {
- AtomNode *an = (AtomNode*) sc->data.sym;
- sc = newAtomNode(sql->sa, an->a);
- } else if (sc->data.sym->token == SQL_SELECT) {
- SelectNode *sn = (SelectNode*) sc->data.sym;
- sc = newSelectNode(sql->sa, sn->distinct,
sn->selection, sn->into, sn->from, sn->where, sn->groupby, sn->having,
- sn->orderby,
sn->name, sn->limit, sn->offset, sn->sample, sn->seed, sn->window);
- } else {
- memmove(sc, sc->data.sym, sizeof(symbol));
- }
- } break;
- case SQL_COMPARE: {
- dnode *cmp_n = sc->data.lval->h;
- comp_type neg_cmp_type =
negate_compare(compare_str2type(cmp_n->next->data.sval)); /* negate the
comparator */
- if (cmp_n->next->next->next) {
- switch(cmp_n->next->next->next->data.i_val)
- {
- case 0: /* negating ANY/ALL */
- cmp_n->next->next->next->data.i_val = 1;
- break;
- case 1: /* negating ANY/ALL */
- cmp_n->next->next->next->data.i_val = 0;
- break;
- case 2: /* negating IS [NOT] DINSTINCT FROM */
- cmp_n->next->next->next->data.i_val = 3;
- break;
- case 3: /* negating IS [NOT] DINSTINCT FROM */
- cmp_n->next->next->next->data.i_val = 2;
- break;
- }
- }
- cmp_n->next->data.sval = sa_strdup(sql->sa,
compare_func(neg_cmp_type, 0));
- } break;
- case SQL_AND:
- case SQL_OR: {
- sc->data.lval->h->data.sym = negate_symbol_tree(sql,
sc->data.lval->h->data.sym);
- sc->data.lval->h->next->data.sym= negate_symbol_tree(sql,
sc->data.lval->h->next->data.sym);
- sc->token = sc->token == SQL_AND ? SQL_OR : SQL_AND;
- } break;
- default:
- break;
- }
- return sc;
-}
-
static int
exp_between_check_types(sql_subtype *res, sql_subtype *t1, sql_subtype *t2,
sql_subtype *t3)
{
@@ -2742,10 +2625,6 @@ rel_logical_value_exp(sql_query *query,
return le;
}
case SQL_NOT: {
- if (not_symbol_can_be_propagated(sql, sc->data.sym)) {
- sc->data.sym = negate_symbol_tree(sql, sc->data.sym);
- return rel_logical_value_exp(query, rel, sc->data.sym,
f, ek);
- }
sql_exp *le = rel_value_exp(query, rel, sc->data.sym,
f|sql_farg, ek);
if (!le)
@@ -3015,10 +2894,6 @@ rel_logical_exp(sql_query *query, sql_re
return rel_select_push_compare_exp_down(sql, rel, le, le->l,
le->r, NULL, f);
}
case SQL_NOT: {
- if (not_symbol_can_be_propagated(sql, sc->data.sym)) {
- sc->data.sym = negate_symbol_tree(sql, sc->data.sym);
- return rel_logical_exp(query, rel, sc->data.sym, f);
- }
sql_exp *le = rel_value_exp(query, &rel, sc->data.sym,
f|sql_farg, ek);
sql_subtype bt;
@@ -4912,7 +4787,7 @@ rel_rankop(sql_query *query, sql_rel **r
}
/* window operations are only allowed in the projection */
- if (!is_sql_sel(f))
+ if (!is_sql_sel(f) && !is_sql_qualify(f))
return sql_error(sql, 02, SQLSTATE(42000) "OVER: only possible
within the selection");
p = *rel;
@@ -5488,50 +5363,48 @@ rel_table_exp(sql_query *query, sql_rel
return NULL;
}
-
- list *exps = NULL;
- sql_rel *project = *rel, *groupby = NULL;
-
- /* if there's a group by relation in the tree, skip it for the
'*' case and use the underlying projection */
- if (project) {
- while (is_groupby(project->op) ||
is_select(project->op)) {
- if (is_groupby(project->op))
- groupby = project;
- if (project->l)
- project = project->l;
- }
- assert(project);
- }
-
- if (project->op == op_project && project->l && project == *rel
&& !tname && !rel_is_ref(project) && !need_distinct(project) && single_exp) {
- sql_rel *l = project->l;
- if (!l || !is_project(l->op) ||
list_length(project->exps) == list_length(l->exps)) {
- rel_remove_internal_exp(*rel);
- exps = project->exps;
- *rel = project->l;
- }
- }
- if ((exps || (exps = rel_table_projections(sql, project, tname,
0)) != NULL) && !list_empty(exps)) {
- if (!(exps = check_distinct_exp_names(sql, exps)))
- return sql_error(sql, 02, SQLSTATE(42000)
"Duplicate column names in table%s%s%s projection list", tname ? " '" : "",
tname ? tname : "", tname ? "'" : "");
- if (groupby) {
- groupby->exps = group_merge_exps(sql,
groupby->exps, exps);
- for (node *n = groupby->exps->h ; n ; n =
n->next) {
- sql_exp *e = n->data;
-
- if (e->card > groupby->card) {
- if (exp_name(e) &&
!has_label(e))
- return sql_error(sql,
ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in
query results without an aggregate function", exp_name(e));
- return sql_error(sql,
ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query
results without an aggregate function");
- }
+ list *exps = NULL;
+ sql_rel *project = *rel, *groupby = NULL;
+
+ /* if there's a group by relation in the tree, skip it for the '*' case
and use the underlying projection */
+ if (project) {
+ while (is_groupby(project->op) || is_select(project->op)) {
+ if (is_groupby(project->op))
+ groupby = project;
+ if (project->l)
+ project = project->l;
+ }
+ assert(project);
+ }
+
+ if (project->op == op_project && project->l && project == *rel &&
!tname && !rel_is_ref(project) && !need_distinct(project) && single_exp) {
+ sql_rel *l = project->l;
+ if (!l || !is_project(l->op) || list_length(project->exps) ==
list_length(l->exps)) {
+ rel_remove_internal_exp(*rel);
+ exps = project->exps;
+ *rel = project->l;
+ }
+ }
+ if ((exps || (exps = rel_table_projections(sql, project, tname, 0)) !=
NULL) && !list_empty(exps)) {
+ if (!(exps = check_distinct_exp_names(sql, exps)))
+ return sql_error(sql, 02, SQLSTATE(42000) "Duplicate
column names in table%s%s%s projection list", tname ? " '" : "", tname ? tname
: "", tname ? "'" : "");
+ if (groupby) {
+ groupby->exps = group_merge_exps(sql, groupby->exps,
exps);
+ for (node *n = groupby->exps->h ; n ; n = n->next) {
+ sql_exp *e = n->data;
+
+ if (e->card > groupby->card) {
+ if (exp_name(e) && !has_label(e))
+ return sql_error(sql,
ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in
query results without an aggregate function", exp_name(e));
+ return sql_error(sql, ERR_GROUPBY,
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results
without an aggregate function");
}
}
- return exps;
- }
- if (!tname)
- return sql_error(sql, 02, SQLSTATE(42000) "Table
expression without table name");
- return sql_error(sql, 02, SQLSTATE(42000) "Column expression
Table '%s' unknown", tname);
- //return NULL;
+ }
+ return exps;
+ }
+ if (!tname)
+ return sql_error(sql, 02, SQLSTATE(42000) "Table expression
without table name");
+ return sql_error(sql, 02, SQLSTATE(42000) "Column expression Table '%s'
unknown", tname);
}
sql_exp *
@@ -5616,6 +5489,11 @@ rel_having_limits_nodes(sql_query *query
rel->l = inner;
}
+ if (sn->qualify) {
+ if (!(rel = rel_logical_exp(query, rel, sn->qualify,
sql_qualify)))
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]