LCOV - code coverage report
Current view: top level - sql/server - rel_basetable.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 302 367 82.3 %
Date: 2024-04-25 20:03:45 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 "sql_privileges.h"
      20             : 
      21             : #define USED_LEN(nr) ((nr+31)/32)
      22             : #define rel_base_set_used(b,nr) b->used[(nr)/32] |= (1U<<((nr)%32))
      23             : #define rel_base_is_used(b,nr) ((b->used[(nr)/32]&(1U<<((nr)%32))) != 0)
      24             : 
      25             : typedef struct rel_base_t {
      26             :         sql_table *mt;
      27             :         char *name;
      28             :         int disallowed; /* ie check per column */
      29             :         uint32_t used[];
      30             : } rel_base_t;
      31             : 
      32             : void
      33          72 : rel_base_disallow(sql_rel *r)
      34             : {
      35          72 :         rel_base_t *ba = r->r;
      36          72 :         ba->disallowed = 1;
      37          72 : }
      38             : 
      39             : char *
      40      126900 : rel_base_name(sql_rel *r)
      41             : {
      42      126900 :         sql_table *t = r->l;
      43      126900 :         rel_base_t *ba = r->r;
      44      126900 :         if (ba->name)
      45             :                 return ba->name;
      46      125512 :         return t->base.name;
      47             : }
      48             : 
      49             : char *
      50           0 : rel_base_rename(sql_rel *r, char *name)
      51             : {
      52           0 :         rel_base_t *ba = r->r;
      53           0 :         ba->name = name;
      54           0 :         return name;
      55             : }
      56             : 
      57             : int
      58     1646644 : rel_base_use( mvc *sql, sql_rel *rt, int nr)
      59             : {
      60     1646644 :         assert(is_basetable(rt->op));
      61     1646644 :         sql_table *t = rt->l;
      62     1646644 :         rel_base_t *ba = rt->r;
      63             : 
      64     1646644 :         if (ba->disallowed && nr < ol_length(t->columns)) {
      65          29 :                 sql_column *c = ol_fetch(t->columns, nr);
      66          29 :                 if (!column_privs(sql, c, PRIV_SELECT))
      67             :                         return -1;
      68             :         }
      69     1646632 :         rel_base_set_used(ba, nr);
      70     1646632 :         return 0;
      71             : }
      72             : 
      73             : void
      74        6800 : rel_base_use_tid( mvc *sql, sql_rel *rt)
      75             : {
      76        6800 :         sql_table *t = rt->l;
      77        6800 :         rel_base_use(sql, rt, ol_length(t->columns));
      78        6800 : }
      79             : 
      80             : void
      81      371781 : rel_base_use_all( mvc *sql, sql_rel *rel)
      82             : {
      83      371781 :         sql_table *t = rel->l;
      84      371781 :         rel_base_t *ba = rel->r;
      85             : 
      86      371781 :         if (ba->disallowed) {
      87          10 :                 int i = 0;
      88          33 :                 for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
      89          23 :                         sql_column *c = cn->data;
      90          23 :                         if (!column_privs(sql, c, PRIV_SELECT))
      91          12 :                                 continue;
      92          11 :                         rel_base_set_used(ba, i);
      93             :                 }
      94             :         } else {
      95      371771 :                 int len = USED_LEN(ol_length(t->columns) + 1 + ol_length(t->idxs));
      96      747654 :                 for (int i = 0; i < len; i++)
      97      375885 :                         ba->used[i] = ~0U;
      98             :         }
      99      371779 : }
     100             : 
     101             : sql_rel *
     102      593868 : rel_basetable(mvc *sql, sql_table *t, const char *atname)
     103             : {
     104      593868 :         sql_allocator *sa = sql->sa;
     105      593868 :         sql_rel *rel = rel_create(sa);
     106      593864 :         int nrcols = ol_length(t->columns), end = nrcols + 1 + ol_length(t->idxs);
     107      593864 :         rel_base_t *ba = (rel_base_t*)sa_zalloc(sa, sizeof(rel_base_t) + sizeof(int)*USED_LEN(end));
     108             : 
     109      593861 :         if(!rel || !ba)
     110             :                 return NULL;
     111             : 
     112      593861 :         assert(atname);
     113      593861 :         if (strcmp(atname, t->base.name) != 0)
     114      231190 :                 ba->name = sa_strdup(sa, atname);
     115     1334665 :         for(int i = nrcols; i<end; i++)
     116      740804 :                 rel_base_set_used(ba, i);
     117      593861 :         rel->l = t;
     118      593861 :         rel->r = ba;
     119      593861 :         rel->op = op_basetable;
     120      593861 :         rel->card = CARD_MULTI;
     121      593861 :         rel->nrcols = nrcols;
     122      593861 :         return rel;
     123             : }
     124             : 
     125             : void
     126          60 : rel_base_copy(mvc *sql, sql_rel *in, sql_rel *out)
     127             : {
     128          60 :         sql_allocator *sa = sql->sa;
     129          60 :         sql_table *t = in->l;
     130          60 :         rel_base_t *ba = in->r;
     131             : 
     132          60 :         assert(is_basetable(in->op) && is_basetable(out->op));
     133          60 :         int nrcols = ol_length(t->columns), end = nrcols + 1 + ol_length(t->idxs);
     134          60 :         size_t bsize = sizeof(rel_base_t) + sizeof(uint32_t)*USED_LEN(end);
     135          60 :         rel_base_t *nba = (rel_base_t*)sa_alloc(sa, bsize);
     136             : 
     137          60 :         memcpy(nba, ba, bsize);
     138          60 :         if (ba->name)
     139           0 :                 nba->name = sa_strdup(sa, ba->name);
     140             : 
     141          60 :         out->l = t;
     142          60 :         out->r = nba;
     143          60 : }
     144             : 
     145             : sql_rel *
     146           2 : rel_base_bind_column_( sql_rel *rel, const char *cname)
     147             : {
     148           2 :         sql_table *t = rel->l;
     149           2 :         node *n = ol_find_name(t->columns, cname);
     150           2 :         if (n)
     151           0 :                 return rel;
     152             :         return NULL;
     153             : }
     154             : 
     155             : static sql_exp *
     156     2179427 : bind_col_exp(mvc *sql, char *name, sql_column *c)
     157             : {
     158     2179427 :         prop *p = NULL;
     159     2179427 :         sql_exp *e = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     160             : 
     161     2179425 :         if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     162       79992 :                 p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     163       79992 :                 p->value.pval = c->t->pkey;
     164     2099433 :         } else if (c->unique == 2) {
     165       21624 :                 p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     166       21624 :                 p->value.pval = NULL;
     167             :         }
     168     2179425 :         set_basecol(e);
     169     2179425 :         return e;
     170             : }
     171             : 
     172             : static sql_exp *
     173     1567556 : bind_col(mvc *sql, sql_rel *rel, char *name, sql_column *c )
     174             : {
     175     1567556 :         if (rel_base_use(sql, rel, c->colnr)) {
     176             :                 /* error */
     177             :                 return NULL;
     178             :         }
     179     1567544 :         return bind_col_exp(sql, name, c);
     180             : }
     181             : 
     182             : sql_exp *
     183         224 : rel_base_bind_colnr( mvc *sql, sql_rel *rel, int nr)
     184             : {
     185         224 :         sql_table *t = rel->l;
     186         224 :         rel_base_t *ba = rel->r;
     187         224 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, ol_fetch(t->columns, nr));
     188             : }
     189             : 
     190             : sql_exp *
     191     4040396 : rel_base_bind_column( mvc *sql, sql_rel *rel, const char *cname, int no_tname)
     192             : {
     193     4040396 :         sql_table *t = rel->l;
     194     4040396 :         rel_base_t *ba = rel->r;
     195     4040396 :         (void)no_tname;
     196     4040396 :         node *n = t ? ol_find_name(t->columns, cname) : NULL;
     197     4040396 :         if (!n)
     198     3233553 :                 return NULL;
     199      806843 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, n->data);
     200             : }
     201             : 
     202             : sql_rel *
     203     1838853 : rel_base_bind_column2_( sql_rel *rel, const char *tname, const char *cname)
     204             : {
     205     1838853 :         sql_table *t = rel->l;
     206     1838853 :         rel_base_t *ba = rel->r;
     207             : 
     208     1838853 :         assert(ba);
     209     1838853 :         if ((ba->name && strcmp(ba->name, tname) != 0) || (!ba->name && strcmp(t->base.name, tname) != 0))
     210             :                 return NULL;
     211      377934 :         node *n = ol_find_name(t->columns, cname);
     212      377934 :         if (!n)
     213             :                 return NULL;
     214             :         return rel;
     215             : }
     216             : 
     217             : sql_exp *
     218     1284480 : rel_base_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname)
     219             : {
     220     1284480 :         sql_table *t = rel->l;
     221     1284480 :         rel_base_t *ba = rel->r;
     222             : 
     223     1284480 :         assert(ba);
     224     1284480 :         if ((ba->name && strcmp(ba->name, tname) != 0) || (!ba->name && strcmp(t->base.name, tname) != 0))
     225             :                 return NULL;
     226      620809 :         node *n = ol_find_name(t->columns, cname);
     227      620809 :         if (!n)
     228             :                 return NULL;
     229      620804 :         sql_column *c = n->data;
     230      620804 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, c);
     231             : }
     232             : 
     233             : sql_exp *
     234           0 : rel_base_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname)
     235             : {
     236           0 :         sql_table *t = rel->l;
     237           0 :         if (!t->s || strcmp(t->s->base.name, sname) != 0)
     238             :                 return NULL;
     239           0 :         return rel_base_bind_column2(sql, rel, tname, cname);
     240             : }
     241             : 
     242             : list *
     243       97557 : rel_base_projection( mvc *sql, sql_rel *rel, int intern)
     244             : {
     245       97557 :         int i = 0;
     246       97557 :         sql_table *t = rel->l;
     247       97557 :         rel_base_t *ba = rel->r;
     248       97557 :         char *name = ba->name?ba->name:t->base.name;
     249       97557 :         list *exps = new_exp_list(sql->sa);
     250       97556 :         prop *p;
     251             : 
     252      709446 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     253      611891 :                 if (rel_base_is_used(ba, i))
     254      611884 :                         append(exps, bind_col_exp(sql, name, cn->data));
     255             :         }
     256       97555 :         if ((intern && rel_base_is_used(ba, i)) || list_empty(exps)) /* Add TID column if no column is used */
     257       74254 :                 append(exps, exp_column(sql->sa, name, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1));
     258       97555 :         i++;
     259       97555 :         if (intern) {
     260      104436 :                 for (node *in = ol_first_node(t->idxs); in; in = in->next, i++) {
     261       30182 :                         if (rel_base_is_used(ba, i)) {
     262       30182 :                                 sql_idx *i = in->data;
     263       30182 :                                 sql_subtype *t = sql_bind_localtype("lng"); /* hash "lng" */
     264       30182 :                                 int has_nils = 0, unique;
     265             : 
     266       30182 :                                 if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
     267       29277 :                                         continue;
     268             : 
     269         905 :                                 if (i->type == join_idx)
     270         765 :                                         t = sql_bind_localtype("oid");
     271             : 
     272         905 :                                 char *iname = sa_strconcat( sql->sa, "%", i->base.name);
     273        1948 :                                 for (node *n = i->columns->h ; n && !has_nils; n = n->next) { /* check for NULL values */
     274        1043 :                                         sql_kc *kc = n->data;
     275             : 
     276        1043 :                                         if (kc->c->null)
     277         724 :                                                 has_nils = 1;
     278             :                                 }
     279         905 :                                 unique = list_length(i->columns) == 1 && is_column_unique(((sql_kc*)i->columns->h->data)->c);
     280         905 :                                 sql_exp *e = exp_column(sql->sa, name, iname, t, CARD_MULTI, has_nils, unique, 1);
     281         905 :                                 if (hash_index(i->type)) {
     282         140 :                                         p = e->p = prop_create(sql->sa, PROP_HASHIDX, e->p);
     283         140 :                                         p->value.pval = i;
     284             :                                 }
     285         905 :                                 if (i->type == join_idx) {
     286         765 :                                         p = e->p = prop_create(sql->sa, PROP_JOINIDX, e->p);
     287         765 :                                         p->value.pval = i;
     288             :                                 }
     289         905 :                                 append(exps, e);
     290             :                         }
     291             :                 }
     292             :         }
     293       97555 :         return exps;
     294             : }
     295             : 
     296             : list *
     297       13979 : rel_base_project_all( mvc *sql, sql_rel *rel, char *tname)
     298             : {
     299       13979 :         sql_table *t = rel->l;
     300       13979 :         rel_base_t *ba = rel->r;
     301       13979 :         char *name = ba->name?ba->name:t->base.name;
     302       13979 :         list *exps = new_exp_list(sql->sa);
     303             : 
     304       13979 :         if (!exps || strcmp(name, tname) != 0)
     305             :                 return NULL;
     306             : 
     307      153652 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next)
     308      139685 :                 append(exps, bind_col( sql, rel, name, cn->data));
     309             :         return exps;
     310             : }
     311             : 
     312             : sql_rel *
     313         470 : rel_base_add_columns( mvc *sql, sql_rel *r)
     314             : {
     315         470 :         sql_table *t = r->l;
     316         470 :         rel_base_t *ba = r->r;
     317             : 
     318         470 :         r->exps = new_exp_list(sql->sa);
     319         470 :         if(!r->exps) {
     320           0 :                 rel_destroy(r);
     321           0 :                 return NULL;
     322             :         }
     323             : 
     324         470 :         int i = 0;
     325         470 :         prop *p = NULL;
     326         470 :         node *cn;
     327         470 :         const char *tname = t->base.name;
     328         470 :         const char *atname = ba->name?ba->name:tname;
     329             : 
     330        1407 :         for (cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     331         937 :                 sql_column *c = cn->data;
     332         937 :                 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);
     333             : 
     334         937 :                 if (e == NULL) {
     335           0 :                         rel_destroy(r);
     336           0 :                         return NULL;
     337             :                 }
     338         937 :                 if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     339           0 :                         p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     340           0 :                         p->value.pval = c->t->pkey;
     341         937 :                 } else if (c->unique == 2) {
     342           0 :                         p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     343           0 :                         p->value.pval = NULL;
     344             :                 }
     345         937 :                 set_basecol(e);
     346         937 :                 append(r->exps, e);
     347             :         }
     348             :         return r;
     349             : }
     350             : 
     351             : sql_rel *
     352     2353005 : rewrite_basetable(mvc *sql, sql_rel *rel)
     353             : {
     354     2353005 :         if (is_basetable(rel->op) && !rel->exps) {
     355      433220 :                 sql_allocator *sa = sql->sa;
     356      433220 :                 sql_table *t = rel->l;
     357      433220 :                 rel_base_t *ba = rel->r;
     358             : 
     359      433220 :                 rel->exps = new_exp_list(sa);
     360      433219 :                 if(!rel->exps) {
     361           0 :                         rel_destroy(rel);
     362           0 :                         return NULL;
     363             :                 }
     364             : 
     365      433219 :                 int i = 0;
     366      433219 :                 prop *p = NULL;
     367      433219 :                 node *cn;
     368      433219 :                 const char *tname = t->base.name;
     369      433219 :                 const char *atname = ba->name?ba->name:tname;
     370             : 
     371      433219 :                 if (isRemote(t))
     372         278 :                         tname = mapiuri_table(t->query, sql->sa, tname);
     373     3045020 :                 for (cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     374     2611805 :                         if (!rel_base_is_used(ba, i))
     375     1012022 :                                 continue;
     376             : 
     377     1599783 :                         sql_column *c = cn->data;
     378     1599783 :                         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);
     379             : 
     380     1599755 :                         if (e == NULL) {
     381           0 :                                 rel_destroy(rel);
     382           0 :                                 return NULL;
     383             :                         }
     384     1599755 :                         if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     385       55510 :                                 p = e->p = prop_create(sa, PROP_HASHCOL, e->p);
     386       55510 :                                 p->value.pval = c->t->pkey;
     387     1544245 :                         } else if (c->unique == 2) {
     388       11451 :                                 p = e->p = prop_create(sa, PROP_HASHCOL, e->p);
     389       11451 :                                 p->value.pval = NULL;
     390             :                         }
     391     1599755 :                         set_basecol(e);
     392     1599755 :                         append(rel->exps, e);
     393             :                 }
     394      433215 :                 if (rel_base_is_used(ba, i) || list_empty(rel->exps)) /* Add TID column if no column is used */
     395      433215 :                         append(rel->exps, exp_alias(sa, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1));
     396      433207 :                 i++;
     397             : 
     398      551998 :                 for (cn = ol_first_node(t->idxs); cn; cn = cn->next, i++) {
     399      118791 :                         if (!rel_base_is_used(ba, i))
     400           0 :                                 continue;
     401             : 
     402      118791 :                         sql_exp *e;
     403      118791 :                         sql_idx *i = cn->data;
     404      118791 :                         sql_subtype *t;
     405      118791 :                         char *iname = NULL;
     406      118791 :                         int has_nils = 0, unique;
     407             : 
     408             :                         /* do not include empty indices in the plan */
     409      118791 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
     410      100764 :                                 continue;
     411             : 
     412       18027 :                         t = (i->type == join_idx) ? sql_bind_localtype("oid") : sql_bind_localtype("lng");
     413       18027 :                         iname = sa_strconcat( sa, "%", i->base.name);
     414       39718 :                         for (node *n = i->columns->h ; n && !has_nils; n = n->next) { /* check for NULL values */
     415       21691 :                                 sql_kc *kc = n->data;
     416             : 
     417       21691 :                                 if (kc->c->null)
     418       13168 :                                         has_nils = 1;
     419             :                         }
     420       18027 :                         unique = list_length(i->columns) == 1 && is_column_unique(((sql_kc*)i->columns->h->data)->c);
     421       18027 :                         e = exp_alias(sa, atname, iname, tname, iname, t, CARD_MULTI, has_nils, unique, 1);
     422             :                         /* index names are prefixed, to make them independent */
     423       18027 :                         if (hash_index(i->type)) {
     424       10007 :                                 p = e->p = prop_create(sa, PROP_HASHIDX, e->p);
     425       10007 :                                 p->value.pval = i;
     426             :                         }
     427       18027 :                         if (i->type == join_idx) {
     428        8020 :                                 p = e->p = prop_create(sa, PROP_JOINIDX, e->p);
     429        8020 :                                 p->value.pval = i;
     430             :                         }
     431       18027 :                         append(rel->exps, e);
     432             :                 }
     433             :         }
     434             :         return rel;
     435             : }
     436             : 
     437             : sql_exp *
     438          15 : basetable_get_tid_or_add_it(mvc *sql, sql_rel *rel)
     439             : {
     440          15 :         sql_exp *res = NULL;
     441             : 
     442          15 :         if (is_basetable(rel->op)) {
     443          15 :                 sql_allocator *sa = sql->sa;
     444          15 :                 sql_table *t = rel->l;
     445          15 :                 rel_base_t *ba = rel->r;
     446          15 :                 const char *tname = t->base.name;
     447          15 :                 const char *atname = ba->name?ba->name:tname;
     448             : 
     449          15 :                 if (isRemote(t))
     450           0 :                         tname = mapiuri_table(t->query, sql->sa, tname);
     451          15 :                 if (!rel->exps) { /* no exps yet, just set TID */
     452           0 :                         rel_base_use_tid(sql, rel);
     453           0 :                         res = exp_alias(sa, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     454          15 :                 } else if (!rel_base_is_used(ba, ol_length(t->columns)) ||  /* exps set, but no TID, add it */
     455          15 :                                    !(res = exps_bind_column2(rel->exps, atname, TID, NULL))) { /* exps set with TID, but maybe rel_dce removed it */
     456           0 :                         node *n = NULL;
     457           0 :                         rel_base_use_tid(sql, rel);
     458           0 :                         res = exp_alias(sa, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     459             : 
     460             :                         /* search for indexes */
     461           0 :                         for (node *cn = rel->exps->h; cn && !n; cn = cn->next) {
     462           0 :                                 sql_exp *e = cn->data;
     463             : 
     464           0 :                                 if (is_intern(e))
     465           0 :                                         n = cn;
     466             :                         }
     467           0 :                         if (n) { /* has indexes, insert TID before them */
     468           0 :                                 list_append_before(rel->exps, n, res);
     469             :                         } else {
     470           0 :                                 list_append(rel->exps, res);
     471             :                         }
     472             :                 }
     473             :         }
     474          15 :         return res;
     475             : }
     476             : 
     477             : sql_rel *
     478         482 : rel_rename_part(mvc *sql, sql_rel *p, sql_rel *mt_rel, const char *mtalias)
     479             : {
     480         482 :         sql_table *mt = rel_base_table(mt_rel), *t = rel_base_table(p);
     481             : 
     482         482 :         assert(!p->exps);
     483         482 :         p->exps = sa_list(sql->sa);
     484         482 :         const char *pname = t->base.name;
     485         482 :         if (isRemote(t))
     486          37 :                 pname = mapiuri_table(t->query, sql->sa, pname);
     487        1367 :         for (node *n = mt_rel->exps->h; n; n = n->next) {
     488         885 :                 sql_exp *e = n->data;
     489         885 :                 node *cn = NULL, *ci = NULL;
     490         885 :                 const char *nname = e->r;
     491             : 
     492         885 :                 if (nname[0] == '%' && strcmp(nname, TID) == 0) {
     493          71 :                         list_append(p->exps, exp_alias(sql->sa, mtalias, TID, pname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1));
     494          71 :                         rel_base_use_tid(sql, p);
     495        1626 :                 } else if (nname[0] != '%' && (cn = ol_find_name(mt->columns, nname))) {
     496         812 :                         sql_column *c = cn->data, *rc = ol_fetch(t->columns, c->colnr);
     497             : 
     498             :                         /* with name find column in merge table, with colnr find column in member */
     499         812 :                         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);
     500         812 :                         if (rc->t->pkey && ((sql_kc*)rc->t->pkey->k.columns->h->data)->c == rc) {
     501          22 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHCOL, ne->p);
     502          22 :                                 p->value.pval = rc->t->pkey;
     503         790 :                         } else if (rc->unique == 2) {
     504           0 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHCOL, ne->p);
     505           0 :                                 p->value.pval = NULL;
     506             :                         }
     507         812 :                         set_basecol(ne);
     508         812 :                         rel_base_use(sql, p, rc->colnr);
     509         812 :                         list_append(p->exps, ne);
     510           2 :                 } else if (nname[0] == '%' && ol_length(mt->idxs) && (ci = ol_find_name(mt->idxs, nname + 1))) {
     511           2 :                         sql_idx *i = ci->data, *ri = NULL;
     512             : 
     513             :                         /* indexes don't have a number field like 'colnr', so get the index the old way */
     514           4 :                         for (node *nn = mt->idxs->l->h, *mm = t->idxs->l->h; nn && mm ; nn = nn->next, mm = mm->next) {
     515           4 :                                 sql_idx *ii = nn->data;
     516             : 
     517           4 :                                 if (ii->base.id == i->base.id) {
     518           2 :                                         ri = mm->data;
     519           2 :                                         break;
     520             :                                 }
     521             :                         }
     522             : 
     523           2 :                         assert((!hash_index(ri->type) || list_length(ri->columns) > 1) && idx_has_column(ri->type));
     524           2 :                         sql_subtype *t = (ri->type == join_idx) ? sql_bind_localtype("oid") : sql_bind_localtype("lng");
     525           2 :                         char *iname1 = sa_strconcat(sql->sa, "%", i->base.name), *iname2 = sa_strconcat(sql->sa, "%", ri->base.name);
     526             : 
     527           2 :                         sql_exp *ne = exp_alias(sql->sa, mtalias, iname1, pname, iname2, t, CARD_MULTI, has_nil(e), is_unique(e), 1);
     528             :                         /* index names are prefixed, to make them independent */
     529           2 :                         if (hash_index(ri->type)) {
     530           0 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHIDX, ne->p);
     531           0 :                                 p->value.pval = ri;
     532           2 :                         } else if (ri->type == join_idx) {
     533           2 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_JOINIDX, ne->p);
     534           2 :                                 p->value.pval = ri;
     535             :                         }
     536           2 :                         list_append(p->exps, ne);
     537             :                 }
     538             :         }
     539         482 :         rel_base_set_mergetable(p, mt);
     540         482 :         return p;
     541             : }
     542             : 
     543             : void
     544           0 : rel_base_dump_exps( stream *fout, sql_rel *rel)
     545             : {
     546           0 :         int i = 0, comma = 0;
     547           0 :         sql_table *t = rel->l;
     548           0 :         rel_base_t *ba = rel->r;
     549           0 :         assert(ba);
     550           0 :         mnstr_printf(fout, "[ ");
     551           0 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     552           0 :                 if (rel_base_is_used(ba, i)) {
     553           0 :                         sql_column *c = cn->data;
     554           0 :                         mnstr_printf(fout, "%s\"%s\".\"%s\"", comma?", ":"", t->base.name, c->base.name);
     555           0 :                         if (ba->name)
     556           0 :                                 mnstr_printf(fout, " as \"%s\".\"%s\"", ba->name, c->base.name);
     557             :                         comma = 1;
     558             :                 }
     559             :         }
     560           0 :         if (rel_base_is_used(ba, i)) {
     561           0 :                 mnstr_printf(fout, "%s\"%s\".\"%%TID\"", comma?", ":"", t->base.name);
     562           0 :                 if (ba->name)
     563           0 :                         mnstr_printf(fout, " as \"%s\".\"%%TID\"", ba->name);
     564             :                 comma = 1;
     565             :         }
     566           0 :         i++;
     567           0 :         for (node *in = ol_first_node(t->idxs); in; in = in->next, i++) {
     568           0 :                 if (rel_base_is_used(ba, i)) {
     569           0 :                         sql_idx *i = in->data;
     570           0 :                         mnstr_printf(fout, "%s\"%s\".\"%s\"", comma?", ":"", t->base.name, i->base.name);
     571           0 :                         if (ba->name)
     572           0 :                                 mnstr_printf(fout, " as \"%s\".\"%s\"", ba->name, i->base.name);
     573             :                         comma = 1;
     574             :                 }
     575             :         }
     576           0 :         mnstr_printf(fout, " ]");
     577           0 : }
     578             : 
     579             : int
     580          72 : rel_base_has_column_privileges(mvc *sql, sql_rel *rel)
     581             : {
     582          72 :         sql_table *t = rel->l;
     583          72 :         int has = 0;
     584             : 
     585         227 :         for (node *m = ol_first_node(t->columns); m && !has; m = m->next) {
     586         155 :                 sql_column *c = m->data;
     587             : 
     588         155 :                 if (column_privs(sql, c, PRIV_SELECT))
     589          33 :                         has = 1;
     590             :         }
     591          72 :         return has;
     592             : }
     593             : 
     594             : void
     595         482 : rel_base_set_mergetable(sql_rel *rel, sql_table *mt)
     596             : {
     597         482 :         rel_base_t *ba = rel->r;
     598             : 
     599         482 :         if (ba)
     600         482 :                 ba->mt = mt;
     601         482 : }
     602             : 
     603             : sql_table *
     604     1053529 : rel_base_get_mergetable(sql_rel *rel)
     605             : {
     606     1053529 :         rel_base_t *ba = rel->r;
     607             : 
     608     1053529 :         return ba ? ba->mt : NULL;
     609             : }

Generated by: LCOV version 1.14