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

Reply via email to