Changeset: 11dd03482987 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/11dd03482987
Modified Files:
        sql/server/rel_optimizer.c
        tools/monetdbe/monetdbe.c
Branch: scatter
Log Message:

merged with default


diffs (truncated from 1368 to 300 lines):

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
@@ -5321,15 +5321,16 @@ find_projection_for_join2semi(sql_rel *r
                                sql_exp *found = NULL;
                                bool underjoin = false;
 
-                               /* if just one groupby column is projected, it 
will be distinct */
-                               if ((is_groupby(rel->op) && list_length(rel->r) 
== 1 && exps_find_exp(rel->r, e)) || need_distinct(rel) || find_prop(e->p, 
PROP_HASHCOL))
+                               /* if just one groupby column is projected or 
the relation needs distinct values and one column is projected or is a primary 
key, it will be distinct */
+                               if ((is_groupby(rel->op) && list_length(rel->r) 
== 1 && exps_find_exp(rel->r, e)) ||
+                                       (is_simple_project(rel->op) && 
need_distinct(rel) && list_length(rel->exps) == 1) || find_prop(e->p, 
PROP_HASHCOL))
                                        return true;
 
                                if ((found = 
rel_find_exp_and_corresponding_rel(rel->l, e, &res, &underjoin)) && !underjoin) 
{ /* grouping column on inner relation */
-                                       if (find_prop(found->p, PROP_HASHCOL)) 
/* primary key always unique */
+                                       if ((is_simple_project(res->op) && 
need_distinct(res) && list_length(res->exps) == 1) || find_prop(found->p, 
PROP_HASHCOL))
                                                return true;
                                        if (found->type == e_column && 
found->card <= CARD_AGGR) {
-                                               if (!(is_groupby(res->op) || 
need_distinct(res)) && list_length(res->exps) != 1)
+                                               if (!is_groupby(res->op) && 
list_length(res->exps) != 1)
                                                        return false;
                                                for (node *n = res->exps->h ; n 
; n = n->next) { /* must be the single column in the group by expression list */
                                                        sql_exp *e = n->data;
@@ -8859,9 +8860,9 @@ exp_range_overlap(atom *min, atom *max, 
 }
 
 static sql_rel *
-rel_rename_part(mvc *sql, sql_rel *p, sql_rel *rel, char *tname, sql_table *mt)
-{
-       sql_table *t = rel_base_table(p);
+rel_rename_part(mvc *sql, sql_rel *p, sql_rel *mt_rel, const char *mtalias)
+{
+       sql_table *mt = rel_base_table(mt_rel), *t = rel_base_table(p);
        node *n;
 
        assert(!p->exps);
@@ -8869,47 +8870,20 @@ rel_rename_part(mvc *sql, sql_rel *p, sq
        const char *pname = t->base.name;
        if (isRemote(t))
                pname = mapiuri_table(t->query, sql->sa, pname);
-       for (n = rel->exps->h; n; n = n->next) {
+       for (n = mt_rel->exps->h; n; n = n->next) {
                sql_exp *e = n->data;
                if (is_intern(e) || exp_name(e)[0] == '%') /* break on tid/idxs 
*/
                        break;
                sql_column *c = ol_find_name(mt->columns, exp_name(e))->data;
                sql_column *rc = ol_fetch(t->columns, c->colnr);
                /* with name find column in merge table, with colnr find column 
in member */
-               e = exp_alias(sql->sa, tname, c->base.name, pname, 
rc->base.name, &rc->type, CARD_MULTI, rc->null, 0);
-               append(p->exps, e);
+               list_append(p->exps, exp_alias(sql->sa, mtalias, c->base.name, 
pname, rc->base.name, &rc->type, CARD_MULTI, rc->null, 0));
        }
        if (n) {
                sql_exp *e = n->data;
-               if (strcmp(exp_name(e), TID) == 0) {
-                       e = exp_alias(sql->sa, tname, TID, pname, TID, 
sql_bind_localtype("oid"), CARD_MULTI, 0, 1);
-                       append(p->exps, e);
-               }
-       }
-#if 0
-       node *n, *m;
-       for( m = ol_first_node(mt->columns); m; m = m->next) {
-               sql_column *c = m->data;
-               append(p->exps, exp_alias(sql->sa, tname, c->base.name, pname, 
c->base.name, &c->type, CARD_MULTI, c->null, 0));
-       }
-       if (n) /* skip TID */
-               n = n->next;
-       if (mt->idxs) {
-               /* also possible index name mismatches */
-               for( m = ol_first_node(mt->idxs); n && m; m = m->next) {
-                       sql_exp *ne = n->data;
-                       sql_idx *i = m->data;
-                       char *iname = NULL;
-
-                       if ((hash_index(i->type) && list_length(i->columns) <= 
1) || !idx_has_column(i->type))
-                               continue;
-
-                       iname = sa_strconcat( sql->sa, "%", i->base.name);
-                       exp_setname(sql->sa, ne, tname, iname);
-                       n = n->next;
-               }
-       }
-#endif
+               if (strcmp(exp_name(e), TID) == 0)
+                       list_append(p->exps, exp_alias(sql->sa, mtalias, TID, 
pname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1));
+       }
        rel_base_set_mergetable(p, mt);
        return p;
 }
@@ -8923,417 +8897,420 @@ typedef struct {
        list *values;
 } range_limit;
 
-/* rewrite merge tables into union of base tables and call optimizer again */
+typedef struct {
+       list *cols;
+       list *ranges;
+       sql_rel *sel;
+} merge_table_prune_info;
+
+static sql_rel *
+merge_table_prune_and_unionize(visitor *v, sql_rel *mt_rel, 
merge_table_prune_info *info)
+{
+       sql_rel *nrel = NULL;
+       sql_table *mt = (sql_table*) mt_rel->l;
+       const char *mtalias = exp_relname(mt_rel->exps->h->data);
+       list *tables = sa_list(v->sql->sa);
+
+       if (mvc_highwater(v->sql))
+               return sql_error(v->sql, 10, SQLSTATE(42000) "Query too 
complex: running out of stack space");
+
+       for (node *nt = mt->members->h; nt; nt = nt->next) {
+               sql_part *pd = nt->data;
+               sql_table *pt = find_sql_table_id(v->sql->session->tr, mt->s, 
pd->member);
+               sqlstore *store = v->sql->session->tr->store;
+               int skip = 0, allowed = 1;
+
+               /* At the moment we throw an error in the optimizer, but later 
this rewriter should move out from the optimizers */
+               if ((isMergeTable(pt) || isReplicaTable(pt)) && 
list_empty(pt->members))
+                       return sql_error(v->sql, 02, SQLSTATE(42000) "The %s 
'%s.%s' should have at least one table associated",
+                                                        
TABLE_TYPE_DESCRIPTION(pt->type, pt->properties), pt->s->base.name, 
pt->base.name);
+               /* Do not include empty partitions */
+               if (isTable(pt) && pt->access == TABLE_READONLY && 
!store->storage_api.count_col(v->sql->session->tr, 
ol_first_node(pt->columns)->data, 0))
+                       continue;
+
+               if (!table_privs(v->sql, pt, PRIV_SELECT)) /* Test for 
privileges */
+                       allowed = 0;
+
+               for (node *n = mt_rel->exps->h; n && !skip; n = n->next) { /* 
for each column of the child table */
+                       sql_exp *e = n->data;
+                       int i = 0;
+                       bool first_attempt = true;
+                       atom *cmin = NULL, *cmax = NULL, *rmin = NULL, *rmax = 
NULL;
+                       list *inlist = NULL;
+                       const char *cname = e->r;
+                       sql_column *mt_col = NULL, *col = NULL;
+
+                       if (cname[0] == '%') /* Ignore TID and indexes here */
+                               continue;
+
+                       mt_col = ol_find_name(mt->columns, exp_name(e))->data;
+                       col = ol_fetch(pt->columns, mt_col->colnr);
+                       assert(e && e->type == e_column && col);
+                       if (!allowed && !column_privs(v->sql, col, PRIV_SELECT))
+                               return sql_error(v->sql, 02, SQLSTATE(42000) 
"The user %s SELECT permissions on table '%s.%s' don't match %s '%s.%s'", 
get_string_global_var(v->sql, "current_user"),
+                                                                
pt->s->base.name, pt->base.name, TABLE_TYPE_DESCRIPTION(mt->type, 
mt->properties), mt->s->base.name, mt->base.name);
+                       if (isTable(pt) && info && !list_empty(info->cols) && 
ATOMlinear(exp_subtype(e)->type->localtype)) {
+                               for (node *nn = info->cols->h ; nn && !skip; nn 
= nn->next) { /* test if it passes all predicates around it */
+                                       if (nn->data == e) {
+                                               range_limit *next = 
list_fetch(info->ranges, i);
+                                               atom *lval = next->lval, *hval 
= next->hval;
+                                               list *values = next->values;
+
+                                               /* I don't handle cmp_in or 
cmp_notin cases with anti or null semantics yet */
+                                               if (next->flag == cmp_in && 
(next->anti || next->semantics))
+                                                       continue;
+
+                                               assert(col && (lval || values));
+                                               if (!skip && pt->access == 
TABLE_READONLY) {
+                                                       /* check if the part 
falls within the bounds of the select expression else skip this (keep at least 
on part-table) */
+                                                       if (!cmin && !cmax && 
first_attempt) {
+                                                               char *min = 
NULL, *max = NULL;
+                                                               (void) 
sql_trans_ranges(v->sql->session->tr, col, &min, &max);
+                                                               if (min && max) 
{
+                                                                       cmin = 
atom_general(v->sql->sa, &col->type, min);
+                                                                       cmax = 
atom_general(v->sql->sa, &col->type, max);
+                                                               }
+                                                               first_attempt = 
false; /* no more attempts to read from storage */
+                                                       }
+
+                                                       if (cmin && cmax) {
+                                                               if (lval) {
+                                                                       if 
(!next->semantics && ((lval && lval->isnull) || (hval && hval->isnull))) {
+                                                                               
skip = 1; /* NULL values don't match, skip them */
+                                                                       } else 
if (!next->semantics) {
+                                                                               
if (next->flag == cmp_equal) {
+                                                                               
        skip |= next->anti ? exp_range_overlap(cmin, cmax, lval, hval, false, 
false) != 0 :
+                                                                               
                                                        exp_range_overlap(cmin, 
cmax, lval, hval, false, false) == 0;
+                                                                               
} else if (hval != lval) { /* range case */
+                                                                               
        comp_type lower = range2lcompare(next->flag), higher = 
range2rcompare(next->flag);
+                                                                               
        skip |= next->anti ? exp_range_overlap(cmin, cmax, lval, hval, higher 
== cmp_lt, lower == cmp_gt) != 0 :
+                                                                               
                                                        exp_range_overlap(cmin, 
cmax, lval, hval, higher == cmp_lt, lower == cmp_gt) == 0;
+                                                                               
} else {
+                                                                               
        switch (next->flag) {
+                                                                               
                case cmp_gt:
+                                                                               
                        skip |= next->anti ? VALcmp(&(lval->data), 
&(cmax->data)) < 0 : VALcmp(&(lval->data), &(cmax->data)) >= 0;
+                                                                               
                        break;
+                                                                               
                case cmp_gte:
+                                                                               
                        skip |= next->anti ? VALcmp(&(lval->data), 
&(cmax->data)) <= 0 : VALcmp(&(lval->data), &(cmax->data)) > 0;
+                                                                               
                        break;
+                                                                               
                case cmp_lt:
+                                                                               
                        skip |= next->anti ? VALcmp(&(lval->data), 
&(cmax->data)) < 0 : VALcmp(&(cmin->data), &(lval->data)) >= 0;
+                                                                               
                        break;
+                                                                               
                case cmp_lte:
+                                                                               
                        skip |= next->anti ? VALcmp(&(lval->data), 
&(cmax->data)) <= 0 : VALcmp(&(cmin->data), &(lval->data)) > 0;
+                                                                               
                        break;
+                                                                               
                default:
+                                                                               
                        break;
+                                                                               
        }
+                                                                               
}
+                                                                       }
+                                                               } else if 
(next->flag == cmp_in) {
+                                                                       int 
nskip = 1;
+                                                                       for 
(node *m = values->h; m && nskip; m = m->next) {
+                                                                               
atom *a = m->data;
+
+                                                                               
if (a->isnull)
+                                                                               
        continue;
+                                                                               
nskip &= exp_range_overlap(cmin, cmax, a, a, false, false) == 0;
+                                                                       }
+                                                                       skip |= 
nskip;
+                                                               }
+                                                       }
+                                               }
+                                               if (!skip && 
isPartitionedByColumnTable(mt) && strcmp(mt->part.pcol->base.name, 
col->base.name) == 0) {
+                                                       if (!next->semantics && 
((lval && lval->isnull) || (hval && hval->isnull))) {
+                                                               skip = 1; /* 
NULL values don't match, skip them */
+                                                       } else if 
(next->semantics) {
+                                                               /* TODO NOT 
NULL prunning for partitions that just hold NULL values is still missing */
+                                                               skip |= 
next->flag == cmp_equal && !next->anti && lval && lval->isnull ? pd->with_nills 
== 0 : 0; /* *= NULL case */
+                                                       } else {
+                                                               if 
(isRangePartitionTable(mt)) {
+                                                                       if 
(!rmin || !rmax) { /* initialize lazily */
+                                                                               
rmin = atom_general_ptr(v->sql->sa, &col->type, pd->part.range.minvalue);
+                                                                               
rmax = atom_general_ptr(v->sql->sa, &col->type, pd->part.range.maxvalue);
+                                                                       }
+
+                                                                       /* 
Prune range partitioned tables */
+                                                                       if 
(rmin->isnull && rmax->isnull) {
+                                                                               
if (pd->with_nills == 1) /* the partition just holds null values, skip it */
+                                                                               
        skip = 1;
+                                                                               
/* otherwise it holds all values in the range, cannot be pruned */
+                                                                       } else 
if (rmin->isnull) { /* MINVALUE to limit */
+                                                                               
if (lval) {
+                                                                               
        if (hval != lval) { /* range case */
+                                                                               
                /* There's need to call range2lcompare, because the partition's 
upper limit is always exclusive */
+                                                                               
                skip |= next->anti ? VALcmp(&(lval->data), &(rmax->data)) < 0 : 
VALcmp(&(lval->data), &(rmax->data)) >= 0;
+                                                                               
        } else {
+                                                                               
                switch (next->flag) { /* upper limit always exclusive */
+                                                                               
                        case cmp_equal:
+                                                                               
                        case cmp_gt:
+                                                                               
                        case cmp_gte:
+                                                                               
                                skip |= next->anti ? VALcmp(&(lval->data), 
&(rmax->data)) < 0 : VALcmp(&(lval->data), &(rmax->data)) >= 0;
+                                                                               
                                break;
+                                                                               
                        default:
+                                                                               
                                break;
+                                                                               
                }
+                                                                               
        }
+                                                                               
} else if (next->flag == cmp_in) {
+                                                                               
        int nskip = 1;
+                                                                               
        for (node *m = values->h; m && nskip; m = m->next) {
+                                                                               
                atom *a = m->data;
+
+                                                                               
                if (a->isnull)
+                                                                               
                        continue;
+                                                                               
                nskip &= VALcmp(&(a->data), &(rmax->data)) >= 0;
+                                                                               
        }
+                                                                               
        skip |= nskip;
+                                                                               
}
+                                                                       } else 
if (rmax->isnull) { /* limit to MAXVALUE */
+                                                                               
if (lval) {
+                                                                               
        if (hval != lval) { /* range case */
+                                                                               
                comp_type higher = range2rcompare(next->flag);
+                                                                               
                if (higher == cmp_lt) {
+                                                                               
                        skip |= next->anti ? VALcmp(&(rmin->data), 
&(hval->data)) < 0 : VALcmp(&(rmin->data), &(hval->data)) >= 0;
+                                                                               
                } else if (higher == cmp_lte) {
+                                                                               
                        skip |= next->anti ? VALcmp(&(rmin->data), 
&(hval->data)) <= 0 : VALcmp(&(rmin->data), &(hval->data)) > 0;
+                                                                               
                } else {
+                                                                               
                        assert(0);
+                                                                               
                }
+                                                                               
        } else {
+                                                                               
                switch (next->flag) {
+                                                                               
                        case cmp_lt:
+                                                                               
                                skip |= next->anti ? VALcmp(&(rmin->data), 
&(hval->data)) < 0 : VALcmp(&(rmin->data), &(hval->data)) >= 0;
+                                                                               
                                break;
+                                                                               
                        case cmp_equal:
+                                                                               
                        case cmp_lte:
+                                                                               
                                skip |= next->anti ? VALcmp(&(rmin->data), 
&(hval->data)) <= 0 : VALcmp(&(rmin->data), &(hval->data)) > 0;
+                                                                               
                                break;
+                                                                               
                        default:
+                                                                               
                                break;
+                                                                               
                }
+                                                                               
        }
+                                                                               
} else if (next->flag == cmp_in) {
+                                                                               
        int nskip = 1;
+                                                                               
        for (node *m = values->h; m && nskip; m = m->next) {
+                                                                               
                atom *a = m->data;
+
+                                                                               
                if (a->isnull)
+                                                                               
                        continue;
+                                                                               
                nskip &= VALcmp(&(rmin->data), &(a->data)) > 0;
+                                                                               
        }
+                                                                               
        skip |= nskip;
+                                                                               
}
+                                                                       } else 
{ /* limit1 to limit2 (general case), limit2 is exclusive */
+                                                                               
bool max_differ_min = ATOMcmp(col->type.type->localtype, &rmin->data.val, 
&rmax->data.val) != 0;
+
+                                                                               
if (lval) {
+                                                                               
        if (next->flag == cmp_equal) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to