Changeset: 0711f13f3fc4 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0711f13f3fc4
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/include/sql_relation.h
        sql/server/rel_optimize_others.c
        sql/server/rel_updates.c
        sql/test/2024/Tests/returning.test
Branch: returning
Log Message:

nest modify relations instead using attr list


diffs (truncated from 331 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
@@ -5352,7 +5352,7 @@ rel2bin_insert(backend *be, sql_rel *rel
        if (!insert)
                return NULL;
 
-       if (rel->attr) {
+       if (rel->returning) {
                list* il = sa_list(sql->sa);
                sql_rel* inner = rel->l;
                assert(inner->op == op_basetable);
@@ -5362,21 +5362,7 @@ rel2bin_insert(backend *be, sql_rel *rel
                        stmt*   s       = stmt_rename(be, ce, ins);// label 
each insert statement with the corresponding col exp label
                        append(il, s);
                }
-               stmt* inserts2 = stmt_list(be, il);
-
-               list* rl = sa_list(sql->sa);
-               for (n = rel->attr->h; n; n = n->next) {
-                       sql_exp *exp = n->data;
-                       stmt *s = exp_bin(be, exp, inserts2, NULL, NULL, NULL, 
NULL, NULL, 0, 0, 0);
-                       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;
-                       }
-                       append(rl, s);
-               }
-               returning = stmt_list(be, rl);
+               returning = stmt_list(be, il);
                sql->type = Q_TABLE;
        }
 
@@ -6427,7 +6413,7 @@ rel2bin_update(backend *be, sql_rel *rel
        }
 
        stmt* returning = NULL;
-       if (rel->attr) {
+       if (rel->returning) {
                sql_rel* b = rel->l;
                int refcnt = b->ref.refcnt; // HACK: forces recalculation of 
base columns since they are assumed to be updated
                b->ref.refcnt = 1;
@@ -6435,25 +6421,6 @@ rel2bin_update(backend *be, sql_rel *rel
                b->ref.refcnt = refcnt;
                returning->cand = tids;
                returning = subrel_project(be, returning, refs, b);
-               list *pl = sa_list(sql->sa);
-               if (pl == NULL)
-                       return NULL;
-               stmt *psub = stmt_list(be, pl);
-               if (psub == NULL)
-                       return NULL;
-               for (node *en = rel->attr->h; en; en = en->next) {
-                       sql_exp *exp = en->data;
-                       stmt *s = exp_bin(be, exp, returning, NULL, NULL, NULL, 
NULL, NULL, 0, 0, 0);
-
-                       if (!exp_name(exp))
-                               exp_label(sql->sa, exp, ++sql->label);
-                       s = stmt_rename(be, exp, s);
-                       s->label = exp->alias.label;
-                       list_append(pl, s);
-               }
-               stmt_set_nrcols(psub);
-               returning = psub;
-               returning = subrel_project(be, returning, refs, NULL);
                sql->type = Q_TABLE;
        }
 
@@ -6703,7 +6670,7 @@ static stmt *
 rel2bin_delete(backend *be, sql_rel *rel, list *refs)
 {
        mvc *sql = be->mvc;
-       stmt *stdelete = NULL, *tids = NULL, *s = NULL;
+       stmt *stdelete = NULL, *tids = NULL, *returning = NULL;
        sql_rel *tr = rel->l;
        sql_table *t = NULL;
 
@@ -6721,19 +6688,13 @@ rel2bin_delete(backend *be, sql_rel *rel
                tids = rows->op4.lval->h->data; /* TODO this should be the 
candidate list instead */
        }
 
-       if (rel->attr) {
-               sql_rel* inner = rel->l;
-               if (rel_is_ref(inner)) {
-                       s = refs_find_rel(refs, inner);
-                       if (s)
-                               s->cand = tids;
-               }
-
-               sql_rel* ret = rel_project(sql->sa, inner, rel->attr);
-               s = subrel_bin(be, ret, refs);
-               s = subrel_project(be, s, refs, rel);
+       if (rel->returning) {
+               returning = subrel_bin(be, rel->l, refs);
+               returning->cand = tids;
+               returning = subrel_project(be, returning, refs, rel->l);
                sql->type = Q_TABLE;
        }
+
        stdelete = sql_delete(be, t, tids);
        if (sql->cascade_action)
                sql->cascade_action = NULL;
@@ -6742,7 +6703,7 @@ rel2bin_delete(backend *be, sql_rel *rel
 
        if (rel->r && !rel_predicates(be, rel->r))
                return NULL;
-       return s?s:stdelete;
+       return returning?returning:stdelete;
 }
 
 struct tablelist {
@@ -7580,17 +7541,17 @@ subrel_bin(backend *be, sql_rel *rel, li
                break;
        case op_insert:
                s = rel2bin_insert(be, rel, refs);
-               if (!rel->attr && sql->type == Q_TABLE)
+               if (!(rel->returning) && sql->type == Q_TABLE)
                        sql->type = Q_UPDATE;
                break;
        case op_update:
                s = rel2bin_update(be, rel, refs);
-               if (!rel->attr && sql->type == Q_TABLE)
+               if (!(rel->returning) && sql->type == Q_TABLE)
                        sql->type = Q_UPDATE;
                break;
        case op_delete:
                s = rel2bin_delete(be, rel, refs);
-               if (!rel->attr && sql->type == Q_TABLE)
+               if (!(rel->returning) && sql->type == Q_TABLE)
                        sql->type = Q_UPDATE;
                break;
        case op_truncate:
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -312,7 +312,8 @@ typedef struct relation {
         processed:1,   /* fully processed or still in the process of building 
*/
         outer:1,       /* used as outer (ungrouped) */
         grouped:1,     /* groupby processed all the group by exps */
-        single:1;
+        single:1,
+        returning:1; /*update|delete|insert relations return modified records*/
        /*
         * Used by rewriters at rel_unnest, rel_optimizer and rel_distribute so 
a relation is not modified twice
         * The list is kept at rel_optimizer_private.h Please update it 
accordingly
diff --git a/sql/server/rel_optimize_others.c b/sql/server/rel_optimize_others.c
--- a/sql/server/rel_optimize_others.c
+++ b/sql/server/rel_optimize_others.c
@@ -532,6 +532,7 @@ rel_mark_used(mvc *sql, sql_rel *rel, in
        case op_update:
        case op_delete:
                if (proj && rel->r) {
+                       rel_used(rel);
                        sql_rel *r = rel->r;
 
                        if (!list_empty(r->exps)) {
diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c
--- a/sql/server/rel_updates.c
+++ b/sql/server/rel_updates.c
@@ -695,7 +695,6 @@ insert_into(sql_query *query, dlist *qna
 
        if (opt_returning) {
                mvc *sql = query->sql;
-               sql->type = Q_TABLE;
                list *pexps = sa_list(sql->sa);
                sql_rel* inner = ins->l;
                for (dnode *n = opt_returning->h; n; n = n->next) {
@@ -704,7 +703,14 @@ insert_into(sql_query *query, dlist *qna
                                return NULL;
                        pexps = append(pexps, ce);
                }
-               ins->attr = is_groupby(inner->op) ? inner->exps : pexps;
+               ins->returning = 1;
+
+               if (is_groupby(inner->op)) {
+                       inner->l = ins;
+                       ins = rel_project(sql->sa, inner, pexps);
+               }
+               else
+                       ins = rel_project(sql->sa, ins, pexps);
        }
 
        return ins;
@@ -1250,6 +1256,7 @@ update_table(sql_query *query, dlist *qn
                        res = rel_crossproduct(sql->sa, res, tables, op_join);
                        set_single(res);
                }
+               query_push_outer(query, res, sql_where);
                if (opt_where) {
                        if (!(r = rel_logical_exp(query, res, opt_where, 
sql_where)))
                                return NULL;
@@ -1262,8 +1269,9 @@ update_table(sql_query *query, dlist *qn
                        r = res;
                }
                r = update_generate_assignments(query, t, r, bt, 
assignmentlist, "UPDATE");
+               query_pop_outer(query);
                if (opt_returning) {
-                       sql->type = Q_TABLE;
+                       r->returning = 1;
                        list *pexps = sa_list(sql->sa);
                        sql_rel* inner = r->l;
                        for (dnode *n = opt_returning->h; n; n = n->next) {
@@ -1272,7 +1280,12 @@ update_table(sql_query *query, dlist *qn
                                        return NULL;
                                pexps = append(pexps, ce);
                        }
-                       r->attr = is_groupby(inner->op) ? inner->exps : pexps;
+                       if (is_groupby(inner->op)) {
+                               inner->l = r;
+                               r = rel_project(sql->sa, inner, pexps);
+                       }
+                       else
+                               r = rel_project(sql->sa, r, pexps);
                }
 
                return r;
@@ -1332,8 +1345,11 @@ delete_table(sql_query *query, dlist *qn
                                                                         
get_string_global_var(sql, "current_user"), tname);
                        }
                        rel_base_use_tid(sql, r);
+
+                       query_push_outer(query, r, sql_where);
                        if (!(r = rel_logical_exp(query, r, opt_where, 
sql_where)))
                                return NULL;
+                       query_pop_outer(query);
                        e = exp_column(sql->sa, rel_name(r), TID, 
sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
                        e->nid = rel_base_nid(bt, NULL);
                        e->alias.label = e->nid;
@@ -1343,16 +1359,21 @@ delete_table(sql_query *query, dlist *qn
                        r = rel_delete(sql->sa, r, NULL);
                }
                if (opt_returning) {
-                       sql->type = Q_TABLE;
+                       r->returning = 1;
                        list *pexps = sa_list(sql->sa);
                        sql_rel* inner = r->l;
                        for (dnode *n = opt_returning->h; n; n = n->next) {
-                               sql_exp *ce = rel_column_exp(query, &inner, 
n->data.sym, sql_sel | sql_no_subquery | sql_update_set);
+                               sql_exp *ce = rel_column_exp(query, &inner, 
n->data.sym, sql_sel | sql_no_subquery);
                                if (ce == NULL)
                                        return NULL;
                                pexps = append(pexps, ce);
                        }
-                       r->attr = is_groupby(inner->op) ? inner->exps : pexps;
+                       if (is_groupby(inner->op)) {
+                               inner->l = r;
+                               r = rel_project(sql->sa, inner, pexps);
+                       }
+                       else
+                               r = rel_project(sql->sa, r, pexps);
                }
                return r;
        }
diff --git a/sql/test/2024/Tests/returning.test 
b/sql/test/2024/Tests/returning.test
--- a/sql/test/2024/Tests/returning.test
+++ b/sql/test/2024/Tests/returning.test
@@ -57,6 +57,31 @@ update foo set i = -i returning sum(j)
 ----
 -60
 
+query II nosort
+update foo set i = -i where i >0 returning sum(j), count(j)
+----
+-60
+3
+
+statement error 42000!SELECT: cannot use non GROUP BY column 'i' in query 
results without an aggregate function
+update foo set i = -i returning sum(j), i
+
+statement error 42000!SELECT: cannot use non GROUP BY column 'foo.i' in query 
results without an aggregate function
+update foo set i = -i returning i, sum(j)
+
+statement error 42000!SELECT: cannot use non GROUP BY column 'i' in query 
results without an aggregate function
+delete from foo where i > 0 returning sum(j), i
+
+statement error 42000!SELECT: cannot use non GROUP BY column 'foo.i' in query 
results without an aggregate function
+delete from foo where i > 0 returning i, sum(j)
+
+statement error 42000!SELECT: cannot use non GROUP BY column 'i' in query 
results without an aggregate function
+insert into foo select * from foo returning sum(j), i
+
+statement error 42000!SELECT: cannot use non GROUP BY column 'foo.i' in query 
results without an aggregate function
+insert into foo select * from foo returning i, sum(j)
+
+
 statement error 42000!SELECT: identifier 'k' unknown
 update foo set i = -i returning k
 
@@ -77,6 +102,23 @@ 4
 9
 
 statement ok
+insert into foo values (1, 10), (2, 20), (3, 30);
+
+query I nosort
+delete from foo returning sum(j)
+----
+60
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to