Changeset: ea48b93845dc for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ea48b93845dc
Modified Files:
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql_gencode.c
        sql/backends/monet5/sql_result.c
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_select.c
        sql/server/rel_unnest.c
        sql/test/sample/Tests/sample.15.stable.out
Branch: Jun2020
Log Message:

Push down sample relations on the same way as topn ones. Also fixed a bug where 
the projection of a sample query was not exported in a prepared statement


diffs (truncated from 364 to 300 lines):

diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -73,7 +73,7 @@ rel_no_mitosis(sql_rel *rel)
 
        if (!rel || is_basetable(rel->op))
                return 1;
-       if (is_topn(rel->op) || rel->op == op_project)
+       if (is_topn(rel->op) || is_sample(rel->op) || 
is_simple_project(rel->op))
                return rel_no_mitosis(rel->l);
        if (is_modify(rel->op) && rel->card <= CARD_AGGR) {
                if (is_delete(rel->op))
@@ -5451,7 +5451,7 @@ SQLsession_prepared_statements_args(Clie
                        int arg_number = 0;
                        bte inout = ARG_OUT;
 
-                       if (r && is_topn(r->op))
+                       if (r && (is_topn(r->op) || is_sample(r->op)))
                                r = r->l;
 
                        if (r && is_project(r->op) && r->exps) {
diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -117,7 +117,7 @@ relational_func_create_result(mvc *sql, 
 
        if (q == NULL)
                return NULL;
-       if (is_topn(r->op))
+       if (is_topn(r->op) || is_sample(r->op))
                r = r->l;
        if (!is_project(r->op))
                r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1, 
1));
@@ -320,7 +320,7 @@ static int
                return -1;
        }
 
-       if (is_topn(r->op))
+       if (is_topn(r->op) || is_sample(r->op))
                r = r->l;
        if (!is_project(r->op))
                r = rel_project(m->sa, r, rel_projections(m, r, NULL, 1, 1));
diff --git a/sql/backends/monet5/sql_result.c b/sql/backends/monet5/sql_result.c
--- a/sql/backends/monet5/sql_result.c
+++ b/sql/backends/monet5/sql_result.c
@@ -1063,7 +1063,7 @@ mvc_export_prepare(mvc *c, stream *out, 
        if (!out)
                return 0;
 
-       if (r && is_topn(r->op))
+       if (r && (is_topn(r->op) || is_sample(r->op)))
                r = r->l;
        if (r && is_project(r->op) && r->exps) {
                unsigned int max2 = 10, max3 = 10;      /* to help calculate 
widths */
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -1960,7 +1960,7 @@ sum_limit_offset(mvc *sql, list *exps )
 }
 
 static int 
-topn_save_exps( list *exps )
+topn_sample_save_exps( list *exps )
 {
        node *n;
 
@@ -2036,22 +2036,24 @@ rel_rename_exps( mvc *sql, list *exps1, 
 }
 
 static sql_rel *
-rel_push_topn_down(mvc *sql, sql_rel *rel, int *changes)
+rel_push_topn_and_sample_down(mvc *sql, sql_rel *rel, int *changes)
 {
        sql_rel *rl, *r = rel->l;
 
-       if (rel->op == op_topn && topn_save_exps(rel->exps)) {
+       if ((is_topn(rel->op) || is_sample(rel->op)) && 
topn_sample_save_exps(rel->exps)) {
                sql_rel *rp = NULL;
-
-               if (r && r->op == op_project && need_distinct(r)) 
+               operator_type relation_type = is_topn(rel->op) ? op_topn : 
op_sample;
+               sql_rel *(*func) (sql_allocator *, sql_rel *, list *) = 
is_topn(rel->op) ? rel_topn : rel_sample;
+
+               if (r && is_simple_project(r->op) && need_distinct(r)) 
                        return rel;
 
-               /* push topN under projections */
-
-               if (r && r->op == op_project && !need_distinct(r) && 
!rel_is_ref(r) && r->l && !r->r) {
+               /* push topn/sample under projections */
+
+               if (r && is_simple_project(r->op) && !need_distinct(r) && 
!rel_is_ref(r) && r->l && !r->r) {
                        sql_rel *x = r, *px = x;
 
-                       while(x->op == op_project && !need_distinct(x) && 
!rel_is_ref(x) && x->l && !x->r) {
+                       while (x && is_simple_project(x->op) && 
!need_distinct(x) && !rel_is_ref(x) && x->l && !x->r) {
                                px = x;
                                x = x->l;
                        }
@@ -2063,52 +2065,51 @@ rel_push_topn_down(mvc *sql, sql_rel *re
                        return rel;
                }
 
-               /* duplicate topn direct under union */
-
-               if (r && r->exps && r->op == op_union && !(rel_is_ref(r)) && 
r->l) {
+               /* duplicate topn/sample direct under union */
+
+               if (r && r->exps && is_union(r->op) && !rel_is_ref(r) && r->l) {
                        sql_rel *u = r, *x;
                        sql_rel *ul = u->l;
                        sql_rel *ur = u->r;
 
                        /* only push topn once */
                        x = ul;
-                       while(x->op == op_project && x->l)
+                       while (is_simple_project(x->op) && x->l)
                                x = x->l;
-                       if (x && x->op == op_topn)
+                       if (x && x->op == relation_type)
                                return rel;
                        x = ur;
-                       while(x->op == op_project && x->l)
+                       while (is_simple_project(x->op) && x->l)
                                x = x->l;
-                       if (x && x->op == op_topn)
+                       if (x && x->op == relation_type)
                                return rel;
 
-                       ul = rel_topn(sql->sa, ul, sum_limit_offset(sql, 
rel->exps));
-                       ur = rel_topn(sql->sa, ur, sum_limit_offset(sql, 
rel->exps));
+                       ul = func(sql->sa, ul, sum_limit_offset(sql, 
rel->exps));
+                       ur = func(sql->sa, ur, sum_limit_offset(sql, 
rel->exps));
                        u->l = ul;
                        u->r = ur;
                        (*changes)++;
                        return rel;
                }
-               /* duplicate topn + [ project-order ] under union */
+               /* duplicate topn/sample + [ project-order ] under union */
                if (r)
                        rp = r->l;
-               if (r && r->exps && r->op == op_project && !(rel_is_ref(r)) && 
r->r && r->l &&
-                   rp->op == op_union) {
+               if (r && r->exps && is_simple_project(r->op) && !rel_is_ref(r) 
&& r->r && r->l && is_union(rp->op)) {
                        sql_rel *u = rp, *ou = u, *x;
                        sql_rel *ul = u->l;
                        sql_rel *ur = u->r;
                        int add_r = 0;
 
-                       /* only push topn once */
+                       /* only push topn/sample once */
                        x = ul;
-                       while(x->op == op_project && x->l)
+                       while (is_simple_project(x->op) && x->l)
                                x = x->l;
-                       if (x && x->op == op_topn)
+                       if (x && x->op == relation_type)
                                return rel;
                        x = ur;
-                       while(x->op == op_project && x->l)
+                       while (is_simple_project(x->op) && x->l)
                                x = x->l;
-                       if (x && x->op == op_topn)
+                       if (x && x->op == relation_type)
                                return rel;
 
                        if (list_length(ul->exps) > list_length(r->exps))
@@ -2132,7 +2133,7 @@ rel_push_topn_down(mvc *sql, sql_rel *re
                                ul->exps = list_merge(ul->exps, exps_copy(sql, 
r->r), NULL);
                        ul->nrcols = list_length(ul->exps);
                        ul->r = exps_copy(sql, r->r);
-                       ul = rel_topn(sql->sa, ul, sum_limit_offset(sql, 
rel->exps));
+                       ul = func(sql->sa, ul, sum_limit_offset(sql, 
rel->exps));
 
                        ur = rel_project(sql->sa, ur, NULL);
                        ur->exps = exps_copy(sql, r->exps);
@@ -2141,7 +2142,7 @@ rel_push_topn_down(mvc *sql, sql_rel *re
                                ur->exps = list_merge(ur->exps, exps_copy(sql, 
r->r), NULL);
                        ur->nrcols = list_length(ur->exps);
                        ur->r = exps_copy(sql, r->r);
-                       ur = rel_topn(sql->sa, ur, sum_limit_offset(sql, 
rel->exps));
+                       ur = func(sql->sa, ur, sum_limit_offset(sql, 
rel->exps));
 
                        u = rel_setop(sql->sa, ul, ur, op_union);
                        u->exps = exps_alias(sql, r->exps); 
@@ -2174,7 +2175,7 @@ rel_push_topn_down(mvc *sql, sql_rel *re
 
                /* pass through projections */
                while (r && is_project(r->op) && !need_distinct(r) &&
-                       !(rel_is_ref(r)) &&
+                       !rel_is_ref(r) &&
                        !r->r && (rl = r->l) != NULL && is_project(rl->op)) {
                        /* ensure there is no order by */
                        if (!r->r) {
@@ -2183,29 +2184,28 @@ rel_push_topn_down(mvc *sql, sql_rel *re
                                r = NULL;
                        }
                }
-               if (r && r != rel && r->op == op_project && !(rel_is_ref(r)) && 
!r->r && r->l) {
-                       r = rel_topn(sql->sa, r, sum_limit_offset(sql, 
rel->exps));
-               }
-
-               /* push topn under crossproduct */
-               if (r && !r->exps && r->op == op_join && !(rel_is_ref(r)) &&
-                   ((sql_rel *)r->l)->op != op_topn && ((sql_rel *)r->r)->op 
!= op_topn) {
-                       r->l = rel_topn(sql->sa, r->l, sum_limit_offset(sql, 
rel->exps));
-                       r->r = rel_topn(sql->sa, r->r, sum_limit_offset(sql, 
rel->exps));
+               if (r && r != rel && is_simple_project(r->op) && !rel_is_ref(r) 
&& !r->r && r->l)
+                       r = func(sql->sa, r, sum_limit_offset(sql, rel->exps));
+
+               /* push topn/sample under crossproduct */
+               if (r && !r->exps && r->op == op_join && !rel_is_ref(r) &&
+                   ((sql_rel *)r->l)->op != relation_type && ((sql_rel 
*)r->r)->op != relation_type) {
+                       r->l = func(sql->sa, r->l, sum_limit_offset(sql, 
rel->exps));
+                       r->r = func(sql->sa, r->r, sum_limit_offset(sql, 
rel->exps));
                        (*changes)++;
                        return rel;
                }
 /* TODO */
 #if 0
-               /* duplicate topn + [ project-order ] under join on independend 
always matching joins */
+               /* duplicate topn/sample + [ project-order ] under join on 
independend always matching joins */
                if (r)
                        rp = r->l;
-               if (r && r->exps && r->op == op_project && !(rel_is_ref(r)) && 
r->r && r->l &&
+               if (r && r->exps && is_simple_project(r->op) && 
!(rel_is_ref(r)) && r->r && r->l &&
                    rp->op == op_join && rp->exps && rp->exps->h && 
((prop*)((sql_exp*)rp->exps->h->data)->p)->kind == PROP_FETCH &&
-                   ((sql_rel *)rp->l)->op != op_topn && ((sql_rel *)rp->r)->op 
!= op_topn) {
+                   ((sql_rel *)rp->l)->op != relation_type && ((sql_rel 
*)rp->r)->op != relation_type) {
                        /* TODO check if order by columns are independend of 
join conditions */
-                       r->l = rel_topn(sql->sa, r->l, sum_limit_offset(sql, 
rel->exps));
-                       r->r = rel_topn(sql->sa, r->r, sum_limit_offset(sql, 
rel->exps));
+                       r->l = func(sql->sa, r->l, sum_limit_offset(sql, 
rel->exps));
+                       r->r = func(sql->sa, r->r, sum_limit_offset(sql, 
rel->exps));
                        (*changes)++;
                        return rel;
                }
@@ -9012,8 +9012,8 @@ optimize_rel(mvc *sql, sql_rel *rel, int
                rel = rel_visitor_bottomup(sql, rel, &rel_remove_empty_select, 
&e_changes); 
        }
 
-       if (gp.cnt[op_topn])
-               rel = rel_visitor_topdown(sql, rel, &rel_push_topn_down, 
&changes); 
+       if (gp.cnt[op_topn] || gp.cnt[op_sample])
+               rel = rel_visitor_topdown(sql, rel, 
&rel_push_topn_and_sample_down, &changes); 
 
        if (value_based_opt)
                rel = rel_visitor_topdown(sql, rel, &rel_merge_table_rewrite, 
&changes);
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
@@ -90,8 +90,8 @@ rel_destroy_(sql_rel *rel)
            is_semi(rel->op) ||
            is_select(rel->op) ||
            is_set(rel->op) ||
-           rel->op == op_topn ||
-               rel->op == op_sample) {
+           is_topn(rel->op) ||
+               is_sample(rel->op)) {
                if (rel->l)
                        rel_destroy(rel->l);
                if (rel->r)
@@ -358,7 +358,8 @@ rel_bind_column2( mvc *sql, sql_rel *rel
                   is_sort(rel) ||
                   is_semi(rel->op) ||
                   is_select(rel->op) ||
-                  is_topn(rel->op)) {
+                  is_topn(rel->op) ||
+                  is_sample(rel->op)) {
                if (rel->l)
                        return rel_bind_column2(sql, rel->l, tname, cname, f);
        }
@@ -1566,7 +1567,7 @@ rel_in_rel(sql_rel *super, sql_rel *sub)
 sql_rel*
 rel_parent(sql_rel *rel)
 {
-       if (rel->l && (is_project(rel->op) || rel->op == op_topn || rel->op == 
op_sample)) {
+       if (rel->l && (is_project(rel->op) || is_topn(rel->op) || 
is_sample(rel->op))) {
                sql_rel *l = rel->l;
                if (is_project(l->op))
                        return l;
@@ -1587,7 +1588,7 @@ lastexp(sql_rel *rel)
 sql_rel *
 rel_zero_or_one(mvc *sql, sql_rel *rel, exp_kind ek)
 {
-       if (is_topn(rel->op))
+       if (is_topn(rel->op) || is_sample(rel->op))
                rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL, 
1, 0));
        if (ek.card < card_set && rel->card > CARD_ATOM) {
                assert (is_simple_project(rel->op) || is_set(rel->op));
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
@@ -123,7 +123,7 @@ rel_lastexp(mvc *sql, sql_rel *rel )
 {
        sql_exp *e;
 
-       if (!is_processed(rel) || is_topn(rel->op))
+       if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to