Changeset: ec9490cf4345 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=ec9490cf4345
Modified Files:
gdk/gdk_logger.c
sql/backends/monet5/sql_cat.c
sql/backends/monet5/sql_statistics.c
sql/backends/monet5/sql_statistics.h
sql/server/rel_optimizer.c
sql/server/rel_optimizer.h
sql/storage/store.c
sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.sql
sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.stable.err
sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.sql
sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.stable.err
sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.stable.out
Branch: default
Log Message:
Merge with Apr2019 branch.
diffs (truncated from 319 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
@@ -3075,8 +3075,11 @@ logger_find_bat(logger *lg, const char *
if (BAThash(lg->catalog_nme) == GDK_SUCCEED) {
HASHloop_str(cni, cni.b->thash, p, name) {
oid pos = p;
- if (BUNfnd(lg->dcatalog, &pos) == BUN_NONE)
- return *(log_bid *)
Tloc(lg->catalog_bid, p);
+ if (BUNfnd(lg->dcatalog, &pos) == BUN_NONE) {
+ oid lid = *(oid*) Tloc(lg->catalog_oid,
p);
+ if (!lid)
+ return *(log_bid *)
Tloc(lg->catalog_bid, p);
+ }
}
}
} else {
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
@@ -19,6 +19,7 @@
#include "sql_mvc.h"
#include "sql_qc.h"
#include "sql_partition.h"
+#include "sql_statistics.h"
#include "mal_namespace.h"
#include "opt_prelude.h"
#include "querylog.h"
@@ -386,7 +387,7 @@ alter_table_del_table(mvc *sql, char *ms
}
static char *
-alter_table_set_access(mvc *sql, char *sname, char *tname, int access)
+alter_table_set_access(Client cntxt, mvc *sql, char *sname, char *tname, int
access)
{
sql_schema *s = mvc_bind_schema(sql, sname);
sql_table *t = NULL;
@@ -401,6 +402,8 @@ alter_table_set_access(mvc *sql, char *s
throw(SQL,"sql.alter_table_set_access",SQLSTATE(40000) "ALTER TABLE: set READ
or INSERT ONLY not possible with outstanding updates (wait until updates are
flushed)\n");
mvc_access(sql, t, access);
+ if (access == 0)
+ sql_drop_statistics(cntxt, t);
}
} else {
throw(SQL,"sql.alter_table_set_access",SQLSTATE(42S02) "ALTER
TABLE: no such table '%s' in schema '%s'", tname, sname);
@@ -1504,7 +1507,7 @@ SQLalter_set_table(Client cntxt, MalBlkP
int access = *getArgReference_int(stk, pci, 3);
initcontext();
- msg = alter_table_set_access(sql, sname, tname, access);
+ msg = alter_table_set_access(cntxt, sql, sname, tname, access);
return msg;
}
diff --git a/sql/backends/monet5/sql_statistics.c
b/sql/backends/monet5/sql_statistics.c
--- a/sql/backends/monet5/sql_statistics.c
+++ b/sql/backends/monet5/sql_statistics.c
@@ -55,6 +55,30 @@ strToStrSQuote(char **dst, size_t *len,
}
str
+sql_drop_statistics(Client cntxt, sql_table *t)
+{
+ node *ncol;
+ char *dquery, *msg = NULL;
+
+ dquery = (char *) GDKzalloc(96);
+ if (dquery == NULL) {
+ throw(SQL, "analyze", SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ }
+ if (isTable(t) && t->columns.set) {
+ for (ncol = (t)->columns.set->h; ncol; ncol = ncol->next) {
+ sql_column *c = ncol->data;
+
+ snprintf(dquery, 96, "delete from sys.statistics where
\"column_id\" = %d;", c->base.id);
+ msg = SQLstatementIntern(cntxt, &dquery, "SQLanalyze",
TRUE, FALSE, NULL);
+ if (msg)
+ break;
+ }
+ }
+ GDKfree(dquery);
+ return msg;
+}
+
+str
sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
mvc *m = NULL;
diff --git a/sql/backends/monet5/sql_statistics.h
b/sql/backends/monet5/sql_statistics.h
--- a/sql/backends/monet5/sql_statistics.h
+++ b/sql/backends/monet5/sql_statistics.h
@@ -25,5 +25,6 @@
#endif
sql5_export str sql_analyze(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
+sql5_export str sql_drop_statistics(Client cntxt, sql_table *t);
#endif /* _SQL_STATISTICS_DEF */
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
@@ -51,7 +51,7 @@ static sql_subfunc *find_func( mvc *sql,
/* currently we only find simple column expressions */
void *
-name_find_column( sql_rel *rel, char *rname, char *name, int pnr, sql_rel **bt
)
+name_find_column( sql_rel *rel, const char *rname, const char *name, int pnr,
sql_rel **bt )
{
sql_exp *alias = NULL;
sql_column *c = NULL;
@@ -8455,6 +8455,103 @@ rel_merge_table_rewrite(int *changes, mv
return rel;
}
+static sql_rel*
+exp_skip_output_parts(sql_rel *rel)
+{
+ while ((is_topn(rel->op) || is_project(rel->op) || is_sample(rel->op))
&& rel->l) {
+ if (rel->op == op_groupby && list_empty(rel->r))
+ return rel; /* a group-by with no
columns is a plain aggregate and hence always returns one row */
+ rel = rel->l;
+ }
+ return rel;
+}
+
+/* return true if the given expression is guaranteed to have no rows */
+static int
+exp_is_zero_rows(mvc *sql, sql_rel *rel, sql_rel *sel)
+{
+ sql_table *t;
+ node *n;
+
+ if (!rel)
+ return 0;
+ rel = exp_skip_output_parts(rel);
+ if (is_select(rel->op) && rel->l) {
+ sel = rel;
+ rel = exp_skip_output_parts(rel->l);
+ }
+ if (!sel)
+ return 0;
+ if (rel->op == op_join)
+ return exp_is_zero_rows(sql, rel->l, sel) ||
exp_is_zero_rows(sql, rel->r, sel);
+ if (rel->op == op_left || is_semi(rel->op))
+ return exp_is_zero_rows(sql, rel->l, sel);
+ if (rel->op == op_right)
+ return exp_is_zero_rows(sql, rel->r, sel);
+ if (!is_basetable(rel->op) || !rel->l)
+ return 0;
+ t = rel->l;
+ if (!isTable(t) || t->access != TABLE_READONLY)
+ return 0;
+
+ if (sel->exps) for (n = sel->exps->h; n; n = n->next) {
+ sql_exp *e = n->data;
+ atom *lval = NULL, *hval = NULL;
+
+ if (e->type == e_cmp && (e->flag == cmp_equal || e->f)) { /*
half-ranges are theoretically optimizable here, but not implemented */
+ sql_exp *c = e->l;
+ if (c->type == e_column) {
+ sql_exp *l = e->r;
+ sql_exp *h = e->f;
+
+ lval = exp_flatten(sql, l);
+ hval = h ? exp_flatten(sql, h) : lval;
+ if (lval && hval) {
+ sql_rel *bt;
+ sql_column *col = name_find_column(sel,
c->rname, c->name, -2, &bt);
+ void *min, *max;
+ if (col
+ && col->t == t
+ &&
sql_trans_ranges(sql->session->tr, col, &min, &max)
+ && !exp_range_overlap(sql, c,
min, max, lval, hval)) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* discard sides of UNION or UNION ALL which cannot produce any rows, as per
+statistics, similarly to the merge table optimizer, e.g.
+ select * from a where x between 1 and 2 union all select * from b where
x between 1 and 2
+-> select * from b where x between 1 and 2 [assuming a has no rows with
1<=x<=2]
+*/
+static sql_rel *
+rel_remove_union_partitions(int *changes, mvc *sql, sql_rel *rel)
+{
+ if (!is_union(rel->op))
+ return rel;
+ if (exp_is_zero_rows(sql, rel->l, NULL)) {
+ sql_rel *r = rel->r;
+ rel->r = NULL;
+ rel_destroy(rel);
+ (*changes)++;
+ sql->caching = 0;
+ return r;
+ }
+ if (exp_is_zero_rows(sql, rel->r, NULL)) {
+ sql_rel *l = rel->l;
+ rel->l = NULL;
+ rel_destroy(rel);
+ (*changes)++;
+ sql->caching = 0;
+ return l;
+ }
+ return rel;
+}
+
/* TODO move all apply related stuff in to rel_apply.c/h */
static int exps_uses_exps(list *users, list *exps);
@@ -9552,6 +9649,9 @@ optimize_rel(mvc *sql, sql_rel *rel, int
if (gp.cnt[op_select])
rel = rewrite_topdown(sql, rel, &rel_push_select_down_union,
&changes);
+ if (gp.cnt[op_union] && gp.cnt[op_select])
+ rel = rewrite(sql, rel, &rel_remove_union_partitions,
&changes);
+
if (gp.cnt[op_groupby]) {
rel = rewrite_topdown(sql, rel, &rel_push_aggr_down, &changes);
rel = rewrite_topdown(sql, rel, &rel_push_groupby_down,
&changes);
diff --git a/sql/server/rel_optimizer.h b/sql/server/rel_optimizer.h
--- a/sql/server/rel_optimizer.h
+++ b/sql/server/rel_optimizer.h
@@ -16,7 +16,7 @@ extern sql_rel * rel_optimizer(mvc *sql,
extern int exp_joins_rels(sql_exp *e, list *rels);
-extern void *name_find_column( sql_rel *rel, char *rname, char *name, int pnr,
sql_rel **bt );
+extern void *name_find_column( sql_rel *rel, const char *rname, const char
*name, int pnr, sql_rel **bt );
extern sql_rel * rel_dce(mvc *sql, sql_rel *rel);
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -2741,7 +2741,7 @@ sql_trans_copy_column( sql_trans *tr, sq
sql_table *syscolumn = find_sql_table(syss, "_columns");
sql_column *col = SA_ZNEW(tr->sa, sql_column);
- if (sql_trans_name_conflict(tr, t->s->base.name, t->base.name,
c->base.name))
+ if (t->system && sql_trans_name_conflict(tr, t->s->base.name,
t->base.name, c->base.name))
return NULL;
base_init(tr->sa, &col->base, c->base.id, TR_NEW, c->base.name);
col->type = c->type;
@@ -5477,7 +5477,7 @@ sql_trans_create_column(sql_trans *tr, s
if (!tpe)
return NULL;
- if (sql_trans_name_conflict(tr, t->s->base.name, t->base.name, name))
+ if (t->system && sql_trans_name_conflict(tr, t->s->base.name,
t->base.name, name))
return NULL;
col = create_sql_column(tr->sa, t, name, tpe);
diff --git a/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.sql
b/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.sql
--- a/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.sql
+++ b/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.sql
@@ -3,3 +3,4 @@ create table foo_bar (id integer);
insert into foo (id, bar_id) values (1,2), (3,4);
select * from foo;
drop table foo;
+drop table foo_bar;
diff --git a/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.stable.err
b/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.stable.err
--- a/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.stable.err
+++ b/sql/test/BugTracker-2015/Tests/name_conflict.Bug-3650.stable.err
@@ -30,10 +30,6 @@ stderr of test 'name_conflict.Bug-3650`
# 18:58:39 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-24602" "--port=35483"
# 18:58:39 >
-MAPI = (monetdb) /var/tmp/mtest-32037/.s.monetdb.32270
-QUERY = create table foo_bar (id integer);
-ERROR = !CREATE TABLE: sys_foo_bar_id conflicts
-CODE = 42000
# 18:58:39 >
# 18:58:39 > "Done."
diff --git a/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.sql
b/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.sql
--- a/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.sql
+++ b/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.sql
@@ -4,3 +4,4 @@ insert into foo values (1);
insert into foo_bar values (2);
select * from foo_bar;
drop table foo_bar;
+drop table foo;
diff --git
a/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.stable.err
b/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.stable.err
--- a/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.stable.err
+++ b/sql/test/BugTracker-2016/Tests/column_name_conflict.Bug-3912.stable.err
@@ -30,14 +30,6 @@ stderr of test 'column_name_conflict.Bug
# 08:21:28 > "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e"
"--host=/var/tmp/mtest-32403" "--port=38022"
# 08:21:28 >
-MAPI = (monetdb) /var/tmp/mtest-32403/.s.monetdb.38022
-QUERY = create table foo (bar_baz int);
-ERROR = !CREATE TABLE: sys_foo_bar_baz conflicts
-CODE = 42000
-MAPI = (monetdb) /var/tmp/mtest-30274/.s.monetdb.37685
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list