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]

Reply via email to