Changeset: 55e394c7e78d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=55e394c7e78d
Added Files:
        sql/test/merge-partitions/Tests/mergepart11.stable.err
        sql/test/merge-partitions/Tests/mergepart11.stable.out
Modified Files:
        sql/server/rel_propagate.c
        sql/server/rel_updates.c
        sql/test/merge-partitions/Tests/mergepart11.sql
Branch: merge-partitions
Log Message:

At this moment we won't be supporting updates on the partitioned column.


diffs (truncated from 548 to 300 lines):

diff --git a/sql/server/rel_propagate.c b/sql/server/rel_propagate.c
--- a/sql/server/rel_propagate.c
+++ b/sql/server/rel_propagate.c
@@ -211,7 +211,7 @@ rel_ddl_distribute(sql_allocator *sa, sq
 }
 
 static sql_rel*
-rel_propagate_delete(mvc *sql, sql_rel *rel, sql_table *t, int *changes)
+rel_generate_subdeletes(mvc *sql, sql_rel *rel, sql_table *t, int *changes)
 {
        int just_one = 1;
        sql_rel *sel = NULL;
@@ -239,21 +239,57 @@ rel_propagate_delete(mvc *sql, sql_rel *
                }
                (*changes)++;
        }
-       return rel_ddl_distribute(sql->sa, sel, NULL, NULL);
+       return sel;
 }
 
 static sql_rel*
