Changeset: 4c9283952843 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4c9283952843
Modified Files:
        sql/backends/monet5/sql_gencode.c
        sql/rel.txt
        sql/server/rel_updates.c
        sql/server/sql_parser.y
Branch: default
Log Message:

add support for multi attribute updates


diffs (242 lines):

diff --git a/sql/backends/monet5/sql_gencode.c 
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -2433,8 +2433,7 @@ backend_create_func(backend *be, sql_fun
                        setVarType(curBlk, varid, type);
                        setVarUDFtype(curBlk, varid);
                }
-       } else
-       if (f->ops) {
+       } else if (f->ops) {
                int argc = 0;
                node *n;
 
diff --git a/sql/rel.txt b/sql/rel.txt
--- a/sql/rel.txt
+++ b/sql/rel.txt
@@ -44,7 +44,7 @@ APPLY
        (card MULTI)
        -> exps         are the bind variables (from the outer, correlated in 
the subquery)
        -> l            is outer relation
-       -> s            is subquery relation
+       -> r            is subquery relation
 
 UNION|EXCEPT|INTERSECT 
        (card ATOM, AGGR or MULTI (same card as lower 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
@@ -778,6 +778,23 @@ 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)
+{
+       if (!c) {
+               rel_destroy(r);
+               return sql_error(sql, 02, "42S22!UPDATE: no such column 
'%s.%s'", t->base.name, cname);
+       }
+       if (!table_privs(sql, t, PRIV_UPDATE) && !sql_privilege(sql, 
sql->user_id, c->base.id, PRIV_UPDATE, 0)) 
+               return sql_error(sql, 02, "UPDATE: insufficient privileges for 
user '%s' to update table '%s' on column '%s'", stack_get_string(sql, 
"current_user"), t->base.name, cname);
+       if (!v || (v = rel_check_type(sql, &c->type, v, type_equal)) == NULL) {
+               rel_destroy(r);
+               return NULL;
+       }
+       return v;
+}
+
 static sql_rel *
 update_table(mvc *sql, dlist *qname, dlist *assignmentlist, symbol *opt_where)
 {
@@ -811,7 +828,7 @@ update_table(mvc *sql, dlist *qname, dli
        } else {
                sql_exp *e = NULL, **updates;
                sql_rel *r = NULL;
-               list *exps = new_exp_list(sql->sa);//, *pexps;
+               list *exps = new_exp_list(sql->sa);
                dnode *n;
 
                if (t && !isTempTable(t) && STORE_READONLY)
@@ -840,84 +857,103 @@ update_table(mvc *sql, dlist *qname, dli
                        bt = r = rel_basetable(sql, t, t->base.name );
                }
        
-               //pexps = rel_projections(sql, r, NULL, 1, 0);
-               /* We simply create a relation TID, updates */
-
                /* first create the project */
                e = exp_column(sql->sa, rel_name(r), TID, 
sql_bind_localtype("oid"), CARD_MULTI, 0, 1);
-               //r = rel_project(sql->sa, r, append(new_exp_list(sql->sa),e));
-               //e = exp_column(sql->sa, rel_name(r), TID, 
sql_bind_localtype("oid"), CARD_MULTI, 0, 1);
                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;
-                       char *cname = assignment->h->next->data.sval;
-                       sql_column *c = mvc_bind_column(sql, t, cname);
+                       int single = (assignment->h->next->type == type_string);
+                       /* Single assignments have a name, multicolumn a list */
 
-                       if (!c) {
-                               rel_destroy(r);
-                               return sql_error(sql, 02, "42S22!UPDATE: no 
such column '%s.%s'", t->base.name, cname);
-                       }
-                       if (!table_privs(sql, t, PRIV_UPDATE) && 
!sql_privilege(sql, sql->user_id, c->base.id, PRIV_UPDATE, 0)) 
-                               return sql_error(sql, 02, "UPDATE: insufficient 
privileges for user '%s' to update table '%s' on column '%s'", 
stack_get_string(sql, "current_user"), tname, c->base.name);
                        a = assignment->h->data.sym;
                        if (a) {
                                int status = sql->session->status;
-                               sql_rel *rel_val = NULL;
-                               exp_kind ek = {type_value, card_column, FALSE};
+                               exp_kind ek = {type_value, 
(single)?card_column:card_relation, FALSE};
 
-                               v = rel_value_exp(sql, &rel_val, a, sql_sel, 
ek);
+                               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) {
-                                       //symbol *s = n->data.sym;
                                        sql->errstr[0] = 0;
                                        sql->session->status = status;
-                                       v = rel_value_exp(sql, &r, a, sql_sel, 
ek);
-                                       //s->token = SQL_COLUMN;
-                                       //v = rel_column_exp(sql, &r, s, 
sql_sel);
-
-                                       /*
-                                       if (v && r && r->op == op_project) {
-                                               sql_rel *rl = r->l;
-
-                                               if (rl && rl->op == op_project)
-                                                       list_merge(rl->exps, 
pexps, (fdup)NULL);
+                                       if (single) {
+                                               v = rel_value_exp(sql, &r, a, 
sql_sel, ek);
+                                       } else {
+                                               list *val_exps;
+                                               r = rel_subquery(sql, r, a, ek, 
APPLY_JOIN);
+                                               val_exps = rel_projections(sql, 
r->r, NULL, 0, 1);
+                                               r = rel_project(sql->sa, r, 
rel_projections(sql, r, NULL, 1, 1));
+                                               list_merge(r->exps, val_exps, 
(fdup)NULL);
                                        }
-                                       */
                                }
-                               if (!v || (v = rel_check_type(sql, &c->type, v, 
type_equal)) == NULL) {
+                               if ((single && !v) || (!single && !r)) {
                                        rel_destroy(r);
                                        return NULL;
                                }
                                if (rel_val) {
-                                       //sql_rel *nr;
-                                       //list *exps;
-
                                        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));
-                                       rel_project_add_exp(sql, rel_val, v);
-                                       //exps = rel_projections(sql, r, NULL, 
0, 1);
-                                       //nr = rel_project(sql->sa, 
rel_crossproduct(sql->sa, rel_dup(r->l), rel_val, op_join), exps);
+                                       if (single) {
+                                               rel_val = rel_project(sql->sa, 
rel_val, rel_projections(sql, rel_val, NULL, 0, 1));
+                                               rel_project_add_exp(sql, 
rel_val, v);
+                                       }
                                        r = rel_crossproduct(sql->sa, r, 
rel_val, op_join);
-                                       //rel_destroy(r);
-                                       //r = nr;
-                                       v = exp_column(sql->sa, NULL, 
exp_name(v), exp_subtype(v), v->card, has_nil(v), is_intern(v));
-                               }               
+                                       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 NULL;
+                               }
+                               nr = 
(list_length(rel_val->exps)-dlist_length(cols));
+                               for(n=rel_val->exps->h; nr; nr--, n = n->next)
+                                       ; 
+                               for(m = cols->h; n && m; n = n->next, m = 
m->next) {
+                                       char *cname = m->data.sval;
+                                       sql_column *c = mvc_bind_column(sql, t, 
cname);
+                                       sql_exp *v = n->data;
+
+                                       v = exp_column(sql->sa, exp_relname(v), 
exp_name(v), exp_subtype(v), v->card, has_nil(v), is_intern(v));
+                                       if (!v) { /* check for NULL */
+                                               v = exp_atom(sql->sa, 
atom_general(sql->sa, &c->type, NULL));
+                                       } else if ((v = 
update_check_column(sql, t, c, v, r, cname)) == NULL) {
+                                               return NULL;
+                                       }
+                                       list_append(exps, exp_column(sql->sa, 
t->base.name, cname, &c->type, CARD_MULTI, 0, 0));
+                                       assert(!updates[c->colnr]);
+                                       exp_setname(sql->sa, v, 
c->t->base.name, c->base.name);
+                                       updates[c->colnr] = v;
+                               }
                        } else {
-                               v = exp_atom(sql->sa, atom_general(sql->sa, 
&c->type, NULL));
+                               char *cname = assignment->h->next->data.sval;
+                               sql_column *c = mvc_bind_column(sql, t, cname);
+
+                               if (!v) {
+                                       v = exp_atom(sql->sa, 
atom_general(sql->sa, &c->type, NULL));
+                               } else if ((v = update_check_column(sql, t, c, 
v, r, cname)) == NULL) {
+                                       return NULL;
+                               }
+                               list_append(exps, exp_column(sql->sa, 
t->base.name, cname, &c->type, CARD_MULTI, 0, 0));
+                               assert(!updates[c->colnr]);
+                               exp_setname(sql->sa, v, c->t->base.name, 
c->base.name);
+                               updates[c->colnr] = v;
                        }
