Changeset: 677ac148fd68 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=677ac148fd68 Modified Files: sql/backends/monet5/rel_bin.c sql/backends/monet5/sql_cat.c sql/backends/monet5/sqlcatalog.mal sql/include/sql_relation.h sql/server/rel_propagate.c sql/server/rel_propagate.h sql/server/rel_schema.c sql/server/sql_parser.y sql/test/merge-partitions/Tests/mergepart05.sql sql/test/merge-partitions/Tests/mergepart05.stable.err sql/test/merge-partitions/Tests/mergepart05.stable.out sql/test/merge-partitions/Tests/mergepart07.stable.err sql/test/merge-partitions/Tests/mergepart09.sql sql/test/merge-partitions/Tests/mergepart09.stable.err sql/test/merge-partitions/Tests/mergepart20.stable.err sql/test/merge-partitions/Tests/mergepart21.stable.err Branch: merge-partitions Log Message:
Pushed the compilation of ranges/list of values to the SQL compiler. Now we use SQL expressions instead of just atom literals, thus more flexibility. diffs (truncated from 823 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 @@ -4953,6 +4953,31 @@ rel2bin_psm(backend *be, sql_rel *rel) } static stmt * +rel2bin_partition_limits(backend *be, sql_rel *rel, list *refs) +{ + stmt *l = NULL, *r = NULL; + node *n = NULL; + list *slist = sa_list(be->mvc->sa); + + if (rel->l) /* first construct the sub relation */ + l = subrel_bin(be, rel->l, refs); + if (rel->r) /* first construct the sub relation */ + r = subrel_bin(be, rel->r, refs); + + assert(rel->exps); + assert(rel->flag == DDL_ALTER_TABLE_ADD_RANGE_PARTITION || rel->flag == DDL_ALTER_TABLE_ADD_LIST_PARTITION); + + 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); + } + } + return stmt_catalog(be, rel->flag, stmt_list(be, slist)); +} + +static stmt * rel2bin_exception(backend *be, sql_rel *rel, list *refs) { stmt *l = NULL, *r = NULL; @@ -5128,6 +5153,9 @@ rel2bin_ddl(backend *be, sql_rel *rel, l } else if (rel->flag <= DDL_DROP_SEQ) { s = rel2bin_catalog2(be, rel, refs); sql->type = Q_SCHEMA; + } else if (rel->flag <= DDL_ALTER_TABLE_ADD_LIST_PARTITION) { + s = rel2bin_partition_limits(be, rel, refs); + sql->type = Q_SCHEMA; } else if (rel->flag <= DDL_TRANS) { s = rel2bin_trans(be, rel, refs); sql->type = Q_TRANS; 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 @@ -150,48 +150,14 @@ alter_table_add_table(mvc *sql, char *ms } static char * -add_quotes(char *atom_str) /* always produce a string between quotes, placing them if they do not exist */ -{ - size_t len; - int plus = 0, off = 0; - char *res; - - if(!atom_str) - return atom_str; - - len = strlen(atom_str); - - if(atom_str[0] != '"') - plus++; - if(len == 0 || atom_str[len - 1] != '"') - plus++; - res = GDKmalloc(len + plus + 1); - if(res) { - if(atom_str[0] != '"') { - res[off] = '"'; - off++; - } - strcpy(res + off, atom_str); - off += len; - if(len == 0 || atom_str[len - 1] != '"') { - res[off] = '"'; - off++; - } - res[off] = '\0'; - } - return res; -} - -static char * -alter_table_add_range_partition(mvc *sql, char *msname, char *mtname, char *psname, char *ptname, char *min, char *max, +alter_table_add_range_partition(mvc *sql, char *msname, char *mtname, char *psname, char *ptname, ptr min, ptr max, int with_nills, int update) { 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; - int tp1 = 0, errcode = 0; - ptr pmin = NULL, pmax = NULL; - size_t smin = 0, smax = 0, serr_min = 0, serr_max = 0; + str msg = MAL_SUCCEED, err_min = NULL, err_max = NULL, conflict_err_min = NULL, conflict_err_max = NULL; + int tp1 = 0, errcode = 0, min_null = 0, max_null = 0; + size_t length = 0; ssize_t (*atomtostr)(str *, size_t *, const void *); sql_subtype tpe; @@ -211,59 +177,23 @@ alter_table_add_range_partition(mvc *sql find_partition_type(&tpe, mt); tp1 = tpe.type->localtype; - if(ATOMcmp(TYPE_str, min, ATOMnilptr(TYPE_str))) { - if (tp1 == TYPE_str) { - if ((escaped_min = add_quotes(min)) == NULL) { - msg = createException(SQL, "sql.alter_table_add_range_partition", SQLSTATE(HY001) MAL_MALLOC_FAIL); - goto finish; - } - if (ATOMfromstr(tp1, &pmin, &smin, escaped_min) < 0) { - msg = createException(SQL, "sql.alter_table_add_range_partition", - SQLSTATE(42000) "ALTER TABLE: error while parsing minimum value"); - goto finish; - } - } else if (ATOMfromstr(tp1, &pmin, &smin, min) < 0) { - msg = createException(SQL, "sql.alter_table_add_range_partition", - SQLSTATE(42000) "ALTER TABLE: error while parsing minimum value"); - goto finish; - } - } else { - //if the ranges are not set, the partition is for null values only - assert(with_nills && !ATOMcmp(TYPE_str, max, ATOMnilptr(TYPE_str))); - } + min_null = ATOMcmp(tp1, min, ATOMnilptr(tp1)) == 0; + max_null = ATOMcmp(tp1, max, ATOMnilptr(tp1)) == 0; + if(min_null || max_null) + with_nills = 1; - if(ATOMcmp(TYPE_str, max, ATOMnilptr(TYPE_str))) { - if (tp1 == TYPE_str) { - if((escaped_max = add_quotes(max)) == NULL) { - msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); - goto finish; - } - if(ATOMfromstr(tp1, &pmax, &smax, escaped_max) < 0) { - msg = createException(SQL,"sql.alter_table_add_range_partition", - SQLSTATE(42000) "ALTER TABLE: error while parsing maximum value"); - goto finish; - } - } else if(ATOMfromstr(tp1, &pmax, &smax, max) < 0) { - msg = createException(SQL,"sql.alter_table_add_range_partition", - SQLSTATE(42000) "ALTER TABLE: error while parsing maximum value"); - goto finish; - } - } else { - assert(with_nills && !ATOMcmp(TYPE_str, min, ATOMnilptr(TYPE_str))); - } - - if(pmin && ATOMcmp(tp1, pmin, ATOMnilptr(tp1)) == 0) { + if(!max_null && min_null) { msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) "ALTER TABLE: range bound cannot be null"); goto finish; - } else if(pmax && ATOMcmp(tp1, pmax, ATOMnilptr(tp1)) == 0) { + } else if(!min_null && max_null) { msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) "ALTER TABLE: range bound cannot be null"); goto finish; - } else if(pmin && pmax && ATOMcmp(tp1, pmin, pmax) > 0) { + } else if(!with_nills && ATOMcmp(tp1, min, max) > 0) { msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) "ALTER TABLE: minimum value is higher than maximum value"); goto finish; } - errcode = sql_trans_add_range_partition(sql->session->tr, mt, pt, tpe, pmin, pmax, with_nills, update, &err); + errcode = sql_trans_add_range_partition(sql->session->tr, mt, pt, tpe, min, max, with_nills, update, &err); switch(errcode) { case 0: break; @@ -286,17 +216,18 @@ alter_table_add_range_partition(mvc *sql "one partition can store null values at the time", err->t->s->base.name, err->t->base.name); } else { atomtostr = BATatoms[tp1].atomToStr; - if(atomtostr(&err_min, &serr_min, err->part.range.minvalue) < 0) { + if(atomtostr(&conflict_err_min, &length, err->part.range.minvalue) < 0) { + msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); + } else if(atomtostr(&conflict_err_max, &length, err->part.range.maxvalue) < 0) { msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); - } else if(atomtostr(&err_max, &serr_max, err->part.range.maxvalue) < 0) { - GDKfree(err_min); + } else if(atomtostr(&err_min, &length, min) < 0) { + msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); + } else if(atomtostr(&err_max, &length, max) < 0) { msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(HY001) MAL_MALLOC_FAIL); } else { msg = createException(SQL,"sql.alter_table_add_range_partition",SQLSTATE(42000) "ALTER TABLE: conflicting partitions: %s to %s and %s to %s from table %s.%s", - min, max, err_min, err_max, err->t->s->base.name, err->t->base.name); - GDKfree(err_min); - GDKfree(err_max); + err_min, err_max, conflict_err_min, conflict_err_max, err->t->s->base.name, err->t->base.name); } } break; @@ -305,14 +236,14 @@ alter_table_add_range_partition(mvc *sql } finish: - if(escaped_min) - GDKfree(escaped_min); - if(escaped_max) - GDKfree(escaped_max); - if(pmin) - GDKfree(pmin); - if(pmax) - GDKfree(pmax); + if(err_min) + GDKfree(err_min); + if(err_max) + GDKfree(err_max); + if(conflict_err_min) + GDKfree(conflict_err_min); + if(conflict_err_max) + GDKfree(conflict_err_max); if(msg != MAL_SUCCEED) pt->p = NULL; return msg; @@ -323,9 +254,9 @@ alter_table_add_value_partition(mvc *sql char *ptname, int with_nills, int update) { sql_table *mt = NULL, *pt = NULL; - str msg = MAL_SUCCEED, escaped = NULL; + str msg = MAL_SUCCEED; sql_part *err = NULL; - int tp1 = 0, errcode = 0, i = 0, ninserts = 0; + int errcode = 0, i = 0, ninserts = 0; list *values = list_new(sql->sa, (fdestroy) NULL); sql_subtype tpe; @@ -344,43 +275,18 @@ alter_table_add_value_partition(mvc *sql } find_partition_type(&tpe, mt); - tp1 = tpe.type->localtype; ninserts = pci->argc - pci->retc - 6; if(ninserts <= 0 && !with_nills) { msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000) "ALTER TABLE: no values in the list"); goto finish; } for( i = pci->retc+6; i < pci->argc; i++){ - ptr pnext = NULL; - size_t len = 0; - str next = *getArgReference_str(stk, pci, i); sql_part_value *nextv = NULL; - - if(escaped) { - GDKfree(escaped); - escaped = NULL; - } + ValRecord *vnext = &(stk)->stk[(pci)->argv[i]]; + ptr pnext = VALget(vnext); + size_t len = ATOMlen(vnext->vtype, pnext); - if(tp1 == TYPE_str && ATOMcmp(tp1, next, ATOMnilptr(tp1)) == 0) { - if ((escaped = add_quotes(next)) == NULL) { /* escape string atoms properly */ - msg = createException(SQL, "sql.alter_table_add_value_partition", SQLSTATE(HY001) MAL_MALLOC_FAIL); - goto finish; - } - if(ATOMfromstr(tp1, &pnext, &len, escaped) < 0) { - msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000) - "ALTER TABLE: error while parsing value %s", next); - goto finish; - } - } else { - if(ATOMfromstr(tp1, &pnext, &len, next) < 0) { - msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000) - "ALTER TABLE: error while parsing value %s", next); - goto finish; - } - } - - if(ATOMcmp(tp1, pnext, ATOMnilptr(tp1)) == 0) { /* check for an eventual null value which cannot be */ - GDKfree(pnext); + if(VALisnil(vnext)) { /* check for an eventual null value which cannot be */ msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000) "ALTER TABLE: list value cannot be null"); goto finish; @@ -393,12 +299,10 @@ alter_table_add_value_partition(mvc *sql nextv->length = len; if(list_append_sorted(values, nextv, sql_values_list_element_validate_and_insert) != NULL) { - GDKfree(pnext); msg = createException(SQL,"sql.alter_table_add_value_partition",SQLSTATE(42000) "ALTER TABLE: there are duplicated values in the list"); goto finish; } - GDKfree(pnext); } errcode = sql_trans_add_value_partition(sql->session->tr, mt, pt, tpe, values, with_nills, update, &err); @@ -418,8 +322,6 @@ alter_table_add_value_partition(mvc *sql } finish: - if(escaped) - GDKfree(escaped); if(msg != MAL_SUCCEED) pt->p = NULL; return msg; @@ -1516,13 +1418,13 @@ SQLalter_add_range_partition(Client cntx _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list