-rel_propagate_insert(mvc *sql, sql_rel *rel, sql_table *t, int *changes)
+rel_generate_subupdates(mvc *sql, sql_rel *rel, sql_table *t, int *changes)
+{
+       int just_one = 1;
+       sql_rel *sel = NULL;
+
+       for (node *n = t->members.set->h; n; n = n->next) {
+               sql_part *pt = (sql_part *) n->data;
+               sql_table *sub = find_sql_table(t->s, pt->base.name);
+               sql_rel *s1, *dup = NULL;
+               list *uexps = exps_copy(sql->sa, rel->exps);
+
+               if(rel->r) {
+                       dup = rel_copy(sql->sa, rel->r, 1);
+                       dup = rel_change_base_table(sql, dup, t, sub);
+               }
+
+               for(node *ne = uexps->h ; ne ; ne = ne->next)
+                       ne->data = exp_change_column_table(sql, (sql_exp*) 
ne->data, t, sub);
+
+               s1 = rel_update(sql, rel_basetable(sql, sub, sub->base.name), 
dup, NULL, uexps);
+               if (just_one == 0) {
+                       sel = rel_list(sql->sa, sel, s1);
+               } else {
+                       sel = s1;
+                       just_one = 0;
+               }
+               (*changes)++;
+       }
+
+       return sel;
+}
+
+static sql_rel*
+rel_generate_subinserts(mvc *sql, sql_rel *rel, sql_rel **anti_rel, sql_exp 
**exception, sql_table *t, int *changes,
+                                               const char *operation, const 
char *desc)
 {
        int colr = t->pcol->colnr, just_one = 1, found_nils = 0;
-       sql_rel *anti_dup = rel_dup(rel->r) /* the anti relation */, *new_table 
= NULL, *sel = NULL;
-       sql_exp *anti_exp = NULL, *anti_le = list_fetch(anti_dup->exps, colr), 
*accum = NULL, *aggr = NULL,
-                       *exception = NULL;
+       sql_rel *new_table = NULL, *sel = NULL;
+       sql_exp *anti_exp = NULL, *anti_le = NULL, *accum = NULL, *aggr = NULL;
        list *anti_exps = new_exp_list(sql->sa);
        sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", 
NULL);
+       char buf[BUFSIZ];
+
+       *anti_rel = rel_dup(rel->r);
+       anti_le = list_fetch((*anti_rel)->exps, colr);
        anti_le = exp_column(sql->sa, exp_relname(anti_le), exp_name(anti_le), 
exp_subtype(anti_le),
                                                 anti_le->card, 
has_nil(anti_le), is_intern(anti_le));
-       char buf[BUFSIZ];
 
        for (node *n = t->members.set->h; n; n = n->next) {
                sql_part *pt = (sql_part *) n->data;
@@ -331,6 +367,7 @@ rel_propagate_insert(mvc *sql, sql_rel *
                (*changes)++;
        }
 
+       //generate the exception
        if(isRangePartitionTable(t)) {
                if (list_length(t->members.set) == 1) //when there is just one 
partition must set the anti_exp
                        set_anti(accum);
@@ -347,63 +384,67 @@ rel_propagate_insert(mvc *sql, sql_rel *
                assert(0);
        }
        //generate a count aggregation for the values not present in any of the 
partitions
-       anti_dup = rel_select(sql->sa, anti_dup, anti_exp);
-       anti_dup = rel_project(sql->sa, anti_dup, rel_projections(sql, 
anti_dup, NULL, 1, 1));
-       anti_dup = rel_groupby(sql, anti_dup, NULL);
-       aggr = exp_aggr(sql->sa, NULL, cf, 0, 0, anti_dup->card, 0);
-       (void) rel_groupby_add_aggr(sql, anti_dup, aggr);
+       *anti_rel = rel_select(sql->sa, *anti_rel, anti_exp);
+       *anti_rel = rel_project(sql->sa, *anti_rel, rel_projections(sql, 
*anti_rel, NULL, 1, 1));
+       *anti_rel = rel_groupby(sql, *anti_rel, NULL);
+       aggr = exp_aggr(sql->sa, NULL, cf, 0, 0, (*anti_rel)->card, 0);
+       (void) rel_groupby_add_aggr(sql, *anti_rel, aggr);
        exp_label(sql->sa, aggr, ++sql->label);
 
-       //generate the exception
        aggr = exp_column(sql->sa, exp_relname(aggr), exp_name(aggr), 
exp_subtype(aggr), aggr->card,
                                          has_nil(aggr), is_intern(aggr));
-       snprintf(buf, BUFSIZ, "INSERT: the insert violates the partition %s of 
values",
+       snprintf(buf, BUFSIZ, "%s: the %s violates the partition %s of values", 
operation, desc,
                         isRangePartitionTable(t) ? "range" : "list");
-       exception = exp_exception(sql->sa, aggr, buf);
-       return rel_ddl_distribute(sql->sa, sel, anti_dup, 
list_append(new_exp_list(sql->sa), exception));
+       *exception = exp_exception(sql->sa, aggr, buf);
+
+       return sel;
+}
+
+static sql_rel*
+rel_propagate_insert(mvc *sql, sql_rel *rel, sql_table *t, int *changes)
+{
+       sql_exp* exception = NULL;
+       sql_rel* anti_rel = NULL;
+       sql_rel* res = rel_generate_subinserts(sql, rel, &anti_rel, &exception, 
t, changes, "INSERT", "insert");
+
+       return rel_ddl_distribute(sql->sa, res, anti_rel, 
list_append(new_exp_list(sql->sa), exception));
+}
+
+static sql_rel*
+rel_propagate_delete(mvc *sql, sql_rel *rel, sql_table *t, int *changes)
+{
+       rel = rel_generate_subdeletes(sql, rel, t, changes);
+       return rel_ddl_distribute(sql->sa, rel, NULL, NULL);
 }
 
 static sql_rel*
 rel_propagate_update(mvc *sql, sql_rel *rel, sql_table *t, int *changes)
 {
-       int just_one = 1;
+       int found_partition_col = 0;
        sql_rel *sel = NULL;
-       /*int found_part_col = 0;
 
        for (node *n = ((sql_rel*)rel->r)->exps->h; n; n = n->next) {
                sql_exp* exp = (sql_exp*) n->data;
-               if(exp->type == e_column) {
-                       sql_exp* l = (sql_exp*) exp->l;
-                       if(!strcmp((char*)l->l, t->base.name) && 
!strcmp((char*)l->r, t->pcol->base.name))
-                               found_part_col = 1;
+               if(exp->type == e_column && exp->l && exp->r && 
!strcmp((char*)exp->l, t->base.name) &&
+                       !strcmp((char*)exp->r, t->pcol->base.name)) {
+                               found_partition_col = 1;
                }
-       }*/
-
-       for (node *n = t->members.set->h; n; n = n->next) {
-               sql_part *pt = (sql_part *) n->data;
-               sql_table *sub = find_sql_table(t->s, pt->base.name);
-               sql_rel *s1, *dup = NULL;
-               list *uexps = exps_copy(sql->sa, rel->exps);
+       }
 
-               if(rel->r) {
-                       dup = rel_copy(sql->sa, rel->r, 1);
-                       dup = rel_change_base_table(sql, dup, t, sub);
-               }
-
-               for(node *ne = uexps->h ; ne ; ne = ne->next)
-                       ne->data = exp_change_column_table(sql, (sql_exp*) 
ne->data, t, sub);
+       if(!found_partition_col) { //easy scenario where the partitioned column 
is not being updated, just propagate
+               sel = rel_generate_subupdates(sql, rel, t, changes);
+               return rel_ddl_distribute(sql->sa, sel, NULL, NULL);
+       } else { //harder scenario, has to insert and delete across partitions.
+               /*sql_exp *exception = NULL;
+               sql_rel *inserts = NULL, *deletes = NULL, *anti_rel = NULL;
 
-               //easy scenario where the partitioned column is not being 
updated
-               s1 = rel_update(sql, rel_basetable(sql, sub, sub->base.name), 
dup, NULL, uexps);
-               if (just_one == 0) {
-                       sel = rel_list(sql->sa, sel, s1);
-               } else {
-                       sel = s1;
-                       just_one = 0;
-               }
-               (*changes)++;
+               deletes = rel_generate_subdeletes(sql, rel, t, changes);
+               deletes = rel_ddl_distribute(sql->sa, deletes, NULL, NULL);
+               inserts = rel_generate_subinserts(sql, rel, &anti_rel, 
&exception, t, changes, "UPDATE", "update");
+               inserts = rel_ddl_distribute(sql->sa, inserts, anti_rel, 
list_append(new_exp_list(sql->sa), exception));
+               return rel_list(sql->sa, deletes, inserts);*/
+               assert(0);
        }
-       return rel_ddl_distribute(sql->sa, sel, NULL, NULL);
 }
 
 static sql_rel*
@@ -412,14 +453,12 @@ rel_subtable_insert(mvc *sql, sql_rel *r
        sql_table *upper = t->p; //is part of a partition table and not been 
used yet
        int colr = upper->pcol->colnr;
        sql_part *pt = find_sql_part(upper, t->base.name);
-       sql_rel *anti_dup = rel_dup(rel->r) /* the anti relation */, *right = 
rel->r, *left = rel->l;
-       sql_exp *le = list_fetch(right->exps, colr), *anti_exp = NULL,
-                       *anti_le = list_fetch(anti_dup->exps, colr), *aggr = 
NULL, *exception = NULL;
+       sql_rel *anti_dup = rel_dup(rel->r) /* the anti relation */, *left = 
rel->l;
+       sql_exp *anti_exp = NULL, *anti_le = list_fetch(anti_dup->exps, colr), 
*aggr = NULL, *exception = NULL;
        list *anti_exps = new_exp_list(sql->sa);
        sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", 
NULL);
        char buf[BUFSIZ];
 
-       le = exp_column(sql->sa, exp_relname(le), exp_name(le), 
exp_subtype(le), le->card, has_nil(le), is_intern(le));
        anti_le = exp_column(sql->sa, exp_relname(anti_le), exp_name(anti_le), 
exp_subtype(anti_le),
                                                 anti_le->card, 
has_nil(anti_le), is_intern(anti_le));
 
@@ -474,7 +513,7 @@ rel_propagate(mvc *sql, sql_rel *rel, in
        if(l->op == op_basetable) {
                sql_table *t = l->l;
 
-               if(isRangePartitionTable(t) || isListPartitionTable(t)) {
+               if((isRangePartitionTable(t) || isListPartitionTable(t)) && 
!find_prop(l->p, PROP_USED)) {
                        assert(list_length(t->members.set) > 0);
                        if(is_delete(rel->op) || is_truncate(rel->op)) { 
//propagate deletions to the partitions
                                return rel_propagate_delete(sql, rel, t, 
changes);
@@ -488,10 +527,6 @@ rel_propagate(mvc *sql, sql_rel *rel, in
                } else if(t->p && (isRangePartitionTable(t->p) || 
isListPartitionTable(t->p)) && !find_prop(l->p, PROP_USED)) {
                        if(is_insert(rel->op)) { //insertion directly to 
sub-table (must do validation)
                                return rel_subtable_insert(sql, rel, t, 
changes);
-                       } else if(is_update(rel->op)) { //do the proper 
validation
-                               //TODO
-                       } else if(!(is_delete(rel->op) || 
is_truncate(rel->op))) { //no validation needed in deletes
-                               assert(0);
                        }
                }
        }
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
@@ -900,6 +900,13 @@ update_table(mvc *sql, dlist *qname, dli
                dnode *n;
                const char *rname = NULL;
                sql_rel *res = NULL, *bt = rel_basetable(sql, t, t->base.name);
+               int partitioned_column = -1;
+
+               if(isRangePartitionTable(t) || isListPartitionTable(t)) {
+                       partitioned_column = t->pcol->colnr;
+               } else if(t->p && (isRangePartitionTable(t->p) || 
isListPartitionTable(t->p))) {
+                       partitioned_column = t->p->pcol->colnr;
+               }
 
                res = bt;
 #if 0
@@ -1075,6 +1082,8 @@ update_table(mvc *sql, dlist *qname, dli
                                        sql_column *c = mvc_bind_column(sql, t, 
cname);
                                        sql_exp *v = n->data;
 
+                                       if(partitioned_column == c->colnr)
+                                               return sql_error(sql, 02, 
SQLSTATE(42000) "UPDATE: Update on the partitioned column not possible at the 
moment");
                                        if (!exp_name(v))
                                                exp_label(sql->sa, v, 
++sql->label);
                                        v = exp_column(sql->sa, exp_relname(v), 
exp_name(v), exp_subtype(v), v->card, has_nil(v), is_intern(v));
@@ -1092,6 +1101,8 @@ update_table(mvc *sql, dlist *qname, dli
                                char *cname = assignment->h->next->data.sval;
                                sql_column *c = mvc_bind_column(sql, t, cname);
 
+                               if(partitioned_column == c->colnr)
+                                       return sql_error(sql, 02, 
SQLSTATE(42000) "UPDATE: Update on the partitioned column not possible at the 
moment");
                                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) {
diff --git a/sql/test/merge-partitions/Tests/mergepart11.sql 
b/sql/test/merge-partitions/Tests/mergepart11.sql
--- a/sql/test/merge-partitions/Tests/mergepart11.sql
+++ b/sql/test/merge-partitions/Tests/mergepart11.sql
@@ -1,11 +1,11 @@
-CREATE MERGE TABLE moveaccrosspartitions (a int, b varchar(32)) PARTITION BY 
VALUES (a);
+CREATE MERGE TABLE moveaccrosspartitions (a int, b varchar(32)) PARTITION BY 
RANGE (a);
 CREATE TABLE sublimits1 (a int, b varchar(32));
 CREATE TABLE sublimits2 (a int, b varchar(32));
 CREATE TABLE sublimits3 (a int, b varchar(32));
 
 ALTER TABLE moveaccrosspartitions ADD TABLE sublimits1 AS PARTITION BETWEEN 1 
AND 100;
 ALTER TABLE moveaccrosspartitions ADD TABLE sublimits2 AS PARTITION BETWEEN 
101 AND 200;
-ALTER TABLE moveaccrosspartitions ADD TABLE sublimits2 AS PARTITION BETWEEN 
201 AND 300;
+ALTER TABLE moveaccrosspartitions ADD TABLE sublimits3 AS PARTITION BETWEEN 
201 AND 300;
 
 INSERT INTO moveaccrosspartitions VALUES (50, 'first'), (150, 'second'), (250, 
'third'), (60, 'fourth'), (120, 'fifth'), (240, 'sixth');
 
diff --git a/sql/test/merge-partitions/Tests/mergepart11.stable.err 
b/sql/test/merge-partitions/Tests/mergepart11.stable.err
new file mode 100644
--- /dev/null
+++ b/sql/test/merge-partitions/Tests/mergepart11.stable.err
@@ -0,0 +1,51 @@
+stderr of test 'mergepart11` in directory 'sql/test/merge-partitions` itself:
+
+
+# 09:47:13 >  
+# 09:47:13 >  "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" 
"mapi_open=true" "--set" "mapi_port=39288" "--set" 
"mapi_usock=/var/tmp/mtest-21121/.s.monetdb.39288" "--set" "monet_prompt=" 
"--forcemito" 
"--dbpath=/home/ferreira/repositories/MonetDB-merge-partitions/BUILD/var/MonetDB/mTests_sql_test_merge-partitions"
 "--set" "embedded_c=true"
+# 09:47:13 >  
+
+# builtin opt  gdk_dbpath = 
/home/ferreira/repositories/MonetDB-merge-partitions/BUILD/var/monetdb5/dbfarm/demo
+# builtin opt  gdk_debug = 0
+# builtin opt  gdk_vmtrim = no
+# builtin opt  monet_prompt = >
+# builtin opt  monet_daemon = no
+# builtin opt  mapi_port = 50000
+# builtin opt  mapi_open = false
+# builtin opt  mapi_autosense = false
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to