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