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

Reply via email to