Changeset: 48419612af46 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=48419612af46 Modified Files: sql/server/rel_propagate.c sql/server/sql_partition.c sql/storage/sql_catalog.c sql/test/merge-partitions/Tests/mergepart01.sql sql/test/merge-partitions/Tests/mergepart01.stable.err sql/test/merge-partitions/Tests/mergepart01.stable.out sql/test/merge-partitions/Tests/mergepart05.sql sql/test/merge-partitions/Tests/mergepart05.stable.out sql/test/merge-partitions/Tests/mergepart06.sql sql/test/merge-partitions/Tests/mergepart06.stable.err sql/test/merge-partitions/Tests/mergepart06.stable.out sql/test/merge-partitions/Tests/mergepart13.sql sql/test/merge-partitions/Tests/mergepart13.stable.err sql/test/merge-partitions/Tests/mergepart13.stable.out sql/test/merge-partitions/Tests/mergepart17.sql sql/test/merge-partitions/Tests/mergepart17.stable.out sql/test/merge-partitions/Tests/mergepart18.sql sql/test/merge-partitions/Tests/mergepart18.stable.out sql/test/merge-partitions/Tests/mergepart24.sql sql/test/merge-partitions/Tests/mergepart24.stable.err sql/test/merge-partitions/Tests/mergepart26.sql sql/test/merge-partitions/Tests/mergepart26.stable.err sql/test/merge-partitions/Tests/mergepart26.stable.out sql/test/merge-partitions/Tests/mergepart28.sql.in sql/test/merge-partitions/Tests/mergepart28.stable.err sql/test/merge-partitions/Tests/mergepart28.stable.out Branch: Apr2019 Log Message:
Changed maximum limit of range partitioned merge tables. The maximum value will now be excluded from the range. This implementation pairs MonetDB with other DBMS supporting partitioned merge tables. diffs (truncated from 1117 to 300 lines): 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 @@ -184,7 +184,8 @@ create_range_partition_anti_rel(mvc* sql anti_le = rel_generate_anti_expression(sql, &anti_rel, mt, pt); anti_nils = rel_unop_(sql, anti_le, NULL, "isnull", card_value); - if(pmin && pmax) { + if (pmin && pmax) { + sql_exp *range1, *range2; e1 = exp_copy(sql->sa, pmin); if (subtype_cmp(exp_subtype(pmin), &tpe) != 0) e1 = exp_convert(sql->sa, e1, &e1->tpe, &tpe); @@ -193,9 +194,11 @@ create_range_partition_anti_rel(mvc* sql if (subtype_cmp(exp_subtype(e2), &tpe) != 0) e2 = exp_convert(sql->sa, e2, &e2->tpe, &tpe); - anti_exp = exp_compare2(sql->sa, anti_le, e1, e2, 3); - set_anti(anti_exp); - if(!with_nills) { + range1 = exp_compare(sql->sa, exp_copy(sql->sa, anti_le), e1, 3); + range2 = exp_compare(sql->sa, exp_copy(sql->sa, anti_le), e2, 1); + anti_exp = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range1), + list_append(new_exp_list(sql->sa), range2), 0); + 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); @@ -264,16 +267,25 @@ static sql_rel * propagate_validation_to_upper_tables(mvc* sql, sql_table *mt, sql_table *pt, sql_rel *rel) { sql->caching = 0; - for(sql_table *prev = mt, *it = prev->p ; it && prev ; prev = it, it = it->p) { + for (sql_table *prev = mt, *it = prev->p ; it && prev ; prev = it, it = it->p) { sql_part *spt = find_sql_part(it, prev->base.name); - if(spt) { - if(isRangePartitionTable(it)) { - sql_exp *e1 = create_table_part_atom_exp(sql, spt->tpe, spt->part.range.minvalue), - *e2 = create_table_part_atom_exp(sql, spt->tpe, spt->part.range.maxvalue); + if (spt) { + if (isRangePartitionTable(it)) { + int tpe = spt->tpe.type->localtype; + int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe); + const void *nil = ATOMnilptr(tpe); + sql_exp *e1 = NULL, *e2 = NULL; + + if (atomcmp(spt->part.range.minvalue, nil) != 0 && atomcmp(spt->part.range.maxvalue, nil) != 0) { + e1 = create_table_part_atom_exp(sql, spt->tpe, spt->part.range.minvalue); + e2 = create_table_part_atom_exp(sql, spt->tpe, spt->part.range.maxvalue); + } else { + assert(spt->with_nills); + } rel = rel_list(sql->sa, rel, create_range_partition_anti_rel(sql, it, pt, spt->with_nills, e1, e2)); - } else if(isListPartitionTable(it)) { + } else if (isListPartitionTable(it)) { list *exps = new_exp_list(sql->sa); - for(node *n = spt->part.values->h ; n ; n = n->next) { + for (node *n = spt->part.values->h ; n ; n = n->next) { sql_part_value *next = (sql_part_value*) n->data; sql_exp *e1 = create_table_part_atom_exp(sql, next->tpe, next->value); list_append(exps, e1); @@ -334,7 +346,7 @@ rel_alter_table_add_partition_range(mvc* rel_psm->card = CARD_MULTI; rel_psm->nrcols = 0; - res = create_range_partition_anti_rel(sql, mt, pt, with_nills, pmin, pmax); + res = create_range_partition_anti_rel(sql, mt, pt, with_nills, (min && max) ? pmin : NULL, (min && max) ? pmax : NULL); res->l = rel_psm; return propagate_validation_to_upper_tables(sql, mt, pt, res); @@ -633,40 +645,53 @@ rel_generate_subinserts(mvc *sql, sql_re assert(0); } - if(isRangePartitionTable(t)) { - sql_exp *e1, *e2, *range; - e1 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.minvalue); - e2 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.maxvalue); - range = exp_compare2(sql->sa, le, e1, e2, 3); + if (isRangePartitionTable(t)) { + sql_exp *range = NULL; + int tpe = pt->tpe.type->localtype; + int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe); + const void *nil = ATOMnilptr(tpe); - if(accum) { - accum = exp_or(sql->sa, list_append(new_exp_list(sql->sa), exp_copy(sql->sa, range)), - list_append(new_exp_list(sql->sa), accum), 1); + if (atomcmp(pt->part.range.minvalue, nil) != 0 && atomcmp(pt->part.range.maxvalue, nil) != 0) { + sql_exp *e1, *e2; + e1 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.minvalue); + e2 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.maxvalue); + range = exp_compare2(sql->sa, le, e1, e2, 1); + } else { + assert(pt->with_nills); + } + if (pt->with_nills) { /* handle the nulls case */ + sql_exp *nils = rel_unop_(sql, le, NULL, "isnull", card_value); + nils = exp_compare(sql->sa, nils, exp_atom_bool(sql->sa, 1), cmp_equal); + if (range) { + range = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range), + list_append(new_exp_list(sql->sa), nils), 0); + } else { + range = nils; + } + found_nils = 1; + } + + if (accum) { + accum = exp_or(sql->sa, list_append(new_exp_list(sql->sa), accum), + list_append(new_exp_list(sql->sa), exp_copy(sql->sa, range)), 0); } else { accum = exp_copy(sql->sa, range); } - if(pt->with_nills) { /* handle the nulls case */ - sql_exp *nils = rel_unop_(sql, le, NULL, "isnull", card_value); - nils = exp_compare(sql->sa, nils, exp_atom_bool(sql->sa, 1), cmp_equal); - range = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range), - list_append(new_exp_list(sql->sa), nils), 0); - found_nils = 1; - } dup = rel_select(sql->sa, dup, range); - } else if(isListPartitionTable(t)) { + } else if (isListPartitionTable(t)) { sql_exp *ein; list *exps = new_exp_list(sql->sa); - for(node *n = pt->part.values->h ; n ; n = n->next) { - sql_part_value *next = (sql_part_value*) n->data; + for (node *nn = pt->part.values->h ; nn ; nn = nn->next) { + sql_part_value *next = (sql_part_value*) nn->data; sql_exp *e1 = create_table_part_atom_exp(sql, next->tpe, next->value); list_append(exps, e1); list_append(anti_exps, exp_copy(sql->sa, e1)); } ein = exp_in(sql->sa, le, exps, cmp_in); - if(pt->with_nills) { /* handle the nulls case */ + if (pt->with_nills) { /* handle the nulls case */ sql_exp *nils = rel_unop_(sql, le, NULL, "isnull", card_value); nils = exp_compare(sql->sa, nils, exp_atom_bool(sql->sa, 1), cmp_equal); ein = exp_or(sql->sa, list_append(new_exp_list(sql->sa), ein), @@ -700,8 +725,7 @@ rel_generate_subinserts(mvc *sql, sql_re //generate the exception if(isRangePartitionTable(t)) { - if (list_length(t->members.set) == 1) //when there is just one partition must set the anti_exp - set_anti(accum); + set_anti(accum); anti_exp = accum; } else if(isListPartitionTable(t)) { anti_exp = exp_in(sql->sa, anti_le, anti_exps, cmp_notin); @@ -814,32 +838,52 @@ rel_subtable_insert(mvc *sql, sql_rel *r sql_part *pt = find_sql_part(upper, t->base.name); sql_rel *anti_dup = rel_create_common_relation(sql, rel, upper), *left = rel->l; sql_exp *anti_exp = NULL, *anti_le = rel_generate_anti_insert_expression(sql, &anti_dup, upper), *aggr = NULL, - *exception = NULL; + *exception = NULL, *anti_nils = NULL; list *anti_exps = new_exp_list(sql->sa); sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL); char buf[BUFSIZ]; - if(isRangePartitionTable(upper)) { - sql_exp *e1 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.minvalue), - *e2 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.maxvalue); - anti_exp = exp_compare2(sql->sa, exp_copy(sql->sa, anti_le), exp_copy(sql->sa, e1), exp_copy(sql->sa, e2), 3); - set_anti(anti_exp); - } else if(isListPartitionTable(upper)) { - for(node *n = pt->part.values->h ; n ; n = n->next) { + if (isRangePartitionTable(upper)) { + int tpe = pt->tpe.type->localtype; + int (*atomcmp)(const void *, const void *) = ATOMcompare(tpe); + const void *nil = ATOMnilptr(tpe); + + if (atomcmp(pt->part.range.minvalue, nil) != 0 && atomcmp(pt->part.range.maxvalue, nil) != 0) { + sql_exp *e1 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.minvalue), + *e2 = create_table_part_atom_exp(sql, pt->tpe, pt->part.range.maxvalue), + *range1 = exp_compare(sql->sa, exp_copy(sql->sa, anti_le), e1, 3), + *range2 = exp_compare(sql->sa, exp_copy(sql->sa, anti_le), e2, 1); + anti_exp = exp_or(sql->sa, list_append(new_exp_list(sql->sa), range1), + list_append(new_exp_list(sql->sa), range2), 0); + + if (!pt->with_nills) { /* handle the nulls case */ + anti_nils = rel_unop_(sql, exp_copy(sql->sa, 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, list_append(new_exp_list(sql->sa), anti_exp), + list_append(new_exp_list(sql->sa), anti_nils), 0); + } + } else { + assert(pt->with_nills); + anti_nils = rel_unop_(sql, exp_copy(sql->sa, anti_le), NULL, "isnull", card_value); + anti_exp = exp_compare(sql->sa, anti_nils, exp_atom_bool(sql->sa, 1), cmp_notequal); + } + } else if (isListPartitionTable(upper)) { + for (node *n = pt->part.values->h ; n ; n = n->next) { sql_part_value *next = (sql_part_value*) n->data; sql_exp *e1 = create_table_part_atom_exp(sql, next->tpe, next->value); list_append(anti_exps, exp_copy(sql->sa, e1)); } anti_exp = exp_in(sql->sa, exp_copy(sql->sa, anti_le), anti_exps, cmp_notin); + + if (!pt->with_nills) { /* handle the nulls case */ + anti_nils = rel_unop_(sql, exp_copy(sql->sa, 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, list_append(new_exp_list(sql->sa), anti_exp), + list_append(new_exp_list(sql->sa), anti_nils), 0); + } } else { assert(0); } - if(!pt->with_nills) { /* handle the nulls case */ - sql_exp *anti_nils = rel_unop_(sql, exp_copy(sql->sa, 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, list_append(new_exp_list(sql->sa), anti_exp), - list_append(new_exp_list(sql->sa), anti_nils), 0); - } //generate a count aggregation for the values not present in any of the partitions anti_dup = rel_select(sql->sa, anti_dup, anti_exp); @@ -852,7 +896,7 @@ rel_subtable_insert(mvc *sql, sql_rel *r 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, "INSERT: table %s.%s is part of merge table %s.%s and the insert violates the " - "partition %s of values", t->s->base.name, t->base.name, upper->s->base.name, + "partition %s of values", t->s->base.name, t->base.name, upper->s->base.name, upper->base.name, isRangePartitionTable(upper) ? "range" : "list"); exception = exp_exception(sql->sa, aggr, buf); 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 @@ -352,7 +352,7 @@ initialize_sql_parts(mvc* sql, sql_table ptr ok; vmin = vmax = (ValRecord) {.vtype = TYPE_void,}; - ok = VALinit(&vmin, TYPE_str, next->part.range.minvalue); + ok = VALinit(&vmin, TYPE_str, next->part.range.minvalue); //Fixme if(ok) ok = VALconvert(localtype, &vmin); if(ok) diff --git a/sql/storage/sql_catalog.c b/sql/storage/sql_catalog.c --- a/sql/storage/sql_catalog.c +++ b/sql/storage/sql_catalog.c @@ -366,16 +366,16 @@ sql_range_part_validate_and_insert(void sql_part* pt = (sql_part*) v1, *newp = (sql_part*) v2; int res1, res2; - if(pt == newp) /* same pointer, skip (used in updates) */ + if (pt == newp) /* same pointer, skip (used in updates) */ return NULL; assert(pt->tpe.type->localtype == newp->tpe.type->localtype); - if(newp->with_nills && pt->with_nills) //only one partition at most has null values + if (newp->with_nills && pt->with_nills) //only one partition at most has null values return pt; res1 = ATOMcmp(pt->tpe.type->localtype, pt->part.range.minvalue, newp->part.range.maxvalue); res2 = ATOMcmp(pt->tpe.type->localtype, newp->part.range.minvalue, pt->part.range.maxvalue); - if (res1 <= 0 && res2 <= 0) //overlap: x1 <= y2 && y1 <= x2 + if (res1 < 0 && res2 < 0) //overlap: x1 < y2 && y1 < x2 return pt; return NULL; } @@ -388,17 +388,17 @@ sql_values_part_validate_and_insert(void node *n1 = b1->h, *n2 = b2->h; int res; - if(pt == newp) /* same pointer, skip (used in updates) */ + if (pt == newp) /* same pointer, skip (used in updates) */ return NULL; assert(pt->tpe.type->localtype == newp->tpe.type->localtype); - if(newp->with_nills && pt->with_nills) + if (newp->with_nills && pt->with_nills) return pt; //check for nulls first - while(n1 && n2) { + while (n1 && n2) { sql_part_value *p1 = (sql_part_value *) n1->data, *p2 = (sql_part_value *) n2->data; res = ATOMcmp(pt->tpe.type->localtype, p1->value, p2->value); - if(!res) { //overlap -> same value in both partitions + if (!res) { //overlap -> same value in both partitions return pt; } else if(res < 0) { n1 = n1->next; diff --git a/sql/test/merge-partitions/Tests/mergepart01.sql b/sql/test/merge-partitions/Tests/mergepart01.sql --- a/sql/test/merge-partitions/Tests/mergepart01.sql +++ b/sql/test/merge-partitions/Tests/mergepart01.sql @@ -20,7 +20,8 @@ ALTER TABLE testme ADD TABLE wrongtable CREATE TABLE subtable2 (a int, b varchar(32)); ALTER TABLE testme ADD TABLE subtable2 AS PARTITION IN ('0', '1', '2'); --error ALTER TABLE testme ADD TABLE subtable2 AS PARTITION BETWEEN 7 AND 9; --error -ALTER TABLE testme ADD TABLE subtable2 AS PARTITION BETWEEN 5 AND 5; --error +ALTER TABLE testme ADD TABLE subtable2 AS PARTITION BETWEEN 5 AND 5; +ALTER TABLE testme DROP TABLE subtable2; DROP TABLE subtable1; --error ALTER TABLE testme SET SCHEMA other_schema; --error, changing schema not allowed while with child tables diff --git a/sql/test/merge-partitions/Tests/mergepart01.stable.err b/sql/test/merge-partitions/Tests/mergepart01.stable.err _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list