Changeset: 731115b9ec29 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=731115b9ec29
Modified Files:
        sql/common/sql_types.c
        sql/server/rel_select.c
        sql/server/sql_parser.y
        sql/server/sql_semantic.c
        sql/server/sql_tokens.h
        sql/test/analytics/Tests/analytics11.sql
Branch: grouping-analytics
Log Message:

Create an aggregate definition for "grouping" call.

We treat it as a special aggregate which gets replaced with a bit mask 
representing the columns not present on the aggregate.


diffs (truncated from 499 to 300 lines):

diff --git a/sql/common/sql_types.c b/sql/common/sql_types.c
--- a/sql/common/sql_types.c
+++ b/sql/common/sql_types.c
@@ -1535,6 +1535,8 @@ sqltypeinit( sql_allocator *sa)
        *t = NULL;
 
 //     sql_create_func(sa, "st_pointfromtext", "geom", "st_pointformtext", 
OID, NULL, OID, SCALE_FIX);
+       /* using ANY for the res type for grouping aggregate gives problems, 
however we don't care about the types of it at all */
+       sql_create_aggr(sa, "grouping", "sql", "grouping", ANY, TABLE);
 
        sql_create_aggr(sa, "not_unique", "sql", "not_unique", OID, BIT);
        /* well to be precise it does reduce and map */
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
@@ -3848,15 +3848,19 @@ rel_intermediates_add_exp(mvc *sql, sql_
        }
 }
 
