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