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