Changeset: 5033a4523f7b for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/5033a4523f7b Modified Files: sql/backends/monet5/rel_bin.c sql/test/2024/Tests/check.test Branch: check Log Message:
implement check constraint for partial row update diffs (99 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 @@ -5917,17 +5917,42 @@ sql_update_triggers(backend *be, sql_tab } static void -sql_update_check(backend *be, sql_key * key, sql_rel *rupdates, list *refs) +sql_update_check(backend *be, sql_key * key, sql_rel *updates, list *refs) { - /* TODO: this won't work for general table check constraints involving updates to a strict subset of check columns*/ mvc *sql = be->mvc; + int pos = 0; + sql_rel* rel = rel_read(sql, sa_strdup(sql->sa, key->check), &pos, sa_list(sql->sa)); + sql_rel* base = rel->l; + assert(strcmp(((sql_exp*) updates->exps->h->data)->alias.name, TID) == 0); + list_append(base->exps, exp_copy(sql, updates->exps->h->data)); + + bool need_join = 0; + list* pexps = sa_list(sql->sa); + sql_exp* tid_exp = exp_copy(sql, updates->exps->h->data); + unsigned label = ++sql->label; + exp_setrelname(sql->sa, tid_exp, label); + list_append(pexps, tid_exp); + for (node* m = base->exps->h; m; m = m->next) { + if (exps_find_exp( updates->exps, m->data) == NULL) { + pexps = list_append(pexps, exp_copy(sql, m->data)); + need_join = 1; + } + } + + if (need_join) { + base = rel_project(sql->sa, base, pexps); + sql_rel* join = rel_crossproduct(sql->sa, base, updates, op_join); + sql_exp* join_cond = exp_compare(sql->sa, exp_ref(sql, base->exps->h->data), exp_ref(sql, updates->exps->h->data), cmp_equal); + join->exps = sa_list(sql->sa); + join->exps = list_append(join->exps, join_cond); + rel->l = join; + } + else { + rel->l = updates; + } + sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true); sql_subtype *bt = sql_bind_localtype("bit"); - - - int pos = 0; - sql_rel* rel = rel_read(sql, sa_strdup(sql->sa, key->check), &pos, sa_list(sql->sa)); - rel->l = rupdates; stmt* s = subrel_bin(be, rel, refs); s = stmt_uselect(be, column(be, s), stmt_atom(be, atom_zero_value(sql->sa, bt)), cmp_equal, NULL, 0, 1); s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1); diff --git a/sql/test/2024/Tests/check.test b/sql/test/2024/Tests/check.test --- a/sql/test/2024/Tests/check.test +++ b/sql/test/2024/Tests/check.test @@ -1,20 +1,35 @@ statement ok -create table bar (i int, j int CHECK (j > 0)); +create table foo (i int CHECK (i > 0), j int CHECK (j > 0)) statement ok -insert into bar values (1,10), (2, 20), (3, 30); +insert into foo values (1,10), (2, 20), (3, 30) statement error -update bar set j = -30 where i = 3; +update foo set j = -30 where i = 3 + +statement error +update foo set j = -j statement error -update bar set j = -j; +insert into foo values (4, -40) + +statement ok +insert into foo select * from foo statement error -insert into bar values (4, -40); +insert into foo select 4, -40 statement ok -insert into bar select * from bar +create table bar (i int, j int, constraint check_i_j CHECK (i < j)) statement error -insert into bar select 4, -40; +insert into bar values (30, 20) + +statement ok +insert into bar values (10,20), (20, 30), (30, 40) + +statement error +update bar set i = 50 where i = 30 + +statement error +update bar set i = 50, j = 40 where i = 30 _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org