Changeset: 0aec5e7c1fbf for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=0aec5e7c1fbf
Added Files:
        sql/test/merge-partitions/Tests/mergepart21.sql
Modified Files:
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql_cat.c
        sql/include/sql_catalog.h
        sql/server/rel_propagate.c
        sql/server/rel_schema.c
        sql/server/sql_mvc.c
        sql/server/sql_parser.y
        sql/server/sql_partition.c
        sql/server/sql_partition.h
        sql/storage/store.c
        sql/test/merge-partitions/Tests/All
Branch: merge-partitions
Log Message:

Doing SQL catalog validations due to expressions (ie. tables depending on 
functions, expressions depending on columns...). Also fixed catalog sql_part 
dups which would cause corrupt data.


diffs (truncated from 536 to 300 lines):

diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -38,7 +38,7 @@
 #include "mal_instruction.h"
 #include "mal_resource.h"
 
-extern str bootstrap_partition_expression(mvc* sql, sql_table *mt);
+extern str bootstrap_partition_expression(mvc* sql, sql_table *mt, int 
instantiate);
 
 static int
 rel_is_table(sql_rel *rel)
@@ -336,22 +336,24 @@ create_table_or_view(mvc *sql, char *sna
 
                if (copied == NULL)
                        throw(SQL, "sql.catalog", SQLSTATE(42000) "CREATE 
TABLE: %s_%s_%s conflicts", s->base.name, t->base.name, c->base.name);
-               if(isPartitionedByColumnTable(t) && c == t->part.pcol)
+               if(isPartitionedByColumnTable(t) && c->base.id == 
t->part.pcol->base.id)
                        nt->part.pcol = copied;
        }
        if(isPartitionedByExpressionTable(t)) {
                char *err = NULL;
+
                nt->part.pexp->exp = sa_strdup(sql->session->tr->sa, 
t->part.pexp->exp);
 
                sql->sa = sa_create();
                if(!sql->sa)
                        throw(SQL, "sql.catalog",SQLSTATE(HY001) 
MAL_MALLOC_FAIL);
 
-               if((err = bootstrap_partition_expression(sql, nt)))
-                       return err;
-
+               err = bootstrap_partition_expression(sql, nt, 1);
                sa_destroy(sql->sa);
                sql->sa = NULL;
+
+               if(err)
+                       return err;
        }
        if(sql_trans_set_partition_table(sql->session->tr, nt))
                throw(SQL, "sql.catalog", SQLSTATE(42000) "CREATE TABLE: %s_%s: 
an internal error occurred", s->base.name, t->base.name);
diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -209,8 +209,7 @@ alter_table_add_range_partition(mvc *sql
                goto finish;
        }
 
-       if((msg = find_partition_type(sql, &tpe, mt)))
-               goto finish;
+       find_partition_type(&tpe, mt);
        tp1 = tpe.type->localtype;
        if(ATOMcmp(TYPE_str, min, ATOMnilptr(TYPE_str))) {
                if (tp1 == TYPE_str) {
@@ -344,8 +343,7 @@ alter_table_add_value_partition(mvc *sql
                goto finish;
        }
 
-       if((msg = find_partition_type(sql, &tpe, mt)))
-               goto finish;
+       find_partition_type(&tpe, mt);
        tp1 = tpe.type->localtype;
        ninserts = pci->argc - pci->retc - 6;
        if(ninserts <= 0 && !with_nills) {
diff --git a/sql/include/sql_catalog.h b/sql/include/sql_catalog.h
--- a/sql/include/sql_catalog.h
+++ b/sql/include/sql_catalog.h
@@ -542,9 +542,9 @@ typedef struct sql_part {
 } sql_part;
 
 typedef struct sql_expression {
-       sql_subtype type;
-       char *exp;
-       list *cols;
+       sql_subtype type; /* the returning sql_subtype of the expression */
+       char *exp;        /* the expression itself */
+       list *cols;       /* list of oids of the columns of the table used in 
the expression */
 } sql_expression;
 
 typedef struct sql_table {
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
@@ -118,14 +118,13 @@ rel_alter_table_add_partition_range(mvc*
        list *exps = new_exp_list(sql->sa);
        sql_exp *exception, *aggr, *anti_exp, *anti_le, *e1, *e2, *anti_nils;
        sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", 
NULL);
-       char buf[BUFSIZ], *pmin = min ? atom2string(sql->sa, min): NULL, *pmax 
= max ? atom2string(sql->sa, max) : NULL, *err;
+       char buf[BUFSIZ], *pmin = min ? atom2string(sql->sa, min): NULL, *pmax 
= max ? atom2string(sql->sa, max) : NULL;
        sql_subtype tpe;
 
        if(!rel_psm || !exps)
                return NULL;
 
-       if((err = find_partition_type(sql, &tpe, mt)))
-               return sql_error(sql, 02,"%s", err);
+       find_partition_type(&tpe, mt);
 
        anti_le = rel_generate_anti_expression(sql, &anti_rel, mt, pt);
        anti_nils = rel_unop_(sql, anti_le, NULL, "isnull", card_value);
@@ -195,14 +194,13 @@ rel_alter_table_add_partition_list(mvc *
        sql_exp *exception, *aggr, *anti_exp, *anti_le, *anti_nils;
        sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", 
NULL);
        int with_nills = 0;
-       char buf[BUFSIZ], *err;
+       char buf[BUFSIZ];
        sql_subtype tpe;
 
        if(!rel_psm || !exps)
                return NULL;
 
-       if((err = find_partition_type(sql, &tpe, mt)))
-               return sql_error(sql, 02,"%s", err);
+       find_partition_type(&tpe, mt);
 
        anti_le = rel_generate_anti_expression(sql, &anti_rel, mt, pt);
        anti_nils = rel_unop_(sql, anti_le, NULL, "isnull", card_value);
diff --git a/sql/server/rel_schema.c b/sql/server/rel_schema.c
--- a/sql/server/rel_schema.c
+++ b/sql/server/rel_schema.c
@@ -886,6 +886,19 @@ table_element(mvc *sql, symbol *s, sql_s
                                }
                        }
                }
+               if (isPartitionedByColumnTable(t) && t->part.pcol->base.id == 
col->base.id) {
+                       sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: cannot 
drop column '%s': is the partitioned column on the table '%s'\n", cname, 
t->base.name);
+                       return SQL_ERR;
+               }
+               if (isPartitionedByExpressionTable(t)) {
+                       for(node *n = t->part.pexp->cols->h; n; n = n->next) {
+                               sqlid next = *(sqlid*) n->data;
+                               if(next == col->base.id) {
+                                       sql_error(sql, 02, SQLSTATE(42000) 
"ALTER TABLE: cannot drop column '%s': the expression used in '%s' depends on 
it\n", cname, t->base.name);
+                                       return SQL_ERR;
+                               }
+                       }
+               }
                if(mvc_drop_column(sql, t, col, drop_action)) {
                        sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE: %s\n", 
MAL_MALLOC_FAIL);
                        return SQL_ERR;
@@ -947,6 +960,7 @@ create_partition_definition(mvc *sql, sq
                        t->part.pexp = SA_ZNEW(sql->sa, sql_expression);
                        t->part.pexp->exp = sa_strdup(sql->sa, query);
                        t->part.pexp->type = *empty;
+                       t->part.pexp->cols = sa_list(sql->sa);
                        _DELETE(query);
                }
        }
@@ -1446,7 +1460,6 @@ sql_alter_table(mvc *sql, dlist *qname, 
                                if(!extra)
                                        return rel_alter_table(sql->sa, 
DDL_ALTER_TABLE_ADD_TABLE, sname, tname, sname, ntname, 0);
                                if(extra->token == SQL_PARTITION_RANGE) {
-                                       char *err;
                                        sql_subtype tpe;
                                        dlist* ll = extra->data.lval;
                                        symbol* min = ll->h->data.sym, *max = 
ll->h->next->data.sym;
@@ -1458,8 +1471,7 @@ sql_alter_table(mvc *sql, dlist *qname, 
                                                                (t->type == 
tt_merge_table)?"merge":"list partition");
                                        }
 
-                                       if((err = find_partition_type(sql, 
&tpe, t)))
-                                               return sql_error(sql, 02, "%s", 
err);
+                                       find_partition_type(&tpe, t);
 
                                        if(min && min->token == SQL_MINVALUE) {
                                                amin = 
atom_absolute_min(sql->sa, &tpe);
diff --git a/sql/server/sql_mvc.c b/sql/server/sql_mvc.c
--- a/sql/server/sql_mvc.c
+++ b/sql/server/sql_mvc.c
@@ -22,7 +22,7 @@
 #include "gdk_logger.h"
 #include "wlc.h"
 
-extern str bootstrap_partition_expression(mvc* sql, sql_table *mt);
+extern str bootstrap_partition_expression(mvc* sql, sql_table *mt, int 
instantiate);
 extern str initialize_sql_parts(mvc* sql, sql_table *mt);
 
 static int mvc_debug = 0;
@@ -290,7 +290,7 @@ mvc_init(int debug, store_type store, in
                if(ss->tables.set) {
                        for (node *nn = ss->tables.set->h; nn; nn = nn->next) {
                                sql_table *tt = (sql_table*) nn->data;
-                               if(isPartitionedByColumnTable(tt) || 
isPartitionedByExpressionTable(tt)) {
+                               if(isPartitionedByExpressionTable(tt)) {
                                        char *err;
                                        if((err = initialize_sql_parts(m, tt)) 
!= NULL) {
                                                fprintf(stderr, "!mvc_init: 
unable to start partitioned table: %s.%s: %s\n",
@@ -1321,7 +1321,7 @@ mvc_create_table(mvc *m, sql_schema *s, 
                t->s = s;
        } else {
                t = sql_trans_create_table(m->session->tr, s, name, NULL, tt, 
system, persistence, commit_action, sz);
-               if(t && isPartitionedByExpressionTable(t) && (err = 
bootstrap_partition_expression(m, t))) {
+               if(t && isPartitionedByExpressionTable(t) && (err = 
bootstrap_partition_expression(m, t, 1))) {
                        (void) sql_error(m, 02, "%s", err);
                        return SQL_ERR;
                }
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -1068,8 +1068,10 @@ alter_statement:
        { dlist *l = L(), *part;
          append_list(l, $3);
          append_symbol(l, _symbol_create_list( SQL_TABLE, 
append_list(L(),$6)));
-         part = $7->data.lval;
-         append_int(part, FALSE);
+         if($7) {
+                 part = $7->data.lval;
+                 append_int(part, FALSE);
+         }
          append_symbol(l, $7);
          $$ = _symbol_create_list( SQL_ALTER_TABLE, l ); }
  | ALTER TABLE qname ALTER alter_table_element
diff --git a/sql/server/sql_partition.c b/sql/server/sql_partition.c
--- a/sql/server/sql_partition.c
+++ b/sql/server/sql_partition.c
@@ -13,6 +13,7 @@
 #include "sql_mvc.h"
 #include "sql_catalog.h"
 #include "sql_relation.h"
+#include "rel_optimizer.h"
 #include "rel_updates.h"
 #include "mal_exception.h"
 
@@ -80,8 +81,11 @@ exp_find_table_columns(mvc *sql, sql_exp
                case e_column: {
                        if(!strcmp(e->l, t->base.name)) {
                                sql_column *col = find_sql_column(t, e->r);
-                               if(col)
-                                       list_append(cols, col);
+                               if(col) {
+                                       sqlid *nid = sa_alloc(cols->sa, 
sizeof(sqlid));
+                                       *nid = col->base.id;
+                                       list_append(cols, nid);
+                               }
                        }
                } break;
                case e_cmp: {
@@ -149,19 +153,21 @@ find_expression_type(sql_exp *e, sql_sub
        return NULL;
 }
 
+extern list *rel_dependencies(sql_allocator *sa, sql_rel *r);
+
 str
-bootstrap_partition_expression(mvc* sql, sql_table *mt)
+bootstrap_partition_expression(mvc* sql, sql_table *mt, int instantiate)
 {
        sql_exp *exp;
        char *query, *msg = NULL;
        int sql_ec;
-       sql_rel* baset;
+       sql_rel *r;
 
-       assert(isPartitionedByExpressionTable(mt));
+       assert(isPartitionedByExpressionTable(mt) && mt->part.pexp->cols);
 
-       baset = rel_basetable(sql, mt, mt->base.name);
+       r = rel_basetable(sql, mt, mt->base.name);
        query = mt->part.pexp->exp;
-       if((exp = rel_parse_val(sql, sa_message(sql->sa, "select %s;", query), 
sql->emode, baset)) == NULL) {
+       if((exp = rel_parse_val(sql, sa_message(sql->sa, "select %s;", query), 
sql->emode, r)) == NULL) {
                if(*sql->errstr) {
                        if (strlen(sql->errstr) > 6 && sql->errstr[5] == '!')
                                throw(SQL, "sql.partition", "%s", sql->errstr);
@@ -171,8 +177,6 @@ bootstrap_partition_expression(mvc* sql,
                throw(SQL,"sql.partition", SQLSTATE(42000) "Incorrect 
expression '%s'", query);
        }
 
-       if(!mt->part.pexp->cols)
-               mt->part.pexp->cols = sa_list(sql->sa);
        exp_find_table_columns(sql, exp, mt, mt->part.pexp->cols);
 
        if((msg = find_expression_type(exp, &(mt->part.pexp->type), query)) != 
NULL)
@@ -189,25 +193,41 @@ bootstrap_partition_expression(mvc* sql,
                        GDKfree(err);
                }
        }
+
+       if(instantiate) {
+               r = rel_project(sql->sa, r, NULL);
+               r->exps = sa_list(sql->sa);
+               list_append(r->exps, exp);
+
+               if (r)
+                       r = rel_optimizer(sql, r, 0);
+               if (r) {
+                       int i;
+                       node *n, *found = NULL;
+                       list *id_l = rel_dependencies(sql->sa, r);
+                       for(i = 0, n = id_l->h ; n ; n = n->next, i++) { 
//remove the table itself from the list of dependencies
+                               if(*(int *) n->data == mt->base.id)
+                                       found = n;
+                       }
+                       assert(found);
+                       list_remove_node(id_l, found);
+                       mvc_create_dependencies(sql, id_l, mt->base.id, 
TABLE_DEPENDENCY);
+               }
+       }
+
        return msg;
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to