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