LCOV - code coverage report
Current view: top level - sql/server - rel_basetable.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 309 374 82.6 %
Date: 2024-04-26 00:35:57 Functions: 23 26 88.5 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "rel_rel.h"
      15             : #include "rel_exp.h"
      16             : #include "rel_prop.h"
      17             : #include "rel_basetable.h"
      18             : #include "rel_remote.h"
      19             : #include "rel_statistics.h"
      20             : #include "rel_rewriter.h"
      21             : #include "sql_privileges.h"
      22             : 
      23             : #define USED_LEN(nr) ((nr+31)/32)
      24             : #define rel_base_set_used(b,nr) b->used[(nr)/32] |= (1U<<((nr)%32))
      25             : #define rel_base_is_used(b,nr) ((b->used[(nr)/32]&(1U<<((nr)%32))) != 0)
      26             : 
      27             : typedef struct rel_base_t {
      28             :         sql_table *mt;
      29             :         char *name;
      30             :         int disallowed; /* ie check per column */
      31             :         uint32_t used[];
      32             : } rel_base_t;
      33             : 
      34             : void
      35          64 : rel_base_disallow(sql_rel *r)
      36             : {
      37          64 :         rel_base_t *ba = r->r;
      38          64 :         ba->disallowed = 1;
      39          64 : }
      40             : 
      41             : char *
      42      132298 : rel_base_name(sql_rel *r)
      43             : {
      44      132298 :         sql_table *t = r->l;
      45      132298 :         rel_base_t *ba = r->r;
      46      132298 :         if (ba->name)
      47             :                 return ba->name;
      48      131140 :         return t->base.name;
      49             : }
      50             : 
      51             : char *
      52           0 : rel_base_rename(sql_rel *r, char *name)
      53             : {
      54           0 :         rel_base_t *ba = r->r;
      55           0 :         ba->name = name;
      56           0 :         return name;
      57             : }
      58             : 
      59             : int
      60     1651167 : rel_base_use( mvc *sql, sql_rel *rt, int nr)
      61             : {
      62     1651167 :         assert(is_basetable(rt->op));
      63     1651167 :         sql_table *t = rt->l;
      64     1651167 :         rel_base_t *ba = rt->r;
      65             : 
      66     1651167 :         if (ba->disallowed && nr < ol_length(t->columns)) {
      67          29 :                 sql_column *c = ol_fetch(t->columns, nr);
      68          29 :                 if (!column_privs(sql, c, PRIV_SELECT))
      69             :                         return -1;
      70             :         }
      71     1651155 :         rel_base_set_used(ba, nr);
      72     1651155 :         return 0;
      73             : }
      74             : 
      75             : void
      76        6971 : rel_base_use_tid( mvc *sql, sql_rel *rt)
      77             : {
      78        6971 :         sql_table *t = rt->l;
      79        6971 :         rel_base_use(sql, rt, ol_length(t->columns));
      80        6971 : }
      81             : 
      82             : void
      83      378747 : rel_base_use_all( mvc *sql, sql_rel *rel)
      84             : {
      85      378747 :         sql_table *t = rel->l;
      86      378747 :         rel_base_t *ba = rel->r;
      87             : 
      88      378747 :         if (ba->disallowed) {
      89          10 :                 int i = 0;
      90          33 :                 for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
      91          23 :                         sql_column *c = cn->data;
      92          23 :                         if (!column_privs(sql, c, PRIV_SELECT))
      93          12 :                                 continue;
      94          11 :                         rel_base_set_used(ba, i);
      95             :                 }
      96             :         } else {
      97      378737 :                 int len = USED_LEN(ol_length(t->columns) + 1 + ol_length(t->idxs));
      98      761696 :                 for (int i = 0; i < len; i++)
      99      382847 :                         ba->used[i] = ~0U;
     100             :         }
     101      378859 : }
     102             : 
     103             : sql_rel *
     104      601020 : rel_basetable(mvc *sql, sql_table *t, const char *atname)
     105             : {
     106      601020 :         allocator *sa = sql->sa;
     107      601020 :         sql_rel *rel = rel_create(sa);
     108      601218 :         int nrcols = ol_length(t->columns), end = nrcols + 1 + ol_length(t->idxs);
     109      601517 :         rel_base_t *ba = (rel_base_t*)sa_zalloc(sa, sizeof(rel_base_t) + sizeof(int)*USED_LEN(end));
     110      601321 :         sqlstore *store = sql->session->tr->store;
     111             : 
     112      601321 :         if(!rel || !ba)
     113             :                 return NULL;
     114             : 
     115      601321 :         if (isTable(t) && t->s && !isDeclaredTable(t)) /* count active rows only */
     116      543217 :                 set_count_prop(sql->sa, rel, (BUN)store->storage_api.count_col(sql->session->tr, ol_first_node(t->columns)->data, 10));
     117      601145 :         assert(atname);
     118      601145 :         if (strcmp(atname, t->base.name) != 0)
     119      234370 :                 ba->name = sa_strdup(sa, atname);
     120     1348842 :         for(int i = nrcols; i<end; i++)
     121      747697 :                 rel_base_set_used(ba, i);
     122      601145 :         rel->l = t;
     123      601145 :         rel->r = ba;
     124      601145 :         rel->op = op_basetable;
     125      601145 :         rel->card = CARD_MULTI;
     126      601145 :         rel->nrcols = nrcols;
     127      601145 :         return rel;
     128             : }
     129             : 
     130             : void
     131          57 : rel_base_copy(mvc *sql, sql_rel *in, sql_rel *out)
     132             : {
     133          57 :         allocator *sa = sql->sa;
     134          57 :         sql_table *t = in->l;
     135          57 :         rel_base_t *ba = in->r;
     136             : 
     137          57 :         assert(is_basetable(in->op) && is_basetable(out->op));
     138          57 :         int nrcols = ol_length(t->columns), end = nrcols + 1 + ol_length(t->idxs);
     139          57 :         size_t bsize = sizeof(rel_base_t) + sizeof(uint32_t)*USED_LEN(end);
     140          57 :         rel_base_t *nba = (rel_base_t*)sa_alloc(sa, bsize);
     141             : 
     142          57 :         memcpy(nba, ba, bsize);
     143          57 :         if (ba->name)
     144           0 :                 nba->name = sa_strdup(sa, ba->name);
     145             : 
     146          57 :         out->l = t;
     147          57 :         out->r = nba;
     148          57 : }
     149             : 
     150             : sql_rel *
     151           2 : rel_base_bind_column_( sql_rel *rel, const char *cname)
     152             : {
     153           2 :         sql_table *t = rel->l;
     154           2 :         node *n = ol_find_name(t->columns, cname);
     155           2 :         if (n)
     156           0 :                 return rel;
     157             :         return NULL;
     158             : }
     159             : 
     160             : static sql_exp *
     161     2186856 : bind_col_exp(mvc *sql, char *name, sql_column *c)
     162             : {
     163     2186856 :         prop *p = NULL;
     164     2186856 :         sql_exp *e = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     165             : 
     166     2186863 :         if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     167       80320 :                 p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     168       80320 :                 p->value.pval = c->t->pkey;
     169     2106543 :         } else if (c->unique == 2) {
     170       21628 :                 p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     171       21628 :                 p->value.pval = NULL;
     172             :         }
     173     2186863 :         set_basecol(e);
     174     2186863 :         sql_column_get_statistics(sql, c, e);
     175     2186864 :         return e;
     176             : }
     177             : 
     178             : static sql_exp *
     179     1571189 : bind_col(mvc *sql, sql_rel *rel, char *name, sql_column *c )
     180             : {
     181     1571189 :         if (rel_base_use(sql, rel, c->colnr)) {
     182             :                 /* error */
     183             :                 return NULL;
     184             :         }
     185     1571177 :         return bind_col_exp(sql, name, c);
     186             : }
     187             : 
     188             : sql_exp *
     189         238 : rel_base_bind_colnr( mvc *sql, sql_rel *rel, int nr)
     190             : {
     191         238 :         sql_table *t = rel->l;
     192         238 :         rel_base_t *ba = rel->r;
     193         238 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, ol_fetch(t->columns, nr));
     194             : }
     195             : 
     196             : sql_exp *
     197     4030557 : rel_base_bind_column( mvc *sql, sql_rel *rel, const char *cname, int no_tname)
     198             : {
     199     4030557 :         sql_table *t = rel->l;
     200     4030557 :         rel_base_t *ba = rel->r;
     201     4030557 :         (void)no_tname;
     202     4030557 :         node *n = t ? ol_find_name(t->columns, cname) : NULL;
     203     4030557 :         if (!n)
     204     3229542 :                 return NULL;
     205      801015 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, n->data);
     206             : }
     207             : 
     208             : sql_rel *
     209     1853136 : rel_base_bind_column2_( sql_rel *rel, const char *tname, const char *cname)
     210             : {
     211     1853136 :         sql_table *t = rel->l;
     212     1853136 :         rel_base_t *ba = rel->r;
     213             : 
     214     1853136 :         assert(ba);
     215     1853136 :         if ((ba->name && strcmp(ba->name, tname) != 0) || (!ba->name && strcmp(t->base.name, tname) != 0))
     216             :                 return NULL;
     217      384637 :         node *n = ol_find_name(t->columns, cname);
     218      384637 :         if (!n)
     219             :                 return NULL;
     220             :         return rel;
     221             : }
     222             : 
     223             : sql_exp *
     224     1308114 : rel_base_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname)
     225             : {
     226     1308114 :         sql_table *t = rel->l;
     227     1308114 :         rel_base_t *ba = rel->r;
     228             : 
     229     1308114 :         assert(ba);
     230     1308114 :         if ((ba->name && strcmp(ba->name, tname) != 0) || (!ba->name && strcmp(t->base.name, tname) != 0))
     231             :                 return NULL;
     232      629089 :         node *n = ol_find_name(t->columns, cname);
     233      629089 :         if (!n)
     234             :                 return NULL;
     235      629085 :         sql_column *c = n->data;
     236      629085 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, c);
     237             : }
     238             : 
     239             : sql_exp *
     240           0 : rel_base_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname)
     241             : {
     242           0 :         sql_table *t = rel->l;
     243           0 :         if (!t->s || strcmp(t->s->base.name, sname) != 0)
     244             :                 return NULL;
     245           0 :         return rel_base_bind_column2(sql, rel, tname, cname);
     246             : }
     247             : 
     248             : list *
     249       98144 : rel_base_projection( mvc *sql, sql_rel *rel, int intern)
     250             : {
     251       98144 :         int i = 0;
     252       98144 :         sql_table *t = rel->l;
     253       98144 :         rel_base_t *ba = rel->r;
     254       98144 :         char *name = ba->name?ba->name:t->base.name;
     255       98144 :         list *exps = new_exp_list(sql->sa);
     256       98147 :         prop *p;
     257             : 
     258      713829 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     259      615675 :                 if (rel_base_is_used(ba, i))
     260      615682 :                         append(exps, bind_col_exp(sql, name, cn->data));
     261             :         }
     262       98154 :         if ((intern && rel_base_is_used(ba, i)) || list_empty(exps)) /* Add TID column if no column is used */
     263       75101 :                 append(exps, exp_column(sql->sa, name, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1));
     264       98153 :         i++;
     265       98153 :         if (intern) {
     266      105749 :                 for (node *in = ol_first_node(t->idxs); in; in = in->next, i++) {
     267       30648 :                         if (rel_base_is_used(ba, i)) {
     268       30648 :                                 sql_idx *i = in->data;
     269       30648 :                                 sql_subtype *t = sql_bind_localtype("lng"); /* hash "lng" */
     270       30648 :                                 int has_nils = 0, unique;
     271             : 
     272       30648 :                                 if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
     273       29750 :                                         continue;
     274             : 
     275         898 :                                 if (i->type == join_idx)
     276         765 :                                         t = sql_bind_localtype("oid");
     277             : 
     278         898 :                                 char *iname = sa_strconcat( sql->sa, "%", i->base.name);
     279        1933 :                                 for (node *n = i->columns->h ; n && !has_nils; n = n->next) { /* check for NULL values */
     280        1035 :                                         sql_kc *kc = n->data;
     281             : 
     282        1035 :                                         if (kc->c->null)
     283         718 :                                                 has_nils = 1;
     284             :                                 }
     285         898 :                                 unique = list_length(i->columns) == 1 && is_column_unique(((sql_kc*)i->columns->h->data)->c);
     286         898 :                                 sql_exp *e = exp_column(sql->sa, name, iname, t, CARD_MULTI, has_nils, unique, 1);
     287         898 :                                 if (hash_index(i->type)) {
     288         133 :                                         p = e->p = prop_create(sql->sa, PROP_HASHIDX, e->p);
     289         133 :                                         p->value.pval = i;
     290             :                                 }
     291         898 :                                 if (i->type == join_idx) {
     292         765 :                                         p = e->p = prop_create(sql->sa, PROP_JOINIDX, e->p);
     293         765 :                                         p->value.pval = i;
     294             :                                 }
     295         898 :                                 append(exps, e);
     296             :                         }
     297             :                 }
     298             :         }
     299       98153 :         return exps;
     300             : }
     301             : 
     302             : list *
     303       14091 : rel_base_project_all( mvc *sql, sql_rel *rel, char *tname)
     304             : {
     305       14091 :         sql_table *t = rel->l;
     306       14091 :         rel_base_t *ba = rel->r;
     307       14091 :         char *name = ba->name?ba->name:t->base.name;
     308       14091 :         list *exps = new_exp_list(sql->sa);
     309             : 
     310       14091 :         if (!exps || strcmp(name, tname) != 0)
     311             :                 return NULL;
     312             : 
     313      154933 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next)
     314      140851 :                 append(exps, bind_col( sql, rel, name, cn->data));
     315             :         return exps;
     316             : }
     317             : 
     318             : sql_rel *
     319         501 : rel_base_add_columns( mvc *sql, sql_rel *r)
     320             : {
     321         501 :         sql_table *t = r->l;
     322         501 :         rel_base_t *ba = r->r;
     323             : 
     324         501 :         r->exps = new_exp_list(sql->sa);
     325         501 :         if(!r->exps) {
     326           0 :                 rel_destroy(r);
     327           0 :                 return NULL;
     328             :         }
     329             : 
     330         501 :         int i = 0;
     331         501 :         prop *p = NULL;
     332         501 :         node *cn;
     333         501 :         const char *tname = t->base.name;
     334         501 :         const char *atname = ba->name?ba->name:tname;
     335             : 
     336        1499 :         for (cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     337         998 :                 sql_column *c = cn->data;
     338         998 :                 sql_exp *e = exp_alias(sql->sa, atname, c->base.name, tname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     339             : 
     340         998 :                 if (e == NULL) {
     341           0 :                         rel_destroy(r);
     342           0 :                         return NULL;
     343             :                 }
     344         998 :                 if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     345           0 :                         p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     346           0 :                         p->value.pval = c->t->pkey;
     347         998 :                 } else if (c->unique == 2) {
     348           0 :                         p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     349           0 :                         p->value.pval = NULL;
     350             :                 }
     351         998 :                 set_basecol(e);
     352         998 :                 sql_column_get_statistics(sql, c, e);
     353         998 :                 append(r->exps, e);
     354             :         }
     355             :         return r;
     356             : }
     357             : 
     358             : sql_rel *
     359     2358173 : rewrite_basetable(mvc *sql, sql_rel *rel)
     360             : {
     361     2358173 :         if (is_basetable(rel->op) && !rel->exps) {
     362      438483 :                 allocator *sa = sql->sa;
     363      438483 :                 sql_table *t = rel->l;
     364      438483 :                 rel_base_t *ba = rel->r;
     365             : 
     366      438483 :                 rel->exps = new_exp_list(sa);
     367      438497 :                 if(!rel->exps) {
     368           0 :                         rel_destroy(rel);
     369           0 :                         return NULL;
     370             :                 }
     371             : 
     372      438497 :                 int i = 0;
     373      438497 :                 prop *p = NULL;
     374      438497 :                 node *cn;
     375      438497 :                 const char *tname = t->base.name;
     376      438497 :                 const char *atname = ba->name?ba->name:tname;
     377             : 
     378      438497 :                 if (isRemote(t))
     379         276 :                         tname = mapiuri_table(t->query, sql->sa, tname);
     380     3095953 :                 for (cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     381     2657279 :                         if (!rel_base_is_used(ba, i))
     382     1012623 :                                 continue;
     383             : 
     384     1644656 :                         sql_column *c = cn->data;
     385     1644656 :                         sql_exp *e = exp_alias(sa, atname, c->base.name, tname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     386             : 
     387     1644552 :                         if (e == NULL) {
     388           0 :                                 rel_destroy(rel);
     389           0 :                                 return NULL;
     390             :                         }
     391     1644552 :                         if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     392       55268 :                                 p = e->p = prop_create(sa, PROP_HASHCOL, e->p);
     393       55268 :                                 p->value.pval = c->t->pkey;
     394     1589284 :                         } else if (c->unique == 2) {
     395       11316 :                                 p = e->p = prop_create(sa, PROP_HASHCOL, e->p);
     396       11316 :                                 p->value.pval = NULL;
     397             :                         }
     398     1644552 :                         set_basecol(e);
     399     1644552 :                         sql_column_get_statistics(sql, c, e);
     400     1645561 :                         append(rel->exps, e);
     401             :                 }
     402      438674 :                 if (rel_base_is_used(ba, i) || list_empty(rel->exps)) /* Add TID column if no column is used */
     403      438674 :                         append(rel->exps, exp_alias(sa, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1));
     404      438802 :                 i++;
     405             : 
     406      556626 :                 for (cn = ol_first_node(t->idxs); cn; cn = cn->next, i++) {
     407      118021 :                         if (!rel_base_is_used(ba, i))
     408           0 :                                 continue;
     409             : 
     410      118021 :                         sql_exp *e;
     411      118021 :                         sql_idx *i = cn->data;
     412      118021 :                         sql_subtype *t;
     413      118021 :                         char *iname = NULL;
     414      118021 :                         int has_nils = 0, unique;
     415             : 
     416             :                         /* do not include empty indices in the plan */
     417      118021 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
     418      100071 :                                 continue;
     419             : 
     420       17950 :                         t = (i->type == join_idx) ? sql_bind_localtype("oid") : sql_bind_localtype("lng");
     421       17950 :                         iname = sa_strconcat( sa, "%", i->base.name);
     422       39526 :                         for (node *n = i->columns->h ; n && !has_nils; n = n->next) { /* check for NULL values */
     423       21576 :                                 sql_kc *kc = n->data;
     424             : 
     425       21576 :                                 if (kc->c->null)
     426       13192 :                                         has_nils = 1;
     427             :                         }
     428       17950 :                         unique = list_length(i->columns) == 1 && is_column_unique(((sql_kc*)i->columns->h->data)->c);
     429       17950 :                         e = exp_alias(sa, atname, iname, tname, iname, t, CARD_MULTI, has_nils, unique, 1);
     430             :                         /* index names are prefixed, to make them independent */
     431       17950 :                         if (hash_index(i->type)) {
     432        9988 :                                 p = e->p = prop_create(sa, PROP_HASHIDX, e->p);
     433        9988 :                                 p->value.pval = i;
     434             :                         }
     435       17950 :                         if (i->type == join_idx) {
     436        7962 :                                 p = e->p = prop_create(sa, PROP_JOINIDX, e->p);
     437        7962 :                                 p->value.pval = i;
     438             :                         }
     439       17950 :                         append(rel->exps, e);
     440             :                 }
     441             :         }
     442             :         return rel;
     443             : }
     444             : 
     445             : sql_exp *
     446          15 : basetable_get_tid_or_add_it(mvc *sql, sql_rel *rel)
     447             : {
     448          15 :         sql_exp *res = NULL;
     449             : 
     450          15 :         if (is_basetable(rel->op)) {
     451          15 :                 allocator *sa = sql->sa;
     452          15 :                 sql_table *t = rel->l;
     453          15 :                 rel_base_t *ba = rel->r;
     454          15 :                 const char *tname = t->base.name;
     455          15 :                 const char *atname = ba->name?ba->name:tname;
     456             : 
     457          15 :                 if (isRemote(t))
     458           0 :                         tname = mapiuri_table(t->query, sql->sa, tname);
     459          15 :                 if (!rel->exps) { /* no exps yet, just set TID */
     460           0 :                         rel_base_use_tid(sql, rel);
     461           0 :                         res = exp_alias(sa, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     462          15 :                 } else if (!rel_base_is_used(ba, ol_length(t->columns)) ||  /* exps set, but no TID, add it */
     463          15 :                                    !(res = exps_bind_column2(rel->exps, atname, TID, NULL))) { /* exps set with TID, but maybe rel_dce removed it */
     464           0 :                         node *n = NULL;
     465           0 :                         rel_base_use_tid(sql, rel);
     466           0 :                         res = exp_alias(sa, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     467             : 
     468             :                         /* search for indexes */
     469           0 :                         for (node *cn = rel->exps->h; cn && !n; cn = cn->next) {
     470           0 :                                 sql_exp *e = cn->data;
     471             : 
     472           0 :                                 if (is_intern(e))
     473           0 :                                         n = cn;
     474             :                         }
     475           0 :                         if (n) { /* has indexes, insert TID before them */
     476           0 :                                 list_append_before(rel->exps, n, res);
     477             :                         } else {
     478           0 :                                 list_append(rel->exps, res);
     479             :                         }
     480             :                 }
     481             :         }
     482          15 :         return res;
     483             : }
     484             : 
     485             : sql_rel *
     486         416 : rel_rename_part(mvc *sql, sql_rel *p, sql_rel *mt_rel, const char *mtalias)
     487             : {
     488         416 :         sql_table *mt = rel_base_table(mt_rel), *t = rel_base_table(p);
     489             : 
     490         416 :         assert(!p->exps);
     491         416 :         p->exps = sa_list(sql->sa);
     492         416 :         const char *pname = t->base.name;
     493         416 :         if (isRemote(t))
     494          37 :                 pname = mapiuri_table(t->query, sql->sa, pname);
     495        1088 :         for (node *n = mt_rel->exps->h; n; n = n->next) {
     496         672 :                 sql_exp *e = n->data;
     497         672 :                 node *cn = NULL, *ci = NULL;
     498         672 :                 const char *nname = e->r;
     499             : 
     500         672 :                 if (nname[0] == '%' && strcmp(nname, TID) == 0) {
     501          49 :                         list_append(p->exps, exp_alias(sql->sa, mtalias, TID, pname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1));
     502          49 :                         rel_base_use_tid(sql, p);
     503        1244 :                 } else if (nname[0] != '%' && (cn = ol_find_name(mt->columns, nname))) {
     504         621 :                         sql_column *c = cn->data, *rc = ol_fetch(t->columns, c->colnr);
     505             : 
     506             :                         /* with name find column in merge table, with colnr find column in member */
     507         621 :                         sql_exp *ne = exp_alias(sql->sa, mtalias, exp_name(e), pname, rc->base.name, &rc->type, CARD_MULTI, rc->null, is_column_unique(rc), 0);
     508         621 :                         if (rc->t->pkey && ((sql_kc*)rc->t->pkey->k.columns->h->data)->c == rc) {
     509           6 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHCOL, ne->p);
     510           6 :                                 p->value.pval = rc->t->pkey;
     511         615 :                         } else if (rc->unique == 2) {
     512           0 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHCOL, ne->p);
     513           0 :                                 p->value.pval = NULL;
     514             :                         }
     515         621 :                         set_basecol(ne);
     516         621 :                         sql_column_get_statistics(sql, c, ne);
     517         621 :                         rel_base_use(sql, p, rc->colnr);
     518         621 :                         list_append(p->exps, ne);
     519           2 :                 } else if (nname[0] == '%' && ol_length(mt->idxs) && (ci = ol_find_name(mt->idxs, nname + 1))) {
     520           2 :                         sql_idx *i = ci->data, *ri = NULL;
     521             : 
     522             :                         /* indexes don't have a number field like 'colnr', so get the index the old way */
     523           4 :                         for (node *nn = mt->idxs->l->h, *mm = t->idxs->l->h; nn && mm ; nn = nn->next, mm = mm->next) {
     524           4 :                                 sql_idx *ii = nn->data;
     525             : 
     526           4 :                                 if (ii->base.id == i->base.id) {
     527           2 :                                         ri = mm->data;
     528           2 :                                         break;
     529             :                                 }
     530             :                         }
     531             : 
     532           2 :                         assert((!hash_index(ri->type) || list_length(ri->columns) > 1) && idx_has_column(ri->type));
     533           2 :                         sql_subtype *t = (ri->type == join_idx) ? sql_bind_localtype("oid") : sql_bind_localtype("lng");
     534           2 :                         char *iname1 = sa_strconcat(sql->sa, "%", i->base.name), *iname2 = sa_strconcat(sql->sa, "%", ri->base.name);
     535             : 
     536           2 :                         sql_exp *ne = exp_alias(sql->sa, mtalias, iname1, pname, iname2, t, CARD_MULTI, has_nil(e), is_unique(e), 1);
     537             :                         /* index names are prefixed, to make them independent */
     538           2 :                         if (hash_index(ri->type)) {
     539           0 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHIDX, ne->p);
     540           0 :                                 p->value.pval = ri;
     541           2 :                         } else if (ri->type == join_idx) {
     542           2 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_JOINIDX, ne->p);
     543           2 :                                 p->value.pval = ri;
     544             :                         }
     545           2 :                         list_append(p->exps, ne);
     546             :                 }
     547             :         }
     548         416 :         rel_base_set_mergetable(p, mt);
     549         416 :         return p;
     550             : }
     551             : 
     552             : void
     553           0 : rel_base_dump_exps( stream *fout, sql_rel *rel)
     554             : {
     555           0 :         int i = 0, comma = 0;
     556           0 :         sql_table *t = rel->l;
     557           0 :         rel_base_t *ba = rel->r;
     558           0 :         assert(ba);
     559           0 :         mnstr_printf(fout, "[ ");
     560           0 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     561           0 :                 if (rel_base_is_used(ba, i)) {
     562           0 :                         sql_column *c = cn->data;
     563           0 :                         mnstr_printf(fout, "%s\"%s\".\"%s\"", comma?", ":"", t->base.name, c->base.name);
     564           0 :                         if (ba->name)
     565           0 :                                 mnstr_printf(fout, " as \"%s\".\"%s\"", ba->name, c->base.name);
     566             :                         comma = 1;
     567             :                 }
     568             :         }
     569           0 :         if (rel_base_is_used(ba, i)) {
     570           0 :                 mnstr_printf(fout, "%s\"%s\".\"%%TID\"", comma?", ":"", t->base.name);
     571           0 :                 if (ba->name)
     572           0 :                         mnstr_printf(fout, " as \"%s\".\"%%TID\"", ba->name);
     573             :                 comma = 1;
     574             :         }
     575           0 :         i++;
     576           0 :         for (node *in = ol_first_node(t->idxs); in; in = in->next, i++) {
     577           0 :                 if (rel_base_is_used(ba, i)) {
     578           0 :                         sql_idx *i = in->data;
     579           0 :                         mnstr_printf(fout, "%s\"%s\".\"%s\"", comma?", ":"", t->base.name, i->base.name);
     580           0 :                         if (ba->name)
     581           0 :                                 mnstr_printf(fout, " as \"%s\".\"%s\"", ba->name, i->base.name);
     582             :                         comma = 1;
     583             :                 }
     584             :         }
     585           0 :         mnstr_printf(fout, " ]");
     586           0 : }
     587             : 
     588             : int
     589          64 : rel_base_has_column_privileges(mvc *sql, sql_rel *rel)
     590             : {
     591          64 :         sql_table *t = rel->l;
     592          64 :         int has = 0;
     593             : 
     594         205 :         for (node *m = ol_first_node(t->columns); m && !has; m = m->next) {
     595         141 :                 sql_column *c = m->data;
     596             : 
     597         141 :                 if (column_privs(sql, c, PRIV_SELECT))
     598          33 :                         has = 1;
     599             :         }
     600          64 :         return has;
     601             : }
     602             : 
     603             : void
     604         416 : rel_base_set_mergetable(sql_rel *rel, sql_table *mt)
     605             : {
     606         416 :         rel_base_t *ba = rel->r;
     607             : 
     608         416 :         if (ba)
     609         416 :                 ba->mt = mt;
     610         416 : }
     611             : 
     612             : sql_table *
     613      429978 : rel_base_get_mergetable(sql_rel *rel)
     614             : {
     615      429978 :         rel_base_t *ba = rel->r;
     616             : 
     617      429978 :         return ba ? ba->mt : NULL;
     618             : }

Generated by: LCOV version 1.14