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
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list