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

Reply via email to