Changeset: 49e9171c9d5d for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=49e9171c9d5d Modified Files: sql/server/rel_optimizer.c Branch: default Log Message:
Merged with Oct2020 diffs (truncated from 703 to 300 lines): 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 @@ -9062,19 +9062,26 @@ rel_merge_table_rewrite(visitor *v, sql_ skip |= nskip; } } else { /* limit1 to limit2 (general case), limit2 is exclusive */ + bool max_differ_min = ATOMcmp(col->type.type->localtype, &rmin->data.val, &rmax->data.val) != 0; + if (lval) { if (next->flag == cmp_equal) { - skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, false, true) != 0 : - exp_range_overlap(rmin, rmax, lval, hval, false, true) == 0; + skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, false, max_differ_min) != 0 : + exp_range_overlap(rmin, rmax, lval, hval, false, max_differ_min) == 0; } else if (hval != lval) { /* For the between case */ comp_type higher = range2rcompare(next->flag); - skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, true) != 0 : - exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, true) == 0; + skip |= next->anti ? exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, max_differ_min) != 0 : + exp_range_overlap(rmin, rmax, lval, hval, higher == cmp_lt, max_differ_min) == 0; } else { switch (next->flag) { case cmp_gt: + skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) < 0 : VALcmp(&(lval->data), &(rmax->data)) >= 0; + break; case cmp_gte: - skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) < 0 : VALcmp(&(lval->data), &(rmax->data)) >= 0; + if (max_differ_min) + skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) < 0 : VALcmp(&(lval->data), &(rmax->data)) >= 0; + else + skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) <= 0 : VALcmp(&(lval->data), &(rmax->data)) > 0; break; case cmp_lt: skip |= next->anti ? VALcmp(&(rmin->data), &(lval->data)) < 0 : VALcmp(&(rmin->data), &(lval->data)) >= 0; @@ -9093,7 +9100,7 @@ rel_merge_table_rewrite(visitor *v, sql_ if (a->isnull) continue; - nskip &= exp_range_overlap(rmin, rmax, a, a, false, true) == 0; + nskip &= exp_range_overlap(rmin, rmax, a, a, false, max_differ_min) == 0; } skip |= nskip; } 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; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list