Changeset: ec5c7a5d7a16 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ec5c7a5d7a16
Added Files:
sql/test/merge-partitions/Tests/mergepart06.stable.err
sql/test/merge-partitions/Tests/mergepart06.stable.out
sql/test/merge-partitions/Tests/mergepart09.stable.err
sql/test/merge-partitions/Tests/mergepart09.stable.out
Modified Files:
sql/backends/monet5/rel_bin.c
sql/backends/monet5/sql_cat.c
sql/server/rel_exp.c
sql/server/rel_optimizer.c
sql/test/merge-partitions/Tests/mergepart06.sql
sql/test/merge-partitions/Tests/mergepart08.sql
sql/test/merge-partitions/Tests/mergepart09.sql
Branch: merge-partitions
Log Message:
When inserting into a sub-table of the partition directly, create the exception
statement as well.
Also made fixes for the other tests.
diffs (truncated from 695 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
@@ -4919,8 +4919,13 @@ rel2bin_distribute(backend *be, sql_rel
if(rel->exps && list_length(rel->exps) == 1) {
n = rel->exps->h;
except = n->data;
+ return exp_bin(be, except, l, r, NULL, NULL, NULL, NULL);
+ } else { //if there is no exception condition, just generate a
statement list
+ list *slist = sa_list(be->mvc->sa);
+ list_append(slist, l);
+ list_append(slist, r);
+ return stmt_list(be, slist);
}
- return exp_bin(be, except, l, r, NULL, NULL, NULL, NULL);
}
static stmt *
diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -344,6 +344,8 @@ finish:
BBPunfix(diff1->batCacheid);
if(diff2)
BBPunfix(diff2->batCacheid);
+ if(msg != MAL_SUCCEED)
+ pt->p = NULL;
return msg;
}
@@ -497,6 +499,8 @@ finish:
BBPunfix(cbind->batCacheid);
if(diff)
BBPunfix(diff->batCacheid);
+ if(msg != MAL_SUCCEED)
+ pt->p = NULL;
return msg;
}
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -634,7 +634,7 @@ exp_exception(sql_allocator *sa, sql_exp
if (e == NULL)
return NULL;
e->l = cond;
- e->r = error_message;
+ e->r = sa_strdup(sa, error_message);
e->flag = PSM_EXCEPTION;
return e;
}
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -8136,6 +8136,7 @@ rel_merge_table_rewrite(int *changes, mv
sql_rel *left = rel->l;
if(left->op == op_basetable) {
sql_table *t = left->l;
+ char buf[BUFSIZ];
if(isRangePartitionTable(t) || isListPartitionTable(t))
{
int just_one = 1;
@@ -8165,13 +8166,14 @@ rel_merge_table_rewrite(int *changes, mv
sel = rel_ddl_distribute(sql->sa, sel,
NULL, NULL);
} else if(is_insert(rel->op)) { //on inserts
create a selection for each partition
int colr = t->pcol->colnr;
- sql_rel *anti_dup = rel_dup(rel->r); /*
the anti relation */
+ sql_rel *anti_dup = rel_dup(rel->r) /*
the anti relation */, *new_table = NULL;
sql_exp *anti_exp = NULL, *anti_le =
list_fetch(anti_dup->exps, colr), *accum = NULL, *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);
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));
+ int found_nils = 0;
for (node *n = t->members.set->h; n; n
= n->next) {
sql_part *pt = (sql_part *)
n->data;
@@ -8202,11 +8204,11 @@ rel_merge_table_rewrite(int *changes, mv
nils =
exp_compare(sql->sa, nils, exp_atom_bool(sql->sa, 1), cmp_equal);
if(accum) {
- sql_exp
*nr = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_equal);
+ sql_exp
*nr = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_notequal);
accum =
exp_or(sql->sa, list_append(new_exp_list(sql->sa), accum),
list_append(new_exp_list(sql->sa), nr), 1);
} else {
- accum =
exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_equal);
+ accum =
exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_notequal);
}
extra =
rel_select(sql->sa, rel->r, nils);
dup =
rel_or(sql, NULL, dup, extra, NULL, NULL, NULL);
@@ -8222,18 +8224,24 @@ rel_merge_table_rewrite(int *changes, mv
list_append(anti_exps, exp_copy(sql->sa, e1));
}
+ ein = exp_in(sql->sa,
le, exps, cmp_in);
if(pt->with_nills) { /*
handle the nulls case */
- sql_exp *e2 =
exp_atom(sql->sa, atom_general(sql->sa, &(t->pcol->type), NULL));
-
list_append(exps, e2);
-
list_append(anti_exps, exp_copy(sql->sa, e2));
+ sql_exp *nils =
rel_unop_(sql, le, NULL, "isnull", card_value);
+ nils =
exp_compare(sql->sa, nils, exp_atom_bool(sql->sa, 1), cmp_equal);
+ ein =
exp_or(sql->sa, list_append(new_exp_list(sql->sa), ein),
+
list_append(new_exp_list(sql->sa), nils), 0);
+ found_nils = 1;
}
- ein = exp_in(sql->sa,
le, exps, cmp_in);
dup =
rel_select(sql->sa, dup, ein);
} else {
assert(0);
}
- s1 = rel_insert(sql,
rel_basetable(sql, sub, sub->base.name), dup);
+ new_table = rel_basetable(sql,
sub, sub->base.name);
+
if(list_length(sub->members.set) == 0) //if this table has no partitions, set
it as used
+ new_table->p =
prop_create(sql->sa, PROP_USED, new_table->p);
+
+ s1 = rel_insert(sql, new_table,
dup);
if (just_one == 0) {
sel = rel_list(sql->sa,
sel, s1);
} else {
@@ -8249,6 +8257,12 @@ rel_merge_table_rewrite(int *changes, mv
anti_exp = accum;
} else if(isListPartitionTable(t)) {
anti_exp = exp_in(sql->sa,
anti_le, anti_exps, cmp_notin);
+ if(!found_nils) {
+ sql_exp *anti_nils =
rel_unop_(sql, anti_le, NULL, "isnull", card_value);
+ anti_nils =
exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_equal);
+ anti_exp =
exp_or(sql->sa, list_append(new_exp_list(sql->sa), anti_exp),
+
list_append(new_exp_list(sql->sa), anti_nils), 0);
+ }
} else {
assert(0);
}
@@ -8263,10 +8277,68 @@ rel_merge_table_rewrite(int *changes, mv
//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));
- exception = exp_exception(sql->sa, aggr,
-
"INSERT INTO: There are values in the insert not corresponding to any
partition");
+ snprintf(buf, BUFSIZ, "INSERT: the
insert violates the partition %s of values",
+
isRangePartitionTable(t) ? "range" : "list");
+ exception = exp_exception(sql->sa,
aggr, buf);
sel = rel_ddl_distribute(sql->sa, sel,
anti_dup, list_append(new_exp_list(sql->sa), exception));
}
+ } else if(t->p && (isRangePartitionTable(t->p) ||
isListPartitionTable(t->p))
+ && !find_prop(left->p, PROP_USED) &&
is_insert(rel->op)) {
+ //is part of a partition table and not been
used yet
+ sql_table *upper = t->p;
+ 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;
+ sql_exp *le = list_fetch(right->exps, colr),
*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);
+
+ 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));
+
+ if(isRangePartitionTable(upper)) {
+ sql_exp *e1 =
create_table_part_atom_exp(sql, pt->tpe, pt->part.range.minvalue),
+ *e2 =
create_table_part_atom_exp(sql, pt->tpe, pt->part.range.maxvalue);
+ anti_exp = exp_compare2(sql->sa,
anti_le, exp_copy(sql->sa, e1), exp_copy(sql->sa, e2), 3);
+ set_anti(anti_exp);
+ } else if(isListPartitionTable(upper)) {
+ for(node *n = pt->part.values->h ; n ;
n = n->next) {
+ sql_part_value *next =
(sql_part_value*) n->data;
+ sql_exp *e1 =
create_table_part_atom_exp(sql, next->tpe, next->value);
+ list_append(anti_exps,
exp_copy(sql->sa, e1));
+ }
+ anti_exp = exp_in(sql->sa, anti_le,
anti_exps, cmp_notin);
+ } else {
+ assert(0);
+ }
+ if(!pt->with_nills) { /* handle the nulls case
*/
+ sql_exp *anti_nils = rel_unop_(sql,
anti_le, NULL, "isnull", card_value);
+ anti_nils = exp_compare(sql->sa,
anti_nils, exp_atom_bool(sql->sa, 1), cmp_equal);
+ anti_exp = exp_or(sql->sa,
list_append(new_exp_list(sql->sa), anti_exp),
+
list_append(new_exp_list(sql->sa), anti_nils), 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);
+ 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: table %s.%s is
part of merge table %s.%s and the insert violates the "
+ "partition %s of
values", t->s->base.name, t->base.name, upper->s->base.name,
+ upper->base.name,
isRangePartitionTable(upper) ? "range" : "list");
+ exception = exp_exception(sql->sa, aggr, buf);
+ sel = rel_ddl_distribute(sql->sa, rel,
anti_dup, list_append(new_exp_list(sql->sa), exception));
+
+ left->p = prop_create(sql->sa, PROP_USED,
left->p);
+ (*changes)++;
}
}
} else {
diff --git a/sql/test/merge-partitions/Tests/mergepart06.sql
b/sql/test/merge-partitions/Tests/mergepart06.sql
--- a/sql/test/merge-partitions/Tests/mergepart06.sql
+++ b/sql/test/merge-partitions/Tests/mergepart06.sql
@@ -20,7 +20,7 @@ INSERT INTO testrangelimits VALUES (201,
INSERT INTO testrangelimits VALUES (444, 'another'), (305, 'error'), (4,
'happening'); --error
INSERT INTO sublimits1 VALUES (2, 'another');
-INSERT INTO sublimits2 VALUES (202, 'successful');
+INSERT INTO sublimits2 VALUES (102, 'successful');
INSERT INTO sublimits3 VALUES (NULL, 'attempt');
INSERT INTO sublimits3 VALUES (2, 'will'); --error
diff --git a/sql/test/merge-partitions/Tests/mergepart06.stable.err
b/sql/test/merge-partitions/Tests/mergepart06.stable.err
new file mode 100644
--- /dev/null
+++ b/sql/test/merge-partitions/Tests/mergepart06.stable.err
@@ -0,0 +1,61 @@
+stderr of test 'mergepart06` in directory 'sql/test/merge-partitions` itself:
+
+
+# 15:49:30 >
+# 15:49:30 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set"
"mapi_open=true" "--set" "mapi_port=35425" "--set"
"mapi_usock=/var/tmp/mtest-655/.s.monetdb.35425" "--set" "monet_prompt="
"--forcemito"
"--dbpath=/home/ferreira/repositories/MonetDB-merge-partitions/BUILD/var/MonetDB/mTests_sql_test_merge-partitions"
"--set" "embedded_r=yes" "--set" "embedded_py=true" "--set" "embedded_c=true"
+# 15:49:30 >
+
+# 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
+# builtin opt sql_optimizer = default_pipe
+# builtin opt sql_debug = 0
+# cmdline opt gdk_nr_threads = 0
+# cmdline opt mapi_open = true
+# cmdline opt mapi_port = 35425
+# cmdline opt mapi_usock = /var/tmp/mtest-655/.s.monetdb.35425
+# cmdline opt monet_prompt =
+# cmdline opt gdk_dbpath =
/home/ferreira/repositories/MonetDB-merge-partitions/BUILD/var/MonetDB/mTests_sql_test_merge-partitions
+# cmdline opt embedded_r = yes
+# cmdline opt embedded_py = true
+# cmdline opt embedded_c = true
+# cmdline opt gdk_debug = 553648138
+
+# 15:49:31 >
+# 15:49:31 > "mclient" "-lsql" "-ftest" "-tnone" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-655" "--port=35425"
+# 15:49:31 >
+
+MAPI = (monetdb) /var/tmp/mtest-655/.s.monetdb.35425
+QUERY = INSERT INTO testrangelimits VALUES (1000, 'ups'); --error
+ERROR = !INSERT: the insert violates the partition range of values
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-655/.s.monetdb.35425
+QUERY = INSERT INTO testrangelimits VALUES (201, 'oh no'); --error
+ERROR = !INSERT: the insert violates the partition range of values
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-655/.s.monetdb.35425
+QUERY = INSERT INTO testrangelimits VALUES (444, 'another'), (305, 'error'),
(4, 'happening'); --error
+ERROR = !INSERT: the insert violates the partition range of values
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-655/.s.monetdb.35425
+QUERY = INSERT INTO sublimits3 VALUES (2, 'will'); --error
+ERROR = !INSERT: table sys.sublimits3 is part of merge table
sys.testrangelimits and the insert violates the partition range of values
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-655/.s.monetdb.35425
+QUERY = INSERT INTO sublimits1 VALUES (202, 'fail'); --error
+ERROR = !INSERT: table sys.sublimits1 is part of merge table
sys.testrangelimits and the insert violates the partition range of values
+CODE = M0M29
+MAPI = (monetdb) /var/tmp/mtest-655/.s.monetdb.35425
+QUERY = INSERT INTO sublimits2 VALUES (NULL, 'again'); --error
+ERROR = !INSERT: table sys.sublimits2 is part of merge table
sys.testrangelimits and the insert violates the partition range of values
+CODE = M0M29
+
+# 15:49:31 >
+# 15:49:31 > "Done."
+# 15:49:31 >
+
diff --git a/sql/test/merge-partitions/Tests/mergepart06.stable.out
b/sql/test/merge-partitions/Tests/mergepart06.stable.out
new file mode 100644
--- /dev/null
+++ b/sql/test/merge-partitions/Tests/mergepart06.stable.out
@@ -0,0 +1,150 @@
+stdout of test 'mergepart06` in directory 'sql/test/merge-partitions` itself:
+
+
+# 15:49:30 >
+# 15:49:30 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set"
"mapi_open=true" "--set" "mapi_port=35425" "--set"
"mapi_usock=/var/tmp/mtest-655/.s.monetdb.35425" "--set" "monet_prompt="
"--forcemito"
"--dbpath=/home/ferreira/repositories/MonetDB-merge-partitions/BUILD/var/MonetDB/mTests_sql_test_merge-partitions"
"--set" "embedded_r=yes" "--set" "embedded_py=true" "--set" "embedded_c=true"
+# 15:49:30 >
+
+# MonetDB 5 server v11.30.0
+# This is an unreleased version
+# Serving database 'mTests_sql_test_merge-partitions', using 8 threads
+# Compiled for x86_64-pc-linux-gnu/64bit with 128bit integers
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list