Changeset: f9f30e5adfdb for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=f9f30e5adfdb
Modified Files:
sql/server/rel_exp.c
sql/server/rel_exp.h
sql/server/rel_rel.c
sql/server/rel_rel.h
sql/server/rel_select.c
sql/server/rel_unnest.c
Branch: sq2
Log Message:
pass rank/window functions a normal functions + list (group by expressions's,
order by expression's).
rewrite these into projection(s) in the rel_unnest.c file/phase
diffs (truncated from 514 to 300 lines):
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -232,6 +232,21 @@ exp_op( sql_allocator *sa, list *l, sql_
}
sql_exp *
+exp_rank_op( sql_allocator *sa, list *l, list *gbe, list *obe, sql_subfunc *f )
+{
+ sql_exp *e = exp_create(sa, e_func);
+ if (e == NULL)
+ return NULL;
+ e->card = exps_card(l);
+ if (!l || list_length(l) == 0)
+ e->card = CARD_ATOM; /* unop returns a single atom */
+ e->l = l;
+ e->r = append(append(sa_list(sa), gbe), obe);
+ e->f = f;
+ return e;
+}
+
+sql_exp *
exp_aggr( sql_allocator *sa, list *l, sql_subaggr *a, int distinct, int
no_nils, unsigned int card, int has_nils )
{
sql_exp *e = exp_create(sa, e_aggr);
@@ -1704,7 +1719,7 @@ exps_bind_column( list *exps, const char
for (en = exps->h; en; en = en->next ) {
sql_exp *ce = en->data;
if (ce->alias.name && strcmp(ce->alias.name, cname) ==
0) {
- if (e) {
+ if (e && e != ce && ce->alias.rname &&
e->alias.rname && strcmp(ce->alias.rname, e->alias.rname) != 0 ) {
if (ambiguous)
*ambiguous = 1;
return NULL;
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -32,6 +32,7 @@ extern sql_exp *exp_in(sql_allocator *sa
extern sql_exp *exp_convert(sql_allocator *sa, sql_exp *exp, sql_subtype
*fromtype, sql_subtype *totype );
extern str number2name(str s, int len, int i);
extern sql_exp *exp_op(sql_allocator *sa, list *l, sql_subfunc *f );
+extern sql_exp *exp_rank_op(sql_allocator *sa, list *largs, list *gbe, list
*obe, sql_subfunc *f );
#define append(l,v) list_append(l,v)
#define exp_unop(sa,l,f) \
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
@@ -348,6 +348,17 @@ rel_bind_column2( mvc *sql, sql_rel *rel
return NULL;
}
+sql_exp *
+rel_first_column(mvc *sql, sql_rel *r)
+{
+ list *exps = rel_projections(sql, r, NULL, 1, 1);
+
+ if (!list_empty(exps))
+ return exps->h->data;
+
+ return NULL;
+}
+
sql_rel *
rel_inplace_setop(sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop,
list *exps)
{
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
@@ -54,6 +54,7 @@ extern sql_rel *rel_select_copy(sql_allo
extern sql_exp *rel_bind_column( mvc *sql, sql_rel *rel, const char *cname,
int f );
extern sql_exp *rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname,
const char *cname, int f );
+extern sql_exp *rel_first_column(mvc *sql, sql_rel *rel);
extern sql_rel *rel_inplace_setop(sql_rel *rel, sql_rel *l, sql_rel *r,
operator_type setop, list *exps);
extern sql_rel *rel_inplace_project(sql_allocator *sa, sql_rel *rel, sql_rel
*l, list *e);
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
@@ -5091,43 +5091,6 @@ get_window_clauses(mvc *sql, char* ident
return window_specification; //return something to say there were no
errors
}
-static sql_exp*
-opt_groupby_add_exp(mvc *sql, sql_rel *p, sql_rel *pp, sql_exp *in)
-{
- sql_exp *found;
-
- if (p->op == op_groupby) {
- if (!exp_name(in))
- exp_label(sql->sa, in, ++sql->label);
- found = exps_find_exp( p->exps, in);
- if (!found)
- append(p->exps, in);
- else
- in = found;
- in = exp_ref(sql->sa, in);
- } else if (pp && pp->op == op_groupby) {
- if (!exp_name(in))
- exp_label(sql->sa, in, ++sql->label);
- found = exps_find_exp( p->exps, in);
- if (!found) {
- sql_rel *l = p->l;
-
- while (l && l != pp && !is_base(l->op)) {
- if (!exps_find_exp(l->exps, in)) {
- if (is_project(l->op))
- append(l->exps,
exp_copy(sql->sa, in));
- } else
- break;
- l = l->l;
- }
- append(p->exps, in);
- } else
- in = found;
- in = exp_ref(sql->sa, in);
- }
- return in;
-}
-
/*
* select x, y, rank_op() over (partition by x order by y) as, ...
aggr_op(z) over (partition by y order by x) as, ...
@@ -5153,11 +5116,11 @@ rel_rankop(sql_query *query, sql_rel **r
char *aname = NULL, *sname = NULL, *window_ident = NULL;
sql_subfunc *wf = NULL;
sql_exp *in = NULL, *pe = NULL, *oe = NULL, *call = NULL, *start =
NULL, *eend = NULL, *fstart = NULL, *fend = NULL;
- sql_rel *r = *rel, *p, *pp, *g = NULL;
+ sql_rel /**r = *rel,*/ *p, *pp/*, *g = NULL*/;
list *gbe = NULL, *obe = NULL, *args = NULL, *types = NULL, *fargs =
NULL;
sql_schema *s = sql->session->schema;
dnode *dn = window_function->data.lval->h;
- int distinct = 0, project_added = 0, is_last, frame_type, pos, group =
0, nf = f;
+ int distinct = 0, is_last, frame_type, pos, nf = f;
bool is_nth_value, supports_frames;
stack_clear_frame_visited_flag(sql); //clear visited flags before
iterating
@@ -5209,144 +5172,36 @@ rel_rankop(sql_query *query, sql_rel **r
return NULL;
}
- /*
- * We need to keep track of the input relation, pp (projection)
- * which may in the first step (which could be in the partitioning,
ordering or window operator) change into a group by.
- * then we project the partitioning/ordering + require result columns
(p).
- * followed by the projection with window operators.
- */
/* window operations are only allowed in the projection */
- if (r && r->op != op_project) {
- *rel = r = rel_project(sql->sa, r, rel_projections(sql, r,
NULL, 1, 1));
- reset_processed(r);
- project_added = 1;
- }
- if (!is_sql_sel(f) || !r || !is_project(r->op))
+ if (!is_sql_sel(f))
return sql_error(sql, 02, SQLSTATE(42000) "OVER: only possible
within the selection");
- /* outer project (*rel) r r->l will be rewritten!
- * in case of project_added (ie outer project added) we add the
expression to r
- * rank project (new or existing non processed project) pp (needed for
rank)
- * inner project/groupby p (if groupby group is set)
- * op used to reset p
- */
- p = r->l;
- if (!p || (!is_joinop(p->op) && !p->exps->h)) { //no from clause, use a
constant as the expression to project
- sql_exp *exp = exp_atom_lng(sql->sa, 0);
- exp_label(sql->sa, exp, ++sql->label);
- if (!p) {
- p = rel_project(sql->sa, NULL, sa_list(sql->sa));
- set_processed(p);
- }
- append(p->exps, exp);
- }
-
- if (p && p->op != op_project) {
- p = rel_project(sql->sa, p, rel_projections(sql, p, NULL, 1,
1));
- reset_processed(p);
- }
- pp = p;
-
- g = p;
- while (g && !group) {
- if (g && g->op == op_groupby) {
- group = 1;
- } else if (g->l && !is_processed(g) && !is_base(g->op)) {
- g = g->l;
- } else {
- g = NULL;
- }
- }
+ p = pp = *rel;
/* Partition By */
if (partition_by_clause) {
gbe = rel_group_by(query, &pp, partition_by_clause, NULL /*
cannot use (selection) column references, as this result is a selection column
*/, nf | sql_window);
- if (!gbe && !group) { /* try with implicit groupby */
- /* reset error */
- sql->session->status = 0;
- sql->errstr[0] = '\0';
- p = pp = rel_project(sql->sa, p, sa_list(sql->sa));
- reset_processed(p);
- gbe = rel_group_by(query, &p, partition_by_clause, NULL
/* cannot use (selection) column references, as this result is a selection
column */, f | sql_window);
- }
if (!gbe)
return NULL;
-
- if (p->op == op_groupby) {
- sql_rel *npp = pp;
-
- pp = g = p;
- p = rel_project(sql->sa, npp, rel_projections(sql, npp,
NULL, 1, 0));
- reset_processed(p);
- }
-
for (n = gbe->h ; n ; n = n->next) {
sql_exp *en = n->data;
- n->data = en = opt_groupby_add_exp(sql, p, group?g:pp,
en);
set_direction(en, 1);
}
- p->r = gbe;
- }
+ }
+
/* Order By */
if (order_by_clause) {
obe = rel_order_by(query, &pp, order_by_clause, nf |
sql_window);
- if (!obe && !group && !gbe) { /* try with implicit groupby */
- /* reset error */
- sql->session->status = 0;
- sql->errstr[0] = '\0';
- p = pp = rel_project(sql->sa, p, sa_list(sql->sa));
- reset_processed(p);
- obe = rel_order_by(query, &p, order_by_clause, f |
sql_window);
- }
if (!obe)
return NULL;
-
- if (p->op == op_groupby) {
- sql_rel *npp = pp;
-
- pp = g = p;
- p = rel_project(sql->sa, npp, rel_projections(sql, npp,
NULL, 1, 0));
- reset_processed(p);
- }
-
for (n = obe->h ; n ; n = n->next) {
- sql_exp *oexp = n->data, *nexp;
-
- if (is_sql_sel(f) && pp->op == op_project &&
!is_processed(pp) && !rel_find_exp(pp, oexp)) {
- append(pp->exps, oexp);
- if (!exp_name(oexp))
- exp_label(sql->sa, oexp, ++sql->label);
- oexp = exp_ref(sql->sa, oexp);
- }
- n->data = nexp = opt_groupby_add_exp(sql, p,
group?g:pp, oexp);
+ sql_exp *oexp = n->data, *nexp = oexp;
+
if (is_ascending(oexp))
set_direction(nexp, 1);
if (nulls_last(oexp))
set_direction(nexp, 2);
}
- if (p->r) {
- p->r = list_merge(sa_list(sql->sa), p->r, (fdup)NULL);
/* make sure the p->r is a different list than the gbe list */
- for(n = obe->h ; n ; n = n->next) {
- sql_exp *e1 = n->data;
- bool found = false;
-
- for(node *nn = ((list*)p->r)->h ; nn && !found
; nn = nn->next) {
- sql_exp *e2 = nn->data;
- //the partition expression order should
be the same as the one in the order by clause (if it's in there as well)
- if(!exp_equal(e1, e2)) {
- if(is_ascending(e1))
- e2->flag |= ASCENDING;
- else
- e2->flag &= ~ASCENDING;
- found = true;
- }
- }
- if(!found)
- append(p->r, e1);
- }
- } else {
- p->r = obe;
- }
}
fargs = sa_list(sql->sa);
@@ -5358,14 +5213,9 @@ rel_rankop(sql_query *query, sql_rel **r
int nfargs = 0;
if (!dnn || is_ntile) { //pass an input column for analytic
functions that don't require it
- sql_rel *lr = p;
-
- if (!lr || !is_project(lr->op)) {
- p = pp = rel_project(sql->sa, p,
rel_projections(sql, p, NULL, 1, 0));
- reset_processed(p);
- lr = p->l;
- }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list