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

Reply via email to