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

Reply via email to