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

Reply via email to