-
-                       if (!v) {
-                               rel_destroy(r);
-                               return NULL;
-                       }
-                       list_append(exps, exp_column(sql->sa, t->base.name, 
cname, &c->type, CARD_MULTI, 0, 0));
-                       assert(!updates[c->colnr]);
-                       exp_setname(sql->sa, v, c->t->base.name, c->base.name);
-                       updates[c->colnr] = v;
                }
                e = exp_column(sql->sa, rel_name(r), TID, 
sql_bind_localtype("oid"), CARD_MULTI, 0, 1);
                r = rel_project(sql->sa, r, append(new_exp_list(sql->sa),e));
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
@@ -2674,18 +2674,20 @@ assignment_commalist:
 
 assignment:
    column '=' search_condition
-
        { dlist *l = L();
          append_symbol(l, $3 );
          append_string(l, $1);
          $$ = _symbol_create_list( SQL_ASSIGN, l); }
-
  | column '=' sqlNULL
-
        { dlist *l = L();
          append_symbol(l, NULL );
          append_string(l, $1);
          $$ = _symbol_create_list( SQL_ASSIGN, l); }
+ |  column_commalist_parens '=' subquery
+       { dlist *l = L();
+         append_symbol(l, $3);
+         append_list(l, $1);
+         $$ = _symbol_create_list( SQL_ASSIGN, l ); }
  ;
 
 opt_where_clause:
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to