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