-
-static sql_rel *
-rel_find_groupby(sql_query *query, sql_rel *groupby, sql_rel **og, sql_rel 
**sel, int *group, int f, char* aname)
+static sql_exp *
+_rel_aggr(sql_query *query, sql_rel **rel, int distinct, sql_schema *s, char 
*aname, dnode *args, int f)
 {
        mvc *sql = query->sql;
+       exp_kind ek = {type_value, card_column, FALSE};
+       sql_subaggr *a = NULL;
+       int no_nil = 0, group = 0, freevar = 1;
+       sql_rel *groupby = *rel, *sel = NULL, *gr, *og = NULL;
+       list *exps = NULL;
 
        /* find having select */
        if (groupby && !is_processed(groupby) && is_sql_having(f)) { 
-               *og = groupby;
+               og = groupby;
                while(!is_processed(groupby) && !is_base(groupby->op)) {
                        if (is_select(groupby->op) || !groupby->l)
                                break;
@@ -3864,20 +3868,20 @@ rel_find_groupby(sql_query *query, sql_r
                                groupby = groupby->l;
                }
                if (groupby && is_select(groupby->op) && 
!is_processed(groupby)) {
-                       *group = 1;
-                       *sel = groupby;
+                       group = 1;
+                       sel = groupby;
                        /* At the end we switch back to the old projection 
relation og. 
                         * During the partitioning and ordering we add the 
expressions to the intermediate relations. */
                }
-               if (!*sel)
-                       groupby = *og;
-               if (*sel && (*sel)->l)
-                       groupby = (*sel)->l;
+               if (!sel)
+                       groupby = og;
+               if (sel && sel->l)
+                       groupby = sel->l;
        }
 
        /* find groupby */
        if (groupby && !is_processed(groupby) && !is_base(groupby->op)) { 
-               *og = groupby;
+               og = groupby;
                while(!is_processed(groupby) && !is_base(groupby->op)) {
                        if (groupby->op == op_groupby || !groupby->l)
                                break;
@@ -3885,12 +3889,12 @@ rel_find_groupby(sql_query *query, sql_r
                                groupby = groupby->l;
                }
                if (groupby && groupby->op == op_groupby) {
-                       *group = 1;
+                       group = 1;
                        /* At the end we switch back to the old projection 
relation og. 
                         * During the partitioning and ordering we add the 
expressions to the intermediate relations. */
                }
-               if (!*group)
-                       groupby = *og;
+               if (!group)
+                       groupby = og;
        }
 
        if (!groupby) {
@@ -3910,56 +3914,6 @@ rel_find_groupby(sql_query *query, sql_r
                return NULL;
        }
 
-       return groupby;
-}
-
-static sql_exp *
-rel_grouping(sql_query *query, sql_rel **rel, symbol *se, int f)
-{
-       mvc *sql = query->sql;
-       sql_rel *groupby, *sel = NULL, *og = NULL;
-       int group = 0;
-       dlist *l = se->data.lval;
-       list *group_cols;
-
-       (void) group;
-       (void) sel;
-       (void) og;
-
-       if (is_sql_groupby(f) || is_sql_partitionby(f) || is_sql_where(f) || 
is_sql_from(f))
-               return sql_error(sql, 02, SQLSTATE(42000) "SELECT: GROUPING 
expression not allowed in %s clause", 
-                                                is_sql_groupby(f) ? "GROUP BY" 
: is_sql_partitionby(f) ? "PARTITION BY" : is_sql_where(f) ? "WHERE" : "FROM");
-       if (!(groupby = rel_find_groupby(query, *rel, &og, &sel, &group, f, 
"GROUPING")))
-               return NULL;
-       if (groupby->op != op_groupby)
-               return sql_error(sql, 02, SQLSTATE(42000) "SELECT: GROUPING 
requires a GROUP BY clause");
-
-       group_cols = (list*) groupby->r;
-
-       for (dnode *dn = l->h; dn; dn = dn->next) {
-               symbol *sym = dn->data.sym;
-               exp_kind ek = {type_value, card_column, FALSE};
-               sql_exp *col = rel_value_exp(query, rel, sym, f, ek);
-               if (!col)
-                       return NULL; /* GROUPING(x, ...) columns must be 
present in the GROUP BY clause */
-       }
-
-       return exp_atom(sql->sa, atom_int(sql->sa, sql_bind_localtype("int"), 
0));
-}
-
-static sql_exp *
-_rel_aggr(sql_query *query, sql_rel **rel, int distinct, sql_schema *s, char 
*aname, dnode *args, int f)
-{
-       mvc *sql = query->sql;
-       exp_kind ek = {type_value, card_column, FALSE};
-       sql_subaggr *a = NULL;
-       int no_nil = 0, group = 0, freevar = 1;
-       sql_rel *groupby, *sel = NULL, *gr, *og = NULL;
-       list *exps = NULL;
-
-       if (!(groupby = rel_find_groupby(query, *rel, &og, &sel, &group, f, 
aname)))
-               return NULL;
-
        if (groupby->op != op_groupby) { /* implicit groupby */
                sql_rel *np = rel_project2groupby(sql, groupby);
 
@@ -4047,7 +4001,11 @@ static sql_exp *
                list_append(exps, e);
        }
 
-       a = sql_bind_aggr_(sql->sa, s, aname, exp_types(sql->sa, exps));
+       if (!strcmp(aname, "grouping"))
+               a = sql_bind_aggr(sql->sa, s, aname, NULL);
+       else
+               a = sql_bind_aggr_(sql->sa, s, aname, exp_types(sql->sa, exps));
+
        if (!a && list_length(exps) > 1) { 
                sql_subtype *t1 = exp_subtype(exps->h->data);
                a = sql_bind_member_aggr(sql->sa, s, aname, 
exp_subtype(exps->h->data), list_length(exps));
@@ -6036,8 +5994,6 @@ rel_value_exp2(sql_query *query, sql_rel
                        return exp_atom(sql->sa, atom_dup(sql->sa, an->a));
                }
        }
-       case SQL_GROUPING:
-               return rel_grouping(query, rel, se, f);
        case SQL_NEXT:
                return rel_next_value_for(sql, se);
        case SQL_CAST:
@@ -6274,6 +6230,175 @@ rel_remove_internal_exp(sql_rel *rel)
        }
 }
 
+static sql_exp*
+exp_replace_groupings(mvc *sql, sql_rel *rel, sql_exp *e)
+{
+       assert(e);
+       switch(e->type) {
+               case e_atom:
+               case e_column:
+               case e_psm:
+                       break;
+               case e_convert: {
+                       e->l = exp_replace_groupings(sql, rel, e->l);
+               } break;
+               case e_func: {
+                       for (node *n = ((list*)e->l)->h ; n ; n = n->next)
+                               n->data = exp_replace_groupings(sql, rel, 
(sql_exp*) n->data);
+                       if (e->r)
+                               for (node *n = ((list*)e->r)->h ; n ; n = 
n->next)
+                                       n->data = exp_replace_groupings(sql, 
rel, (sql_exp*) n->data);
+               } break;
+               case e_aggr: {
+                       sql_subaggr *aggr = (sql_subaggr*) e->f;
+                       if (!strcmp(aggr->aggr->base.name, "grouping")) {
+                               sql_subtype *tpe;
+                               sql_exp *res;
+                               list *groups = (list*)e->l, *group_cols;
+                               atom *a;
+#ifdef HAVE_HGE
+                               hge counter = (hge) list_length(groups) - 1;
+#else
+                               lng counter = (lng) list_length(groups) - 1;
+#endif
+                               assert(groups && list_length(groups) > 0 && 
is_groupby(rel->op));
+                               group_cols = (list*) rel->r;
+
+                               if (list_length(group_cols) <= 7)
+                                       tpe = sql_bind_localtype("bte");
+                               else if (list_length(group_cols) <= 15)
+                                       tpe = sql_bind_localtype("sht");
+                               else if (list_length(group_cols) <= 31)
+                                       tpe = sql_bind_localtype("int");
+                               else if (list_length(group_cols) <= 63)
+                                       tpe = sql_bind_localtype("lng");
+#ifdef HAVE_HGE
+                               else if (list_length(group_cols) <= 127)
+                                       tpe = sql_bind_localtype("hge");
+#endif
+                               else
+                                       return sql_error(sql, 02, 
SQLSTATE(42000) "SELECT: GROUPING the number of grouping columns is larger than"
+                                                                        " the 
maximum possible for this call (%d > %d)", list_length(group_cols),
+#ifdef HAVE_HGE
+                                                                        127
+#else
+                                                                        63
+#endif
+                                                                       );
+
+                               a = atom_int(sql->sa, tpe, 0);
+                               for (node *n = groups->h ; n ; n = n->next) {
+                                       sql_exp *exp = (sql_exp*) n->data;
+                                       if (!exps_find_exp(group_cols, exp)) {
+                                               switch 
(ATOMstorage(a->data.vtype)) {
+                                                       case TYPE_bte:
+                                                               
a->data.val.btval += (bte) (1 << counter);
+                                                               break;
+                                                       case TYPE_sht:
+                                                               
a->data.val.shval += (sht) (1 << counter);
+                                                               break;
+                                                       case TYPE_int:
+                                                               
a->data.val.ival += (int) (1 << counter);
+                                                               break;
+                                                       case TYPE_lng:
+                                                               
a->data.val.lval += (lng) (1 << counter);
+                                                               break;
+#ifdef HAVE_HGE
+                                                       case TYPE_hge:
+                                                               
a->data.val.hval += (hge) (1 << counter);
+                                                               break;
+#endif
+                                                       default:
+                                                               assert(0);
+                                               }
+                                       }
+                                       counter--;
+                               }
+
+                               res = exp_atom(sql->sa, a);
+                               exp_setname(sql->sa, res, e->alias.rname, 
e->alias.name);
+                               return res;
+                       }
+               } break;
+               case e_cmp: {
+                       if (e->flag == cmp_in || e->flag == cmp_notin) {
+                               e->l = exp_replace_groupings(sql, rel, e->l);
+                               for (node *n = ((list*)e->r)->h ; n ; n = 
n->next)
+                                       n->data = exp_replace_groupings(sql, 
rel, (sql_exp*) n->data);
+                       } else if (get_cmp(e) == cmp_or || get_cmp(e) == 
cmp_filter) {
+                               for (node *n = ((list*)e->l)->h ; n ; n = 
n->next)
+                                       n->data = exp_replace_groupings(sql, 
rel, (sql_exp*) n->data);
+                               for (node *n = ((list*)e->r)->h ; n ; n = 
n->next)
+                                       n->data = exp_replace_groupings(sql, 
rel, (sql_exp*) n->data);
+                       } else {
+                               if (e->l)
+                                       e->l = exp_replace_groupings(sql, rel, 
e->l);
+                               if (e->r)
+                                       e->l = exp_replace_groupings(sql, rel, 
e->r);
+                               if (e->f)
+                                       e->l = exp_replace_groupings(sql, rel, 
e->f);
+                       }
+               } break;
+       }
+       return e;
+}
+
+static sql_rel*
+rel_replace_groupings(mvc *sql, sql_rel *rel)
+{
+       assert(rel);
+       if (THRhighwater())
+               return sql_error(sql, 10, SQLSTATE(42000) "query too complex: 
running out of stack space");
+
+       switch (rel->op) {
+               case op_basetable:
+               case op_table:
+               case op_ddl:
+                       break;
+               case op_join:
+               case op_left:
+               case op_right:
+               case op_full:
+               case op_semi:
+               case op_anti:
+               case op_union:
+               case op_inter:
+               case op_except:
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to