Changeset: 94013ed66263 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=94013ed66263 Modified Files: sql/backends/monet5/rel_bin.c sql/backends/monet5/sql_cat.c sql/rel.txt sql/server/rel_schema.c sql/test/merge-partitions/Tests/mergepart03.stable.err sql/test/merge-partitions/Tests/mergepart03.stable.out sql/test/merge-partitions/Tests/mergepart04.stable.err sql/test/merge-partitions/Tests/mergepart05.stable.err sql/test/merge-partitions/Tests/mergepart07.stable.err Branch: merge-partitions Log Message:
Do the proper validation for partitions by range. However I found another bug :( diffs (truncated from 432 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 @@ -4904,7 +4904,7 @@ rel2bin_exception(backend *be, sql_rel * { stmt *l = NULL, *r = NULL; node *n = NULL; - sql_exp *except = NULL; + list *slist = sa_list(be->mvc->sa); if(find_prop(rel->p, PROP_DISTRIBUTE) && be->cur_append == 0) /* create affected rows accumulator */ create_merge_partitions_accumulator(be); @@ -4914,16 +4914,17 @@ rel2bin_exception(backend *be, sql_rel * if (rel->r) /* first construct the sub relation */ r = subrel_bin(be, rel->r, refs); - if(rel->exps && list_length(rel->exps) == 1) { - n = rel->exps->h; - except = n->data; - return exp_bin(be, except, l, r, NULL, NULL, NULL, NULL); + if(rel->exps) { + for(n = rel->exps->h; n; n = n->next) { + sql_exp *e = n->data; + stmt *s = exp_bin(be, e, l, r, NULL, NULL, NULL, NULL); + append(slist, s); + } } else { //if there is no exception condition, just generate a statement list - list *slist = sa_list(be->mvc->sa); list_append(slist, l); list_append(slist, r); - return stmt_list(be, slist); } + return stmt_list(be, slist); } static stmt * 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 @@ -185,13 +185,12 @@ alter_table_add_range_partition(mvc *sql sql_table *mt = NULL, *pt = NULL; sql_part *err = NULL; str msg = MAL_SUCCEED, err_min = NULL, err_max = NULL, escaped_min = NULL, escaped_max = NULL; - sql_column *col = NULL, *bcol = NULL; - BAT *diff1 = NULL, *diff2 = NULL, *cbind = NULL; - int tp1 = 0, errcode = 0, i = 0; + sql_column *col = NULL; + int tp1 = 0, errcode = 0; ptr pmin = NULL, pmax = NULL; size_t smin = 0, smax = 0, serr_min = 0, serr_max = 0; ssize_t (*atomtostr)(str *, size_t *, const void *); - int accesses[3] = {RDONLY, RD_INS, RD_UPD_VAL}, free_pmin = 1, free_pmax = 1; + int free_pmin = 1, free_pmax = 1; if((msg = validate_alter_table_add_table(sql, "sql.alter_table_add_range_partition", msname, mtname, psname, ptname, &mt, &pt))) { return msg; @@ -261,62 +260,6 @@ alter_table_add_range_partition(mvc *sql goto finish; } - bcol = mvc_bind_column(sql, pt, col->base.name); - - for(i = 0 ; i < 3 ; i++) { - if(cbind) { - BBPunfix(cbind->batCacheid); - cbind = NULL; - } - if(diff1) { - BBPunfix(diff1->batCacheid); - diff1 = NULL; - } - if(diff2) { - BBPunfix(diff2->batCacheid); - diff2 = NULL; - } - if((cbind = store_funcs.bind_col(sql->session->tr, bcol, accesses[i])) == NULL) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); - goto finish; - } - if(!with_nills && cbind->tnil) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) - "ALTER TABLE: there are null values in the column which is not allowed for this partition"); - goto finish; - } - if(!pmin && !pmax) { - if((diff1 = BATselect(cbind, NULL, ATOMnilptr(tp1), NULL, 1, 1, 1)) == NULL) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); - goto finish; - } - if(BATcount(diff1) > 0) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) - "ALTER TABLE: there are non-null values in the column which is not allowed for this partition"); - goto finish; - } - } else { - if((diff1 = BATthetaselect(cbind, NULL, pmin, "<")) == NULL) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); - goto finish; - } - if(BATcount(diff1) > 0) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) - "ALTER TABLE: there are values in the column %s with values lesser than the partition minimum", col->base.name); - goto finish; - } - if((diff2 = BATthetaselect(cbind, NULL, pmax, ">")) == NULL) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); - goto finish; - } - if(BATcount(diff2) > 0) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) - "ALTER TABLE: there are values in the column %s with values higher than the partition maximum", col->base.name); - goto finish; - } - } - } - if(!pmin) { pmin = (ptr) ATOMnilptr(tp1); smin = ATOMsize(tp1); @@ -378,12 +321,6 @@ finish: GDKfree(pmin); if(pmax && free_pmax) GDKfree(pmax); - if(cbind) - BBPunfix(cbind->batCacheid); - if(diff1) - BBPunfix(diff1->batCacheid); - if(diff2) - BBPunfix(diff2->batCacheid); if(msg != MAL_SUCCEED) pt->p = NULL; return msg; diff --git a/sql/rel.txt b/sql/rel.txt --- a/sql/rel.txt +++ b/sql/rel.txt @@ -23,7 +23,7 @@ TABLE (card MULTI) */ DDL (card 0!, top of the tree always) -> flags /* OUTPUT, TRANSACTION-types, CREATE/DROP/ALTER* */ - -> exps For 'OUTPUT' is list of output options, for DISTRIBUTE has a single exception expression + -> exps For 'OUTPUT' is list of output options, for DDL_EXCEPTION is a list of psm_exception For 'transactions' simple flags for CREATE etc full sql string. -> l used in DDL_OUTPUT as the relation to output and DDL_EXCEPTION as a DDL_LIST 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 @@ -85,33 +85,81 @@ rel_alter_table(sql_allocator *sa, int c } static sql_rel * -rel_alter_table_add_partition_range(sql_allocator *sa, char *sname, char *tname, char *sname2, char *tname2, atom* min, - atom* max, int with_nills) +rel_alter_table_add_partition_range(mvc* sql, sql_table *mt, sql_table *pt, char *sname, char *tname, char *sname2, + char *tname2, atom* min, atom* max, int with_nills) { - sql_rel *rel = rel_create(sa); - list *exps = new_exp_list(sa); - char *pmin = min ? atom2string(sa, min): NULL, *pmax = max ? atom2string(sa, max) : NULL; - if(!rel || !exps) + sql_rel *rel_psm = rel_create(sql->sa), *anti_rel; + list *exps = new_exp_list(sql->sa); + sql_exp *exception, *aggr, *anti_exp = NULL, *anti_le, *e1, *e2, *anti_nils; + sql_column *col = mt->pcol; + sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL); + int colr = mt->pcol->colnr; + char buf[BUFSIZ], *pmin = min ? atom2string(sql->sa, min): NULL, *pmax = max ? atom2string(sql->sa, max) : NULL; + + if(!rel_psm || !exps) return NULL; - append(exps, exp_atom_clob(sa, sname)); - append(exps, exp_atom_clob(sa, tname)); + anti_rel = rel_basetable(sql, pt, tname2); + anti_le = list_fetch(anti_rel->exps, colr); + anti_le = exp_column(sql->sa, exp_relname(anti_le), exp_name(anti_le), exp_subtype(anti_le), + anti_le->card, has_nil(anti_le), is_intern(anti_le)); + anti_rel->exps = new_exp_list(sql->sa); + append(anti_rel->exps, anti_le); + anti_nils = rel_unop_(sql, anti_le, NULL, "isnull", card_value); + + assert((!min && !max && with_nills) || (min && max)); + if(min && max) { + e1 = create_table_part_atom_exp(sql, min->tpe, VALget(&min->data)); + if (subtype_cmp(&e1->tpe, &col->type) != 0) + e1 = exp_convert(sql->sa, e1, &e1->tpe, &col->type); + + e2 = create_table_part_atom_exp(sql, max->tpe, VALget(&max->data)); + if (subtype_cmp(&e2->tpe, &col->type) != 0) + e2 = exp_convert(sql->sa, e2, &e2->tpe, &col->type); + + anti_exp = exp_compare2(sql->sa, anti_le, e1, e2, 3); + set_anti(anti_exp); + if(!with_nills) { + anti_nils = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_equal); + anti_exp = exp_or(sql->sa, list_append(new_exp_list(sql->sa), anti_exp), + list_append(new_exp_list(sql->sa), anti_nils), 0); + } + } else { + anti_exp = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_notequal); + } + + anti_rel = rel_select(sql->sa, anti_rel, anti_exp); + anti_rel = rel_groupby(sql, anti_rel, NULL); + aggr = exp_aggr(sql->sa, NULL, cf, 0, 0, anti_rel->card, 0); + (void) rel_groupby_add_aggr(sql, anti_rel, aggr); + exp_label(sql->sa, aggr, ++sql->label); + + //generate the exception + aggr = exp_column(sql->sa, exp_relname(aggr), exp_name(aggr), exp_subtype(aggr), aggr->card, has_nil(aggr), + is_intern(aggr)); + snprintf(buf, BUFSIZ, "ALTER TABLE: there are values in the column %s, outside the partition range", col->base.name); + exception = exp_exception(sql->sa, aggr, buf); + + //generate the psm statement + append(exps, exp_atom_clob(sql->sa, sname)); + append(exps, exp_atom_clob(sql->sa, tname)); assert((sname2 && tname2) || (!sname2 && !tname2)); if (sname2) { - append(exps, exp_atom_clob(sa, sname2)); - append(exps, exp_atom_clob(sa, tname2)); + append(exps, exp_atom_clob(sql->sa, sname2)); + append(exps, exp_atom_clob(sql->sa, tname2)); } - append(exps, exp_atom_clob(sa, pmin)); - append(exps, exp_atom_clob(sa, pmax)); - append(exps, exp_atom_int(sa, with_nills)); - rel->l = NULL; - rel->r = NULL; - rel->op = op_ddl; - rel->flag = DDL_ALTER_TABLE_ADD_RANGE_PARTITION; - rel->exps = exps; - rel->card = CARD_MULTI; - rel->nrcols = 0; - return rel; + append(exps, exp_atom_clob(sql->sa, pmin)); + append(exps, exp_atom_clob(sql->sa, pmax)); + append(exps, exp_atom_int(sql->sa, with_nills)); + rel_psm->l = NULL; + rel_psm->r = NULL; + rel_psm->op = op_ddl; + rel_psm->flag = DDL_ALTER_TABLE_ADD_RANGE_PARTITION; + rel_psm->exps = exps; + rel_psm->card = CARD_MULTI; + rel_psm->nrcols = 0; + + return rel_exception(sql->sa, rel_psm, anti_rel, list_append(new_exp_list(sql->sa), exception)); } static sql_rel * @@ -120,7 +168,7 @@ rel_alter_table_add_partition_list(mvc * { sql_rel *rel_psm = rel_create(sql->sa), *anti_rel; list *exps = new_exp_list(sql->sa), *anti_exps = new_exp_list(sql->sa), *lvals = new_exp_list(sql->sa); - sql_exp *exception, *aggr, *anti_exp, *anti_le; + sql_exp *exception, *aggr, *anti_exp, *anti_le, *anti_nils; sql_column *col = mt->pcol; sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL); int with_nills = 0, colr = mt->pcol->colnr; @@ -135,6 +183,7 @@ rel_alter_table_add_partition_list(mvc * anti_le->card, has_nil(anti_le), is_intern(anti_le)); anti_rel->exps = new_exp_list(sql->sa); append(anti_rel->exps, anti_le); + anti_nils = rel_unop_(sql, anti_le, NULL, "isnull", card_value); for (dnode *dn = values->h; dn ; dn = dn->next) { /* parse the atoms and generate the expressions */ symbol* next = dn->data.sym; @@ -155,14 +204,12 @@ rel_alter_table_add_partition_list(mvc * if(list_length(anti_exps) > 0) { anti_exp = exp_in(sql->sa, anti_le, anti_exps, cmp_notin); if(!with_nills) { - sql_exp *anti_nils = rel_unop_(sql, anti_le, NULL, "isnull", card_value); anti_nils = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_equal); anti_exp = exp_or(sql->sa, append(new_exp_list(sql->sa), anti_exp), append(new_exp_list(sql->sa), anti_nils), 0); } } else { assert(with_nills); - sql_exp *anti_nils = rel_unop_(sql, anti_le, NULL, "isnull", card_value); anti_exp = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_notequal); } @@ -175,8 +222,8 @@ rel_alter_table_add_partition_list(mvc * //generate the exception aggr = exp_column(sql->sa, exp_relname(aggr), exp_name(aggr), exp_subtype(aggr), aggr->card, has_nil(aggr), is_intern(aggr)); - snprintf(buf, BUFSIZ, "ALTER TABLE: there are values in the column %s not according to the partition values list", - col->base.name); + snprintf(buf, BUFSIZ, "ALTER TABLE: there are values in the column %s which is outside the partition list of values", + col->base.name); exception = exp_exception(sql->sa, aggr, buf); //generate the psm statement @@ -1574,7 +1621,7 @@ sql_alter_table(mvc *sql, dlist *qname, } else if(max) { amax = ((AtomNode *) max)->a; } - return rel_alter_table_add_partition_range(sql->sa, sname, tname, sname, ntname, amin, amax, nills); + return rel_alter_table_add_partition_range(sql, t, pt, sname, tname, sname, ntname, amin, amax, nills); } else if(extra->token == SQL_PARTITION_LIST) { _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list