Changeset: 43a0834f3796 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/43a0834f3796 Modified Files: sql/server/rel_select.c Branch: literal_features Log Message:
factor out code and check multiple unique keys diffs (115 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 @@ -1226,6 +1226,59 @@ sql_rel* find_union(visitor *v, sql_rel return rel; } +static inline +bool group_by_pk_project_uk_cond(mvc* sql, sql_rel* inner, sql_exp* exp,const char* sname, const char* tname) { + sql_table* t = find_table_or_view_on_scope(sql, NULL, sname, tname, "SELECT", false); + bool allow = false; + if (t) { + sql_idx* pki = NULL; + list *ukil = sa_list(sql->sa); + + for (node * n = ol_first_node(t->idxs); n; n = n->next) { + sql_idx *i = n->data; + switch (i->key->type) { + case pkey: + pki = i; + continue; + case ukey: + case unndkey: + list_append(ukil, i); + continue; + default: + continue; + } + } + if (pki && pki->columns->cnt == 1 && ((list*) inner->r)->cnt == 1) { + /* for now only check simple case where primary key and group by expression is a single column*/ + sql_exp* gbe = ((list*) inner->r)->h->data; + assert(gbe->type == e_column); + sql_column* pkc = ((sql_kc *)pki->columns->h->data)->c; + if (strcmp(gbe->alias.name, pkc->base.name) == 0) { + node *n; + for (n = ukil->h; n; n = n->next){ + sql_idx* uki = n->data; + if (uki->columns->cnt == 1) { + /* for now only check simple case where unique key is a single column*/ + sql_column* ukc = ((sql_kc *)uki->columns->h->data)->c; + if (strcmp(exp->alias.name, ukc->base.name) == 0) + allow = true; + } + } + } + } + + /* sufficiency condition: abort if relation contains union subrelation + * because it may break functional dependency between pk and uk */ + visitor v = {.sql=sql}; + rel_visitor_topdown(&v, inner, &find_union); + if (v.data) + allow = false; + } + + return allow; + +} + static sql_exp * rel_column_ref(sql_query *query, sql_rel **rel, symbol *column_r, int f) { @@ -1422,48 +1475,9 @@ rel_column_ref(sql_query *query, sql_rel } if (!exp) { if (inner && !is_sql_aggr(f) && is_groupby(inner->op) && inner->l && (exp = rel_bind_column3(sql, inner->l, sname, tname, cname, f))) { - sql_table* t = find_table_or_view_on_scope(sql, NULL, sname, tname, "SELECT", false); - bool check_pk_with_uk = false; - if (t) { - sql_idx* pki = NULL; - sql_idx* uki = NULL; - for (node * n = ol_first_node(t->idxs); n; n = n->next) { - sql_idx *i = n->data; - - switch (i->key->type) { - case pkey: - pki = i; - continue; - case ukey: - case unndkey: - uki = i; - continue; - default: - continue; - } - } - - if (uki && pki) { - if (pki->columns->cnt == 1 && uki->columns->cnt == 1 && ((list*) inner->r)->cnt == 1) { - sql_column* pkc = ((sql_kc *)pki->columns->h->data)->c; - sql_column* ukc = ((sql_kc *)uki->columns->h->data)->c; - (void) pkc; - (void) ukc; - sql_exp* gbe = ((list*) inner->r)->h->data; - assert(gbe->type == e_column); - if (strcmp(gbe->alias.name, pkc->base.name) == 0 && strcmp(exp->alias.name, ukc->base.name) == 0) - check_pk_with_uk = true; - } - } - if (check_pk_with_uk) { - visitor v = {.sql=sql}; - rel_visitor_topdown(&v, inner, &find_union); - if (v.data) - check_pk_with_uk = false; - } - } - - if (check_pk_with_uk) { + if (group_by_pk_project_uk_cond(sql, inner, exp, sname, tname)) { + /* SQL23 feature: very special case where primary key is used in GROUP BY expression and + * unique key is in the project list or ORDER BY clause */ sql->session->status = 0; sql->errstr[0] = 0; exp->card = CARD_AGGR; _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org