Changeset: 85f70509ee6b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=85f70509ee6b
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/server/rel_optimizer.c
        sql/server/rel_select.c
        sql/server/rel_select.h
        sql/server/rel_updates.c
        sql/test/merge-partitions/Tests/mergepart06.sql
Branch: merge-partitions
Log Message:

Propagate inserts in range partitioned tables.

The next step is to handle value partitioned tables and inserts with no 
partition to go into (error case).


diffs (truncated from 331 to 300 lines):

diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -3326,7 +3326,7 @@ rel2bin_insert(backend *be, sql_rel *rel
 {
        mvc *sql = be->mvc;
        list *l;
-       stmt *inserts = NULL, *insert = NULL, *s, *ddl = NULL, *pin = NULL, 
**updates;
+       stmt *inserts = NULL, *insert = NULL, *s, *ddl = NULL, *pin = NULL, 
**updates, *ret = NULL;
        int idx_ins = 0, constraint = 1, len = 0;
        node *n, *m;
        sql_rel *tr = rel->l, *prel = rel->r;
@@ -3340,6 +3340,10 @@ rel2bin_insert(backend *be, sql_rel *rel
                rel = rel->r;
                tr = rel->l;
        }
+
+       if(find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0) /* create 
BAT to hold the sum of affected rows */
+               create_append_bat(be, TYPE_lng);
+
        if (tr->op == op_basetable) {
                t = tr->l;
        } else {
@@ -3408,6 +3412,7 @@ rel2bin_insert(backend *be, sql_rel *rel
        if (!sql_insert_triggers(be, t, updates, 1)) 
                return sql_error(sql, 02, SQLSTATE(42000) "INSERT INTO: 
triggers failed for table '%s'", t->base.name);
        if (ddl) {
+               ret = ddl;
                list_prepend(l, ddl);
        } else {
                if (insert->op1->nrcols == 0) {
@@ -3415,9 +3420,16 @@ rel2bin_insert(backend *be, sql_rel *rel
                } else {
                        s = stmt_aggr(be, insert->op1, NULL, NULL, 
sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL), 1, 0, 1);
                }
-               return s;
+               ret = s;
        }
-       return stmt_list(be, l);
+
+       if(be->cur_append) //building the total number of rows affected across 
all tables
+               ret->nr = append_bat_value(be, TYPE_lng, ret->nr);
+
+       if (ddl)
+               return stmt_list(be, l);
+       else
+               return ret;
 }
 
 static int
@@ -4586,7 +4598,7 @@ rel2bin_delete(backend *be, sql_rel *rel
        else
                assert(0/*ddl statement*/);
 
-       if(find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0)
+       if(find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0) /* create 
BAT to hold the sum of affected rows */
                create_append_bat(be, TYPE_lng);
 
        if (rel->r) { /* first construct the deletes relation */
@@ -4784,7 +4796,7 @@ rel2bin_truncate(backend *be, sql_rel *r
        else
                assert(0/*ddl statement*/);
 
-       if(find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0)
+       if(find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0) /* create 
BAT to hold the sum of affected rows */
                create_append_bat(be, TYPE_lng);
 
        n = rel->exps->h;
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
@@ -15,6 +15,7 @@
 #include "rel_prop.h"
 #include "rel_dump.h"
 #include "rel_planner.h"
+#include "rel_select.h"
 #include "rel_updates.h"
 #include "sql_mvc.h"
 #ifdef HAVE_HGE
@@ -8147,41 +8148,134 @@ rel_truncate_duplicate(sql_allocator *sa
        return r;
 }
 
+static sql_exp *
+create_table_part_atom_exp(mvc *sql, sht tpe, ptr value)
+{
+       switch (tpe) {
+               case TYPE_bit: {
+                       bit bval = *((bit*) value);
+                       return exp_atom_bool(sql->sa, bval ? 1 : 0);
+               }
+               case TYPE_bte: {
+                       bte bbval = *((bte *) value);
+                       return exp_atom_bte(sql->sa, bbval);
+               }
+               case TYPE_sht: {
+                       sht sval = *((sht*) value);
+                       return exp_atom_sht(sql->sa, sval);
+               }
+               case TYPE_int: {
+                       int ival = *((int*) value);
+                       return exp_atom_int(sql->sa, ival);
+               }
+               case TYPE_lng: {
+                       lng lval = *((lng*) value);
+                       return exp_atom_lng(sql->sa, lval);
+               }
+               case TYPE_flt: {
+                       flt fval = *((flt*) value);
+                       return exp_atom_flt(sql->sa, fval);
+               }
+               case TYPE_dbl: {
+                       dbl dval = *((dbl*) value);
+                       return exp_atom_dbl(sql->sa, dval);
+               }
+               case TYPE_str:
+                       return exp_atom_clob(sql->sa, sa_strdup(sql->sa, 
value));
+#ifdef HAVE_HGE
+               case TYPE_hge: {
+                       hge hval = *((hge*) value);
+                       return exp_atom_hge(sql->sa, hval);
+               }
+#endif
+               default:
+                       assert(0);
+       }
+}
+
 /* rewrite merge tables into union of base tables and call optimizer again */
 static sql_rel *
 rel_merge_table_rewrite(int *changes, mvc *sql, sql_rel *rel)
 {
        sql_rel *sel = NULL;
 
-       if(is_delete(rel->op) || is_truncate(rel->op)) {
+       if(is_delete(rel->op) || is_truncate(rel->op) || is_insert(rel->op)) {
                sql_rel *left = rel->l;
-               sql_table *t = left->l;
-
-               if(isRangePartitionTable(t) || isListPartitionTable(t)) {  
//propagate deletions to the partitions
-                       int just_one = 1;
-
-                       for (node *n = t->members.set->h; n; n = n->next) {
-                               sql_part *pt = (sql_part *) n->data;
-                               sql_table *sub = find_sql_table(t->s, 
pt->base.name);
-                               sql_rel *s1, *dup = NULL;
-
-                               if(rel->r) {
-                                       dup = rel_copy(sql->sa, rel->r);
-                                       dup = rel_change_base_table(dup, t, 
sub);
+               if(left->op == op_basetable) {
+                       sql_table *t = left->l;
+
+                       if(isRangePartitionTable(t) || isListPartitionTable(t)) 
{
+                               int just_one = 1;
+
+                               if(is_delete(rel->op) || is_truncate(rel->op)) 
{  //propagate deletions to the partitions
+                                       for (node *n = t->members.set->h; n; n 
= n->next) {
+                                               sql_part *pt = (sql_part *) 
n->data;
+                                               sql_table *sub = 
find_sql_table(t->s, pt->base.name);
+                                               sql_rel *s1, *dup = NULL;
+
+                                               if(rel->r) {
+                                                       dup = rel_copy(sql->sa, 
rel->r);
+                                                       dup = 
rel_change_base_table(dup, t, sub);
+                                               }
+                                               if(is_delete(rel->op))
+                                                       s1 = 
rel_delete(sql->sa, rel_basetable(sql, sub, sub->base.name), dup);
+                                               else
+                                                       s1 = 
rel_truncate_duplicate(sql->sa, rel_basetable(sql, sub, sub->base.name), rel);
+                                               s1->p = prop_create(sql->sa, 
PROP_DISTRIBUTE, s1->p);
+                                               if (just_one == 0) {
+                                                       sel = 
rel_setop(sql->sa, sel, s1, op_union);
+                                                       sel->p = 
prop_create(sql->sa, PROP_DISTRIBUTE, sel->p);
+                                               } else {
+                                                       sel = s1;
+                                                       just_one = 0;
+                                               }
+                                               (*changes)++;
+                                       }
+                               } else { //on inserts create a selection for 
each partition
+                                       int colr = t->pcol->colnr;
+
+                                       for (node *n = t->members.set->h; n; n 
= n->next) {
+                                               sql_part *pt = (sql_part *) 
n->data;
+                                               sql_table *sub = 
find_sql_table(t->s, pt->base.name);
+                                               sql_rel *s1, *dup = 
rel_dup(rel->r);
+                                               sql_exp *le = 
list_fetch(dup->exps, colr);
+                                               le = exp_column(sql->sa, 
exp_relname(le), exp_name(le), exp_subtype(le), le->card, has_nil(le), 
is_intern(le));
+
+                                               if(isRangePartitionTable(t)) {
+                                                       sql_exp *e1, *e2;
+
+                                                       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);
+                                                       dup = 
rel_compare_exp_(sql, dup, le, e1, e2, 3, 0);
+
+                                                       
if(pt->part.range.with_nills) { /* handle the nulls case */
+                                                               sql_rel* extra;
+                                                               sql_exp *nils = 
rel_unop_(sql, le, NULL, "isnull", card_value);
+                                                               nils = 
exp_compare(sql->sa, nils, exp_atom_bool(sql->sa, 1), cmp_equal);
+
+                                                               extra = 
rel_select(sql->sa, rel->r, nils);
+                                                               dup = 
rel_or(sql, NULL, dup, extra, NULL, NULL, NULL);
+                                                       }
+                                               } else 
if(isListPartitionTable(t)) {
+                                                       list *exps = 
new_exp_list(sql->sa); /* TODO the list should come from the partition itself */
+                                                       sql_exp *ein = 
exp_in(sql->sa, le, exps, cmp_in);
+                                                       dup = 
rel_select(sql->sa, dup, ein);
+                                               } else {
+                                                       assert(0);
+                                               }
+
+                                               s1 = rel_insert(sql, 
rel_basetable(sql, sub, sub->base.name), dup);
+                                               s1->p = prop_create(sql->sa, 
PROP_DISTRIBUTE, s1->p);
+                                               if (just_one == 0) {
+                                                       sel = 
rel_setop(sql->sa, sel, s1, op_union);
+                                                       sel->p = 
prop_create(sql->sa, PROP_DISTRIBUTE, sel->p);
+                                               } else {
+                                                       sel = s1;
+                                                       just_one = 0;
+                                               }
+                                               (*changes)++;
+                                       }
                                }
-                               if(is_delete(rel->op))
-                                       s1 = rel_delete(sql->sa, 
rel_basetable(sql, sub, sub->base.name), dup);
-                               else
-                                       s1 = rel_truncate_duplicate(sql->sa, 
rel_basetable(sql, sub, sub->base.name), rel);
-                               s1->p = prop_create(sql->sa, PROP_DISTRIBUTE, 
s1->p);
-                               if (just_one == 0) {
-                                       sel = rel_setop(sql->sa, sel, s1, 
op_union);
-                                       sel->p = prop_create(sql->sa, 
PROP_DISTRIBUTE, sel->p);
-                               } else {
-                                       sel = s1;
-                                       just_one = 0;
-                               }
-                               (*changes)++;
                        }
                }
        } else {
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -1645,7 +1645,7 @@ exp_is_subquery( mvc *sql, sql_exp *e)
        return 0;
 }
 
-static sql_rel *
+sql_rel *
 rel_compare_exp_(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp 
*rs2, int type, int anti )
 {
        sql_exp *L = ls, *R = rs, *e = NULL;
diff --git a/sql/server/rel_select.h b/sql/server/rel_select.h
--- a/sql/server/rel_select.h
+++ b/sql/server/rel_select.h
@@ -12,6 +12,7 @@
 #include "rel_semantic.h"
 #include "sql_semantic.h"
 
+extern sql_rel *rel_compare_exp_(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp 
*rs, sql_exp *rs2, int type, int anti);
 extern sql_rel *rel_selects(mvc *sql, symbol *sym);
 extern sql_rel *schema_selects(mvc *sql, sql_schema *s, symbol *sym);
 extern sql_rel * rel_subquery(mvc *sql, sql_rel *rel, symbol *sq, exp_kind ek, 
int apply);
diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c
--- a/sql/server/rel_updates.c
+++ b/sql/server/rel_updates.c
@@ -395,7 +395,7 @@ insert_allowed(mvc *sql, sql_table *t, c
                return sql_error(sql, 02, SQLSTATE(42S02) "%s: no such table 
'%s'", op, tname);
        } else if (isView(t)) {
                return sql_error(sql, 02, SQLSTATE(42000) "%s: cannot %s view 
'%s'", op, opname, tname);
-       } else if (isMergeTable(t)) {
+       } else if (isNonPartitionedTable(t)) {
                return sql_error(sql, 02, SQLSTATE(42000) "%s: cannot %s merge 
table '%s'", op, opname, tname);
        } else if (isStream(t)) {
                return sql_error(sql, 02, SQLSTATE(42000) "%s: cannot %s stream 
'%s'", op, opname, tname);
diff --git a/sql/test/merge-partitions/Tests/mergepart06.sql 
b/sql/test/merge-partitions/Tests/mergepart06.sql
--- a/sql/test/merge-partitions/Tests/mergepart06.sql
+++ b/sql/test/merge-partitions/Tests/mergepart06.sql
@@ -1,31 +1,38 @@
 CREATE MERGE TABLE testrangelimits (a int, b varchar(32)) PARTITION BY RANGE 
(a);
 CREATE TABLE sublimits1 (a int, b varchar(32));
 CREATE TABLE sublimits2 (a int, b varchar(32));
+CREATE TABLE sublimits3 (a int, b varchar(32));
 
 ALTER TABLE testrangelimits ADD TABLE sublimits1 AS PARTITION BETWEEN 0 AND 
100;
-ALTER TABLE testrangelimits ADD TABLE sublimits1 AS PARTITION BETWEEN 101 AND 
200;
+ALTER TABLE testrangelimits ADD TABLE sublimits2 AS PARTITION BETWEEN 101 AND 
200;
+ALTER TABLE testrangelimits ADD TABLE sublimits3 AS PARTITION BETWEEN 401 AND 
500 WITH NULL;
 
-INSERT INTO testrangelimits VALUES (1, 'hello'); --go to first partition
-INSERT INTO testrangelimits VALUES (101, 'thanks'); --go to second partition
+INSERT INTO testrangelimits VALUES (1, 'a'), (101, 'b'), (401, 'c');
+INSERT INTO testrangelimits VALUES (50, 'more'); --1st partition
+INSERT INTO testrangelimits VALUES (171, 'test'); --2nd partition
+INSERT INTO testrangelimits VALUES (401, 'another'), (NULL, 'test'), (450, 
'to'), (500, 'pass'); --3rd partition
+
 INSERT INTO testrangelimits VALUES (201, 'oh no'); --error
-
-SELECT a FROM testrangelimits;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to