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