Changeset: d7e9bed179b1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d7e9bed179b1
Modified Files:
        sql/server/rel_select.c
        sql/server/rel_unnest.c
        sql/test/BugTracker/Tests/bug_in_selection.SF-1892413.stable.out
        sql/test/Tests/marcin1.stable.out
Branch: subquery
Log Message:

improvements on handling EXISTs (both on the unnesting as the semantic side)


diffs (truncated from 464 to 300 lines):

diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -124,7 +124,7 @@ static sql_exp *
 {
        sql_exp *e;
 
-       if (!is_processed(rel) || is_topn(rel->op))
+       if (!is_processed(rel) || is_topn(rel->op) || is_sample(rel->op))
                rel = rel_parent(rel);
        assert(list_length(rel->exps));
        assert(is_project(rel->op));
@@ -1867,7 +1867,10 @@ rel_compare(sql_query *query, sql_rel *r
                                        rs = rel_groupby_add_aggr(sql, r->r, 
rs);
                                        rs = exp_column(sql->sa, 
exp_relname(rs), exp_name(rs), exp_subtype(rs), exp_card(rs), has_nil(rs), 
is_intern(rs));
                                }
-                               rel = r;
+                               if (rel) { 
+                                       rel = rel_crossproduct(sql->sa, rel, r, 
(!quantifier)?op_semi:op_join);
+                                       set_dependent(rel);
+                               }
                        }
                } else if (r) {
                        if (list_length(r->exps) != 1) 
@@ -2468,61 +2471,55 @@ rel_logical_value_exp(sql_query *query, 
        case SQL_NOT_EXISTS:
        {
                symbol *lo = sc->data.sym;
-               sql_rel *sq = NULL, *outer = NULL;
+               sql_rel *orel = *rel, *sq = NULL;
+               list *pexps = NULL;
+               int needproj = 0, exists=(sc->token == SQL_EXISTS);
+
                sql_exp *le;
-               sql_subfunc *exists = NULL;
+
+               /* no input, assume single value */
+               if ((!orel || (is_project(orel->op) && !is_processed(orel) && 
!orel->l && list_empty(orel->exps))) && !query->outer) 
+                       orel = *rel = rel_project_exp(sql->sa, 
exp_atom_bool(sql->sa, 1));
 
                ek.card = card_set;
+               if (is_sql_sel(f) && orel && is_project(orel->op) && 
!is_processed(orel)) {
+                       needproj = 1;
+                       pexps = orel->exps;
+                       *rel = orel->l;
+               }
+
                le = rel_value_exp(query, &sq, lo, f, ek);
-               /* correlated */
-               if (!le && sql->session->status != -ERR_AMBIGUOUS) {
+               if (!le && sql->session->status != -ERR_AMBIGUOUS) { /* 
correlated */
                        sql_subaggr *ea = NULL;
-                       /* dependent left/mark join */
-                       sql_rel *orel = *rel;
-                       //sql_exp *ident = NULL;
-                       list *pexps = NULL;
-                       int needproj = 0;
-                       //int apply = (sc->token == 
SQL_EXISTS)?APPLY_EXISTS:APPLY_NOTEXISTS;
-
-                       if (is_project(orel->op) && !is_processed(orel)) {
-                               needproj = 1;
-                               pexps = orel->exps;
-                               *rel = orel->l;
-                       }
-
-                       //outer = *rel;
-                       sq = *rel;
+
                        /* reset error */
                        sql->session->status = 0;
                        sql->errstr[0] = 0;
-                       /* add identity early, used in the apply optimizer */
-                       //sq = *rel = rel_add_identity(sql, rel_dup(*rel), 
&ident);
-                       query->outer = sq; //TODO: later move into rel_subquery
-                       sq = rel_subquery(query, NULL, lo, ek, 0);//apply);
-                       query->outer = NULL; //TODO: later move into 
rel_subquery
-                       /* add group by */
-                       //le = rel_value_exp(query, &sq, lo, f, ek);
-                       //if (is_apply(sq->op))
-                               //sq->flag = 
(sc->token==SQL_EXISTS)?APPLY_EXISTS:APPLY_NOTEXISTS;
-                       if (*rel != orel) {
+
+                       query->outer = *rel;
+                       sq = rel_subquery(query, NULL, lo, ek, 0);
+                       query->outer = NULL;
+
+                       if (!sq)
+                               return NULL;
+
+                       if (*rel != orel) { /* remove proejct */
                                orel->l = NULL;
                                rel_destroy(orel);
                        }
-                       le = rel_lastexp(sql, sq);
-                       /* aggr (not) exist */
-                       sq = rel_groupby(sql, sq, NULL);
-                       ea = sql_bind_aggr(sql->sa, sql->session->schema, 
"count", exp_subtype(le));
-                       le = exp_aggr1(sql->sa, le, ea, 0, 0, CARD_ATOM, 0);
-                       le = rel_groupby_add_aggr(sql, sq, le);
-                       le = exp_ref(sql->sa, le);
-                       *rel = rel_crossproduct(sql->sa, *rel, sq, op_left); 
+
+                       //le = rel_lastexp(sql, sq);
+                       le = _rel_lastexp(sql, sq);
+                       if (is_sql_sel(f)) { /* aggr (not) exist */
+                               sq = rel_groupby(sql, sq, NULL);
+                               ea = sql_bind_aggr(sql->sa, 
sql->session->schema, exists?"exist":"not_exist", exp_subtype(le));
+                               le = exp_aggr1(sql->sa, le, ea, 0, 0, 
CARD_ATOM, 0);
+                               le = rel_groupby_add_aggr(sql, sq, le);
+                               le = exp_ref(sql->sa, le);
+                       } 
+                       *rel = rel_crossproduct(sql->sa, *rel, sq, 
is_sql_sel(f)?op_left:exists?op_semi:op_anti); 
                        set_dependent(*rel);
-                       le = rel_unop_(query, le, NULL, "isnull", card_value);
-                       if (sc->token == SQL_EXISTS)
-                               le = rel_unop_(query, le, NULL, "not", 
card_value);
-                       if (!is_sql_sel(f)) { /* handle where/having etc */
-                               rel_join_add_exp(sql->sa, *rel, le);
-                       } else if (*rel && needproj) {
+                       if (*rel && needproj) {
                                *rel = rel_project(sql->sa, *rel, pexps);
                                reset_processed(*rel);
                        } 
@@ -2533,35 +2530,42 @@ rel_logical_value_exp(sql_query *query, 
 
                le = rel_is_constant(&sq, le);
 
-               if (!sq) { 
-                       if (sc->token != SQL_EXISTS)
-                               exists = sql_bind_func(sql->sa, 
sql->session->schema, "sql_not_exists", exp_subtype(le), NULL, F_FUNC);
+               if (!sq) {
+                       sql_subfunc *exists_func = NULL;
+                       
+                       if (exists)
+                               exists_func = sql_bind_func(sql->sa, 
sql->session->schema, "sql_exists", exp_subtype(le), NULL, F_FUNC);
                        else
-                               exists = sql_bind_func(sql->sa, 
sql->session->schema, "sql_exists", exp_subtype(le), NULL, F_FUNC);
-
-                       if (!exists) 
+                               exists_func = sql_bind_func(sql->sa, 
sql->session->schema, "sql_not_exists", exp_subtype(le), NULL, F_FUNC);
+
+                       if (!exists_func) 
                                return sql_error(sql, 02, SQLSTATE(42000) 
"exist operator on type %s missing", exp_subtype(le)->type->sqlname);
-                       return exp_unop(sql->sa, le, exists);
+                       *rel = orel;
+                       return exp_unop(sql->sa, le, exists_func);
                } else {
-                       sql_exp *e;
-                       list *pexps = NULL;
-                       int needproj = 0;
-
-                       if (outer && is_sql_sel(f) && is_project(outer->op) && 
!is_processed(outer)) {
-                               needproj = 1;
-                               pexps = outer->exps;
-                               *rel = outer->l;
+                       sql_subaggr *ea = NULL;
+
+                       if (*rel != orel) { /* remove proejct */
+                               orel->l = NULL;
+                               rel_destroy(orel);
                        }
-                       if (sq->processed)
-                               sq = rel_label(sql, sq, 0);
-                       le = rel_lastexp(sql, sq);
-                       *rel = rel_mark(sql, *rel, sq, NULL, 
exp_atom_int(sql->sa, 1), le, (sc->token == 
SQL_EXISTS)?mark_exists:mark_notexists);
-                       e = rel_lastexp(sql, *rel);
+
+                       //le = rel_lastexp(sql, sq);
+                       le = _rel_lastexp(sql, sq);
+                       if (is_sql_sel(f)) { /* aggr (not) exist */
+                               sq = rel_groupby(sql, sq, NULL);
+                               ea = sql_bind_aggr(sql->sa, 
sql->session->schema, exists?"exist":"not_exist", exp_subtype(le));
+                               le = exp_aggr1(sql->sa, le, ea, 0, 0, 
CARD_ATOM, 0);
+                               le = rel_groupby_add_aggr(sql, sq, le);
+                               le = exp_ref(sql->sa, le);
+                       }
+                       *rel = rel_crossproduct(sql->sa, *rel, sq, 
is_sql_sel(f)?op_left:exists?op_semi:op_anti); 
+                       set_dependent(*rel);
                        if (*rel && needproj) {
                                *rel = rel_project(sql->sa, *rel, pexps);
                                reset_processed(*rel);
                        } 
-                       return e;
+                       return le;
                }
        }
        case SQL_LIKE:
@@ -2802,10 +2806,14 @@ rel_logical_exp(sql_query *query, sql_re
                for(n=nors->h; n; n = n->next) {
                        symbol *lo = n->data;
                        rel = rel_logical_exp(query, rel, lo, f);
+                       if (!rel)
+                               return NULL;
                }
                for(n=ors->h; n; n = n->next) {
                        symbol *lo = n->data;
                        rel = rel_logical_exp(query, rel, lo, f);
+                       if (!rel)
+                               return NULL;
                }
                /*
                rel = rel_logical_exp(query, rel, lo, f);
@@ -3092,33 +3100,65 @@ rel_logical_exp(sql_query *query, sql_re
        case SQL_NOT_EXISTS:
        {
                symbol *lo = sc->data.sym;
-               sql_rel *r;
-               int apply = (sc->token == 
SQL_EXISTS)?APPLY_EXISTS:APPLY_NOTEXISTS;
+               sql_rel *orel = rel, *sq = NULL;
+               list *pexps = NULL;
+               int needproj = 0, exists=(sc->token == SQL_EXISTS);
 
                ek.card = card_set;
-               r = rel_subquery(query, NULL, lo, ek, apply);
-               if (!r && rel && sql->session->status != -ERR_AMBIGUOUS) { /* 
correlation */
-                       sql_rel *orel = rel;
-                       sql_exp *ident = NULL;
+               if (orel && is_project(orel->op) && !is_processed(orel)) {
+                       needproj = 1;
+                       pexps = orel->exps;
+                       rel = orel->l;
+               }
+
+               sq = rel_subquery(query, NULL, lo, ek, 0);
+               if (!sq && rel && sql->session->status != -ERR_AMBIGUOUS) { /* 
correlation */
+                       sql_rel *outer = query->outer; /* should join the 
outers? */
+                       sql_subaggr *ea = NULL;
+                       sql_exp *le;
 
                        /* reset error */
                        sql->session->status = 0;
                        sql->errstr[0] = '\0';
-                       /* add identity early, used in the apply optimizer */
-                       rel = rel_add_identity(sql, rel_dup(rel), &ident);
-                       r = rel_subquery(query, rel, lo, ek, apply);
-                       rel_destroy(orel);
-                       return r;
-               }
-               if (r && query->outer)
-                       return r;
-               if (!r || !rel)
+
+                       query->outer = rel; 
+                       sq = rel_subquery(query, NULL, lo, ek, 0);
+                       query->outer = outer; 
+
+                       if (!sq)
+                               return NULL;
+
+                       if (rel != orel) { /* remove project */
+                               orel->l = NULL;
+                               rel_destroy(orel);
+                       }
+
+                       //le = rel_lastexp(sql, sq);
+                       le = _rel_lastexp(sql, sq);
+                       if (is_sql_sel(f)) { /* aggr (not) exist */
+                               sq = rel_groupby(sql, sq, NULL);
+                               ea = sql_bind_aggr(sql->sa, 
sql->session->schema, exists?"exist":"not_exist", exp_subtype(le));
+                               le = exp_aggr1(sql->sa, le, ea, 0, 0, 
CARD_ATOM, 0);
+                               le = rel_groupby_add_aggr(sql, sq, le);
+                               le = exp_ref(sql->sa, le);
+                       }
+                       rel = rel_crossproduct(sql->sa, rel, sq, 
is_sql_sel(f)?op_left:exists?op_semi:op_anti); 
+                       set_dependent(rel);
+                       if (rel && needproj) {
+                               rel = rel_project(sql->sa, rel, pexps);
+                               reset_processed(rel);
+                       } 
+                       return rel;
+               }
+               if (!sq || !rel)
                        return NULL;
-               r = rel = rel_crossproduct(sql->sa, rel, r, op_join);
+               if (!rel)
+                       assert(0);
+               rel = rel_crossproduct(sql->sa, rel, sq, op_join);
                if (sc->token == SQL_EXISTS) {
-                       r->op = op_semi;
+                       rel->op = op_semi;
                } else {        
-                       r->op = op_anti;
+                       rel->op = op_anti;
                }
                return rel;
        }
@@ -4865,8 +4905,14 @@ rel_order_by(sql_query *query, sql_rel *
                                        } else if (e->type == e_atom) {
                                                return sql_error(sql, 02, 
SQLSTATE(42000) "order not of type SQL_COLUMN");
                                        }
-                               } else if (e && e->card != rel->card) 
-                                       e = NULL;
+                               } else if (e && e->card != rel->card) {
+                                       if (e && e->name) {
+                                               return sql_error(sql, 02, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results 
without an aggregate function", e->name);
+                                       } else {
+                                               return sql_error(sql, 02, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results 
without an aggregate function");
+                                       }
+                                       //e = NULL;
+                               }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to