Changeset: 3af76395e12f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3af76395e12f
Added Files:
        sql/test/SQLancer/Tests/sqlancer02.sql
        sql/test/SQLancer/Tests/sqlancer02.stable.err
        sql/test/SQLancer/Tests/sqlancer02.stable.out
Modified Files:
        monetdb5/optimizer/opt_emptybind.c
        sql/backends/monet5/rel_bin.c
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_select.c
        sql/storage/bat/bat_storage.c
        sql/storage/bat/bat_storage.h
        sql/test/SQLancer/Tests/All
        sql/test/SQLancer/Tests/sqlancer01.stable.out
        sql/test/subquery/Tests/subquery6.sql
Branch: unlock
Log Message:

merged 43197e85a61b


diffs (truncated from 1345 to 300 lines):

diff --git a/monetdb5/optimizer/opt_emptybind.c 
b/monetdb5/optimizer/opt_emptybind.c
--- a/monetdb5/optimizer/opt_emptybind.c
+++ b/monetdb5/optimizer/opt_emptybind.c
@@ -55,11 +55,11 @@ OPTemptybindImplementation(Client cntxt,
        //if ( optimizerIsApplied(mb,"emptybind") )
                //return 0;
        // use an instruction reference table to keep
-       
+
        for( i=0; i< mb->stop; i++)
                if( getFunctionId(getInstrPtr(mb,i)) == emptybindRef || 
getFunctionId(getInstrPtr(mb,i)) == emptybindidxRef)
                        extras += getInstrPtr(mb,i)->argc;
-       if( extras == 0)
+       if (extras == 0)
                goto wrapup;
 
        // track of where 'emptybind' results are produced
@@ -74,7 +74,7 @@ OPTemptybindImplementation(Client cntxt,
                return 0;
        }
 
-       if ( newMalBlkStmt(mb, mb->ssize) < 0) {
+       if (newMalBlkStmt(mb, mb->ssize) < 0) {
                GDKfree(empty);
                GDKfree(updated);
                throw(MAL,"optimizer.emptybind", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
@@ -95,12 +95,12 @@ OPTemptybindImplementation(Client cntxt,
 
                /*
                 * The bulk of the intelligence lies in inspecting calling
-                * sequences to filter and replace results 
+                * sequences to filter and replace results
                 */
                if ( getModuleId(p) == batRef && getFunctionId(p) == newRef){
                        empty[getArg(p,0)] = i;
                        continue;
-               } 
+               }
 
                // any of these instructions leave a non-empty BAT behind
                if(p && getModuleId(p) == sqlRef && isUpdateInstruction(p)){
@@ -116,7 +116,7 @@ OPTemptybindImplementation(Client cntxt,
                        updated[etop++]= p;
                }
 
-               /* restore the naming, dropping the runtime property 'empty' 
+               /* restore the naming, dropping the runtime property 'empty'
                 * Keep the bind operation, because it is cheap, rather focus 
on their re-use
                 */
 
@@ -127,7 +127,7 @@ OPTemptybindImplementation(Client cntxt,
                        if( p->retc == 2){
                                empty[getArg(p,1)] = i;
                        }
-                       // replace the call into a empty bat creation unless 
the table was updated already in the same query 
+                       // replace the call into a empty bat creation unless 
the table was updated already in the same query
                        sch = getVarConstant(mb,getArg(p,2  + 
(p->retc==2))).val.sval;
                        tbl = getVarConstant(mb,getArg(p,3  + 
(p->retc==2))).val.sval;
                        for(j= 0; j< etop; j++){
@@ -159,7 +159,7 @@ OPTemptybindImplementation(Client cntxt,
                        setFunctionId(p,bindidxRef);
                        p->typechk= TYPE_UNKNOWN;
                        empty[getArg(p,0)] = i;
-                       // replace the call into a empty bat creation unless 
the table was updated already in the same query 
+                       // replace the call into a empty bat creation unless 
the table was updated already in the same query
                        sch = getVarConstant(mb,getArg(p,2  + 
(p->retc==2))).val.sval;
                        tbl = getVarConstant(mb,getArg(p,3  + 
(p->retc==2))).val.sval;
                        for(j= 0; j< etop; j++){
@@ -198,7 +198,7 @@ OPTemptybindImplementation(Client cntxt,
                }
 
                if (getModuleId(p)== sqlRef && getFunctionId(p) == 
projectdeltaRef) {
-                       if (empty[getArg(p,3)] && empty[getArg(p,4)]){
+                       if( empty[getArg(p,3)] && empty[getArg(p,4)] ){
                                actions++;
                                setModuleId(p,algebraRef);
                                setFunctionId(p,projectionRef);
@@ -230,17 +230,16 @@ OPTemptybindImplementation(Client cntxt,
                if (getModuleId(p)== batRef && isUpdateInstruction(p)){
                        if( empty[getArg(p,1)] && empty[getArg(p,2)]){
                                emptyresult(0);
-                       } else
-                       if( empty[getArg(p,2)]){
+                       } else if (empty[getArg(p,2)]){
                                actions++;
-                               clrFunction(p); 
+                               clrFunction(p);
                                p->argc = 2;
                        }
                }
        }
 
        for(; i<slimit; i++)
-               if( old[i])
+               if (old[i])
                        freeInstruction(old[i]);
        GDKfree(old);
        GDKfree(empty);
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
@@ -2181,6 +2181,89 @@ releqjoin( backend *be, list *l1, list *
        return res;
 }
 
+static void
+split_join_exps(sql_rel *rel, list *joinable, list *not_joinable)
+{
+       if (!list_empty(rel->exps)) {
+               for (node *n = rel->exps->h; n; n = n->next) {
+                       sql_exp *e = n->data;
+                       int left_reference = 0, right_reference = 0;
+
+                       /* we can handle thetajoins, rangejoins and filter 
joins (like) */
+                       /* ToDo how about mark_exists/not_exists and atom 
expressions? */
+                       if (e->type == e_cmp) {
+                               int flag = e->flag & ~CMP_BETWEEN;
+                               /* check if its a select or join expression, ie 
use only expressions of one relation left and of the other right (than join) */
+                               if (flag < cmp_filter || flag == mark_in || 
flag == mark_notin) { /* theta and range joins */
+                                       /* join or select ? */
+                                       sql_exp *l = e->l, *r = e->r, *f = e->f;
+
+                                       if (l->card != CARD_ATOM) {
+                                               left_reference += 
rel_find_exp(rel->l, l) != NULL;
+                                               right_reference += 
rel_find_exp(rel->r, l) != NULL;
+                                       }
+                                       if (r->card != CARD_ATOM) {
+                                               left_reference += 
rel_find_exp(rel->l, r) != NULL;
+                                               right_reference += 
rel_find_exp(rel->r, r) != NULL;
+                                       }
+                                       if (f && f->card != CARD_ATOM) {
+                                               left_reference += 
rel_find_exp(rel->l, f) != NULL;
+                                               right_reference += 
rel_find_exp(rel->r, f) != NULL;
+                                       }
+                               } else if (flag == cmp_filter) {
+                                       list *l = e->l, *r = e->r;
+
+                                       for (node *n = l->h ; n ; n = n->next) {
+                                               sql_exp *ee = n->data;
+
+                                               if (ee->card != CARD_ATOM) {
+                                                       left_reference += 
rel_find_exp(rel->l, ee) != NULL;
+                                                       right_reference += 
rel_find_exp(rel->r, ee) != NULL;
+                                               }
+                                       }
+                                       for (node *n = r->h ; n ; n = n->next) {
+                                               sql_exp *ee = n->data;
+
+                                               if (ee->card != CARD_ATOM) {
+                                                       left_reference += 
rel_find_exp(rel->l, ee) != NULL;
+                                                       right_reference += 
rel_find_exp(rel->r, ee) != NULL;
+                                               }
+                                       }
+                               }
+                       }
+                       if (left_reference && right_reference) {
+                               append(joinable, e);
+                       } else {
+                               append(not_joinable, e);
+                       }
+               }
+       }
+}
+
+#define is_priority_exp(e) ((e)->type == e_cmp && (e)->flag == cmp_equal)
+
+static list *
+get_equi_joins_first(mvc *sql, list *exps, int *equality_only)
+{
+       list *new_exps = sa_list(sql->sa);
+
+       for( node *n = exps->h; n; n = n->next ) {
+               sql_exp *e = n->data;
+               if (is_priority_exp(e)) {
+                       list_append(new_exps, e);
+                       *equality_only &= (e->flag == cmp_equal);
+               }
+       }
+       for( node *n = exps->h; n; n = n->next ) {
+               sql_exp *e = n->data;
+               if (!is_priority_exp(e)) {
+                       list_append(new_exps, e);
+                       *equality_only &= (e->flag == mark_in || e->flag == 
mark_notin);
+               }
+       }
+       return new_exps;
+}
+
 static stmt *
 rel2bin_join(backend *be, sql_rel *rel, list *refs)
 {
@@ -2207,129 +2290,75 @@ rel2bin_join(backend *be, sql_rel *rel, 
         *      second selects/filters 
         */
        if (!list_empty(rel->exps)) {
-               int used_hash = 0;
-               int idx = 0, i;
                list *jexps = sa_list(sql->sa);
-               list *lje = sa_list(sql->sa);
-               list *rje = sa_list(sql->sa);
-               list *exps = sa_list(sql->sa);
                sexps = sa_list(sql->sa);
 
-               /* stage one split join and select expressions (include complex 
expressions which physical layer cannot handle without a crossproduct first) */
-               if (!list_empty(rel->exps)) {
-                       for( en = rel->exps->h, i=0; en; en = en->next, i++) {
-                               sql_exp *e = en->data;
-                               int left_reference = 0, right_reference = 0;
-
-                               /* we can handle thetajoins, rangejoins and 
filter joins (like) */
-                               /* ToDo how about in/notin, mark_in/notin, 
mark_exists/not_exists and atom expressions? */
-                               if (e->type == e_cmp) {
-                                       int flag = e->flag & ~CMP_BETWEEN;
-                                       /* check if its a select or join 
expression, ie use only expressions of one relation left and of the other right 
(than join) */
-                                       if (flag < cmp_filter) { /* theta and 
range joins */
-                                               /* join or select ? */
-                                               sql_exp *l = e->l, *r = e->r, 
*f = e->f;
-
-                                               if (l->card != CARD_ATOM) {
-                                                       left_reference += 
rel_find_exp(rel->l, l) != NULL;
-                                                       right_reference += 
rel_find_exp(rel->r, l) != NULL;
-                                               }
-                                               if (r->card != CARD_ATOM) {
-                                                       left_reference += 
rel_find_exp(rel->l, r) != NULL;
-                                                       right_reference += 
rel_find_exp(rel->r, r) != NULL;
-                                               }
-                                               if (f && f->card != CARD_ATOM) {
-                                                       left_reference += 
rel_find_exp(rel->l, f) != NULL;
-                                                       right_reference += 
rel_find_exp(rel->r, f) != NULL;
-                                               }
-                                       } else if (flag == cmp_filter) {
-                                               list *l = e->l, *r = e->r;
-
-                                               for (node *n = l->h ; n ; n = 
n->next) {
-                                                       sql_exp *ee = n->data;
-
-                                                       if (ee->card != 
CARD_ATOM) {
-                                                               left_reference 
+= rel_find_exp(rel->l, ee) != NULL;
-                                                               right_reference 
+= rel_find_exp(rel->r, ee) != NULL;
-                                                       }
-                                               }
-                                               for (node *n = r->h ; n ; n = 
n->next) {
-                                                       sql_exp *ee = n->data;
-
-                                                       if (ee->card != 
CARD_ATOM) {
-                                                               left_reference 
+= rel_find_exp(rel->l, ee) != NULL;
-                                                               right_reference 
+= rel_find_exp(rel->r, ee) != NULL;
-                                                       }
-                                               }
-                                       }
-                               }
-                               if (left_reference && right_reference) {
-                                       append(jexps, e);
-                               } else {
-                                       append(sexps, e);
-                               }
-                       }
-               }
-
+               split_join_exps(rel, jexps, sexps);
                if (list_empty(jexps)) { /* cross product and continue after 
project */
                        stmt *l = bin_first_column(be, left);
                        stmt *r = bin_first_column(be, right);
                        join = stmt_join(be, l, r, 0, cmp_all, 0, false); 
                }
 
-               if (join)
+               if (join) {
                        en = rel->exps->h;
-               else
+               } else {
+                       list *lje = sa_list(sql->sa), *rje = sa_list(sql->sa), 
*exps = sa_list(sql->sa);
+                       int used_hash = 0, idx = 0, equality_only = 1;
+
+                       (void) equality_only;
+                       jexps = get_equi_joins_first(sql, jexps, 
&equality_only);
                        /* generate a relational join (releqjoin) which does a 
multi attribute (equi) join */
-               for( en = jexps->h; en; en = en->next ) {
-                       int join_idx = sql->opt_stats[0];
-                       sql_exp *e = en->data;
-                       stmt *s = NULL;
-                       prop *p;
-
-                       /* stop search for equi joins on first non equi */
-                       if (list_length(lje) && (idx || e->type != e_cmp || 
e->flag != cmp_equal))
-                               break;
-
-                       /* handle possible index lookups, expressions are in 
index order! */
-                       if (!join &&
-                           (p=find_prop(e->p, PROP_HASHCOL)) != NULL) {
-                               sql_idx *i = p->value;
-
-                               join = s = rel2bin_hash_lookup(be, rel, left, 
right, i, en);
-                               if (s) {
-                                       list_append(lje, s->op1);
-                                       list_append(rje, s->op2);
-                                       list_append(exps, NULL);
-                                       used_hash = 1;
+                       for( en = jexps->h; en; en = en->next ) {
+                               int join_idx = sql->opt_stats[0];
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to