Changeset: 3165455501ef for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3165455501ef Branch: Jun2020 Log Message:
merged diffs (truncated from 666 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 @@ -166,7 +166,7 @@ generate_partition_limits(sql_query *que } static sql_rel* -create_range_partition_anti_rel(sql_query* query, sql_table *mt, sql_table *pt, bit with_nills, sql_exp *pmin, sql_exp *pmax, bool all_ranges) +create_range_partition_anti_rel(sql_query* query, sql_table *mt, sql_table *pt, bit with_nills, sql_exp *pmin, sql_exp *pmax, bool all_ranges, bool max_equal_min) { mvc *sql = query->sql; sql_rel *anti_rel; @@ -190,14 +190,18 @@ create_range_partition_anti_rel(sql_quer if (!(e1 = exp_check_type(sql, &tpe, NULL, e1, type_equal))) return NULL; - e2 = exp_copy(sql, pmax); - if (!(e2 = exp_check_type(sql, &tpe, NULL, e2, type_equal))) - return NULL; + if (max_equal_min) { + anti_exp = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, cmp_notequal); + } else { + e2 = exp_copy(sql, pmax); + if (!(e2 = exp_check_type(sql, &tpe, NULL, e2, type_equal))) + return NULL; - range1 = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, 3); - range2 = exp_compare(sql->sa, exp_copy(sql, anti_le), e2, 1); - anti_exp = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range1), - list_append(new_exp_list(sql->sa), range2), 0); + range1 = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, cmp_lt); + range2 = exp_compare(sql->sa, exp_copy(sql, anti_le), e2, cmp_gte); + anti_exp = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range1), + list_append(new_exp_list(sql->sa), range2), 0); + } } if (!with_nills) { anti_nils = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_equal); @@ -284,17 +288,19 @@ propagate_validation_to_upper_tables(sql int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe); const void *nil = ATOMnilptr(tpe); sql_exp *e1 = NULL, *e2 = NULL; - bool found_all = false; + bool found_all = false, max_equal_min = false; if (atomcmp(spt->part.range.minvalue, nil) != 0 && atomcmp(spt->part.range.maxvalue, nil) != 0) { + max_equal_min = ATOMcmp(spt->tpe.type->localtype, spt->part.range.maxvalue, spt->part.range.minvalue) == 0; e1 = create_table_part_atom_exp(sql, spt->tpe, spt->part.range.minvalue); - e2 = create_table_part_atom_exp(sql, spt->tpe, spt->part.range.maxvalue); + if (!max_equal_min) + e2 = create_table_part_atom_exp(sql, spt->tpe, spt->part.range.maxvalue); } else { assert(spt->with_nills); found_all = is_bit_nil(spt->with_nills); } if (!found_all || !spt->with_nills) - rel = rel_list(sql->sa, rel, create_range_partition_anti_rel(query, it->t, pt, spt->with_nills, e1, e2, false)); + rel = rel_list(sql->sa, rel, create_range_partition_anti_rel(query, it->t, pt, spt->with_nills, e1, e2, false, max_equal_min)); } else if (isListPartitionTable(it->t)) { list *exps = new_exp_list(sql->sa); for (node *n = spt->part.values->h ; n ; n = n->next) { @@ -364,7 +370,12 @@ rel_alter_table_add_partition_range(sql_ rel_psm->nrcols = 0; if (!is_bit_nil(with_nills)) { - res = create_range_partition_anti_rel(query, mt, pt, with_nills, (min && max) ? pmin : NULL, (min && max) ? pmax : NULL, all_ranges); + bool min_max_equal = false; + if (pmin && pmax && pmin->type == e_atom && pmax->type == e_atom && pmin->l && pmax->l) { + atom *e1 = pmin->l, *e2 = pmax->l; + min_max_equal = ATOMcmp(tpe.type->localtype, &e1->data.val, &e2->data.val) == 0; + } + res = create_range_partition_anti_rel(query, mt, pt, with_nills, (min && max) ? pmin : NULL, (min && max) ? pmax : NULL, all_ranges, min_max_equal); res->l = rel_psm; } else { res = rel_psm; @@ -720,9 +731,15 @@ rel_generate_subinserts(sql_query *query if (atomcmp(pt->part.range.minvalue, nil) != 0 || atomcmp(pt->part.range.maxvalue, nil) != 0) { sql_exp *e1, *e2; + bool max_equal_min = ATOMcmp(pt->tpe.type->localtype, pt->part.range.maxvalue, pt->part.range.minvalue) == 0; + 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); - range = exp_compare2(sql->sa, le, e1, e2, cmp_gte|CMP_BETWEEN); + if (!max_equal_min) { + e2 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.maxvalue); + range = exp_compare2(sql->sa, le, e1, e2, cmp_gte|CMP_BETWEEN); + } else { + range = exp_compare(sql->sa, le, e1, cmp_equal); + } full_range = range; } else { found_all_range_values |= (pt->with_nills != 1); @@ -964,12 +981,19 @@ rel_subtable_insert(sql_query *query, sq sql_exp *e1 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.minvalue); anti_exp = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, cmp_lt); } else { - 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), - *range1 = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, cmp_lt), - *range2 = exp_compare(sql->sa, exp_copy(sql, anti_le), e2, cmp_gte); - anti_exp = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range1), - list_append(new_exp_list(sql->sa), range2), 0); + sql_exp *e1 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.minvalue); + bool max_equal_min = ATOMcmp(pt->tpe.type->localtype, pt->part.range.maxvalue, pt->part.range.minvalue) == 0; + + if (max_equal_min) { + anti_exp = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, cmp_notequal); + } else { + sql_exp *e2 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.maxvalue), + *range1 = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, cmp_lt), + *range2 = exp_compare(sql->sa, exp_copy(sql, anti_le), e2, cmp_gte); + + anti_exp = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range1), + list_append(new_exp_list(sql->sa), range2), 0); + } } } if (!pt->with_nills) { /* handle the nulls case */ diff --git a/sql/storage/sql_catalog.c b/sql/storage/sql_catalog.c --- a/sql/storage/sql_catalog.c +++ b/sql/storage/sql_catalog.c @@ -464,44 +464,62 @@ sql_range_part_validate_and_insert(void sql_part* pt = (sql_part*) v1, *newp = (sql_part*) v2; int res1, res2, tpe = pt->tpe.type->localtype; const void *nil = ATOMnilptr(tpe); - bool pt_down_all = false, pt_upper_all = false; + bool pt_down_all = false, pt_upper_all = false, newp_down_all = false, newp_upper_all = false, pt_min_max_same = false, newp_min_max_same = false; if (pt == newp) /* same pointer, skip (used in updates) */ return NULL; assert(tpe == newp->tpe.type->localtype); - if (is_bit_nil(pt->with_nills)) //if one partition holds all including nills, then conflicts + if (is_bit_nil(pt->with_nills) || is_bit_nil(newp->with_nills)) /* if one partition holds all including nills, then conflicts */ return pt; - if (newp->with_nills && pt->with_nills) //only one partition at most has null values + if (newp->with_nills && pt->with_nills) /* only one partition at most has null values */ return pt; pt_down_all = !ATOMcmp(tpe, nil, pt->part.range.minvalue); pt_upper_all = !ATOMcmp(tpe, nil, pt->part.range.maxvalue); + newp_down_all = !ATOMcmp(tpe, nil, newp->part.range.minvalue); + newp_upper_all = !ATOMcmp(tpe, nil, newp->part.range.maxvalue); - if (pt_down_all || pt_upper_all) { - if (pt_down_all) { - if (pt->with_nills == true) /* only holds nils, allowed */ - return NULL; - if (pt_upper_all) /* holds all range, conflicts if newp holds more than nills */ - return newp->with_nills ? NULL : pt; - if (!ATOMcmp(tpe, nil, newp->part.range.minvalue) || ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue) > 0) - return pt; - } - if (pt_upper_all) { - if (pt->with_nills == true) /* only holds nils, allowed */ - return NULL; - if (pt_down_all) /* holds all range, conflicts if newp holds more than nills */ - return newp->with_nills ? NULL : pt; - if (!ATOMcmp(tpe, nil, newp->part.range.maxvalue) || ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue) > 0) - return pt; - } + /* if one partition just holds NULL values, then there's no conflict */ + if ((newp_down_all && newp_upper_all && newp->with_nills) || (pt_down_all && pt_upper_all && pt->with_nills)) + return NULL; + /* holds all range, will always conflict */ + if ((pt_down_all && pt_upper_all && !pt->with_nills) || (newp_down_all && newp_upper_all && !newp->with_nills)) + return pt; + + pt_min_max_same = !ATOMcmp(tpe, pt->part.range.maxvalue, pt->part.range.minvalue); + newp_min_max_same = !ATOMcmp(tpe, newp->part.range.maxvalue, newp->part.range.minvalue); + + if (pt_down_all) { /* from range min value until a value */ + res1 = ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue); + if (newp_down_all || (!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0)) + return pt; + return NULL; + } + if (pt_upper_all) { /* from value until range max value */ + res1 = ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue); + if (newp_upper_all || (!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0)) + return pt; + return NULL; + } + if (newp_down_all) { /* from range min value until a value */ + res1 = ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue); + if (pt_down_all || (!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0)) + return pt; + return NULL; + } + if (newp_upper_all) { /* from value until range max value */ + res1 = ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue); + if (pt_upper_all || (!pt_min_max_same && res1 > 0) || (pt_min_max_same && res1 >= 0)) + return pt; return NULL; } /* Fallback into normal cases */ - res1 = ATOMcmp(tpe, pt->part.range.minvalue, newp->part.range.maxvalue); - res2 = ATOMcmp(tpe, newp->part.range.minvalue, pt->part.range.maxvalue); - if (res1 < 0 && res2 < 0) //overlap: x1 < y2 && y1 < x2 + res1 = ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue); + res2 = ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue); + /* overlap: y2 > x1 && x2 > y1 */ + if (((!newp_min_max_same && res1 > 0) || (newp_min_max_same && res1 >= 0)) && ((!pt_min_max_same && res2 > 0) || (pt_min_max_same && res2 >= 0))) return pt; return NULL; } diff --git a/sql/test/merge-partitions/Tests/All b/sql/test/merge-partitions/Tests/All --- a/sql/test/merge-partitions/Tests/All +++ b/sql/test/merge-partitions/Tests/All @@ -29,3 +29,5 @@ mergepart27 HAVE_DATA_PATH&HAVE_LIBPY3?mergepart28 HAVE_PYMONETDB?mergepart29 mergepart30 + +mergepart32 diff --git a/sql/test/merge-partitions/Tests/mergepart01.sql b/sql/test/merge-partitions/Tests/mergepart01.sql --- a/sql/test/merge-partitions/Tests/mergepart01.sql +++ b/sql/test/merge-partitions/Tests/mergepart01.sql @@ -20,8 +20,8 @@ ALTER TABLE testme ADD TABLE wrongtable CREATE TABLE subtable2 (a int, b varchar(32)); ALTER TABLE testme ADD TABLE subtable2 AS PARTITION IN ('0', '1', '2'); --error ALTER TABLE testme ADD TABLE subtable2 AS PARTITION FROM 7 TO 9; --error -ALTER TABLE testme ADD TABLE subtable2 AS PARTITION FROM 5 TO 5; -ALTER TABLE testme DROP TABLE subtable2; +ALTER TABLE testme ADD TABLE subtable2 AS PARTITION FROM 5 TO 5; --error +ALTER TABLE testme DROP TABLE subtable2; --error DROP TABLE subtable1; --error ALTER TABLE testme SET SCHEMA other_schema; --error, changing schema not allowed while with child tables diff --git a/sql/test/merge-partitions/Tests/mergepart01.stable.err b/sql/test/merge-partitions/Tests/mergepart01.stable.err --- a/sql/test/merge-partitions/Tests/mergepart01.stable.err +++ b/sql/test/merge-partitions/Tests/mergepart01.stable.err @@ -45,7 +45,15 @@ MAPI = (monetdb) /var/tmp/mtest-13251/. QUERY = ALTER TABLE testme ADD TABLE subtable2 AS PARTITION FROM 7 TO 9; --error ERROR = !ALTER TABLE: conflicting partitions: 7 to 9 and 5 to 10 from table sys.subtable1 CODE = 42000 -MAPI = (monetdb) /var/tmp/mtest-28117/.s.monetdb.35132 +MAPI = (monetdb) /var/tmp/mtest-131881/.s.monetdb.39742 +QUERY = ALTER TABLE testme ADD TABLE subtable2 AS PARTITION FROM 5 TO 5; --error +ERROR = !ALTER TABLE: conflicting partitions: 5 to 5 and 5 to 10 from table sys.subtable1 +CODE = 42000 +MAPI = (monetdb) /var/tmp/mtest-131881/.s.monetdb.39742 +QUERY = ALTER TABLE testme DROP TABLE subtable2; --error +ERROR = !ALTER TABLE: table 'sys.subtable2' isn't part of RANGE PARTITION TABLE 'sys.testme' +CODE = 42S02 +MAPI = (monetdb) /var/tmp/mtest-128084/.s.monetdb.39134 QUERY = DROP TABLE subtable1; --error ERROR = !DROP TABLE: unable to drop table subtable1 (there are database objects which depend on it) CODE = 42000 diff --git a/sql/test/merge-partitions/Tests/mergepart30.sql b/sql/test/merge-partitions/Tests/mergepart30.sql --- a/sql/test/merge-partitions/Tests/mergepart30.sql +++ b/sql/test/merge-partitions/Tests/mergepart30.sql @@ -12,6 +12,9 @@ DROP TABLE table2; CREATE MERGE TABLE table1 (a int) PARTITION BY RANGE ON (a); CREATE TABLE another1 (a int); CREATE TABLE another2 (a int); +CREATE TABLE another3 (a int); +CREATE TABLE another4 (a int); +CREATE TABLE another5 (a int); ALTER TABLE table1 ADD TABLE another1 AS PARTITION FROM RANGE MINVALUE TO RANGE MAXVALUE WITH NULL VALUES; --holds all INSERT INTO table1 VALUES (1), (NULL); @@ -42,7 +45,7 @@ ALTER TABLE table1 ADD TABLE another2 AS ALTER TABLE table1 ADD TABLE another2 AS PARTITION FOR NULL VALUES; TRUNCATE table1; -INSERT INTO table1 VALUES (2), (NULL); +INSERT INTO table1 VALUES (2), (NULL); INSERT INTO another1 VALUES (3); INSERT INTO another1 VALUES (NULL); --error @@ -55,6 +58,69 @@ SELECT a FROM another2; ALTER TABLE table1 DROP TABLE another1; ALTER TABLE table1 DROP TABLE another2; + +ALTER TABLE table1 ADD TABLE another1 AS PARTITION FROM RANGE MINVALUE TO 10; +ALTER TABLE table1 ADD TABLE another2 AS PARTITION FOR NULL VALUES; +SELECT a FROM table1; +SELECT a FROM another1; +SELECT a FROM another2; +ALTER TABLE table1 DROP TABLE another1; +ALTER TABLE table1 DROP TABLE another2; + +ALTER TABLE table1 ADD TABLE another1 AS PARTITION FROM RANGE MINVALUE TO 10 WITH NULL VALUES; +ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 0 to 5; --error, conflicts with another1 +SELECT a FROM table1; +SELECT a FROM another1; +SELECT a FROM another2; +ALTER TABLE table1 DROP TABLE another1; +ALTER TABLE table1 DROP TABLE another2; --error, not there + +ALTER TABLE table1 ADD TABLE another1 AS PARTITION FROM RANGE MINVALUE TO RANGE MAXVALUE; +ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 0 to 5; --error, conflicts with another1 +ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM RANGE MINVALUE to 2; --error, conflicts with another1 +ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 2 to RANGE MAXVALUE; --error, conflicts with another1 +SELECT a FROM table1; +SELECT a FROM another1; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list