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

implement INSERT INTO ... RETURNING ... statements


diffs (170 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
@@ -5238,7 +5238,7 @@ rel2bin_insert(backend *be, sql_rel *rel
 {
        mvc *sql = be->mvc;
        list *l;
-       stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, 
**updates, *ret = NULL, *cnt = NULL, *pos = NULL;
+       stmt *inserts = NULL, *insert = NULL, *ddl = NULL, *pin = NULL, 
**updates, *ret = NULL, *cnt = NULL, *pos = NULL, *returning = NULL;
        int idx_ins = 0, len = 0;
        node *n, *m, *idx_m = NULL;
        sql_rel *tr = rel->l, *prel = rel->r;
@@ -5352,6 +5352,34 @@ rel2bin_insert(backend *be, sql_rel *rel
        if (!insert)
                return NULL;
 
+       if (rel->attr) {
+               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);
+               }
+               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);
+               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 */
@@ -5368,7 +5396,7 @@ rel2bin_insert(backend *be, sql_rel *rel
                        return sql_error(sql, 10, SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
                if (t->s && isGlobal(t) && !isGlobalTemp(t))
                        stmt_add_dependency_change(be, t, ret);
-               return ret;
+               return returning?returning:ret;
        }
 }
 
@@ -7552,7 +7580,7 @@ subrel_bin(backend *be, sql_rel *rel, li
                break;
        case op_insert:
                s = rel2bin_insert(be, rel, refs);
-               if (sql->type == Q_TABLE)
+               if (!rel->attr && sql->type == Q_TABLE)
                        sql->type = Q_UPDATE;
                break;
        case op_update:
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
@@ -677,7 +677,7 @@ merge_generate_inserts(sql_query *query,
 }
 
 static sql_rel *
-insert_into(sql_query *query, dlist *qname, dlist *columns, symbol *val_or_q)
+insert_into(sql_query *query, dlist *qname, dlist *columns, symbol *val_or_q, 
dlist *opt_returning)
 {
        mvc *sql = query->sql;
        char *sname = qname_schema(qname);
@@ -691,7 +691,23 @@ insert_into(sql_query *query, dlist *qna
        r = insert_generate_inserts(query, t, columns, val_or_q, "INSERT INTO");
        if(!r)
                return NULL;
-       return rel_insert_table(query, t, t->base.name, r);
+       sql_rel* ins = rel_insert_table(query, t, t->base.name, r);
+
+       if (opt_returning) {
+               mvc *sql = query->sql;
+               sql->type = Q_TABLE;
+               list *pexps = sa_list(sql->sa);
+               for (dnode *n = opt_returning->h; n; n = n->next) {
+                       sql_rel* inner = ins->l;
+                       sql_exp *ce = rel_column_exp(query, &inner, 
n->data.sym, sql_sel | sql_no_subquery | sql_update_set);
+                       if (ce == NULL)
+                               return NULL;
+                       pexps = append(pexps, ce);
+               }
+               ins->attr = pexps;
+       }
+
+       return ins;
 }
 
 static int
@@ -2206,7 +2222,7 @@ rel_updates(sql_query *query, symbol *s)
        {
                dlist *l = s->data.lval;
 
-               ret = insert_into(query, l->h->data.lval, 
l->h->next->data.lval, l->h->next->next->data.sym);
+               ret = insert_into(query, l->h->data.lval, 
l->h->next->data.lval, l->h->next->next->data.sym, 
l->h->next->next->next->data.lval);
                sql->type = Q_UPDATE;
        }
                break;
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
@@ -3293,17 +3293,19 @@ merge_stmt:
  ;
 
 insert_stmt:
-    INSERT INTO qname values_or_query_spec
+    INSERT INTO qname values_or_query_spec opt_returning_clause
        { dlist *l = L();
          append_list(l, $3);
          append_list(l, NULL);
          append_symbol(l, $4);
+         append_list(l, $5);
          $$ = _symbol_create_list( SQL_INSERT, l ); }
- |  INSERT INTO qname column_commalist_parens values_or_query_spec
+ |  INSERT INTO qname column_commalist_parens values_or_query_spec 
opt_returning_clause
        { dlist *l = L();
          append_list(l, $3);
          append_list(l, $4);
          append_symbol(l, $5);
+         append_list(l, $6);
          $$ = _symbol_create_list( SQL_INSERT, l ); }
  ;
 
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
@@ -73,3 +73,30 @@ delete from foo returning i*i
 1
 4
 9
+
+statement ok
+truncate foo
+
+query I nosort
+insert into foo(j,i) values (1,10), (-1,-10) returning j as bla
+----
+1
+-1
+
+query I nosort
+insert into foo values (1,10), (-1,-10) returning i+2*j
+----
+21
+-21
+
+
+query I nosort
+insert into foo(j) values (10), (-10) returning i IS NOT DISTINCT FROM NULL
+----
+1
+1
+
+query I nosort
+select count(*) from foo
+----
+6
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to