Changeset: d80919e1bc62 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d80919e1bc62 Modified Files: sql/server/rel_propagate.c sql/storage/sql_catalog.c sql/test/merge-partitions/Tests/All sql/test/merge-partitions/Tests/mergepart01.stable.err sql/test/merge-partitions/Tests/mergepart30.sql sql/test/merge-partitions/Tests/mergepart30.stable.err Branch: Oct2020 Log Message:
Merged with Jun2020 diffs (truncated from 488 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 @@ -160,7 +160,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; @@ -184,14 +184,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); @@ -277,17 +281,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 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &spt->tpe, spt->part.range.minvalue)); - e2 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &spt->tpe, spt->part.range.maxvalue)); + if (!max_equal_min) + e2 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &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) { @@ -357,7 +363,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; @@ -710,9 +721,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 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &pt->tpe, pt->part.range.minvalue)); - e2 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &pt->tpe, pt->part.range.maxvalue)); - range = exp_compare2(sql->sa, le, e1, e2, cmp_gte|CMP_BETWEEN); + if (!max_equal_min) { + e2 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &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); @@ -954,12 +971,19 @@ rel_subtable_insert(sql_query *query, sq sql_exp *e1 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &pt->tpe, pt->part.range.minvalue)); anti_exp = exp_compare(sql->sa, exp_copy(sql, anti_le), e1, cmp_lt); } else { - sql_exp *e1 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &pt->tpe, pt->part.range.minvalue)), - *e2 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &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 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &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 = exp_atom(sql->sa, atom_general_ptr(sql->sa, &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 @@ -453,7 +453,7 @@ 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, newp_down_all = false, newp_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; @@ -476,31 +476,39 @@ sql_range_part_validate_and_insert(void 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 */ - if (newp_down_all || ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue) > 0) + 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 */ - if (newp_upper_all || ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue) > 0) + 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 */ - if (pt_down_all || ATOMcmp(tpe, newp->part.range.maxvalue, pt->part.range.minvalue) > 0) + 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 */ - if (pt_upper_all || ATOMcmp(tpe, pt->part.range.maxvalue, newp->part.range.minvalue) > 0) + 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 @@ -30,3 +30,4 @@ HAVE_DATA_PATH&HAVE_LIBPY3?mergepart28 HAVE_PYMONETDB?mergepart29 mergepart30 mergepart31 +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); @@ -97,6 +100,27 @@ ALTER TABLE table1 ADD TABLE another2 AS 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 0; +ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 10 TO RANGE MAXVALUE; +ALTER TABLE table1 ADD TABLE another3 AS PARTITION FROM 0 TO 10; +ALTER TABLE table1 ADD TABLE another4 AS PARTITION FOR NULL VALUES; + +ALTER TABLE table1 ADD TABLE another5 AS PARTITION FROM -100 TO -1; --error, conflicts with another1 +ALTER TABLE table1 ADD TABLE another5 AS PARTITION FROM 0 TO 0; --error, conflicts with another1 +ALTER TABLE table1 ADD TABLE another5 AS PARTITION FROM 10 TO 10; --error, conflicts with another2 +ALTER TABLE table1 ADD TABLE another5 AS PARTITION FROM 10 TO 11; --error, conflicts with another2 +ALTER TABLE table1 ADD TABLE another5 AS PARTITION FROM 9 TO 10; --error, conflicts with another3 +ALTER TABLE table1 ADD TABLE another5 AS PARTITION FOR NULL VALUES; --error, conflicts with another4 + +ALTER TABLE table1 DROP TABLE another1; +ALTER TABLE table1 DROP TABLE another2; +ALTER TABLE table1 DROP TABLE another3; +ALTER TABLE table1 DROP TABLE another4; +ALTER TABLE table1 DROP TABLE another5; --error, not there + DROP TABLE another1; DROP TABLE another2; +DROP TABLE another3; +DROP TABLE another4; +DROP TABLE another5; DROP TABLE table1; diff --git a/sql/test/merge-partitions/Tests/mergepart30.stable.err b/sql/test/merge-partitions/Tests/mergepart30.stable.err --- a/sql/test/merge-partitions/Tests/mergepart30.stable.err +++ b/sql/test/merge-partitions/Tests/mergepart30.stable.err @@ -69,15 +69,15 @@ MAPI = (monetdb) /var/tmp/mtest-84239/. QUERY = ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 0 to 5; --error, conflicts with another1 ERROR = !ALTER TABLE: conflicting partitions: 0 to 5 and absolute min value to absolute max value from table sys.another1 CODE = 42000 -MAPI = (monetdb) /var/tmp/mtest-89788/.s.monetdb.36023 +MAPI = (monetdb) /var/tmp/mtest-99796/.s.monetdb.30680 QUERY = ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM RANGE MINVALUE to 2; --error, conflicts with another1 ERROR = !ALTER TABLE: conflicting partitions: absolute min value to 2 and absolute min value to absolute max value from table sys.another1 CODE = 42000 -MAPI = (monetdb) /var/tmp/mtest-89788/.s.monetdb.36023 +MAPI = (monetdb) /var/tmp/mtest-99796/.s.monetdb.30680 QUERY = ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 2 to RANGE MAXVALUE; --error, conflicts with another1 ERROR = !ALTER TABLE: conflicting partitions: 2 to absolute max value and absolute min value to absolute max value from table sys.another1 CODE = 42000 -MAPI = (monetdb) /var/tmp/mtest-89788/.s.monetdb.36023 +MAPI = (monetdb) /var/tmp/mtest-99796/.s.monetdb.30680 QUERY = ALTER TABLE table1 DROP TABLE another2; --error, not there ERROR = !ALTER TABLE: table 'sys.another2' isn't part of RANGE PARTITION TABLE 'sys.table1' CODE = 42S02 @@ -85,11 +85,11 @@ MAPI = (monetdb) /var/tmp/mtest-86521/. QUERY = ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM RANGE MINVALUE TO 1; --error, conflicts with another1 ERROR = !ALTER TABLE: conflicting partitions: absolute min value to 1 and absolute min value to 2 from table sys.another1 CODE = 42000 -MAPI = (monetdb) /var/tmp/mtest-89557/.s.monetdb.34879 +MAPI = (monetdb) /var/tmp/mtest-99796/.s.monetdb.30680 QUERY = ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 0 TO 1; --error, conflicts with another1 ERROR = !ALTER TABLE: conflicting partitions: 0 to 1 and absolute min value to 2 from table sys.another1 CODE = 42000 -MAPI = (monetdb) /var/tmp/mtest-89557/.s.monetdb.34879 +MAPI = (monetdb) /var/tmp/mtest-99796/.s.monetdb.30680 QUERY = ALTER TABLE table1 DROP TABLE another2; --error, not there ERROR = !ALTER TABLE: table 'sys.another2' isn't part of RANGE PARTITION TABLE 'sys.table1' CODE = 42S02 @@ -97,14 +97,42 @@ MAPI = (monetdb) /var/tmp/mtest-86671/. QUERY = ALTER TABLE table1 ADD TABLE another2 AS PARTITION FROM 10 TO RANGE MAXVALUE; --error, conflicts with another1 ERROR = !ALTER TABLE: conflicting partitions: 10 to absolute max value and 2 to absolute max value from table sys.another1 _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list