Changeset: 9db08f0c28ec for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/9db08f0c28ec Branch: default Log Message:
merge with check diffs (truncated from 1717 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 @@ -16,6 +16,7 @@ #include "rel_rel.h" #include "rel_basetable.h" #include "rel_exp.h" +#include "rel_dump.h" #include "rel_psm.h" #include "rel_prop.h" #include "rel_select.h" @@ -4988,6 +4989,35 @@ sql_insert_triggers(backend *be, sql_tab return res; } +static void +sql_insert_check(backend *be, sql_key *key, sql_rel *inserts, list *refs) +{ + mvc *sql = be->mvc; + node *m, *n; + + inserts = rel_copy(sql, inserts, 1); + list* exps = inserts->exps; + + for (n = ol_first_node(key->t->columns), m = exps->h; n && m; + n = n->next, m = m->next) { + sql_exp *i = m->data; + sql_column *c = n->data; + i->alias.rname= sa_strdup(sql->sa, c->t->base.name); + i->alias.name= sa_strdup(sql->sa, c->base.name); + } + + int pos = 0; + sql_rel* rel = rel_read(sql, sa_strdup(sql->sa, key->check), &pos, sa_list(sql->sa)); + rel->l = inserts; + stmt* s = subrel_bin(be, rel, refs); + sql_subtype *bt = sql_bind_localtype("bit"); + s = stmt_uselect(be, column(be, s), stmt_atom(be, atom_zero_value(sql->sa, bt)), cmp_equal, NULL, 0, 1); + sql_subfunc *cnt = sql_bind_func(sql, "sys", "count", sql_bind_localtype("void"), NULL, F_AGGR, true, true); + s = stmt_aggr(be, s, NULL, NULL, cnt, 1, 0, 1); + char *msg = sa_message(sql->sa, SQLSTATE(40002) "INSERT INTO: CHECK constraint violated: %s", key->base.name); + (void)stmt_exception(be, s, msg, 00001); +} + static sql_table * sql_insert_check_null(backend *be, sql_table *t, list *inserts) { @@ -5066,6 +5096,12 @@ rel2bin_insert(backend *be, sql_rel *rel if (idx_ins) pin = refs_find_rel(refs, prel); + for (n = ol_first_node(t->keys); n; n = n->next) { + sql_key * key = n->data; + if (key->type == ckey) + sql_insert_check(be, key, rel->r, refs); + } + if (!sql_insert_check_null(be, t, inserts->op4.lval)) return NULL; @@ -5948,6 +5984,61 @@ sql_update_triggers(backend *be, sql_tab } static void +sql_update_check(backend *be, sql_key * key, sql_rel *updates, list *refs) +{ + mvc *sql = be->mvc; + int pos = 0; + + + stack_push_frame(be->mvc, "ALTER TABLE ADD CONSTRAINT CHECK"); + sql_schema* ss = key->t->s; + frame_push_table(sql, key->t); + key->t->s = ss; // recover the schema because frame_push_table removes it + + sql_rel* rel = rel_read(sql, sa_strdup(sql->sa, key->check), &pos, sa_list(sql->sa)); + stack_pop_frame(sql); + + if (!key->base.new) { + 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"); + 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); + char *msg = sa_message(sql->sa, SQLSTATE(40002) "UPDATE: CHECK constraint violated: %s", key->base.name); + (void)stmt_exception(be, s, msg, 00001); +} + +static void sql_update_check_null(backend *be, sql_table *t, stmt **updates) { mvc *sql = be->mvc; @@ -6050,9 +6141,15 @@ rel2bin_update(backend *be, sql_rel *rel return NULL; t = rel_ddl_table_get(tr); - /* no columns to update (probably an new pkey!) */ - if (!rel->exps) + /* no columns to update (probably an new pkey or ckey!) */ + if (!rel->exps) { + for (m = ol_first_node(t->keys); m; m = m->next) { + sql_key * key = m->data; + if (key->type == ckey && key->base.new) + sql_update_check(be, key, rel->r, refs); + } return ddl; + } } if (rel->r) /* first construct the update relation */ @@ -6076,6 +6173,12 @@ rel2bin_update(backend *be, sql_rel *rel if (c) updates[c->colnr] = bin_find_column(be, update, ce->l, ce->r); } + + for (m = ol_first_node(t->keys); m; m = m->next) { + sql_key * key = m->data; + if (key->type == ckey) + sql_update_check(be, key, rel->r, refs); + } sql_update_check_null(be, t, updates); /* check keys + get idx */ 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 @@ -316,36 +316,6 @@ static int return -1; } -static str -rel2str( mvc *sql, sql_rel *rel) -{ - buffer *b = NULL; - stream *s = NULL; - list *refs = NULL; - char *res = NULL; - - b = buffer_create(1024); - if(b == NULL) - goto cleanup; - s = buffer_wastream(b, "rel_dump"); - if(s == NULL) - goto cleanup; - refs = sa_list(sql->sa); - if (!refs) - goto cleanup; - - rel_print_refs(sql, s, rel, 0, refs, 0); - rel_print_(sql, s, rel, 0, refs, 0); - mnstr_printf(s, "\n"); - res = buffer_get_buf(b); - -cleanup: - if(b) - buffer_destroy(b); - if(s) - close_stream(s); - return res; -} /* stub and remote function */ static int @@ -360,7 +330,7 @@ static int node *n; int i, q, v, res = -1, added_to_cache = 0, *lret, *rret; size_t len = 1024, nr, pwlen = 0; - char *lname = NULL, *buf = NULL, *mal_session_uuid, *err = NULL, *pwhash = NULL; + char *lname = NULL, *rel_str, *buf = NULL, *mal_session_uuid, *err = NULL, *pwhash = NULL; str username = NULL, password = NULL, msg = NULL; sql_rel *r = rel; @@ -517,23 +487,21 @@ static int pushInstruction(curBlk, o); p = pushArgument(curBlk, p, getArg(o,0)); - if (!(buf = rel2str(m, rel))) { + if (!(rel_str = rel2str(m, rel))) { freeInstruction(p); sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL); goto cleanup; } o = newFcnCall(curBlk, remoteRef, putRef); if (o == NULL) { - free(buf); freeInstruction(p); sql_error(m, 10, SQLSTATE(HY013) MAL_MALLOC_FAIL); goto cleanup; } o = pushArgument(curBlk, o, q); - o = pushStr(curBlk, o, buf); /* relational plan */ + o = pushStr(curBlk, o, rel_str); /* relational plan */ pushInstruction(curBlk, o); p = pushArgument(curBlk, p, getArg(o,0)); - free(buf); if (!(buf = sa_alloc(m->ta, len))) { freeInstruction(p); diff --git a/sql/backends/monet5/sql_upgrades.c b/sql/backends/monet5/sql_upgrades.c --- a/sql/backends/monet5/sql_upgrades.c +++ b/sql/backends/monet5/sql_upgrades.c @@ -7157,6 +7157,27 @@ sql_update_default(Client c, mvc *sql, s end: sa_destroy(sql->sa); sql->sa = old_sa; + + if (err) + return err; + sql_table *t; + if ((t = mvc_bind_table(sql, s, "key_types")) != NULL) + t->system = 0; + err = SQLstatementIntern(c, + "DROP TABLE sys.key_types;\n" + "CREATE TABLE sys.key_types (\n" + " key_type_id SMALLINT NOT NULL PRIMARY KEY,\n" + " key_type_name VARCHAR(35) NOT NULL UNIQUE);\n" + "INSERT INTO sys.key_types VALUES\n" + "(0, 'Primary Key'),\n" + "(1, 'Unique Key'),\n" + "(2, 'Foreign Key'),\n" + "(3, 'Unique Key With Nulls Not Distinct'),\n" + "(4, 'Check Constraint');\n" + "ALTER TABLE sys.key_types SET READ ONLY;\n" + "GRANT SELECT ON sys.key_types TO PUBLIC;\n" + "UPDATE sys._tables SET system = true WHERE schema_id = 2000 AND name = 'key_types';\n" + , "update", true, false, NULL); return err; } diff --git a/sql/include/sql_catalog.h b/sql/include/sql_catalog.h --- a/sql/include/sql_catalog.h +++ b/sql/include/sql_catalog.h @@ -534,7 +534,8 @@ typedef enum key_type { pkey, ukey, /* default behavior is that NULLS are distinct, e.g. there can be multiple null values in a column with regular UNIQUE constraint */ fkey, - unndkey /* NULLS are not distinct, i.e. NULLS act as regular values for uniqueness checks */ + unndkey, /* NULLS are not distinct, i.e. NULLS act as regular values for uniqueness checks */ + ckey /* CHECK constraint behaves as a key type*/ } key_type; typedef struct sql_kc { @@ -571,6 +572,7 @@ typedef struct sql_key { /* pkey, ukey, sql_base base; key_type type; /* pkey, ukey, fkey */ sql_idx *idx; /* idx to accelerate key check */ + char *check; /* check condition*/ struct list *columns; /* list of sql_kc */ struct sql_table *t; diff --git a/sql/scripts/10_sys_schema_extension.sql b/sql/scripts/10_sys_schema_extension.sql --- a/sql/scripts/10_sys_schema_extension.sql +++ b/sql/scripts/10_sys_schema_extension.sql @@ -396,14 +396,16 @@ GRANT SELECT ON sys.function_languages T CREATE TABLE sys.key_types ( key_type_id SMALLINT NOT NULL PRIMARY KEY, - key_type_name VARCHAR(15) NOT NULL UNIQUE); + key_type_name VARCHAR(35) NOT NULL UNIQUE); -- Values taken from sql/include/sql_catalog.h see typedef enum -- key_type: pkey, ukey, fkey. INSERT INTO sys.key_types (key_type_id, key_type_name) VALUES (0, 'Primary Key'), (1, 'Unique Key'), - (2, 'Foreign Key'); + (2, 'Foreign Key'), + (3, 'Unique Key With Nulls Not Distinct'), + (4, 'Check Constraint'); _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org