Changeset: 5389bf9e901d for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5389bf9e901d Modified Files: gdk/gdk_logger.c gdk/gdk_string.c sql/server/rel_optimizer.c sql/server/rel_rel.c sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-query.stable.out sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-view.stable.out sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-2join-query.stable.out sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-2join-view.stable.out sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-prologue.stable.out Branch: Oct2020 Log Message:
Merged with Jun2020 diffs (truncated from 725 to 300 lines): diff --git a/gdk/gdk_logger.c b/gdk/gdk_logger.c --- a/gdk/gdk_logger.c +++ b/gdk/gdk_logger.c @@ -2898,7 +2898,7 @@ log_delta(logger *lg, BAT *uid, BAT *uva fprintf(stderr, "#Logged %s " LLFMT " inserts\n", name, l.nr); } if (ok != GDK_SUCCEED) - TRC_CRITICAL(GDK, "write failed\n"); + TRC_CRITICAL(GDK, "write failed for %s\n", name); return ok; } @@ -2946,7 +2946,7 @@ log_bat(logger *lg, BAT *b, const char * } if (ok != GDK_SUCCEED) - TRC_CRITICAL(GDK, "write failed\n"); + TRC_CRITICAL(GDK, "write failed for %s\n", name); return ok; } diff --git a/gdk/gdk_string.c b/gdk/gdk_string.c --- a/gdk/gdk_string.c +++ b/gdk/gdk_string.c @@ -176,6 +176,46 @@ strLocate(Heap *h, const char *v) return 0; } +static inline gdk_return +checkUTF8(const char *v) +{ + if (v[0] != '\200' || v[1] != '\0') { + /* check that string is correctly encoded UTF-8; there + * was no need to do this earlier: if the string was + * found above, it must have gone through here in the + * past */ + int nutf8 = 0; + int m = 0; + for (size_t i = 0; v[i]; i++) { + if (nutf8 > 0) { + if ((v[i] & 0xC0) != 0x80 || + (m != 0 && (v[i] & m) == 0)) + goto badutf8; + m = 0; + nutf8--; + } else if ((v[i] & 0xE0) == 0xC0) { + nutf8 = 1; + if ((v[i] & 0x1E) == 0) + goto badutf8; + } else if ((v[i] & 0xF0) == 0xE0) { + nutf8 = 2; + if ((v[i] & 0x0F) == 0) + m = 0x20; + } else if ((v[i] & 0xF8) == 0xF0) { + nutf8 = 3; + if ((v[i] & 0x07) == 0) + m = 0x30; + } else if ((v[i] & 0x80) != 0) { + goto badutf8; + } + } + } + return GDK_SUCCEED; + + badutf8: + return GDK_FAIL; +} + var_t strPut(Heap *h, var_t *dst, const char *v) { @@ -219,39 +259,9 @@ strPut(Heap *h, var_t *dst, const char * } /* the string was not found in the heap, we need to enter it */ - if (v[0] != '\200' || v[1] != '\0') { - /* check that string is correctly encoded UTF-8; there - * was no need to do this earlier: if the string was - * found above, it must have gone through here in the - * past */ - int nutf8 = 0; - int m = 0; - for (size_t i = 0; v[i]; i++) { - if (nutf8 > 0) { - if ((v[i] & 0xC0) != 0x80 || - (m != 0 && (v[i] & m) == 0)) { - badutf8: - GDKerror("incorrectly encoded UTF-8"); - return 0; - } - m = 0; - nutf8--; - } else if ((v[i] & 0xE0) == 0xC0) { - nutf8 = 1; - if ((v[i] & 0x1E) == 0) - goto badutf8; - } else if ((v[i] & 0xF0) == 0xE0) { - nutf8 = 2; - if ((v[i] & 0x0F) == 0) - m = 0x20; - } else if ((v[i] & 0xF8) == 0xF0) { - nutf8 = 3; - if ((v[i] & 0x07) == 0) - m = 0x30; - } else if ((v[i] & 0x80) != 0) { - goto badutf8; - } - } + if (checkUTF8(v) != GDK_SUCCEED) { + GDKerror("incorrectly encoded UTF-8\n"); + return 0; } pad = GDK_VARALIGN - (h->free & (GDK_VARALIGN - 1)); @@ -780,6 +790,10 @@ strWrite(const char *a, stream *s, size_ (void) cnt; assert(cnt == 1); + if (checkUTF8(a) != GDK_SUCCEED) { + GDKerror("incorrectly encoded UTF-8\n"); + return GDK_FAIL; + } if (mnstr_writeInt(s, (int) len) && mnstr_write(s, a, len, 1) == 1) return GDK_SUCCEED; else 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 @@ -1680,12 +1680,12 @@ rel_simplify_project_fk_join(mvc *sql, s { sql_rel *rl = r->l; sql_rel *rr = r->r; - sql_exp *je; + sql_exp *je, *le, *nje, *re; node *n; int fk_left = 1; /* check for foreign key join */ - if (!r->exps || list_length(r->exps) != 1) + if (list_length(r->exps) != 1) return r; je = r->exps->h->data; if (je && !find_prop(je->p, PROP_JOINIDX)) @@ -1729,11 +1729,24 @@ rel_simplify_project_fk_join(mvc *sql, s return r; } + /* rewrite, ie remove pkey side if possible */ + le = (sql_exp*)je->l, re = (sql_exp*)je->l; + + /* both have NULL and there are semantics, the join cannot be removed */ + if (is_semantics(je) && has_nil(le) && has_nil(re)) + return r; + (*changes)++; - /* rewrite, ie remove pkey side */ - if (fk_left) - return r->l; - return r->r; + /* if the foreign key column doesn't have NULL values, then return it */ + if (!has_nil(le) || is_full(r->op) || (fk_left && is_left(r->op)) || (!fk_left && is_right(r->op))) + return fk_left ? r->l : r->r; + + /* remove NULL values, ie generate a select not null */ + nje = exp_compare(sql->sa, exp_ref(sql, le), exp_atom(sql->sa, atom_general(sql->sa, exp_subtype(le), NULL)), cmp_equal); + set_anti(nje); + set_has_no_nil(nje); + set_semantics(nje); + return rel_select(sql->sa, fk_left ? r->l : r->r, nje); } static sql_rel * @@ -1741,11 +1754,11 @@ rel_simplify_count_fk_join(mvc *sql, sql { sql_rel *rl = r->l; sql_rel *rr = r->r; - sql_exp *oce, *je; + sql_exp *je, *le, *nje, *re, *oce; int fk_left = 1; /* check for foreign key join */ - if (!r->exps || list_length(r->exps) != 1) + if (list_length(r->exps) != 1) return r; je = r->exps->h->data; if (je && !find_prop(je->p, PROP_JOINIDX)) @@ -1777,11 +1790,24 @@ rel_simplify_count_fk_join(mvc *sql, sql r->r = rr; } + /* rewrite, ie remove pkey side if possible */ + le = (sql_exp*)je->l, re = (sql_exp*)je->l; + + /* both have NULL and there are semantics, the join cannot be removed */ + if (is_semantics(je) && has_nil(le) && has_nil(re)) + return r; + (*changes)++; - /* rewrite, ie remove pkey side */ - if (fk_left) - return r->l; - return r->r; + /* if the foreign key column doesn't have NULL values, then return it */ + if (!has_nil(le) || is_full(r->op) || (fk_left && is_left(r->op)) || (!fk_left && is_right(r->op))) + return fk_left ? r->l : r->r; + + /* remove NULL values, ie generate a select not null */ + nje = exp_compare(sql->sa, exp_ref(sql, le), exp_atom(sql->sa, atom_general(sql->sa, exp_subtype(le), NULL)), cmp_equal); + set_anti(nje); + set_has_no_nil(nje); + set_semantics(nje); + return rel_select(sql->sa, fk_left ? r->l : r->r, nje); } /* diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c --- a/sql/server/rel_rel.c +++ b/sql/server/rel_rel.c @@ -828,6 +828,7 @@ rel_basetable(mvc *sql, sql_table *t, co sql_idx *i = cn->data; sql_subtype *t = sql_bind_localtype("lng"); /* hash "lng" */ char *iname = NULL; + int has_nils = 0; /* do not include empty indices in the plan */ if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type)) @@ -837,7 +838,13 @@ rel_basetable(mvc *sql, sql_table *t, co t = sql_bind_localtype("oid"); iname = sa_strconcat( sa, "%", i->base.name); - e = exp_alias(sa, atname, iname, tname, iname, t, CARD_MULTI, 0, 1); + for (node *n = i->columns->h ; n && !has_nils; n = n->next) { /* check for NULL values */ + sql_kc *kc = n->data; + + if (kc->c->null) + has_nils = 1; + } + e = exp_alias(sa, atname, iname, tname, iname, t, CARD_MULTI, has_nils, 1); /* index names are prefixed, to make them independent */ if (hash_index(i->type)) { p = e->p = prop_create(sa, PROP_HASHIDX, e->p); diff --git a/sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-query.stable.out b/sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-query.stable.out --- a/sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-query.stable.out +++ b/sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-query.stable.out @@ -50,24 +50,24 @@ project ( % .plan # table_name % rel # name % clob # type -% 124 # length +% 115 # length project ( | left outer join ( -| | table("sys"."fk") [ "fk"."id" NOT NULL HASHCOL , "fk"."%fk_fk1_fkey" NOT NULL JOINIDX "sys"."fk"."fk_fk1_fkey" ] COUNT , +| | table("sys"."fk") [ "fk"."id" NOT NULL HASHCOL , "fk"."%fk_fk1_fkey" JOINIDX "sys"."fk"."fk_fk1_fkey" ] COUNT , | | table("sys"."pk1") [ "pk1"."v1", "pk1"."%TID%" NOT NULL ] COUNT -| ) [ "fk"."%fk_fk1_fkey" NOT NULL = "pk1"."%TID%" NOT NULL JOINIDX "sys"."fk"."fk_fk1_fkey" ] +| ) [ "fk"."%fk_fk1_fkey" = "pk1"."%TID%" NOT NULL JOINIDX "sys"."fk"."fk_fk1_fkey" ] ) [ "fk"."id" NOT NULL HASHCOL , "pk1"."v1" ] [ "fk"."id" ASC NOT NULL HASHCOL ] #plan select id , v2 from fk left outer join pk2 on fk.fk2 = pk2.pk2 order by id; % .plan # table_name % rel # name % clob # type -% 124 # length +% 115 # length project ( | left outer join ( -| | table("sys"."fk") [ "fk"."id" NOT NULL HASHCOL , "fk"."%fk_fk2_fkey" NOT NULL JOINIDX "sys"."fk"."fk_fk2_fkey" ] COUNT , +| | table("sys"."fk") [ "fk"."id" NOT NULL HASHCOL , "fk"."%fk_fk2_fkey" JOINIDX "sys"."fk"."fk_fk2_fkey" ] COUNT , | | table("sys"."pk2") [ "pk2"."v2", "pk2"."%TID%" NOT NULL ] COUNT -| ) [ "fk"."%fk_fk2_fkey" NOT NULL = "pk2"."%TID%" NOT NULL JOINIDX "sys"."fk"."fk_fk2_fkey" ] +| ) [ "fk"."%fk_fk2_fkey" = "pk2"."%TID%" NOT NULL JOINIDX "sys"."fk"."fk_fk2_fkey" ] ) [ "fk"."id" NOT NULL HASHCOL , "pk2"."v2" ] [ "fk"."id" ASC NOT NULL HASHCOL ] #plan select count(*) from pk1 right outer join fk on fk.fk1 = pk1.pk1; % .plan # table_name @@ -91,23 +91,23 @@ project ( % .plan # table_name % rel # name % clob # type -% 123 # length +% 114 # length project ( | right outer join ( | | table("sys"."pk1") [ "pk1"."v1", "pk1"."%TID%" NOT NULL ] COUNT , -| | table("sys"."fk") [ "fk"."id" NOT NULL HASHCOL , "fk"."%fk_fk1_fkey" NOT NULL JOINIDX "sys"."fk"."fk_fk1_fkey" ] COUNT -| ) [ "fk"."%fk_fk1_fkey" NOT NULL = "pk1"."%TID%" NOT NULL JOINIDX "sys"."fk"."fk_fk1_fkey" ] +| | table("sys"."fk") [ "fk"."id" NOT NULL HASHCOL , "fk"."%fk_fk1_fkey" JOINIDX "sys"."fk"."fk_fk1_fkey" ] COUNT +| ) [ "fk"."%fk_fk1_fkey" = "pk1"."%TID%" NOT NULL JOINIDX "sys"."fk"."fk_fk1_fkey" ] ) [ "fk"."id" NOT NULL HASHCOL , "pk1"."v1" ] [ "fk"."id" ASC NOT NULL HASHCOL ] #plan select id , v2 from pk2 right outer join fk on fk.fk2 = pk2.pk2 order by id; % .plan # table_name % rel # name % clob # type -% 123 # length +% 114 # length project ( | right outer join ( | | table("sys"."pk2") [ "pk2"."v2", "pk2"."%TID%" NOT NULL ] COUNT , -| | table("sys"."fk") [ "fk"."id" NOT NULL HASHCOL , "fk"."%fk_fk2_fkey" NOT NULL JOINIDX "sys"."fk"."fk_fk2_fkey" ] COUNT -| ) [ "fk"."%fk_fk2_fkey" NOT NULL = "pk2"."%TID%" NOT NULL JOINIDX "sys"."fk"."fk_fk2_fkey" ] _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list