Changeset: cf2de4ff9917 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/cf2de4ff9917
Modified Files:
clients/Tests/exports.stable.out
sql/backends/monet5/rel_physical.c
sql/common/sql_list.c
sql/include/sql_list.h
sql/server/rel_dump.c
sql/server/rel_exp.c
sql/server/rel_optimizer_private.h
sql/server/rel_prop.c
sql/server/rel_prop.h
sql/server/rel_rel.c
sql/server/rel_rel.h
sql/server/rel_select.c
sql/server/rel_unnest.c
sql/test/BugTracker-2021/Tests/batappend-undefined.Bug-7130.test
Branch: unnest2
Log Message:
initial implementation of 'Improving Unnesting of Complex Queries, by Neumann'
diffs (truncated from 2887 to 300 lines):
diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out
--- a/clients/Tests/exports.stable.out
+++ b/clients/Tests/exports.stable.out
@@ -1607,6 +1607,7 @@ cq *qc_find(qc *cache, int id);
cq *qc_insert(qc *cache, allocator *sa, sql_rel *r, symbol *s, list *params,
mapi_query_t type, char *codedstr, int no_mitosis);
void rel_base_use_all(mvc *sql, sql_rel *rel);
sql_rel *rel_basetable(mvc *sql, sql_table *t, const char *tname);
+list *rel_boundvar(mvc *sql, sql_rel *rel);
sql_rel *rel_project(allocator *sa, sql_rel *l, list *e);
list *rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname,
int intern);
void res_tables_destroy(res_table *results);
diff --git a/sql/backends/monet5/rel_physical.c
b/sql/backends/monet5/rel_physical.c
--- a/sql/backends/monet5/rel_physical.c
+++ b/sql/backends/monet5/rel_physical.c
@@ -183,7 +183,9 @@ has_groupby(sql_rel *rel)
case op_select:
case op_topn:
case op_sample:
- return has_groupby(rel->l);
+ if (rel->l)
+ return has_groupby(rel->l);
+ return 0;
case op_insert:
case op_update:
case op_delete:
@@ -206,11 +208,14 @@ has_groupby(sql_rel *rel)
}
static sql_rel *
-rel_partition(mvc *sql, sql_rel *rel)
+rel_partition(visitor *v, mvc *sql, sql_rel *rel)
{
if (mvc_highwater(sql))
return sql_error(sql, 10, SQLSTATE(42000) "Query too complex:
running out of stack space");
+ if (v->opt >= 0 && rel->opt >= v->opt) /* only once */
+ return 0;
+
switch (rel->op) {
case op_basetable:
case op_sample:
@@ -221,7 +226,7 @@ rel_partition(mvc *sql, sql_rel *rel)
case op_groupby:
case op_topn:
if (rel->l)
- rel_partition(sql, rel->l);
+ rel_partition(v, sql, rel->l);
break;
case op_semi:
case op_anti:
@@ -229,20 +234,20 @@ rel_partition(mvc *sql, sql_rel *rel)
case op_inter:
case op_except:
if (rel->l)
- rel_partition(sql, rel->l);
+ rel_partition(v, sql, rel->l);
if (rel->r)
- rel_partition(sql, rel->r);
+ rel_partition(v, sql, rel->r);
break;
case op_munion:
for (node *n = ((list*)rel->l)->h; n; n = n->next)
- rel_partition(sql, n->data);
+ rel_partition(v, sql, n->data);
break;
case op_insert:
case op_update:
case op_delete:
case op_truncate:
if (rel->r && rel->card <= CARD_AGGR)
- rel_partition(sql, rel->r);
+ rel_partition(v, sql, rel->r);
break;
case op_join:
case op_left:
@@ -250,9 +255,9 @@ rel_partition(mvc *sql, sql_rel *rel)
case op_full:
if (has_groupby(rel->l) || has_groupby(rel->r)) {
if (rel->l)
- rel_partition(sql, rel->l);
+ rel_partition(v, sql, rel->l);
if (rel->r)
- rel_partition(sql, rel->r);
+ rel_partition(v, sql, rel->r);
} else {
_rel_partition(sql, rel);
}
@@ -260,22 +265,24 @@ rel_partition(mvc *sql, sql_rel *rel)
case op_ddl:
if (rel->flag == ddl_output || rel->flag == ddl_create_seq ||
rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag ==
ddl_create_table || rel->flag == ddl_create_view) {
if (rel->l)
- rel_partition(sql, rel->l);
+ rel_partition(v, sql, rel->l);
} else if (rel->flag == ddl_list || rel->flag == ddl_exception)
{
if (rel->l)
- rel_partition(sql, rel->l);
+ rel_partition(v, sql, rel->l);
if (rel->r)
- rel_partition(sql, rel->r);
+ rel_partition(v, sql, rel->r);
}
break;
case op_table:
if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag ==
TABLE_FROM_RELATION) && rel->l)
- rel_partition(sql, rel->l);
+ rel_partition(v, sql, rel->l);
break;
default:
assert(0);
break;
}
+ if (rel && v->opt >= 0)
+ rel->opt = v->opt;
return rel;
}
@@ -378,7 +385,9 @@ rel_physical(mvc *sql, sql_rel *rel)
v.changes = 0;
if (!sql->recursive) {
- (void)rel_partition(sql, rel);
+ if (v.opt >= 0)
+ v.opt = rel->opt+1;
+ (void)rel_partition(&v, sql, rel);
}
rel = rel_exp_visitor_topdown(&v, rel, &exp_timezone, true);
diff --git a/sql/common/sql_list.c b/sql/common/sql_list.c
--- a/sql/common/sql_list.c
+++ b/sql/common/sql_list.c
@@ -59,6 +59,14 @@ sa_list_append(allocator *sa, list *l, v
}
list *
+sa_list_prepend(allocator *sa, list *l, void *data)
+{
+ if (!l)
+ l = SA_LIST(sa, NULL);
+ return list_prepend(l, data);
+}
+
+list *
list_add(list *l, void *data)
{
if (!l)
diff --git a/sql/include/sql_list.h b/sql/include/sql_list.h
--- a/sql/include/sql_list.h
+++ b/sql/include/sql_list.h
@@ -41,6 +41,7 @@ sql_export list *sa_list(allocator *sa);
extern list *list_new(allocator *sa, fdestroy destroy);
extern list *sa_list_append( allocator *sa, list *l, void *data);
+extern list *sa_list_prepend( allocator *sa, list *l, void *data);
extern list *list_add( list *l, void *data);
extern void list_destroy(list *l);
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -750,7 +750,7 @@ rel_print_rel(mvc *sql, stream *fout, s
}
if (sql->show_details && decorate && rel->p) {
for (prop *p = rel->p; p; p = p->p) {
- if ((p->kind != PROP_COUNT && p->kind != PROP_UKEY) ||
(ATOMIC_GET(&GDKdebug) & TESTINGMASK) == 0) {
+ if ((p->kind != PROP_COUNT && p->kind != PROP_UKEY &&
p->kind != PROP_UNNESTING) || (ATOMIC_GET(&GDKdebug) & TESTINGMASK) == 0) {
char *pv = propvalue2string(ta, p);
mnstr_printf(fout, " %s %s",
propkind2string(p), pv);
}
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
@@ -813,6 +813,8 @@ exp_ref_by_label(allocator *sa, sql_exp
*/
if (is_intern(o))
set_intern(e);
+ if (is_freevar(o) && o->alias.label == o->nid /* only original IU */)
+ set_freevar(e, is_freevar(o)-1);
return exp_propagate(sa, e, o);
}
@@ -1912,8 +1914,9 @@ rel_find_exp_and_corresponding_rel(sql_r
case op_basetable:
break;
case op_munion:
- for (node* n = ((list*)rel->l)->h; n && !ne; n =
n->next)
- ne =
rel_find_exp_and_corresponding_rel(n->data, e, subexp, res, under_join);
+ if (!is_project(rel->op) && rel->l)
+ for (node* n = ((list*)rel->l)->h; n && !ne; n
= n->next)
+ ne =
rel_find_exp_and_corresponding_rel(n->data, e, subexp, res, under_join);
break;
default:
if (!is_project(rel->op) && rel->l)
diff --git a/sql/server/rel_optimizer_private.h
b/sql/server/rel_optimizer_private.h
--- a/sql/server/rel_optimizer_private.h
+++ b/sql/server/rel_optimizer_private.h
@@ -44,6 +44,7 @@ typedef struct sql_optimizer {
#define statistics_gathered (1 << 3)
#define rel_remote_func_used (1 << 4)
#define rewrite_gt_zero_used (1 << 5)
+#define unnest_used (1 << 6)
#define is_rewrite_fix_count_used(X) ((X & rewrite_fix_count_used) ==
rewrite_fix_count_used)
#define is_rewrite_values_used(X) ((X & rewrite_values_used) ==
rewrite_values_used)
@@ -51,6 +52,7 @@ typedef struct sql_optimizer {
#define are_statistics_gathered(X) ((X & statistics_gathered) ==
statistics_gathered)
#define is_rel_remote_func_used(X) ((X & rel_remote_func_used) ==
rel_remote_func_used)
#define is_rewrite_gt_zero_used(X) ((X & rewrite_gt_zero_used) ==
rewrite_gt_zero_used)
+#define is_unnest_used(X) ((X & unnest_used) ==
unnest_used)
/* At the moment the following optimizers 'packs' can be disabled,
later we could disable individual optimizers from the 'pack' */
diff --git a/sql/server/rel_prop.c b/sql/server/rel_prop.c
--- a/sql/server/rel_prop.c
+++ b/sql/server/rel_prop.c
@@ -114,6 +114,7 @@ propkind2string( prop *p)
PT(GROUPINGS);
PT(MIN);
PT(MAX);
+ PT(UNNESTING);
}
return "UNKNOWN";
}
diff --git a/sql/server/rel_prop.h b/sql/server/rel_prop.h
--- a/sql/server/rel_prop.h
+++ b/sql/server/rel_prop.h
@@ -22,7 +22,8 @@ typedef enum rel_prop {
PROP_UKEY, /* p = list of exps */
PROP_REMOTE, /* uri for remote execution */
PROP_USED, /* number of times exp is used */
- PROP_GROUPINGS /* used by ROLLUP/CUBE/GROUPING SETS, value contains
the list of sets */
+ PROP_GROUPINGS, /* used by ROLLUP/CUBE/GROUPING SETS, value contains
the list of sets */
+ PROP_UNNESTING /* used by unnesting rewriter */
} rel_prop;
typedef struct prop {
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
@@ -1142,6 +1142,8 @@ rel_groupby(mvc *sql, sql_rel *l, list *
exp_label(sql->sa, e, ++sql->label);
ne = exp_ref(sql, e);
ne = exp_propagate(sql->sa, ne, e);
+ if (is_freevar(e))
+ set_freevar(ne, is_freevar(e)-1);
append(aggrs, ne);
}
}
@@ -1272,7 +1274,8 @@ exps_reset_props(list *exps, bool setnil
* refer to the tname relation, anywhere in the relational tree
*/
list *
-_rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int
intern, int basecol /* basecol only */ )
+_rel_projections(mvc *sql, sql_rel *rel, const char *tname, int settname, int
intern, int basecol /* basecol only */,
+ bool bound )
{
list *lexps, *rexps = NULL, *exps = NULL, *rels;
@@ -1290,10 +1293,10 @@ _rel_projections(mvc *sql, sql_rel *rel,
case op_left:
case op_right:
case op_full:
- lexps = _rel_projections(sql, rel->l, tname, settname, intern,
basecol);
+ lexps = _rel_projections(sql, rel->l, tname, settname, intern,
basecol, bound);
exps_reset_props(lexps, is_right(rel->op) || is_full(rel->op));
if (!rel->attr)
- rexps = _rel_projections(sql, rel->r, tname, settname,
intern, basecol);
+ rexps = _rel_projections(sql, rel->r, tname, settname,
intern, basecol, bound);
exps_reset_props(rexps, is_left(rel->op) || is_full(rel->op));
if (rexps)
lexps = list_join(lexps, rexps);
@@ -1308,6 +1311,8 @@ _rel_projections(mvc *sql, sql_rel *rel,
for (node *en = r->h; en; en = en->next) {
sql_exp *e = en->data;
+ if (is_freevar(e) && e->alias.label == e->nid
&& bound)
+ continue;
if (basecol && !is_basecol(e))
continue;
if (intern || !is_intern(e)) {
@@ -1336,6 +1341,8 @@ _rel_projections(mvc *sql, sql_rel *rel,
for (node *en = rel->exps->h; en; en = en->next) {
sql_exp *e = en->data;
+ if (is_freevar(e) && e->alias.label == e->nid
&& bound)
+ continue;
if (basecol && !is_basecol(e))
continue;
if (intern || !is_intern(e)) {
@@ -1360,7 +1367,7 @@ _rel_projections(mvc *sql, sql_rel *rel,
if (rels->h)
r = rels->h->data;
if (r)
- exps = _rel_projections(sql, r, tname,
settname, intern, basecol);
+ exps = _rel_projections(sql, r, tname,
settname, intern, basecol, bound);
/* it's a multi-union (expressions have to be the same
in all the operands)
* so we are ok only with the expressions of the first
operand
*/
@@ -1368,6 +1375,8 @@ _rel_projections(mvc *sql, sql_rel *rel,
for (node *en = exps->h; en; en = en->next) {
sql_exp *e = en->data;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]