Update of /cvsroot/monetdb/sql/src/server
In directory sc8-pr-cvs16.sourceforge.net:/tmp/cvs-serv9668/src/server

Modified Files:
        rel_bin.mx rel_dump.mx rel_exp.mx rel_optimizer.mx 
        rel_select.mx sql_optimize.mx 
Log Message:
handle range joins efficiently in the algebra version


U rel_select.mx
Index: rel_select.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_select.mx,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -d -r1.73 -r1.74
--- rel_select.mx       1 Apr 2008 17:04:56 -0000       1.73
+++ rel_select.mx       9 Apr 2008 09:56:23 -0000       1.74
@@ -1652,47 +1652,18 @@
 }
 
 static sql_rel *
-rel_compare_exp(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, char 
*compare_op, sql_exp *esc, int f )
+rel_compare_exp_(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp 
*rs2, int type, int anti )
 {
        sql_exp *L = ls, *R = rs, *e = NULL;
-       comp_type type = cmp_equal;
-
-       if (!ls || !rs)
-               return NULL;
 
-       if (rel_convert_types(sql, &ls, &rs, 1, type_equal) < 0) {
-               if (ls)
-                       exp_destroy(ls);
-               if (rs)
-                       exp_destroy(rs);
+       if (rel_convert_types(sql, &ls, &rs, 1, type_equal) < 0 ||
+          (rs2 && rel_convert_types(sql, &ls, &rs2, 1, type_equal) < 0)) {
+               exp_destroy(ls);
+               exp_destroy(rs);
+               exp_destroy(rs2);
                return NULL;
        }
-       if (!rel || f == sql_sel || (ls->card <= CARD_ATOM && rs->card <= 
CARD_ATOM)) {
-               sql_exp *e;
-
-               if (compare_op[0] == 'l') 
-                       compare_op = "like";
-               if (compare_op[0] == 'n') 
-                       compare_op = "not_like";
-               e = rel_binop_(sql, ls, rs, NULL, compare_op);
-
-               if (!e)
-                       return NULL;
-               if (f == sql_sel) {
-                       if (rel->op == op_project) { 
-                               append(rel->exps, e);
-                       } else {
-                               list *exps = new_exp_list();
-
-                               append(exps, e);
-                               return rel_project(rel, exps);
-                       }
-               } else {
-                       return rel_select(rel, e);
-               }
-       }
-       type = compare_str2type(compare_op);
-       if (type != cmp_like && type != cmp_notlike) {
+       if (!rs2 && type != cmp_like && type != cmp_notlike) {
                if (ls->card < rs->card) {
                        sql_exp *swap = ls;
        
@@ -1707,8 +1678,10 @@
                }
                e = exp_compare( ls, rs, type );
        } else {
-               e = exp_compare2( ls, rs, esc, type );
+               e = exp_compare2( ls, rs, rs2, type );
        }
+       if (anti)
+               set_anti(e);
 
        /* atom or row => select */
        if (ls->card > rel->card)
@@ -1728,6 +1701,47 @@
 }
 
 static sql_rel *
+rel_compare_exp(mvc *sql, sql_rel *rel, sql_exp *ls, sql_exp *rs, char 
*compare_op, sql_exp *esc, int f )
+{
+       comp_type type = cmp_equal;
+
+       if (!ls || !rs)
+               return NULL;
+
+       if (!rel || f == sql_sel || (ls->card <= CARD_ATOM && rs->card <= 
CARD_ATOM)) {
+               sql_exp *e;
+
+               if (compare_op[0] == 'l') 
+                       compare_op = "like";
+               if (compare_op[0] == 'n') 
+                       compare_op = "not_like";
+               if (rel_convert_types(sql, &ls, &rs, 1, type_equal) < 0) {
+                       exp_destroy(ls);
+                       exp_destroy(rs);
+                       return NULL;
+               }
+               e = rel_binop_(sql, ls, rs, NULL, compare_op);
+
+               if (!e)
+                       return NULL;
+               if (f == sql_sel) {
+                       if (rel->op == op_project) { 
+                               append(rel->exps, e);
+                       } else {
+                               list *exps = new_exp_list();
+
+                               append(exps, e);
+                               return rel_project(rel, exps);
+                       }
+               } else {
+                       return rel_select(rel, e);
+               }
+       }
+       type = compare_str2type(compare_op);
+       return rel_compare_exp_(sql, rel, ls, rs, esc, type, 0);
+}
+
+static sql_rel *
 rel_compare(mvc *sql, sql_rel *rel, symbol *lo, symbol *ro, char *compare_op, 
int f )
 {
        sql_exp *rs = 0, *ls;
@@ -2397,12 +2411,9 @@
                }
 
                if (sc->token == SQL_NOT_BETWEEN) {
-                       /* TODO should be 'or' */
-                       rel = rel_compare_exp(sql, rel, le, re1, "<", NULL, f);
-                       rel = rel_compare_exp(sql, rel, exp_dup(le), re2, ">", 
NULL, f);
+                       rel = rel_compare_exp_(sql, rel, le, re1, re2, 3, 1);
                } else {
-                       rel = rel_compare_exp(sql, rel, le, re1, ">=", NULL, f);
-                       rel = rel_compare_exp(sql, rel, exp_dup(le), re2, "<=", 
NULL, f);
+                       rel = rel_compare_exp_(sql, rel, le, re1, re2, 3, 0);
                }
                return rel;
        }

U rel_dump.mx
Index: rel_dump.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_dump.mx,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- rel_dump.mx 8 Mar 2008 07:27:00 -0000       1.25
+++ rel_dump.mx 9 Apr 2008 09:56:23 -0000       1.26
@@ -131,6 +131,8 @@
                break;
        case e_cmp: 
                exp_print(sql, e->l, depth+1, 0, 0);
+               if (is_anti(e))
+                       printf(" ! ");
                cmp_print(sql, e->flag );
                exp_print(sql, e->r, depth+1, 0, 0);
                if (e->f) {

U rel_optimizer.mx
Index: rel_optimizer.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_optimizer.mx,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- rel_optimizer.mx    21 Mar 2008 14:47:57 -0000      1.14
+++ rel_optimizer.mx    9 Apr 2008 09:56:23 -0000       1.15
@@ -299,17 +299,21 @@
        case e_cmp:
                switch (e->flag) {
                case cmp_equal:
-                       *cnt += 20;
-                       return 20;
-               case cmp_notequal:
                        *cnt += 10;
                        return 10;
+               case cmp_notequal:
+                       *cnt += 7;
+                       return 7;
                case cmp_gt:
                case cmp_gte:
                case cmp_lt:
                case cmp_lte:
-                       *cnt += 4;
-                       return 4;
+                       *cnt += 6;
+                       if (e->f){ /* range */
+                               *cnt += 6;
+                               return 12;
+                       }
+                       return 6;
                case cmp_like:
                case cmp_notlike:
                        *cnt += 2;
@@ -491,7 +495,7 @@
        sql_exp *cje;
        node *djn;
        list *sdje, *n_rels = list_create(NULL);
-       int fnd;
+       int fnd = 0;
 
        /* first find the distinct join expressions */
        list *aje = list_select(exps, (void*)1, (fcmp) &exp_is_join, 
(fdup)exp_dup);
@@ -591,33 +595,33 @@
        /* find the involved relations */
        l = find_rel(rels, cje->l);
        r = find_rel(rels, cje->r);
-       list_remove_data(rels, l);
-       list_remove_data(rels, r);
-       list_append(n_rels, l);
-       list_append(n_rels, r);
+       if (l && r) {
+               list_remove_data(rels, l);
+               list_remove_data(rels, r);
+               list_append(n_rels, l);
+               list_append(n_rels, r);
 
-       /* Create a relation between l and r. Since the calling 
-          functions rewrote the join tree, into a list of expressions 
-          and a list of (simple) relations, there are no outer joins 
-          involved, we can simply do a crossproduct here.
-        */
-       top = rel_crossproduct(l, r, op_join);
-       rel_join_add_exp(top, exp_dup(cje));
+               /* Create a relation between l and r. Since the calling 
+                  functions rewrote the join tree, into a list of expressions 
+                  and a list of (simple) relations, there are no outer joins 
+                  involved, we can simply do a crossproduct here.
+                */
+               top = rel_crossproduct(l, r, op_join);
+               rel_join_add_exp(top, exp_dup(cje));
 
-       /* all other join expressions on these 2 relations */
-       while((djn = list_find(exps, n_rels, (fcmp)&exp_joins_rels)) != NULL) {
-               sql_exp *e = djn->data;
+               /* all other join expressions on these 2 relations */
+               while((djn = list_find(exps, n_rels, (fcmp)&exp_joins_rels)) != 
NULL) {
+                       sql_exp *e = djn->data;
 
-               rel_join_add_exp(top, exp_dup(e));
-               list_remove_data(exps, e);
+                       rel_join_add_exp(top, exp_dup(e));
+                       list_remove_data(exps, e);
+               }
+               /* Remove other joins on the current 'n_rels' set in the 
distinct list too */
+               while((djn = list_find(sdje, n_rels, (fcmp)&exp_joins_rels)) != 
NULL) 
+                       list_remove_data(sdje, djn->data);
+               fnd = 1;
        }
-       /* Remove other joins on the current 'n_rels' 
-          set in the distinct list too */
-       while((djn = list_find(sdje, n_rels, (fcmp)&exp_joins_rels)) != NULL) 
-               list_remove_data(sdje, djn->data);
-
        /* build join tree using the ordered list */
-       fnd = 1;
        while(list_length(exps) && fnd) {
                fnd = 0;
                /* find the first expression which could be added */
@@ -671,8 +675,12 @@
        }
        if (list_length(rels)) { /* more relations */
                node *n;
-               for(n=rels->h; n; n = n->next) 
-                       top = rel_crossproduct(top, n->data, op_join);
+               for(n=rels->h; n; n = n->next) {
+                       if (top)
+                               top = rel_crossproduct(top, n->data, op_join);
+                       else 
+                               top = n->data;
+               }
        }
        if (list_length(exps)) { /* more expressions */
                node *n;

U sql_optimize.mx
Index: sql_optimize.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_optimize.mx,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- sql_optimize.mx     14 Mar 2008 12:55:18 -0000      1.91
+++ sql_optimize.mx     9 Apr 2008 09:56:23 -0000       1.92
@@ -377,11 +377,11 @@
         * without unique head identifiers + semijoin is wrong
         */
        if (!reverse) {
+               stmt *ml = stmt_mark(stmt_reverse(stmt_dup(op1)), 50);
+               stmt *mr = stmt_mark(stmt_dup(op1), 50);
+               stmt *l = stmt_join(stmt_dup(ml),
+                               stmt_dup(op2->op1.stval), cmp_equal);
                if (op2->type == st_join2) {
-                       stmt *ml = stmt_mark(stmt_reverse(stmt_dup(op1)), 50);
-                       stmt *mr = stmt_mark(stmt_dup(op1), 50);
-                       stmt *l = stmt_join(stmt_dup(ml),
-                                       stmt_dup(op2->op1.stval), cmp_equal);
                        stmt *r1 = stmt_join(stmt_dup(mr),
                                        stmt_dup(op2->op2.stval), cmp_equal);
                        stmt *r2 = stmt_join(stmt_dup(mr),
@@ -395,10 +395,6 @@
                        ml = stmt_semijoin(ml, v2);
                        res = stmt_join(stmt_reverse(ml), mr, cmp_equal);
                } else {
-                       stmt *ml = stmt_mark(stmt_reverse(stmt_dup(op1)), 50);
-                       stmt *mr = stmt_mark(stmt_dup(op1), 50);
-                       stmt *l = stmt_join(stmt_dup(ml),
-                                       stmt_dup(op2->op1.stval), cmp_equal);
                        stmt *r = stmt_join(stmt_dup(mr),
                                        stmt_reverse(stmt_dup(op2->op2.stval)), 
cmp_equal);
                        stmt *v = stmt_uselect(l, r, (comp_type) op2->flag);

U rel_exp.mx
Index: rel_exp.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_exp.mx,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- rel_exp.mx  14 Mar 2008 12:55:15 -0000      1.9
+++ rel_exp.mx  9 Apr 2008 09:56:23 -0000       1.10
@@ -545,7 +545,7 @@
 sql_exp *
 exps_bind_column( list *exps, char *cname ) 
 {
-       if (exps) {
+       if (exps && cname) {
                node *en;
 
                for (en = exps->h; en; en = en->next ) {

U rel_bin.mx
Index: rel_bin.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_bin.mx,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- rel_bin.mx  21 Mar 2008 08:41:28 -0000      1.38
+++ rel_bin.mx  9 Apr 2008 09:56:23 -0000       1.39
@@ -277,9 +277,9 @@
                }
         }      break;
        case e_cmp: {
-               stmt *l = NULL, *r = NULL;
+               stmt *l = NULL, *r = NULL, *r2 = NULL;
                int swapped = 0, sel = 0;
-               sql_exp *re = e->r;
+               sql_exp *re = e->r, *re2 = e->f;
                prop *p;
 
                /* here we handle join indices */
@@ -319,25 +319,6 @@
                        l = exp_bin(sql, e->l, right, NULL, grp);
                        swapped = 1;
                }
-               /* the escape charachter of like is in the right expression */
-               if (e->flag == cmp_notlike || e->flag == cmp_like) {
-                       stmt *escape = NULL;
-
-                       r = exp_bin(sql, e->r, left, right, grp);
-                       if (e->f) {
-                               escape = exp_bin(sql, e->f, left, right, grp);
-                       } else {
-                               escape = stmt_atom_string(_strdup(""));
-                       }
-                       if (!l || !r || !escape) {
-                               assert(0);
-                               if (l) stmt_destroy(l);
-                               if (r) stmt_destroy(r);
-                               if (escape) stmt_destroy(escape);
-                               return NULL;
-                       }
-                       return stmt_likeselect(l, r, escape, 
(comp_type)e->flag);
-               }
                if (swapped || !right)
                        r = exp_bin(sql, e->r, left, NULL, grp);
                else
@@ -346,12 +327,29 @@
                        r = exp_bin(sql, e->r, left, NULL, grp);
                        sel = 1;
                }
-               if (!l || !r) {
+               if (re2)
+                       r2 = exp_bin(sql, e->f, left, right, grp);
+               if (!l || !r || (re2 && !r2)) {
                        assert(0);
                        if (l) stmt_destroy(l);
                        if (r) stmt_destroy(r);
+                       if (r2) stmt_destroy(r2);
                        return NULL;
                }
+
+               /* the escape charachter of like is in the right expression */
+               if (e->flag == cmp_notlike || e->flag == cmp_like) {
+                       if (!e->f)
+                               r2 = stmt_atom_string(_strdup(""));
+                       if (!l || !r || !r2) {
+                               assert(0);
+                               if (l) stmt_destroy(l);
+                               if (r) stmt_destroy(r);
+                               if (r2) stmt_destroy(r2);
+                               return NULL;
+                       }
+                       return stmt_likeselect(l, r, r2, (comp_type)e->flag);
+               }
                if (left && right && re->card > CARD_ATOM && !sel) {
                        if (l->nrcols == 0)
                                l = 
stmt_const(bin_first_column(swapped?right:left), l); 
@@ -359,12 +357,20 @@
                                r = 
stmt_const(bin_first_column(swapped?left:right), r); 
                        if (swapped) {
                                s = stmt_join(r, stmt_reverse(l), 
swap_compare((comp_type)e->flag));
+                       } else if (r2) {
+                               s = stmt_join2(l, r, r2, (comp_type)e->flag);
                        } else {
                                s = stmt_join(l, stmt_reverse(r), 
(comp_type)e->flag);
                        }
                } else {
-                       s = stmt_uselect(l, r, (comp_type)e->flag);
+                       if (r2) {
+                               s = stmt_uselect2(l, r, r2, (comp_type)e->flag);
+                       } else {
+                               s = stmt_uselect(l, r, (comp_type)e->flag);
+                       }
                }
+               if (is_anti(e))
+                       s->flag |= ANTI;
         }      break;
        default:
                ;
@@ -541,7 +547,7 @@
                        }
                        if (!join) {
                                join = s;
-                       } else if (s->type != st_join) {
+                       } else if (s->type != st_join && s->type != st_join2) {
                                /* handle select expressions */
                                if (s->h == join->h) {
                                        join = stmt_semijoin(join,s);
@@ -555,24 +561,38 @@
                                stmt *l = stmt_mark(stmt_reverse(join), 100);
                                stmt *r = stmt_mark(stmt_dup(join), 100);
                                stmt *ld = stmt_dup(s->op1.stval);
-                               stmt *rd = stmt_reverse(stmt_dup(s->op2.stval));
                                stmt *le = stmt_join(l, ld, cmp_equal);
-                               stmt *re = stmt_join(r, rd, cmp_equal);
-
-                               sql_subfunc *f = 
sql_bind_func(sql->session->schema, compare_func((comp_type)s->flag), 
tail_type(le), tail_type(le));
-                               stmt * cmp;
-
-                               assert(f);
-
-
-                               cmp = stmt_binop(le, re, f);
+                               if (s->type == st_join2) {
+                                       stmt *rd = stmt_dup(s->op2.stval);
+                                       stmt *re = stmt_join(r, rd, cmp_equal);
+                                       stmt *r2 = stmt_dup(s->op3.stval);
+                                       stmt *re2 = stmt_join(stmt_dup(r), r2, 
cmp_equal);
+                                       comp_type c1 = s->flag&2?cmp_gte:cmp_gt;
+                                       comp_type c2 = s->flag&1?cmp_lte:cmp_lt;
+                                       stmt *v1 = stmt_uselect(le, re, c1);
+                                       stmt *v2 = stmt_uselect(stmt_dup(le), 
re2, c2);
+                                       l = stmt_semijoin(stmt_dup(l), 
stmt_dup(v1));
+                                       l = stmt_semijoin(l, stmt_dup(v2));
+                                       r = stmt_semijoin(stmt_dup(r), v1);
+                                       r = stmt_semijoin(r, v2);
+                                       join = stmt_join(stmt_reverse(l), r, 
cmp_equal);
+                                       stmt_destroy(s);
+                               } else {
+                                       stmt *rd = 
stmt_reverse(stmt_dup(s->op2.stval));
+                                       stmt *re = stmt_join(r, rd, cmp_equal);
+                                       sql_subfunc *f = 
sql_bind_func(sql->session->schema, compare_func((comp_type)s->flag), 
tail_type(le), tail_type(le));
+                                       stmt * cmp;
+       
+                                       assert(f);
 
-                               cmp = stmt_uselect(cmp, stmt_bool(1), 
cmp_equal);
+                                       cmp = stmt_binop(le, re, f);
+                                       cmp = stmt_uselect(cmp, stmt_bool(1), 
cmp_equal);
 
-                               l = stmt_semijoin(stmt_dup(l), stmt_dup(cmp));
-                               r = stmt_semijoin(stmt_dup(r), cmp);
-                               join = stmt_join(stmt_reverse(l), r, cmp_equal);
-                               stmt_destroy(s);
+                                       l = stmt_semijoin(stmt_dup(l), 
stmt_dup(cmp));
+                                       r = stmt_semijoin(stmt_dup(r), cmp);
+                                       join = stmt_join(stmt_reverse(l), r, 
cmp_equal);
+                                       stmt_destroy(s);
+                               }
                        }
                }
        } else {


-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Monetdb-sql-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-sql-checkins

Reply via email to