Changeset: 9f5f007db116 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=9f5f007db116
Added Files:
sql/test/merge-statements/Tests/All
sql/test/merge-statements/Tests/mergestmt00.sql
Modified Files:
sql/backends/monet5/rel_bin.c
sql/server/rel_updates.c
sql/server/sql_parser.y
Branch: merge-statements
Log Message:
Doing progress for merge statements, but the rel_optimizer is causing problems.
diffs (truncated from 862 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
@@ -4690,7 +4690,7 @@ sql_delete(backend *be, sql_table *t, st
if(be->cur_append && !be->first_statement_generated) {
for(sql_table *up = t->p ; up ; up = up->p) {
if (!sql_delete_triggers(be, up, v, 0, 1, 3))
- return sql_error(sql, 02, SQLSTATE(42000)
"UPDATE: triggers failed for table '%s'", up->base.name);
+ return sql_error(sql, 02, SQLSTATE(42000)
"DELETE: triggers failed for table '%s'", up->base.name);
}
}
if (!sql_delete_triggers(be, t, v, 0, 1, 3))
@@ -5008,6 +5008,10 @@ rel2bin_list(backend *be, sql_rel *rel,
list *slist = sa_list(sql->sa);
(void)refs;
+
+ if(find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0) /* create
affected rows accumulator */
+ create_merge_partitions_accumulator(be);
+
if (rel->l) /* first construct the sub relation */
l = subrel_bin(be, rel->l, refs);
if (rel->r) /* first construct the sub relation */
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
@@ -17,6 +17,7 @@
#include "rel_dump.h"
#include "rel_psm.h"
#include "sql_symbol.h"
+#include "rel_prop.h"
static sql_exp *
insert_value(mvc *sql, sql_column *c, sql_rel **r, symbol *s)
@@ -307,7 +308,7 @@ check_table_columns(mvc *sql, sql_table
if (c) {
list_append(collist, c);
} else {
- return sql_error(sql, 02, SQLSTATE(42S22) "%s
INTO: no such column '%s.%s'", op, tname, n->data.sval);
+ return sql_error(sql, 02, SQLSTATE(42S22) "%s:
no such column '%s.%s'", op, tname, n->data.sval);
}
}
} else {
@@ -458,34 +459,14 @@ update_allowed(mvc *sql, sql_table *t, c
}
static sql_rel *
-insert_into(mvc *sql, dlist *qname, dlist *columns, symbol *val_or_q)
+insert_generate_inserts(mvc *sql, sql_table *t, dlist *columns, symbol
*val_or_q, const str action)
{
- size_t rowcount = 1;
- char *sname = qname_schema(qname);
- char *tname = qname_table(qname);
- sql_schema *s = NULL;
- sql_table *t = NULL;
- list *collist = NULL;
sql_rel *r = NULL;
-
- if (sname && !(s=mvc_bind_schema(sql, sname))) {
- (void) sql_error(sql, 02, SQLSTATE(3F000) "INSERT INTO: no such
schema '%s'", sname);
- return NULL;
- }
- if (!s)
- s = cur_schema(sql);
- t = mvc_bind_table(sql, s, tname);
- if (!t && !sname) {
- s = tmp_schema(sql);
- t = mvc_bind_table(sql, s, tname);
- if (!t)
- t = mvc_bind_table(sql, NULL, tname);
- }
- if (insert_allowed(sql, t, tname, "INSERT INTO", "insert into") ==
NULL)
- return NULL;
- collist = check_table_columns(sql, t, columns, "INSERT", tname);
+ size_t rowcount = 1;
+ list *collist = check_table_columns(sql, t, columns, action,
t->base.name);
if (!collist)
return NULL;
+
if (val_or_q->token == SQL_VALUES) {
dlist *rowlist = val_or_q->data.lval;
dlist *values;
@@ -503,7 +484,7 @@ insert_into(mvc *sql, dlist *qname, dlis
values = o->data.lval;
if (dlist_length(values) != list_length(collist)) {
- return sql_error(sql, 02, SQLSTATE(21S01)
"INSERT INTO: number of values doesn't match number of columns of table '%s'",
tname);
+ return sql_error(sql, 02, SQLSTATE(21S01) "%s:
number of values doesn't match number of columns of table '%s'", action,
t->base.name);
} else {
dnode *n;
node *v, *m;
@@ -512,8 +493,8 @@ insert_into(mvc *sql, dlist *qname, dlis
for (n = values->h, m = collist->h; n
&& m; n = n->next, m = m->next) {
sql_exp *vals =
exp_values(sql->sa, sa_list(sql->sa));
sql_column *c = m->data;
-
- vals->tpe = c->type;
+
+ vals->tpe = c->type;
exp_label(sql->sa, vals,
++sql->label);
list_append(exps, vals);
}
@@ -525,11 +506,11 @@ insert_into(mvc *sql, dlist *qname, dlis
sql_column *c = m->data;
sql_rel *r = NULL;
sql_exp *ins =
insert_value(sql, c, &r, n->data.sym);
- if (!ins)
+ if (!ins)
return NULL;
if (r && inner)
inner =
rel_crossproduct(sql->sa, inner, r, op_join);
- else if (r)
+ else if (r)
inner = r;
if (inner && !ins->name &&
!exp_is_atom(ins)) {
exp_label(sql->sa, ins,
++sql->label);
@@ -547,7 +528,7 @@ insert_into(mvc *sql, dlist *qname, dlis
return NULL;
if (r && inner)
inner =
rel_crossproduct(sql->sa, inner, r, op_join);
- else if (r)
+ else if (r)
inner = r;
if (!ins->name)
exp_label(sql->sa, ins,
++sql->label);
@@ -563,21 +544,51 @@ insert_into(mvc *sql, dlist *qname, dlis
r = rel_subquery(sql, NULL, val_or_q, ek, APPLY_JOIN);
}
- if (!r)
+ if (!r)
return NULL;
- /* In case of missing project, order by or distinct, we need to add
+ /* In case of missing project, order by or distinct, we need to add
and projection */
if (r->op != op_project || r->r || need_distinct(r))
r = rel_project(sql->sa, r, rel_projections(sql, r, NULL, 1,
0));
if ((r->exps && list_length(r->exps) != list_length(collist)) ||
- (!r->exps && collist))
- return sql_error(sql, 02, SQLSTATE(21S01) "INSERT INTO: query
result doesn't match number of columns in table '%s'", tname);
+ (!r->exps && collist))
+ return sql_error(sql, 02, SQLSTATE(21S01) "%s: query result
doesn't match number of columns in table '%s'", action, t->base.name);
r->exps = rel_inserts(sql, t, r, collist, rowcount, 0);
if(!r->exps)
return NULL;
- return rel_insert_table(sql, t, tname, r);
+ return r;
+}
+
+static sql_rel *
+insert_into(mvc *sql, dlist *qname, dlist *columns, symbol *val_or_q)
+{
+ char *sname = qname_schema(qname);
+ char *tname = qname_table(qname);
+ sql_schema *s = NULL;
+ sql_table *t = NULL;
+ sql_rel *r = NULL;
+
+ if (sname && !(s=mvc_bind_schema(sql, sname))) {
+ (void) sql_error(sql, 02, SQLSTATE(3F000) "INSERT INTO: no such
schema '%s'", sname);
+ return NULL;
+ }
+ if (!s)
+ s = cur_schema(sql);
+ t = mvc_bind_table(sql, s, tname);
+ if (!t && !sname) {
+ s = tmp_schema(sql);
+ t = mvc_bind_table(sql, s, tname);
+ if (!t)
+ t = mvc_bind_table(sql, NULL, tname);
+ }
+ if (insert_allowed(sql, t, tname, "INSERT INTO", "insert into") ==
NULL)
+ return NULL;
+ r = insert_generate_inserts(sql, t, columns, val_or_q, "INSERT INTO");
+ if(!r)
+ return NULL;
+ return rel_insert_table(sql, t, t->base.name, r);
}
static int
@@ -868,7 +879,6 @@ rel_update(mvc *sql, sql_rel *t, sql_rel
return r;
}
-
static sql_exp *
update_check_column(mvc *sql, sql_table *t, sql_column *c, sql_exp *v, sql_rel
*r, char *cname)
{
@@ -886,6 +896,176 @@ update_check_column(mvc *sql, sql_table
}
static sql_rel *
+update_generate_assignments(mvc *sql, sql_table *t, sql_rel *r, sql_rel *bt,
dlist *assignmentlist, const str action)
+{
+ sql_table *mt = NULL;
+ sql_exp *e = NULL, **updates;
+ list *exps, *pcols = NULL;
+ dnode *n;
+ const char *rname = NULL;
+
+ if(isPartitionedByColumnTable(t) || isPartitionedByExpressionTable(t)) {
+ mt = t;
+ } else if(t->p && (isPartitionedByColumnTable(t->p) ||
isPartitionedByExpressionTable(t->p))) {
+ mt = t->p;
+ }
+ if(mt && isPartitionedByColumnTable(mt)) {
+ pcols = sa_list(sql->sa);
+ int *nid = sa_alloc(sql->sa, sizeof(int));
+ *nid = mt->part.pcol->colnr;
+ list_append(pcols, nid);
+ } else if(mt && isPartitionedByExpressionTable(mt)) {
+ pcols = mt->part.pexp->cols;
+ }
+ /* first create the project */
+ e = exp_column(sql->sa, rname = rel_name(r), TID,
sql_bind_localtype("oid"), CARD_MULTI, 0, 1);
+ exps = new_exp_list(sql->sa);
+ append(exps, e);
+ updates = table_update_array(sql, t);
+ for (n = assignmentlist->h; n; n = n->next) {
+ symbol *a = NULL;
+ sql_exp *v = NULL;
+ sql_rel *rel_val = NULL;
+ dlist *assignment = n->data.sym->data.lval;
+ int single = (assignment->h->next->type == type_string);
+ /* Single assignments have a name, multicolumn a list */
+
+ a = assignment->h->data.sym;
+ if (a) {
+ int status = sql->session->status;
+ exp_kind ek = {type_value,
(single)?card_column:card_relation, FALSE};
+
+ if(single && a->token == SQL_DEFAULT) {
+ char *colname = assignment->h->next->data.sval;
+ sql_column *col = mvc_bind_column(sql, t,
colname);
+ if (col->def) {
+ char *typestr =
subtype2string2(&col->type);
+ if(!typestr)
+ return sql_error(sql, 02,
SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ v = rel_parse_val(sql,
sa_message(sql->sa, "select cast(%s as %s);", col->def, typestr), sql->emode,
NULL);
+ _DELETE(typestr);
+ } else {
+ return sql_error(sql, 02,
SQLSTATE(42000) "%s: column '%s' has no valid default value", action,
col->base.name);
+ }
+ } else if (single) {
+ v = rel_value_exp(sql, &rel_val, a, sql_sel,
ek);
+ } else {
+ rel_val = rel_subquery(sql, NULL, a, ek,
APPLY_JOIN);
+ }
+ if (!v) {
+ sql->errstr[0] = 0;
+ sql->session->status = status;
+ if (single) {
+ rel_val = NULL;
+ v = rel_value_exp(sql, &r, a, sql_sel,
ek);
+ } else if (!rel_val && r) {
+ r = rel_subquery(sql, r, a, ek,
APPLY_LOJ);
+ if (r) {
+ list *val_exps =
rel_projections(sql, r->r, NULL, 0, 1);
+
+ r = rel_project(sql->sa, r,
rel_projections(sql, r, NULL, 1, 1));
+ if (r)
+ list_merge(r->exps,
val_exps, (fdup)NULL);
+ reset_processed(r);
+ }
+ }
+ }
+ if ((single && !v) || (!single && !r)) {
+ rel_destroy(r);
+ return NULL;
+ }
+ if (rel_val) {
+ if (single) {
+ if (!exp_name(v))
+ exp_label(sql->sa, v,
++sql->label);
+ rel_val = rel_project(sql->sa, rel_val,
rel_projections(sql, rel_val, NULL, 0, 1));
+ v = rel_project_add_exp(sql, rel_val,
v);
+ reset_processed(rel_val);
+ }
+ r = rel_crossproduct(sql->sa, r, rel_val,
op_left);
+ if (single)
+ v = exp_column(sql->sa, NULL,
exp_name(v), exp_subtype(v), v->card, has_nil(v), is_intern(v));
+ }
+ }
+ if (!single) {
+ dlist *cols = assignment->h->next->data.lval;
+ dnode *m;
+ node *n;
+ int nr;
+
+ if (!rel_val)
+ rel_val = r;
+ if (!rel_val || !is_project(rel_val->op) ||
+ dlist_length(cols) >
list_length(rel_val->exps)) {
+ rel_destroy(r);
+ return sql_error(sql, 02, SQLSTATE(42000) "%s:
too many columns specified", action);
+ }
+ nr = (list_length(rel_val->exps)-dlist_length(cols));
+ for(n=rel_val->exps->h; nr; nr--, n = n->next)
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list