Update of /cvsroot/monetdb/sql/src/server
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv15984/src/server

Modified Files:
        rel_bin.mx rel_exp.mx rel_optimizer.mx rel_select.mx 
        sql_parser.mx sql_rel2bin.mx sql_schema.mx sql_statement.mx 
        sql_updates.mx 
Log Message:
added support for sql/xml namespaces
fixed bug in algebra version for handling exist/not exists in exists/not exists
with correlation 

added optimizer steps for algebra version to rewrite semi/anti joins followed
by joins on the same (referenced) relation into a single semijoin
push selects through semi/anti joins

approved tests



U sql_updates.mx
Index: sql_updates.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_updates.mx,v
retrieving revision 1.151
retrieving revision 1.152
diff -u -d -r1.151 -r1.152
--- sql_updates.mx      10 Oct 2008 09:01:18 -0000      1.151
+++ sql_updates.mx      28 Oct 2008 20:05:04 -0000      1.152
@@ -128,6 +128,30 @@
 
                /* 2e stage: find out if inserted are unique */
                if (idx_inserts->nrcols) {      /* insert columns not atoms */
+#if 0
+                       sql_subtype *Oid = sql_bind_localtype("oid");
+                       sql_subfunc *nu, *or = 
sql_bind_func_result(sql->session->schema, "or", bt, bt, bt);
+                       stmt *ss = NULL;
+
+                       /* implementation uses group, not_uniques,
+                               join, derive, not_uniques keyed check */
+                       for (m = k->columns->h; m; m = m->next) {
+                               sql_kc *c = m->data;
+
+                               if (ss) {
+                                       ss = stmt_derive(ss, 
stmt_join(stmt_mirror(stmt_dup(ss)), stmt_dup(inserts[c->c->colnr]->op2.stval), 
cmp_equal));
+                               } else {
+                                       ss = 
stmt_group(stmt_dup(inserts[c->c->colnr]->op2.stval));
+                               }
+                       }
+                       nu = sql_bind_func_result(sql->session->schema, 
"not_uniques", tail_type(ss), NULL, Oid);
+                       ss = stmt_unop(ss, nu);
+
+                       sum = sql_bind_aggr(sql->session->schema, "not_unique", 
tail_type(ss));
+                       ssum = stmt_aggr(ss, NULL, sum, 1);
+                       /* combine results */
+                       s = stmt_binop(s, ssum, or);
+#else
                        stmt *ss;
                        sql_subfunc *or = 
sql_bind_func_result(sql->session->schema, "or", bt, bt, bt);
                        /* implementation uses sort,refine, keyed check */
@@ -145,6 +169,7 @@
                        ssum = stmt_aggr(ss, NULL, sum, 1);
                        /* combine results */
                        s = stmt_binop(s, ssum, or);
+#endif
                }
 
                if (k->type == pkey) {

U sql_schema.mx
Index: sql_schema.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_schema.mx,v
retrieving revision 1.150
retrieving revision 1.151
diff -u -d -r1.150 -r1.151
--- sql_schema.mx       10 Oct 2008 09:00:45 -0000      1.150
+++ sql_schema.mx       28 Oct 2008 20:05:04 -0000      1.151
@@ -825,10 +825,18 @@
 {
 
        char *name = qname_table(qname);
-       sql_idx *i = mvc_bind_idx(sql, ss, iname);
+       char *sname = qname_schema(qname);
+       sql_schema *s = NULL;
+       sql_table *t = NULL;
+       sql_idx *i = NULL;
 
-       sql_table *t = mvc_bind_table(sql, ss, name);
+       if (sname && !(s = mvc_bind_schema(sql, sname)))
+               return sql_error(sql, 02, "CREATE INDEX: no such schema '%s'", 
sname);
+       if (s == NULL) 
+               s = ss;
 
+       i = mvc_bind_idx(sql, s, iname);
+       t = mvc_bind_table(sql, s, name);
        if (i) {
                return sql_error(sql, 02, "CREATE INDEX: name '%s' already in 
use", iname);
        } else if (!t) {
@@ -861,7 +869,7 @@
                        int l;
                        node *n;
                        sql_kc *ic = NULL;
-                       sql_table *t = mvc_create_cluster(sql, ss, 
i->base.name, 1, SQL_PERSIST, CA_COMMIT, 0); 
+                       sql_table *t = mvc_create_cluster(sql, s, i->base.name, 
1, SQL_PERSIST, CA_COMMIT, 0); 
 
                        if (!t) 
                                return sql_error(sql, 02, "CREATE INDEX: cannot 
create cluster table '%s'", iname);
@@ -900,16 +908,23 @@
 {
        stmt *res = NULL;
        char *iname = qname_table(qname);
-       sql_schema *ss = cur_schema(sql);
-
-       sql_idx *i = mvc_bind_idx(sql, ss, iname);
+       char *sname = qname_schema(qname);
+       sql_schema *s = NULL;
+       sql_idx *i = NULL;
 
-       if (!schema_privs(sql->role_id, ss)) 
-               return sql_error(sql, 02, "DROP INDEX: access denied for %s to 
schema ;'%s'", stack_get_string(sql, "current_user"), ss->base.name);
+       if (sname && !(s=mvc_bind_schema(sql, sname))) {
+               (void) sql_error(sql, 02, "DROP INDEX: no such schema '%s'", 
sname);
+               return NULL;
+       }
+       if (!s)
+               s = cur_schema(sql);
+       i = mvc_bind_idx(sql, s, iname);
        if (!i) {
                return sql_error(sql, 02, "DROP INDEX: no such index '%s'", 
iname);
+       } else if (!schema_privs(sql->role_id, s)) {
+               return sql_error(sql, 02, "DROP INDEX: access denied for %s to 
schema ;'%s'", stack_get_string(sql, "current_user"), s->base.name);
        } else {
-               mvc_drop_idx(sql, ss, i);
+               mvc_drop_idx(sql, s, i);
                res = stmt_none();
        }
        return res;

U sql_rel2bin.mx
Index: sql_rel2bin.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_rel2bin.mx,v
retrieving revision 1.125
retrieving revision 1.126
diff -u -d -r1.125 -r1.126
--- sql_rel2bin.mx      10 Oct 2008 09:00:37 -0000      1.125
+++ sql_rel2bin.mx      28 Oct 2008 20:05:04 -0000      1.126
@@ -423,8 +423,13 @@
 
                assert(tt);
                if (list_length(colsels) == 1) {
+                       stmt *s = stmt_dup(colsels->h->data);
                        /* only one select on this column; simply keep it. */
-                       list_append(newsels, stmt_dup(colsels->h->data));
+                       /* we prefer range selects over simple selects */
+                       if (s->type == st_uselect2 || s->type == st_select2)
+                               list_prepend(newsels, s);
+                       else
+                               list_append(newsels, s);
                } else if (tt->type->localtype == TYPE_str || !(min = 
sql_bind_func_result(sql->session->schema, "sql_min", tt, tt, tt)) || !(max = 
sql_bind_func_result(sql->session->schema, "sql_max", tt, tt, tt))) {
                        /* no "min" and/or "max" available on this data type, 
hence, we cannot apply the following "tricks" */
                        list_merge(newsels, colsels, (fdup) &stmt_dup);
@@ -589,7 +594,7 @@
                                        assert(0);
                                }
                                if (bound[cl] && bound[cr]) {
-                                       list_append(newsels, 
stmt_uselect2(stmt_dup(col[cl]), bound[cl], bound[cr], flg));
+                                       list_prepend(newsels, 
stmt_uselect2(stmt_dup(col[cl]), bound[cl], bound[cr], flg));
                                        bound[cl] = bound[cr] = NULL;
                                }
                        }
@@ -957,6 +962,7 @@
                list *ol, *l = s->op1.lval;
 
                ol = l;
+               assert(list_length(l));
                if (list_length(l) == 1) {
                        res = rel2bin(c, l->h->data);
                } else {

U rel_optimizer.mx
Index: rel_optimizer.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_optimizer.mx,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- rel_optimizer.mx    10 Oct 2008 08:59:37 -0000      1.24
+++ rel_optimizer.mx    28 Oct 2008 20:05:04 -0000      1.25
@@ -43,7 +43,7 @@
        int cnt[MAXOPS];
 } global_props;
 
-typedef sql_rel *(*rewrite_fptr)(mvc *sql, sql_rel *rel);
+typedef sql_rel *(*rewrite_fptr)(int *changes, mvc *sql, sql_rel *rel);
 typedef int (*find_prop_fptr)(mvc *sql, sql_rel *rel);
 
 /* The important task of the relational optimizer is to optimize the
@@ -830,8 +830,9 @@
 }
 
 static sql_rel *
-rel_join_order(mvc *sql, sql_rel *rel) 
+rel_join_order(int *changes, mvc *sql, sql_rel *rel) 
 {
+       *changes = 0; 
        if (is_join(rel->op) && rel->exps) {
 #ifdef DEBUG
 printf("BEFORE\n");
@@ -932,41 +933,57 @@
  * it cleans up the projections which become useless.
  */
 sql_rel *
-rel_push_select_down(mvc *sql, sql_rel *rel) 
+rel_push_select_down(int *changes, mvc *sql, sql_rel *rel) 
 {
        list *exps = NULL;
        sql_rel *r = NULL;
        node *n;
 
        (void)sql;
-       if ((is_join(rel->op) || is_project(rel->op) || rel->op == op_topn) && 
rel->l) {
+       /* remove empty select's */
+       if ((is_join(rel->op) || is_semi(rel->op) || is_project(rel->op) || 
rel->op == op_topn) && rel->l) {
                sql_rel *l = rel->l;
                if (l->op == op_select && !(rel_is_ref(l)) &&
                   (!l->exps || list_length(l->exps) == 0)) {
                        rel->l = l->l;
                        l->l = NULL;
                        rel_destroy(l);
-                       return rel_push_select_down(sql, rel);
+                       (*changes)++;
+                       return rel;
                } 
        }
-       if ((is_join(rel->op) || is_set(rel->op)) && rel->r) {
+       if ((is_join(rel->op) || is_semi(rel->op) || is_set(rel->op)) && 
rel->r) {
                sql_rel *r = rel->r;
                if (r->op == op_select && !(rel_is_ref(r)) &&
                   (!r->exps || list_length(r->exps) == 0)) {
                        rel->r = r->l;
                        r->l = NULL;
                        rel_destroy(r);
-                       return rel_push_select_down(sql, rel);
+                       (*changes)++;
+                       return rel;
                }
        } 
+       /* merge 2 selects */
+       r = rel->l;
        if (rel->op == op_select && r && !(rel_is_ref(r)) && (r->op == 
op_select || r->op == op_except)) {
                (void)list_merge(r->exps, rel->exps, (fdup)&exp_dup);
                rel->l = NULL;
                rel_destroy(rel);
-               return rel_push_select_down(sql, r);
+               (*changes)++;
+               return r;
+       }
+       /* push select through semi/anti join 
+        * select (semi(A,B)) == semi(select(A), B) */
+       if (rel->op == op_select && r && is_semi(r->op) && !(rel_is_ref(r))) {
+               rel->l = r->l;
+               r->l = rel;
+               (*changes)++;
+               return r;
        }
        exps = rel->exps;
-       r = rel->l;
+       /* push select through set */
+/* disabled, currently crashes on assert */
+#if 0
        if (rel->op == op_select && r && is_set(r->op) && !(rel_is_ref(r))) {
                rel->exps = new_exp_list(); 
                for (n = exps->h; n; n = n->next) { 
@@ -1000,9 +1017,13 @@
                                list_append(rel->exps, exp_dup(e));
                        } 
                }
+               /* TODO looks buggy */
                list_destroy(exps);
-               return rel_push_select_down(sql, r);
+               (*changes)++;
+               return r;
        }
+#endif
+       /* merge projects */
        if (rel->op == op_project && r && r->op == op_project && 
!(rel_is_ref(r))) {
                int all = 1;
 
@@ -1034,13 +1055,14 @@
                        r->l = NULL;
                        rel_destroy(r);
                        list_destroy(exps);
-                       return rel_push_select_down(sql, rel);
+                       (*changes)++;
                } else {
                        /* leave as is */
                        list_destroy(rel->exps);
                        rel->exps = exps;
                }
                return rel;
+       /* push select through project */
        } else if (rel->op == op_select && r && r->op == op_project && 
!(rel_is_ref(r))) {
                /* here we need to fix aliases */
                rel->exps = new_exp_list(); 
@@ -1052,8 +1074,10 @@
                        /* sometimes we also have functions in the expression 
list (TODO change them to e_cmp (predicates like (1=0))) */
                        if (e->type == e_cmp) {
                                ne = exp_push_down(sql, e, prj, prj->l);
+
                                /* can we move it down */
                                if (ne && ne != e) {
+                                       (*changes)++;
                                        nr = prj->l;
                                } else {
                                        nr = rel;
@@ -1085,12 +1109,13 @@
  * under the group by.
  */
 sql_rel *
-rel_push_join_down(mvc *sql, sql_rel *rel) 
+rel_push_join_down(int *changes, mvc *sql, sql_rel *rel) 
 {
        list *exps = NULL;
        sql_rel *gb = NULL, *l = NULL;
 
        (void)sql;
+       *changes = 0;
        if ((is_join(rel->op) || is_semi(rel->op)) && rel->l) {
                gb = rel->r;
                exps = rel->exps;
@@ -1132,9 +1157,9 @@
                        }
                        if (is_join(rel->op)) {
                                /* push join's left side (as semijoin) down 
group by */
-                               l = rel_copy(rel->l);
-                               /* now we need to translate the names using the 
join
-                               expressions */
+                               //l = rel_copy(rel->l);
+                               l = rel_dup(rel_dup(rel->l));
+                               /* now we need to translate the names using the 
join expressions */
                                gb->l = rel_crossproduct(gb->l, l, op_semi);
                                l = gb->l;
                                l->exps = jes;
@@ -1264,9 +1289,10 @@
 }
 
 static sql_rel *
-rel_select_use_index(mvc *sql, sql_rel *rel) 
+rel_select_use_index(int *changes, mvc *sql, sql_rel *rel) 
 {
        (void)sql;
+       *changes = 0; 
        if (rel->op == op_select) {
                list *exps = NULL;
                sql_idx *i = find_index(rel, &exps);
@@ -1329,9 +1355,10 @@
 }
 
 static sql_rel *
-rel_select_order(mvc *sql, sql_rel *rel) 
+rel_select_order(int *changes, mvc *sql, sql_rel *rel) 
 {
        (void)sql;
+       *changes = 0; 
        if (rel->op == op_select && rel->exps && list_length(rel->exps)>1) {
                list *exps = NULL;
                        
@@ -1345,9 +1372,43 @@
        return rel;
 }
 
+/* rewrite {semi,anti}join (A, join(A,B)) into {semi,anti}join (A,B) */
+
+static sql_rel *
+rel_rewrite_semijoin(int *changes, mvc *sql, sql_rel *rel)
+{
+       (void)sql;
+       if (is_semi(rel->op)) {
+               sql_rel *l = rel->l;
+               sql_rel *r = rel->r;
+
+               if (l->ref.refcnt == 3 && is_join(r->op) && l == r->l ) {
+                       /* okay to rewrite, maybe later we should check 
+                          the semi/anti join condition (should be tid based) */
+#ifdef DEBUG
+                       rel_print(sql, rel, 0);
+#endif
+                       rel->r = rel_dup(r->r);
+                       /* maybe rename exps ? */
+                       list_destroy(rel->exps);
+                       rel->exps = r->exps;
+                       r->exps = NULL;
+                       rel_destroy(l);
+                       rel_destroy(r);
+#ifdef DEBUG
+                       rel_print(sql, rel, 0);
+#endif
+                       (*changes)++;
+               }
+       }
+       return rel;
+}
+
 static sql_rel *
 rewrite(mvc *sql, sql_rel *rel, rewrite_fptr rewriter) 
 {
+       int changes = 0;
+
        switch (rel->op) {
        case op_basetable:
        case op_table:
@@ -1376,7 +1437,10 @@
        }
        if (rel_is_ref(rel))
                return rel;
-       return rewriter(sql, rel);
+       rel = rewriter(&changes, sql, rel);
+       if (changes)
+               return rewrite(sql, rel, rewriter);
+       return rel;
 }
 
 sql_rel *
@@ -1401,11 +1465,17 @@
        rel_print(sql, rel, 0);
 #endif
 
+       /* TODO cleanup rel_optimzer.mx (reorder code, remove unused etc) */
+
        /* TODO add optimizer which removes unions 
                (for example common rels, with only one different expression) */
 
        /* TODO common sub relation/expression optimizer */
 
+       /* TODO rewrite op_anti/semi (A,C=join(A,B)) [ A.tid  = C.A.tid ] */
+       if (gp.cnt[op_anti] || gp.cnt[op_semi])
+               rel = rewrite(sql, rel, &rel_rewrite_semijoin);
+
        if (gp.cnt[op_select])
                rel = rewrite(sql, rel, &rel_push_select_down); 
 

U sql_statement.mx
Index: sql_statement.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_statement.mx,v
retrieving revision 1.173
retrieving revision 1.174
diff -u -d -r1.173 -r1.174
--- sql_statement.mx    10 Oct 2008 09:01:06 -0000      1.173
+++ sql_statement.mx    28 Oct 2008 20:05:04 -0000      1.174
@@ -264,6 +264,7 @@
 extern stmt *stmt_diff(stmt *op1, stmt *op2);
 extern stmt *stmt_union(stmt *op1, stmt *op2);
 extern stmt *stmt_list(list *l);
+extern void stmt_set_nrcols(stmt *s);
 extern stmt *stmt_set(stmt *s1);
 extern stmt *stmt_sets(list *s1);
 extern stmt *stmt_ptable(stmt *p);
@@ -331,6 +332,9 @@
 extern group *grp_dup(group *g);
 extern stmt *grp_find_groupby_col(group *g, stmt *s);
 
+extern stmt *stmt_group(stmt *s);
+extern stmt *stmt_derive(stmt *g, stmt *s);
+
 #endif /* _SQL_STATEMENT_H_ */
 
 @c
@@ -543,7 +547,7 @@
        return ns;
 }
 
-static stmt *
+stmt *
 stmt_group(stmt *s)
 {
        stmt *ns = stmt_create(st_group);
@@ -556,7 +560,7 @@
        return ns;
 }
 
-static stmt *
+stmt *
 stmt_derive(stmt *s, stmt *t)
 {
        stmt *ns = stmt_create(st_derive);
@@ -1908,16 +1912,15 @@
        return s;
 }
 
-stmt *
-stmt_list(list *l)
+void
+stmt_set_nrcols(stmt *s)
 {
        int nrcols = 0;
        int key = 1;
        node *n;
-       stmt *s = stmt_create(st_list);
-
-       s->op1.lval = l;
+       list *l = s->op1.lval;
 
+       assert(s->type == st_list);
        for (n = l->h; n; n = n->next) {
                stmt *f = n->data;
 
@@ -1927,6 +1930,15 @@
        }
        s->nrcols = nrcols;
        s->key = key;
+}
+
+stmt *
+stmt_list(list *l)
+{
+       stmt *s = stmt_create(st_list);
+
+       s->op1.lval = l;
+       stmt_set_nrcols(s);
        return s;
 }
 

U rel_exp.mx
Index: rel_exp.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_exp.mx,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- rel_exp.mx  10 Oct 2008 08:59:33 -0000      1.14
+++ rel_exp.mx  28 Oct 2008 20:05:04 -0000      1.15
@@ -445,10 +445,11 @@
 
        switch(e->type) {
        case e_column:
-               if (e->l) { 
+               if (e->l && !rel->name) { 
                        ne = exps_bind_column2(rel->exps, e->l, e->r);
-                       /* if relation name matches expressions relation name, 
find column based on column name alone */
-                       if (!ne && rel->name && strcmp(e->l, rel->name) == 0) 
+               /* if relation name matches expressions relation name, find 
column based on column name alone */
+               } else if (e->l && rel->name) { 
+                       if (strcmp(e->l, rel->name) == 0) 
                                ne = exps_bind_column(rel->exps, e->r);
                } else {
                        ne = exps_bind_column(rel->exps, e->r);

U rel_select.mx
Index: rel_select.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_select.mx,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -d -r1.89 -r1.90
--- rel_select.mx       22 Oct 2008 07:10:12 -0000      1.89
+++ rel_select.mx       28 Oct 2008 20:05:04 -0000      1.90
@@ -102,8 +102,11 @@
                _DELETE(rel->name);
        if (rel->exps)
                list_destroy(rel->exps);
-       if (is_join(rel->op) || is_select(rel->op) || 
-           is_set(rel->op) || rel->op == op_topn) {
+       if (is_join(rel->op) || 
+           is_semi(rel->op) || 
+           is_select(rel->op) || 
+           is_set(rel->op) || 
+           rel->op == op_topn) {
                if (rel->l)
                        rel_destroy(rel->l);
                if (rel->r)
@@ -367,7 +370,7 @@
        if (settname && !tname)
                tname = rel->name;
 
-       if (is_subquery(rel))
+       if (is_subquery(rel) && is_project(rel->op))
                return list_create(NULL);
 
        switch(rel->op) {
@@ -894,7 +897,9 @@
                        break;
                
                /* push down as long as the operators allow this */
-               if (!is_select(lrel->op) && lrel->op != op_join && 
+               if (!is_select(lrel->op) && 
+                   !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
+                   lrel->op != op_join && 
                    lrel->op != op_left)
                        break;
                /* pushing through left head of a left join is allowed */
@@ -911,7 +916,7 @@
                sql_rel *n = rel_select(lrel, e);
 
                if (p && p != lrel) {
-                       assert(p->op == op_join || p->op == op_left);
+                       assert(p->op == op_join || p->op == op_left || 
is_semi(p->op));
                        if (p->l == lrel) {
                                assert(p->l != n);
                                p->l = n;
@@ -956,7 +961,9 @@
                        and the relation is equal.
                 */
                if (lrel != rrel || 
-                  (!is_select(lrel->op) && lrel->op != op_join &&
+                  (!is_select(lrel->op) && 
+                   !(is_semi(lrel->op) && !rel_is_ref(lrel->l)) &&
+                   lrel->op != op_join &&
                    lrel->op != op_left))
                        break;
                /* pushing through left head of a left join is allowed */
@@ -1146,6 +1153,7 @@
        return NULL;
 }
 
+#if 0
 static sql_exp *
 rel_rename_column( mvc *sql, sql_rel *rel, char *cname )
 {
@@ -1162,6 +1170,25 @@
        exp_setname(e, NULL, nme);
        return exp_column(NULL, nme, exp_subtype(e), rel->card, has_nil(e));
 }
+#endif
+
+sql_exp *
+rel_find_column( mvc *sql, sql_rel *rel, char *cname )
+{
+       sql_rel *p = NULL;
+
+       if (!rel || (rel = rel_bind_column_(sql, &p, rel, cname)) == NULL)
+               return NULL;
+
+       if (is_project(rel->op) || rel->op == op_table) {
+               if (rel->exps) {
+                       sql_exp *e = exps_bind_column(rel->exps, cname);
+                       if (e)
+                               return e;
+               }
+       }
+       return NULL;
+}
 
 sql_exp *
 rel_bind_column( mvc *sql, sql_rel *rel, char *cname )
@@ -1171,10 +1198,12 @@
        if (!rel || (rel = rel_bind_column_(sql, &p, rel, cname)) == NULL)
                return NULL;
 
+/* 
        if (rel && is_subquery(rel) && p && is_join(p->op) && 
            rel->op == op_basetable && (p->l == rel || p->r == rel)) {
                return rel_rename_column(sql, rel, cname);
        }
+*/
 
        if (is_project(rel->op) || rel->op == op_table) {
                if (rel->exps) {
@@ -1209,7 +1238,10 @@
                if (!e)
                        e = rel_bind_column2(sql, rel->r, tname, cname);
                return e;
-       } else if (is_set(rel->op) || is_sort(rel) || is_select(rel->op)) {
+       } else if (is_set(rel->op) || 
+                  is_sort(rel) || 
+                  is_semi(rel->op) || 
+                  is_select(rel->op)) {
                if (rel->l)
                        return rel_bind_column2(sql, rel->l, tname, cname);
        } else if (rel->op == op_basetable && strcmp(rel->name, tname) == 0) {
@@ -2218,22 +2250,25 @@
                        return NULL;
                return rel_or(sql, lr, rr, f);
 
-/*
-               char *name;
-               sql_rel *lr, *rr;
+               //char *name;
+//             sql_rel *lr, *rr;
 
+/* don't name them, else rel_bin cannot find the correct stmts 
                rel_label(rel, ++sql->label);
                name = rel->name;
                stack_push_rel_view(sql, name, rel);
                lr = stack_find_rel_view(sql, name);
                rr = stack_find_rel_view(sql, name);
+*/
+/*
+               lr = rel_dup(rel);
+               rr = rel_dup(rel);
                
                lr = rel_logical_exp(sql, lr, lo, f);
                rr = rel_logical_exp(sql, rr, ro, f);
 
                if (!lr || !rr)
                        return NULL;
-               
                return rel_or(sql, lr, rr, f);
 */
        }
@@ -2296,8 +2331,15 @@
                                sql_rel *rl;
 
                                if (!r) {
-                                       r = rel_value_exp(sql, &left, sval, f, 
ek);
-                                       z = left;
+                                       /* reset error */
+                                       sql->session->status = 0;
+                                       sql->errstr[0] = 0;
+
+                                       /* TODO double dup to make sure we 
reference the rel */
+                                       /* TODO remove null checking (not 
needed in correlated case because of the semi/anti join) ! */
+                                       rel = left = rel_dup(rel_dup(left));
+                                       r = rel_value_exp(sql, &rel, sval, f, 
ek);
+                                       z = rel;
                                        correlated = 1;
                                }
                                if (!r || !(r=rel_check_type(sql, st, r, 
type_equal))) {
@@ -2332,10 +2374,7 @@
 
                        r = rel_lastexp(sql, right);
                        rel_setsubquery(right);
-                       if (correlated)
-                               rel = left;
-                       else
-                               rel = rel_crossproduct(left, right, op_join);
+                       rel = rel_crossproduct(left, right, op_join);
                        if (rel_convert_types(sql, &l, &r, 1, type_equal) < 0) {
                                exp_destroy(l);
                                exp_destroy(r);
@@ -2343,7 +2382,9 @@
                        }
                        e = exp_compare( l, r, cmp_equal );
                        rel_join_add_exp(rel, e);
-                       if (sc->token == SQL_NOT_IN) {
+                       if (correlated) {
+                               rel->op = (sc->token == SQL_IN)?op_semi:op_anti;
+                       } else if (sc->token == SQL_NOT_IN) {
                                rel->op = op_left;
                                e = rel_unop_(sql, exp_dup(r), NULL, "isnull");
                                r = exp_atom_bool(1);
@@ -2359,34 +2400,47 @@
        {
                symbol *lo = sc->data.sym;
                sql_rel *r;
+               sql_exp *e = NULL;
 
                ek.card = card_set;
                r = rel_subquery(sql, NULL, lo, ek);
-               if (!r) {
+               if (!r) { /* correlation */
+                       sql_exp *le, *re;
                        /* reset error */
                        sql->session->status = 0;
                        sql->errstr[0] = '\0';
 
-                       r = rel = rel_subquery(sql, rel, lo, ek);
-                       if (!rel)
+                       /* We don't have a natural anti/semi join but versions
+                          which require (join) expression. So we should 
+                          generate row id's which we use in the anti/semi
+                          join expression.
+                        */
+                       rel = rel_project(rel, rel_projections(sql, rel, NULL, 
1));
+                       e = rel_unop_(sql, exp_dup(rel->exps->h->data), NULL, 
"identity");
+                       rel_project_add_exp(sql, rel, e);
+                       e = exp_label(e, ++sql->label);
+
+                       /* TODO double dup to make sure we reference the rel */
+                       r = rel_subquery(sql, rel_dup(rel_dup(rel)), lo, ek);
+                       if (!r) 
                                return NULL;
-                       /* remove extra projection */
-                       if (!is_join(r->op)) {
-                               sql_rel *p = r;
 
-                               assert(is_project(r->op));
-                               rel = r = rel_dup(r->l);
-                               rel_destroy(p);
-                       }
-                       assert(r->op == op_join);
-               } else {        /* no correlation */
-                       r = rel = rel_crossproduct(rel, r, op_join);
+                       rel_label(r, ++sql->label);
+
+                       /* lookup the identity columns and label these */
+                       le = rel_bind_column(sql, rel, e->name);
+                       re = rel_bind_column(sql, r, e->name);
+
+                       e = exp_compare(le, re, cmp_equal);
                }
+               r = rel = rel_crossproduct(rel, r, op_join);
                if (sc->token == SQL_EXISTS) {
                        r->op = op_semi;
                } else {        
                        r->op = op_anti;
                }
+               if (e)
+                       rel->exps = append(new_exp_list(), e);
                return rel;
        }
        case SQL_LIKE:
@@ -3672,7 +3726,7 @@
                return rel_simple_select(sql, rel, sn->where, sn->selection);
 
        /* if within the selection, keep the current projections */
-       if (outer && is_project(outer->op) && !is_processed(outer)) {
+       if (outer && is_project(outer->op) && !is_processed(outer) && 
!rel_is_ref(outer)) {
                /* keep projections the hard way, ie don't rename them */
                assert(rel->l == outer);
 
@@ -3705,7 +3759,7 @@
 
                /* TODO if ek.card == card_set (IN/EXISTS etc), we could do 
                        something less expensive as group by's ! */
-               if (outer && rel->op == op_join && rel->l == outer) {
+               if (outer && rel->op == op_join && rel->l == outer && ek.card 
!= card_set) {
                        node *n;
                        /* correlation expressions */
                        list *ce = list_select(rel->exps, rel, (fcmp) 
&exp_is_correlation, (fdup)&exp_dup);
@@ -3914,7 +3968,7 @@
                l = rel = rel_project(rel, pre_prj);
                while(l && l->op != op_join) 
                        l = l->l;
-               if (l && l->op == op_join && l->l == outer)
+               if (l && l->op == op_join && l->l == outer && ek.card != 
card_set)
                        l->op = op_left;
        }
 

U sql_parser.mx
Index: sql_parser.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/sql_parser.mx,v
retrieving revision 1.294
retrieving revision 1.295
diff -u -d -r1.294 -r1.295
--- sql_parser.mx       23 Oct 2008 09:13:08 -0000      1.294
+++ sql_parser.mx       28 Oct 2008 20:05:04 -0000      1.295
@@ -409,6 +409,11 @@
        XML_validate
        XML_namespace_declaration
        opt_XML_namespace_declaration_and_comma
+       XML_namespace_declaration_item_list
+       XML_namespace_declaration_item
+       XML_regular_namespace_declaration_item
+       XML_default_namespace_declaration_item
+       XML_namespace_URI
        XML_attributes
        XML_attribute_list
        XML_attribute
@@ -454,7 +459,6 @@
        XML_attribute_name
        opt_forest_element_name
        forest_element_name
-       XML_namespace_URI
        XML_namespace_prefix
        XML_PI_target
 
@@ -534,10 +538,6 @@
        XML_element_content_list
        forest_element_list
        forest_element
-       XML_namespace_declaration_item_list
-       XML_namespace_declaration_item
-       XML_regular_namespace_declaration_item
-       XML_default_namespace_declaration_item
        XML_value_expression_list
 
 %type <i_val>
@@ -581,6 +581,9 @@
        opt_XML_content_option
        XML_content_option
        opt_XML_returning_clause
+       document_or_content
+       document_or_content_or_sequence
+       XML_whitespace_option
 
 %type <l_val>
        opt_start
@@ -4710,11 +4713,15 @@
 XML_parse:
   XMLPARSE '(' document_or_content value_exp /* should be a string */
       XML_whitespace_option ')'
-       { $$ = NULL; }
+       { dlist *l = L();
+         append_int(l, $3 );
+         append_symbol(l, $4);
+         append_int(l, $5);
+         $$ = _symbol_create_list( SQL_XMLPARSE, l); }
 
 XML_whitespace_option:
-    PRESERVE WHITESPACE
-  | STRIP WHITESPACE
+    PRESERVE WHITESPACE                { $$ = 0; }
+  | STRIP WHITESPACE           { $$ = 1; }
   ;
 
 XML_PI:
@@ -4808,12 +4815,12 @@
 
 document_or_content_or_sequence:
     document_or_content
-  | SEQUENCE
+  | SEQUENCE           { $$ = 2; }
   ;
 
 document_or_content:
-    DOCUMENT
-  | CONTENT
+    DOCUMENT           { $$ = 0; }
+  | CONTENT            { $$ = 1; }
   ;
 
 opt_XML_returning_clause:
@@ -4834,39 +4841,48 @@
 */
 
 XML_namespace_declaration:
-  XMLNAMESPACES '(' XML_namespace_declaration_item_list ')'
-       { $$ = _symbol_create_list(SQL_XMLNAMESPACES, $3); }
+  XMLNAMESPACES '(' XML_namespace_declaration_item_list ')'    { $$ = $3; }
   ;
 
 XML_namespace_declaration_item_list:
-       XML_namespace_declaration_item
-               { $$ = append_list(L(), $1); }
+       XML_namespace_declaration_item  { $$ = $1; }
   |     XML_namespace_declaration_item_list ',' XML_namespace_declaration_item
-               { $$ = append_list($1, $3); }
+               { dlist *l = L();
+                 append_list(l, 
+                       append_string(L(), sa_strdup(SA, "concat")));
+                 append_symbol(l, $1);
+                 append_symbol(l, $3);
+                 $$ = _symbol_create_list( SQL_BINOP, l ); }
   ;
 
 XML_namespace_declaration_item:
-    XML_regular_namespace_declaration_item
-  | XML_default_namespace_declaration_item
+       XML_regular_namespace_declaration_item
+  |    XML_default_namespace_declaration_item
   ;
 
 XML_namespace_prefix:
-    ident
+       ident
   ;
 
 XML_namespace_URI:
-       STRING
+       scalar_exp
   ;
 
 XML_regular_namespace_declaration_item:
     XML_namespace_URI AS XML_namespace_prefix
-                               { $$ = append_string(L(), $1);
-                                 $$ = append_string($$, $3); }
+                               { char *s = strconcat("xmlns:", $3);
+                                 dlist *l = L();
+                                 append_string(l, sa_strdup(SA, s));
+                                 _DELETE(s);
+                                 append_symbol(l, $1);
+                                 $$ = _symbol_create_list( SQL_XMLATTRIBUTE, l 
); }
   ;
 
 XML_default_namespace_declaration_item:
-    DEFAULT XML_namespace_URI  { $$ = append_string(L(), $2); 
-                                 $$ = append_string($$, NULL); }
+    DEFAULT XML_namespace_URI  { dlist *l = L();
+                                 append_string(l, sa_strdup(SA, "xmlns" ));
+                                 append_symbol(l, $2);
+                                 $$ = _symbol_create_list( SQL_XMLATTRIBUTE, l 
); }
   | NO DEFAULT                 { $$ = NULL; }
   ;
 

U rel_bin.mx
Index: rel_bin.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_bin.mx,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- rel_bin.mx  10 Oct 2008 08:59:25 -0000      1.54
+++ rel_bin.mx  28 Oct 2008 20:05:04 -0000      1.55
@@ -253,7 +253,7 @@
                                as = bin_first_column(left);
                        } else {
                                /* create dummy single value in a column */
-                               as = stmt_atom_int(0);
+                               as = stmt_atom_wrd(0);
                                as = stmt_append(stmt_temp(tail_type(as)), as);
                        }
                }
@@ -925,7 +925,7 @@
                sub = sql_bind_func(sql->session->schema, "sql_sub", 
tail_type(ls), tail_type(rs));
                /*s = sql_binop_(sql, NULL, "sql_sub", ls, rs);*/
                s = stmt_binop(ls, rs, sub);
-               s = stmt_select(s, stmt_atom_int(0), cmp_gt);
+               s = stmt_select(s, stmt_atom_wrd(0), cmp_gt);
 
                /* A ids */
                s = stmt_join(stmt_reverse(lm), s, cmp_equal);
@@ -1355,6 +1355,7 @@
        }
        if (sub) stmt_destroy(sub);
        if (groupby) grp_destroy(groupby);
+       stmt_set_nrcols(cursub);
        return cursub;
 }
 


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Monetdb-sql-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-sql-checkins

Reply via email to