Changeset: cb92947332fa for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/cb92947332fa
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/server/rel_updates.c
        sql/server/sql_parser.y
Branch: returning
Log Message:

UPDATE ... RETURNING ...


diffs (146 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
@@ -6398,6 +6398,37 @@ rel2bin_update(backend *be, sql_rel *rel
                        append(l, stmt_update_col(be,  c, tids, 
updates[c->colnr]));
        }
 
+       stmt* returning = NULL;
+       if (rel->attr) {
+               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;
+               returning = subrel_bin(be, b, refs);
+               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;
+       }
+
        if (cascade_updates(be, t, tids, updates)) {
                if (sql->cascade_action)
                        sql->cascade_action = NULL;
@@ -6426,7 +6457,7 @@ rel2bin_update(backend *be, sql_rel *rel
                sql->cascade_action = NULL;
        if (rel->r && !rel_predicates(be, rel->r))
                return NULL;
-       return cnt;
+       return returning?returning:cnt;
 }
 
 static int
@@ -6654,6 +6685,11 @@ rel2bin_delete(backend *be, sql_rel *rel
                assert(0/*ddl statement*/);
 
        if (rel->r) { /* first construct the deletes relation */
+               if (rel->attr) {
+                       sql_rel* sel = ((sql_rel*) rel->r)->l;
+                       assert(is_select(sel->op));
+                       (void) rel_dup (sel); // required to prevent 
recalculating select in rel2bin_delete
+               }
                stmt *rows = subrel_bin(be, rel->r, refs);
                rows = subrel_project(be, rows, refs, rel->r);
                if (!rows)
@@ -6663,7 +6699,8 @@ rel2bin_delete(backend *be, sql_rel *rel
        }
 
        if (rel->attr) {
-               sql_rel* ret = rel_project(sql->sa, ((sql_rel*) rel->r)->l, 
rel->attr);
+               sql_rel* sel = ((sql_rel*) rel->r)->l;
+               sql_rel* ret = rel_project(sql->sa, sel, rel->attr);
                s = subrel_bin(be, ret, refs);
                s = subrel_project(be, s, refs, rel);
                sql->type = Q_TABLE;
@@ -7519,7 +7556,7 @@ subrel_bin(backend *be, sql_rel *rel, li
                break;
        case op_update:
                s = rel2bin_update(be, rel, refs);
-               if (sql->type == Q_TABLE)
+               if (!rel->attr && sql->type == Q_TABLE)
                        sql->type = Q_UPDATE;
                break;
        case op_delete:
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
@@ -1194,7 +1194,7 @@ update_generate_assignments(sql_query *q
 }
 
 static sql_rel *
-update_table(sql_query *query, dlist *qname, str alias, dlist *assignmentlist, 
symbol *opt_from, symbol *opt_where)
+update_table(sql_query *query, dlist *qname, str alias, dlist *assignmentlist, 
symbol *opt_from, symbol *opt_where, dlist *opt_returning)
 {
        mvc *sql = query->sql;
        char *sname = qname_schema(qname);
@@ -1245,7 +1245,21 @@ update_table(sql_query *query, dlist *qn
                } else {        /* update all */
                        r = res;
                }
-               return update_generate_assignments(query, t, r, bt, 
assignmentlist, "UPDATE");
+               r = update_generate_assignments(query, t, r, bt, 
assignmentlist, "UPDATE");
+               if (opt_returning) {
+                       sql->type = Q_TABLE;
+                       list *pexps = sa_list(sql->sa);
+                       for (dnode *n = opt_returning->h; n; n = n->next) {
+                               sql_rel* inner = r->l;
+                               sql_exp *ce = rel_column_exp(query, &inner, 
n->data.sym, sql_sel | sql_no_subquery | sql_update_set);
+                               if (ce == NULL)
+                                       return sql_error(sql, 02, 
SQLSTATE(42000) "aggregate functions and subqueries are not allowed in 
RETURNING clause");
+                               pexps = append(pexps, ce);
+                       }
+                       r->attr = pexps;
+               }
+
+               return r;
        }
        return NULL;
 }
@@ -2204,8 +2218,8 @@ rel_updates(sql_query *query, symbol *s)
                dlist *l = s->data.lval;
 
                ret = update_table(query, l->h->data.lval, 
l->h->next->data.sval, l->h->next->next->data.lval,
-                                                  
l->h->next->next->next->data.sym, l->h->next->next->next->next->data.sym);
-               sql->type = Q_UPDATE;
+                                                  
l->h->next->next->next->data.sym, l->h->next->next->next->next->data.sym, 
l->h->next->next->next->next->next->data.lval);
+               if (ret && !ret->attr) sql->type = Q_UPDATE;
        }
                break;
        case SQL_DELETE:
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -3230,13 +3230,14 @@ truncate_stmt:
  ;
 
 update_stmt:
-    UPDATE qname opt_alias_name SET assignment_commalist opt_from_clause 
opt_where_clause
+    UPDATE qname opt_alias_name SET assignment_commalist opt_from_clause 
opt_where_clause opt_returning_clause
        { dlist *l = L();
          append_list(l, $2);
          append_string(l, $3);
          append_list(l, $5);
          append_symbol(l, $6);
          append_symbol(l, $7);
+         append_list(l, $8);
          $$ = _symbol_create_list( SQL_UPDATE, l ); }
  ;
 
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to