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 -- [email protected]
To unsubscribe send an email to [email protected]