Changeset: 25c5c509d9b6 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=25c5c509d9b6 Modified Files: clients/Tests/MAL-signatures.stable.out clients/Tests/MAL-signatures.stable.out.int128 clients/Tests/exports.stable.out clients/mapilib/mapi.c gdk/gdk_batop.c gdk/gdk_logger.c monetdb5/modules/kernel/algebra.c monetdb5/modules/kernel/algebra.h monetdb5/modules/kernel/algebra.mal sql/backends/monet5/rel_bin.c sql/backends/monet5/sql_statement.c sql/include/sql_mem.h sql/rel.txt sql/server/rel_exp.c sql/server/rel_optimizer.c sql/server/rel_rel.c sql/server/rel_schema.c sql/server/rel_unnest.c sql/server/rel_updates.c sql/server/rel_updates.h sql/test/Triggers/Tests/All sql/test/Triggers/trigger_action.sql sql/test/mergetables/Tests/mergequery.stable.out sql/test/miscellaneous/Tests/alter_table_add_column.sql sql/test/miscellaneous/Tests/alter_table_add_column.stable.out sql/test/remote/Tests/partition_elim.stable.out sql/test/sys-schema/Tests/check_ForeignKey_referential_integrity.sql sql/test/sys-schema/Tests/check_ForeignKey_referential_integrity.stable.out testing/exportutils.py Branch: default Log Message:
Merge with Nov2019 diffs (truncated from 1865 to 300 lines): diff --git a/clients/Tests/MAL-signatures.stable.out b/clients/Tests/MAL-signatures.stable.out --- a/clients/Tests/MAL-signatures.stable.out +++ b/clients/Tests/MAL-signatures.stable.out @@ -576,7 +576,9 @@ stdout of test 'MAL-signatures` in direc [ "algebra", "rangejoin", "command algebra.rangejoin(l:bat[:any_1], r1:bat[:any_1], r2:bat[:any_1], sl:bat[:oid], sr:bat[:oid], li:bit, hi:bit, estimate:lng) (X_0:bat[:oid], X_1:bat[:oid]) ", "ALGrangejoin;", "Range join: values in l and r1/r2 match if r1 <[=] l <[=] r2" ] [ "algebra", "reuse", "command algebra.reuse(b:bat[:any_1]):bat[:any_1] ", "ALGreuse;", "Reuse a temporary BAT if you can. Otherwise,\n\tallocate enough storage to accept result of an\n \toperation (not involving the heap)" ] [ "algebra", "select", "command algebra.select(b:bat[:any_1], low:any_1, high:any_1, li:bit, hi:bit, anti:bit):bat[:oid] ", "ALGselect1;", "Select all head values for which the tail value is in range.\n\tInput is a dense-headed BAT, output is a dense-headed BAT with in\n\tthe tail the head value of the input BAT for which the tail value\n\tis between the values low and high (inclusive if li respectively\n\thi is set). The output BAT is sorted on the tail value. If low\n\tor high is nil, the boundary is not considered (effectively - and\n\t+ infinity). If anti is set, the result is the complement. Nil\n\tvalues in the tail are never matched, unless low=nil, high=nil,\n\tli=1, hi=1, anti=0. All non-nil values are returned if low=nil,\n\thigh=nil, and li, hi are not both 1, or anti=1.\n\tNote that the output is suitable as second input for the other\n\tversion of this function." ] +[ "algebra", "select", "command algebra.select(b:bat[:any_1], low:any_1, high:any_1, li:bit, hi:bit, anti:bit, unknown:bit):bat[:oid] ", "ALGselect1nil;", "With unknow set, each nil != nil" ] [ "algebra", "select", "command algebra.select(b:bat[:any_1], s:bat[:oid], low:any_1, high:any_1, li:bit, hi:bit, anti:bit):bat[:oid] ", "ALGselect2;", "Select all head values of the first input BAT for which the tail value\n\tis in range and for which the head value occurs in the tail of the\n\tsecond input BAT.\n\tThe first input is a dense-headed BAT, the second input is a\n\tdense-headed BAT with sorted tail, output is a dense-headed BAT\n\twith in the tail the head value of the input BAT for which the\n\ttail value is between the values low and high (inclusive if li\n\trespectively hi is set). The output BAT is sorted on the tail\n\tvalue. If low or high is nil, the boundary is not considered\n\t(effectively - and + infinity). If anti is set, the result is the\n\tcomplement. Nil values in the tail are never matched, unless\n\tlow=nil, high=nil, li=1, hi=1, anti=0. All non-nil values are\n\treturned if low=nil, high=nil, and li, hi are not both 1, or anti=1.\n\tNote that th e output is suitable as second input for this\n\tfunction." ] +[ "algebra", "select", "command algebra.select(b:bat[:any_1], s:bat[:oid], low:any_1, high:any_1, li:bit, hi:bit, anti:bit, unknown:bit):bat[:oid] ", "ALGselect2nil;", "With unknow set, each nil != nil" ] [ "algebra", "selectNotNil", "command algebra.selectNotNil(b:bat[:any_2]):bat[:any_2] ", "ALGselectNotNil;", "Select all not-nil values" ] [ "algebra", "semijoin", "command algebra.semijoin(l:bat[:any_1], r:bat[:any_1], sl:bat[:oid], sr:bat[:oid], nil_matches:bit, estimate:lng) (X_0:bat[:oid], X_1:bat[:oid]) ", "ALGsemijoin;", "Semi join with candidate lists" ] [ "algebra", "slice", "command algebra.slice(b:bat[:any_1], x:lng, y:lng):bat[:any_1] ", "ALGslice;", "Return the slice with the BUNs at position x till y." ] diff --git a/clients/Tests/MAL-signatures.stable.out.int128 b/clients/Tests/MAL-signatures.stable.out.int128 --- a/clients/Tests/MAL-signatures.stable.out.int128 +++ b/clients/Tests/MAL-signatures.stable.out.int128 @@ -680,7 +680,9 @@ stdout of test 'MAL-signatures` in direc [ "algebra", "rangejoin", "command algebra.rangejoin(l:bat[:any_1], r1:bat[:any_1], r2:bat[:any_1], sl:bat[:oid], sr:bat[:oid], li:bit, hi:bit, estimate:lng) (X_0:bat[:oid], X_1:bat[:oid]) ", "ALGrangejoin;", "Range join: values in l and r1/r2 match if r1 <[=] l <[=] r2" ] [ "algebra", "reuse", "command algebra.reuse(b:bat[:any_1]):bat[:any_1] ", "ALGreuse;", "Reuse a temporary BAT if you can. Otherwise,\n\tallocate enough storage to accept result of an\n \toperation (not involving the heap)" ] [ "algebra", "select", "command algebra.select(b:bat[:any_1], low:any_1, high:any_1, li:bit, hi:bit, anti:bit):bat[:oid] ", "ALGselect1;", "Select all head values for which the tail value is in range.\n\tInput is a dense-headed BAT, output is a dense-headed BAT with in\n\tthe tail the head value of the input BAT for which the tail value\n\tis between the values low and high (inclusive if li respectively\n\thi is set). The output BAT is sorted on the tail value. If low\n\tor high is nil, the boundary is not considered (effectively - and\n\t+ infinity). If anti is set, the result is the complement. Nil\n\tvalues in the tail are never matched, unless low=nil, high=nil,\n\tli=1, hi=1, anti=0. All non-nil values are returned if low=nil,\n\thigh=nil, and li, hi are not both 1, or anti=1.\n\tNote that the output is suitable as second input for the other\n\tversion of this function." ] +[ "algebra", "select", "command algebra.select(b:bat[:any_1], low:any_1, high:any_1, li:bit, hi:bit, anti:bit, unknown:bit):bat[:oid] ", "ALGselect1nil;", "With unknow set, each nil != nil" ] [ "algebra", "select", "command algebra.select(b:bat[:any_1], s:bat[:oid], low:any_1, high:any_1, li:bit, hi:bit, anti:bit):bat[:oid] ", "ALGselect2;", "Select all head values of the first input BAT for which the tail value\n\tis in range and for which the head value occurs in the tail of the\n\tsecond input BAT.\n\tThe first input is a dense-headed BAT, the second input is a\n\tdense-headed BAT with sorted tail, output is a dense-headed BAT\n\twith in the tail the head value of the input BAT for which the\n\ttail value is between the values low and high (inclusive if li\n\trespectively hi is set). The output BAT is sorted on the tail\n\tvalue. If low or high is nil, the boundary is not considered\n\t(effectively - and + infinity). If anti is set, the result is the\n\tcomplement. Nil values in the tail are never matched, unless\n\tlow=nil, high=nil, li=1, hi=1, anti=0. All non-nil values are\n\treturned if low=nil, high=nil, and li, hi are not both 1, or anti=1.\n\tNote that th e output is suitable as second input for this\n\tfunction." ] +[ "algebra", "select", "command algebra.select(b:bat[:any_1], s:bat[:oid], low:any_1, high:any_1, li:bit, hi:bit, anti:bit, unknown:bit):bat[:oid] ", "ALGselect2nil;", "With unknow set, each nil != nil" ] [ "algebra", "selectNotNil", "command algebra.selectNotNil(b:bat[:any_2]):bat[:any_2] ", "ALGselectNotNil;", "Select all not-nil values" ] [ "algebra", "semijoin", "command algebra.semijoin(l:bat[:any_1], r:bat[:any_1], sl:bat[:oid], sr:bat[:oid], nil_matches:bit, estimate:lng) (X_0:bat[:oid], X_1:bat[:oid]) ", "ALGsemijoin;", "Semi join with candidate lists" ] [ "algebra", "slice", "command algebra.slice(b:bat[:any_1], x:lng, y:lng):bat[:any_1] ", "ALGslice;", "Return the slice with the BUNs at position x till y." ] diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out --- a/clients/Tests/exports.stable.out +++ b/clients/Tests/exports.stable.out @@ -740,7 +740,9 @@ str ALGprojecttail(Client cntxt, MalBlkP str ALGrangejoin(bat *r1, bat *r2, const bat *lid, const bat *rlid, const bat *rhid, const bat *slid, const bat *srid, const bit *li, const bit *hi, const lng *estimate); str ALGreuse(bat *ret, const bat *bid); str ALGselect1(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti); +str ALGselect1nil(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown); str ALGselect2(bat *result, const bat *bid, const bat *sid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti); +str ALGselect2nil(bat *result, const bat *bid, const bat *sid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown); str ALGselectNotNil(bat *result, const bat *bid); str ALGsemijoin(bat *r1, bat *r2, const bat *l, const bat *r, const bat *sl, const bat *sr, const bit *nil_matches, const lng *estimate); str ALGslice(bat *ret, const bat *bid, const lng *start, const lng *end); diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c --- a/clients/mapilib/mapi.c +++ b/clients/mapilib/mapi.c @@ -890,10 +890,6 @@ struct MapiStatement { #define debugprint(fmt,arg) ((void) 0) #endif -#ifdef HAVE_EMBEDDED -#define printf(...) ((void)0) -#endif - /* * All external calls to the library should pass the mapi-check * routine. It assures a working connection and proper reset of diff --git a/gdk/gdk_batop.c b/gdk/gdk_batop.c --- a/gdk/gdk_batop.c +++ b/gdk/gdk_batop.c @@ -1047,12 +1047,6 @@ BATkeyed(BAT *b) return false; } - /* In order that multiple threads don't scan the same BAT at - * the same time (happens a lot with mitosis/mergetable), we - * use a lock. We reuse the hash lock for this, not because - * this scanning interferes with hashes, but because it's - * there, and not so likely to be used at the same time. */ - MT_lock_set(&b->batIdxLock); b->batDirtydesc = true; if (!b->tkey && b->tnokey[0] == 0 && b->tnokey[1] == 0) { if (b->tsorted || b->trevsorted) { @@ -1160,7 +1154,6 @@ BATkeyed(BAT *b) } } doreturn: - MT_lock_unset(&b->batIdxLock); return b->tkey; } diff --git a/gdk/gdk_logger.c b/gdk/gdk_logger.c --- a/gdk/gdk_logger.c +++ b/gdk/gdk_logger.c @@ -81,10 +81,6 @@ #define LOG_USE_ID 15 #define LOG_CLEAR_ID 16 -#ifdef HAVE_EMBEDDED -#define printf(fmt,...) ((void) 0) -#endif - #ifdef NATIVE_WIN32 #define getfilepos _ftelli64 #else diff --git a/monetdb5/modules/kernel/algebra.c b/monetdb5/modules/kernel/algebra.c --- a/monetdb5/modules/kernel/algebra.c +++ b/monetdb5/modules/kernel/algebra.c @@ -281,12 +281,58 @@ ALGselect2(bat *result, const bat *bid, } str +ALGselect2nil(bat *result, const bat *bid, const bat *sid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown) +{ + BAT *b, *s = NULL, *bn; + const void *nilptr; + + if (!*unknown) + return ALGselect2(result, bid, sid, low, high, li, hi, anti); + + if ((*li != 0 && *li != 1) || + (*hi != 0 && *hi != 1) || + (*anti != 0 && *anti != 1)) { + throw(MAL, "algebra.select", ILLEGAL_ARGUMENT); + } + if ((b = BATdescriptor(*bid)) == NULL) { + throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) { + BBPunfix(b->batCacheid); + throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); + } + derefStr(b, low); + derefStr(b, high); + /* here we don't need open ended parts with nil */ + nilptr = ATOMnilptr(b->ttype); + if (*li == 1 && ATOMcmp(b->ttype, low, nilptr) == 0) + low = high; + else if (*hi == 1 && ATOMcmp(b->ttype, high, nilptr) == 0) + high = low; + bn = BATselect(b, s, low, high, *li, *hi, *anti); + BBPunfix(b->batCacheid); + if (s) + BBPunfix(s->batCacheid); + if (bn == NULL) + throw(MAL, "algebra.select", GDK_EXCEPTION); + *result = bn->batCacheid; + BBPkeepref(bn->batCacheid); + return MAL_SUCCEED; +} + +str ALGselect1(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti) { return ALGselect2(result, bid, NULL, low, high, li, hi, anti); } str +ALGselect1nil(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown) +{ + return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown); +} + +str ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val, const char **op) { BAT *b, *s = NULL, *bn; diff --git a/monetdb5/modules/kernel/algebra.h b/monetdb5/modules/kernel/algebra.h --- a/monetdb5/modules/kernel/algebra.h +++ b/monetdb5/modules/kernel/algebra.h @@ -26,6 +26,8 @@ mal_export str ALGgroupby(bat *res, cons mal_export str ALGcard(lng *result, const bat *bid); mal_export str ALGselect1(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti); mal_export str ALGselect2(bat *result, const bat *bid, const bat *sid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti); +mal_export str ALGselect1nil(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown); +mal_export str ALGselect2nil(bat *result, const bat *bid, const bat *sid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown); mal_export str ALGthetaselect1(bat *result, const bat *bid, const void *val, const char **op); mal_export str ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val, const char **op); diff --git a/monetdb5/modules/kernel/algebra.mal b/monetdb5/modules/kernel/algebra.mal --- a/monetdb5/modules/kernel/algebra.mal +++ b/monetdb5/modules/kernel/algebra.mal @@ -70,6 +70,14 @@ comment "Select all head values of the f Note that the output is suitable as second input for this function."; +command select(b:bat[:any_1], low:any_1, high:any_1, li:bit, hi:bit, anti:bit, unknown:bit) :bat[:oid] +address ALGselect1nil +comment "With unknow set, each nil != nil"; + +command select(b:bat[:any_1], s:bat[:oid], low:any_1, high:any_1, li:bit, hi:bit, anti:bit, unknown:bit) :bat[:oid] +address ALGselect2nil +comment "With unknow set, each nil != nil"; + command thetaselect(b:bat[:any_1], val:any_1, op:str) :bat[:oid] address ALGthetaselect1 comment "Select all head values for which the tail value obeys the relation 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 @@ -3621,20 +3621,8 @@ sql_insert_check_null(backend *be, sql_t static stmt ** table_update_stmts(mvc *sql, sql_table *t, int *Len) { - stmt **updates; - int i, len = list_length(t->columns.set); - node *m; - - *Len = len; - updates = SA_NEW_ARRAY(sql->sa, stmt *, len); - for (m = t->columns.set->h, i = 0; m; m = m->next, i++) { - sql_column *c = m->data; - - /* update the column number, for correct array access */ - c->colnr = i; - updates[i] = NULL; - } - return updates; + *Len = list_length(t->columns.set); + return SA_ZNEW_ARRAY(sql->sa, stmt *, *Len); } static stmt * @@ -4499,7 +4487,7 @@ sql_stack_add_updated(mvc *sql, const ch append(exps, oe); append(exps, ne); - } else { /* later select correct updated rows only ? */ + } else { sql_exp *oe = exp_column(sql->sa, on, c->base.name, &c->type, CARD_MULTI, c->null, 0); sql_exp *ne = exp_column(sql->sa, nn, c->base.name, &c->type, CARD_MULTI, c->null, 0); diff --git a/sql/backends/monet5/sql_statement.c b/sql/backends/monet5/sql_statement.c --- a/sql/backends/monet5/sql_statement.c +++ b/sql/backends/monet5/sql_statement.c @@ -1589,7 +1589,7 @@ select2_join2(backend *be, stmt *op1, st if (op1->nr < 0 && (sub && sub->nr < 0)) return NULL; l = op1->nr; - if (((cmp & CMP_BETWEEN) || op2->nrcols > 0 || op3->nrcols > 0) && (type == st_uselect2)) { + if (((cmp & CMP_BETWEEN && cmp & CMP_SYMMETRIC) || op2->nrcols > 0 || op3->nrcols > 0) && (type == st_uselect2)) { int k; if (op2->nr < 0 || op3->nr < 0) @@ -1691,8 +1691,8 @@ select2_join2(backend *be, stmt *op1, st q = pushNil(mb, q, TYPE_lng); /* estimate */ if (type == st_uselect2) { q = pushBit(mb, q, anti); - if (q == NULL) - return NULL; + if (cmp & CMP_BETWEEN) + q = pushBit(mb, q, TRUE); /* all nil's are != */ } if (q == NULL) return NULL; diff --git a/sql/include/sql_mem.h b/sql/include/sql_mem.h --- a/sql/include/sql_mem.h +++ b/sql/include/sql_mem.h @@ -74,6 +74,7 @@ extern size_t sa_size( sql_allocator *sa #define SA_NEW( sa, type ) ((type*)sa_alloc( sa, sizeof(type)) ) #define SA_ZNEW( sa, type ) ((type*)sa_zalloc( sa, sizeof(type)) ) #define SA_NEW_ARRAY( sa, type, size ) (type*)sa_alloc( sa, ((size)*sizeof(type))) +#define SA_ZNEW_ARRAY( sa, type, size ) (type*)sa_zalloc( sa, ((size)*sizeof(type))) #define SA_RENEW_ARRAY( sa, type, ptr, sz, osz ) (type*)sa_realloc( sa, ptr, ((sz)*sizeof(type)), ((osz)*sizeof(type))) #define _strlen(s) (int)strlen(s) diff --git a/sql/rel.txt b/sql/rel.txt --- a/sql/rel.txt +++ b/sql/rel.txt @@ -130,6 +130,7 @@ e_cmp cmp_all = 14, cross product cmp_project = 15, special case for projection joins + ) e_func diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c --- a/sql/server/rel_exp.c +++ b/sql/server/rel_exp.c @@ -1068,6 +1068,9 @@ exp_match_exp( sql_exp *e1, sql_exp *e2) exp_match_exp(e1->l, e2->l) && exp_match_list(e1->r, e2->r)) return 1; + else if (e1->flag == e2->flag && (e1->flag == cmp_equal || e1->flag == cmp_notequal) && + exp_match_exp(e1->l, e2->r) && exp_match_exp(e1->r, e2->l)) + return 1; /* = and <> operations are reflective, so exp_match_exp can be called crossed */ break; case e_convert: if (!subtype_cmp(exp_totype(e1), exp_totype(e2)) && diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c --- a/sql/server/rel_optimizer.c +++ b/sql/server/rel_optimizer.c @@ -5246,6 +5246,114 @@ rel_remove_empty_join(mvc *sql, sql_rel return rel; } +typedef struct { + sql_rel *p; /* the found join's parent */ + sql_rel *j; /* the found join relation itself */ +} found_join; + +static void +rel_find_joins(mvc *sql, sql_rel *parent, sql_rel *rel, list *l) +{ + if (!rel) + return; + + switch (rel->op) { + case op_basetable: + case op_table: + case op_ddl: + break; + case op_join: _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list