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]