Changeset: f90d650657f1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/f90d650657f1
Modified Files:
sql/backends/monet5/rel_bin.c
sql/backends/monet5/sql_result.c
sql/include/sql_relation.h
sql/rel.txt
sql/server/rel_dump.c
sql/server/rel_exp.c
sql/server/rel_optimizer.c
sql/server/rel_propagate.c
sql/server/rel_propagate.h
sql/server/rel_rel.c
sql/server/rel_updates.c
sql/server/rel_updates.h
sql/test/2024/Tests/returning.test
sql/test/BugTracker-2009/Tests/copy_multiple_files.SF-2902320-Windows.test
sql/test/BugTracker-2009/Tests/copy_multiple_files.SF-2902320.test
sql/test/astro/Tests/astro.test
Branch: default
Log Message:
reimplemented returning, all update/insert and delete relational operators now
behave like projects (ie returning the changed content).
The counts are handled using an extra groupby unless returning is used.
diffs (truncated from 1275 to 300 lines):
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -590,6 +590,7 @@ handle_in_exps(backend *be, sql_exp *ce,
/* The actual in-value-list should not contain duplicates to
ensure that final join results are unique. */
s = distinct_value_list(be, nl, &last_null_value, depth+1,
push);
+ assert(!last_null_value);
if (!s)
return NULL;
@@ -789,8 +790,6 @@ exp_bin_disjunctive(backend *be, sql_exp
}
cur = s;
}
- //if (reduce)
- // return stmt_uselect(be, cur, stmt_bool(be, 1), cmp_equal, sel,
0/*anti*/, 0);
return cur;
}
@@ -4718,7 +4717,6 @@ rel2bin_project(backend *be, sql_rel *re
}
if (!lpiv) {
stmt *orderbycolstmt = pl->h->data;
- //stmt *orderbycolstmt = exp_bin(be, orderbycole, sub,
psub, NULL, NULL, NULL, NULL, 0, 0, 0);
if (!orderbycolstmt)
return NULL;
@@ -4903,6 +4901,15 @@ rel2bin_groupby(backend *be, sql_rel *re
}
if (sub && sub->type == st_list && sub->op4.lval->h &&
!((stmt*)sub->op4.lval->h->data)->nrcols) {
+ if (!rel->r && list_length(rel->exps) == 1) {
+ sql_exp *cnt = rel->exps->h->data;
+ if (cnt->type == e_aggr && !cnt->l && cnt->intern) {
+ stmt *cntstmt = stmt_atom_lng(be, 1);
+ if (add_to_rowcount_accumulator(be,
cntstmt->nr) < 0)
+ return sql_error(sql, 10,
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+ return stmt_list(be, append(sa_list(sql->sa),
cntstmt));
+ }
+ }
list *newl = sa_list(sql->sa);
node *n;
@@ -4992,6 +4999,13 @@ rel2bin_groupby(backend *be, sql_rel *re
aggrstmt = stmt_rename(be, aggrexp, aggrstmt);
list_append(l, aggrstmt);
}
+
+ if (!rel->r && list_length(aggrs) == 1) {
+ sql_exp *cnt = aggrs->h->data;
+ stmt *cntstmt = l->h->data;
+ if (cnt->type == e_aggr && !cnt->l && cnt->intern &&
add_to_rowcount_accumulator(be, cntstmt->nr) < 0)
+ return sql_error(sql, 10, SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ }
stmt_set_nrcols(cursub);
return cursub;
}
@@ -5535,13 +5549,6 @@ rel2bin_insert(backend *be, sql_rel *rel
sql_rel *tr = rel->l, *prel = rel->r;
sql_table *t = NULL;
- if ((rel->flag&UPD_COMP)) { /* special case ! */
- idx_ins = 1;
- prel = rel->l;
- rel = rel->r;
- tr = rel->l;
- }
-
if (tr->op == op_basetable) {
t = tr->l;
} else {
@@ -5643,36 +5650,44 @@ rel2bin_insert(backend *be, sql_rel *rel
if (!insert)
return NULL;
- if (rel->returning) {
- list* il = sa_list(sql->sa);
- sql_rel* inner = rel->l;
- assert(inner->op == op_basetable);
- for (n = inner->exps->h, m = inserts->op4.lval->h; n && m; n =
n->next, m = m->next) {
- sql_exp* ce = n->data;
- stmt* ins = m->data;
- stmt* s = stmt_rename(be, ce, ins);// label
each insert statement with the corresponding col exp label
- append(il, s);
- }
- returning = stmt_list(be, il);
- sql->type = Q_TABLE;
- }
-
if (!sql_insert_triggers(be, t, updates, 1))
return sql_error(sql, 10, SQLSTATE(27000) "INSERT INTO:
triggers failed for table '%s'", t->base.name);
/* update predicate list */
if (rel->r && !rel_predicates(be, rel->r))
return NULL;
+ if (rel->exps) {
+ list *pl = sa_list(be->mvc->sa);
+ for (node *en = rel->exps->h; en; en = en->next) {
+ sql_exp *exp = en->data;
+ stmt *s = exp_bin(be, exp, inserts, NULL /*psub*/,
NULL, NULL, NULL, NULL, 0, 0, 0);
+
+ if (!s) /* error */
+ return NULL;
+ /* single value with limit */
+ if (inserts && inserts->nrcols >= 1 && s->nrcols == 0)
+ s = stmt_const(be, bin_find_smallest_column(be,
inserts), s);
+
+ if (!exp_name(exp))
+ exp_label(sql->sa, exp, ++sql->label);
+ if (exp_name(exp)) {
+ s = stmt_rename(be, exp, s);
+ s->label = exp->alias.label;
+ }
+ list_append(pl, s);
+ }
+ returning = stmt_list(be, pl);
+ sql->type = Q_TABLE;
+ }
+
if (ddl) {
ret = ddl;
list_prepend(l, ddl);
return stmt_list(be, l);
} else {
ret = cnt;
- if (add_to_rowcount_accumulator(be, ret->nr) < 0)
- return sql_error(sql, 10, SQLSTATE(HY013)
MAL_MALLOC_FAIL);
if (t->s && isGlobal(t) && !isGlobalTemp(t))
- stmt_add_dependency_change(be, t, ret);
+ stmt_add_dependency_change(be, t, ret?ret:returning);
return returning?returning:ret;
}
}
@@ -6599,13 +6614,12 @@ static stmt *
rel2bin_update(backend *be, sql_rel *rel, list *refs)
{
mvc *sql = be->mvc;
- stmt *update = NULL, **updates = NULL, *tids, *ddl = NULL, *pup = NULL,
*cnt;
- list *l = sa_list(sql->sa);
+ stmt *update = NULL, **updates = NULL, *tids, *ddl = NULL, *pup = NULL;
+ list *l = sa_list(sql->sa), *attr = rel->attr;
int nr_cols, updcol, idx_ups = 0;
node *m;
sql_rel *tr = rel->l, *prel = rel->r;
sql_table *t = NULL;
- bool needs_returning = rel->returning;
if ((rel->flag&UPD_COMP)) { /* special case ! */
idx_ups = 1;
@@ -6641,8 +6655,13 @@ rel2bin_update(backend *be, sql_rel *rel
if (!update)
return NULL;
- if (idx_ups)
+ if (idx_ups) {
pup = refs_find_rel(refs, prel);
+ if (!pup) {
+ pup = subrel_bin(be, prel, refs);
+ pup = subrel_project(be, pup, refs, prel);
+ }
+ }
updates = table_update_stmts(sql, t, &nr_cols);
tids = update->op4.lval->h->data;
@@ -6701,19 +6720,18 @@ rel2bin_update(backend *be, sql_rel *rel
sql_column *c = find_sql_column(t, exp_name(ce));
if (c)
- append(l, stmt_update_col(be, c, tids,
updates[c->colnr]));
+ append(l, stmt_update_col(be, c, tids,
updates[c->colnr])); /* do the update */
}
stmt* returning = NULL;
- if (needs_returning) {
+ if (!list_empty(attr)) {
sql_rel* b = rel->l;
- int refcnt = b->ref.refcnt; // HACK: forces recalculation of
base columns since they are assumed to be updated
+ int refcnt = b->ref.refcnt; /* clean basetable */
b->ref.refcnt = 1;
returning = subrel_bin(be, b, refs);
b->ref.refcnt = refcnt;
- returning->cand = tids;
+ returning->cand = tids; /* only updated rows */
returning = subrel_project(be, returning, refs, b);
- sql->type = Q_TABLE;
}
if (cascade_updates(be, t, tids, updates)) {
@@ -6729,22 +6747,19 @@ rel2bin_update(backend *be, sql_rel *rel
return sql_error(sql, 10, SQLSTATE(27000) "UPDATE: triggers
failed for table '%s'", t->base.name);
}
- if (ddl) {
- list_prepend(l, ddl);
- cnt = stmt_list(be, l);
- } else {
- cnt = stmt_aggr(be, tids, NULL, NULL, sql_bind_func(sql, "sys",
"count", sql_bind_localtype("void"), NULL, F_AGGR, true, true), 1, 0, 1);
- if (add_to_rowcount_accumulator(be, cnt->nr) < 0)
- return sql_error(sql, 10, SQLSTATE(HY013)
MAL_MALLOC_FAIL);
- if (t->s && isGlobal(t) && !isGlobalTemp(t))
- stmt_add_dependency_change(be, t, cnt);
- }
-
if (sql->cascade_action)
sql->cascade_action = NULL;
if (rel->r && !rel_predicates(be, rel->r))
return NULL;
- return returning?returning:cnt;
+
+ if (!returning) {
+ returning = stmt_list(be, append(sa_list(sql->sa), tids));
+ if (t->s && isGlobal(t) && !isGlobalTemp(t)) {
+ stmt *cnt = stmt_aggr(be, tids, NULL, NULL,
sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR,
true, true), 1, 0, 1);
+ stmt_add_dependency_change(be, t, cnt);
+ }
+ }
+ return returning;
}
static int
@@ -6951,8 +6966,6 @@ sql_delete(backend *be, sql_table *t, st
if (!sql_delete_triggers(be, t, v, deleted_cols, 1, 1, 3))
return sql_error(sql, 10, SQLSTATE(27000) "DELETE: triggers
failed for table '%s'", t->base.name);
- if (add_to_rowcount_accumulator(be, s->nr) < 0)
- return sql_error(sql, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL);
if (t->s && isGlobal(t) && !isGlobalTemp(t))
stmt_add_dependency_change(be, t, s);
return s;
@@ -6979,14 +6992,12 @@ rel2bin_delete(backend *be, sql_rel *rel
assert(rows->type == st_list);
tids = rows->op4.lval->h->data; /* TODO this should be the
candidate list instead */
}
-
- if (rel->returning) {
+ if (list_length(rel->exps) > 1)
returning = subrel_bin(be, rel->l, refs);
- returning->cand = tids;
- returning = subrel_project(be, returning, refs, rel->l);
- sql->type = Q_TABLE;
- }
-
+
+ stmt *rows = tids;
+ if (!rows)
+ rows = stmt_tid(be, t, 0);
stdelete = sql_delete(be, t, tids);
if (sql->cascade_action)
sql->cascade_action = NULL;
@@ -6995,6 +7006,36 @@ rel2bin_delete(backend *be, sql_rel *rel
if (rel->r && !rel_predicates(be, rel->r))
return NULL;
+
+ if (list_length(rel->exps) > 1) {
+ list *pl = sa_list(be->mvc->sa);
+ node *n = rel->exps->h;
+
+ if (tids)
+ n = n->next;
+ for(; n; n = n->next) {
+ sql_exp *exp = n->data;
+ stmt *s = exp_bin(be, exp, returning, NULL, NULL, NULL,
NULL, NULL, 0, 0, 0);
+
+ if (tids && s)
+ s = stmt_project(be, tids, s);
+ if (!s) /* error */
+ return NULL;
+
+ if (!exp_name(exp))
+ exp_label(sql->sa, exp, ++sql->label);
+ if (exp_name(exp)) {
+ s = stmt_rename(be, exp, s);
+ s->label = exp->alias.label;
+ }
+ list_append(pl, s);
+ }
+ returning = stmt_list(be, pl);
+ sql->type = Q_TABLE;
+ } else {
+ returning = stmt_list(be, append(sa_list(sql->sa), rows));
+ sql->type = Q_TABLE;
+ }
return returning?returning:stdelete;
}
@@ -7702,18 +7743,15 @@ subrel_bin(backend *be, sql_rel *rel, li
break;
case op_insert:
s = rel2bin_insert(be, rel, refs);
- if (!(rel->returning) && sql->type == Q_TABLE)
- sql->type = Q_UPDATE;
+ sql->type = Q_UPDATE;
break;
case op_update:
s = rel2bin_update(be, rel, refs);
- if (!(rel->returning) && sql->type == Q_TABLE)
- sql->type = Q_UPDATE;
+ sql->type = Q_UPDATE;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]