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