LCOV - code coverage report
Current view: top level - sql/server - rel_basetable.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 360 447 80.5 %
Date: 2024-12-20 21:24:02 Functions: 25 31 80.6 %

          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             : #include "sql_storage.h"
      23             : 
      24             : #define USED_LEN(nr) ((nr+31)/32)
      25             : #define rel_base_set_used(b,nr) b->used[(nr)/32] |= (1U<<((nr)%32))
      26             : #define rel_base_is_used(b,nr) ((b->used[(nr)/32]&(1U<<((nr)%32))) != 0)
      27             : 
      28             : typedef struct rel_base_t {
      29             :         sql_table *mt;
      30             :         char *name;
      31             :         int disallowed; /* ie check per column */
      32             :         int basenr;
      33             :         uint32_t used[];
      34             : } rel_base_t;
      35             : 
      36             : void
      37          72 : rel_base_disallow(sql_rel *r)
      38             : {
      39          72 :         rel_base_t *ba = r->r;
      40          72 :         ba->disallowed = 1;
      41          72 : }
      42             : 
      43             : char *
      44      212114 : rel_base_name(sql_rel *r)
      45             : {
      46      212114 :         sql_table *t = r->l;
      47      212114 :         rel_base_t *ba = r->r;
      48      212114 :         if (ba->name)
      49             :                 return ba->name;
      50      134588 :         return t->base.name;
      51             : }
      52             : 
      53             : char *
      54           0 : rel_base_rename(sql_rel *r, char *name)
      55             : {
      56           0 :         rel_base_t *ba = r->r;
      57           0 :         ba->name = name;
      58           0 :         return name;
      59             : }
      60             : 
      61             : int
      62        1046 : rel_base_idx_nid(sql_rel *r, sql_idx *i)
      63             : {
      64        1046 :         rel_base_t *ba = r->r;
      65        1046 :         sql_table *b = r->l;
      66        1046 :         if (i) {
      67        1046 :                 int j = ba->basenr + ol_length(b->columns) + 1;
      68        1116 :                 for (node *in = ol_first_node(i->t->idxs); in; in = in->next, j++) {
      69        1116 :                         if (i == in->data)
      70        1046 :                                 return -(ba->basenr + j);
      71             :                 }
      72             :         }
      73             :         return 0;
      74             : }
      75             : 
      76             : sql_column*
      77      304165 : rel_base_find_column(sql_rel *r, int nid)
      78             : {
      79      304165 :         rel_base_t *ba = r->r;
      80      304165 :         sql_table *b = r->l;
      81      304165 :         nid = -nid;
      82      304165 :         if ((nid - ba->basenr) >= ol_length(b->columns))
      83             :                 return NULL;
      84      206825 :         return ol_fetch(b->columns, nid - ba->basenr);
      85             : }
      86             : 
      87             : int
      88       34786 : rel_base_nid(sql_rel *r, sql_column *c)
      89             : {
      90       34786 :         rel_base_t *ba = r->r;
      91       34786 :         sql_table *b = r->l;
      92       34786 :         if (c)
      93       24035 :                 return -(ba->basenr + c->colnr);
      94       10751 :         return -(ba->basenr + ol_length(b->columns));
      95             : }
      96             : 
      97             : bool
      98     1913588 : rel_base_has_nid(sql_rel *r, int nid)
      99             : {
     100     1913588 :         rel_base_t *ba = r->r;
     101     1913588 :         sql_table *b = r->l;
     102             : 
     103     1913588 :         nid = -nid;
     104     1913588 :         return (nid >= ba->basenr && nid <= ba->basenr + ol_length(b->columns));
     105             : }
     106             : 
     107             : int
     108     1724714 : rel_base_use( mvc *sql, sql_rel *rt, int nr)
     109             : {
     110     1724714 :         assert(is_basetable(rt->op));
     111     1724714 :         sql_table *t = rt->l;
     112     1724714 :         rel_base_t *ba = rt->r;
     113             : 
     114     1724714 :         if (ba->disallowed && nr < ol_length(t->columns)) {
     115          34 :                 sql_column *c = ol_fetch(t->columns, nr);
     116          34 :                 if (!column_privs(sql, c, PRIV_SELECT))
     117             :                         return -1;
     118             :         }
     119     1724697 :         rel_base_set_used(ba, nr);
     120     1724697 :         return 0;
     121             : }
     122             : 
     123             : void
     124        7968 : rel_base_use_tid( mvc *sql, sql_rel *rt)
     125             : {
     126        7968 :         sql_table *t = rt->l;
     127        7968 :         rel_base_use(sql, rt, ol_length(t->columns));
     128        7968 : }
     129             : 
     130             : void
     131      405536 : rel_base_use_all( mvc *sql, sql_rel *rel)
     132             : {
     133      405536 :         sql_table *t = rel->l;
     134      405536 :         rel_base_t *ba = rel->r;
     135             : 
     136      405536 :         if (ba->disallowed) {
     137          10 :                 int i = 0;
     138          33 :                 for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     139          23 :                         sql_column *c = cn->data;
     140          23 :                         if (!column_privs(sql, c, PRIV_SELECT))
     141          12 :                                 continue;
     142          11 :                         rel_base_set_used(ba, i);
     143             :                 }
     144             :         } else {
     145      405526 :                 int len = USED_LEN(ol_length(t->columns) + 1 + ol_length(t->idxs));
     146      815328 :                 for (int i = 0; i < len; i++)
     147      409662 :                         ba->used[i] = ~0U;
     148             :         }
     149      405676 : }
     150             : 
     151             : sql_rel *
     152      626784 : rel_basetable(mvc *sql, sql_table *t, const char *atname)
     153             : {
     154      626784 :         allocator *sa = sql->sa;
     155      626784 :         sql_rel *rel = rel_create(sa);
     156      626965 :         int nrcols = ol_length(t->columns), end = nrcols + 1 + ol_length(t->idxs);
     157      627253 :         rel_base_t *ba = (rel_base_t*)sa_zalloc(sa, sizeof(rel_base_t) + sizeof(int)*USED_LEN(end));
     158      627108 :         sqlstore *store = sql->session->tr->store;
     159             : 
     160      627108 :         if(!rel || !ba)
     161             :                 return NULL;
     162             : 
     163      627108 :         ba->basenr = sql->nid;
     164      627108 :         sql->nid += end;
     165      627108 :         if (isTable(t) && t->s && !isDeclaredTable(t)) /* count active rows only */
     166      566805 :                 set_count_prop(sql->sa, rel, (BUN)store->storage_api.count_col(sql->session->tr, ol_first_node(t->columns)->data, 10));
     167      627092 :         assert(atname);
     168      627092 :         if (strcmp(atname, t->base.name) != 0)
     169      252446 :                 ba->name = sa_strdup(sa, atname);
     170     1409227 :         for(int i = nrcols; i<end; i++)
     171      782135 :                 rel_base_set_used(ba, i);
     172      627092 :         rel->l = t;
     173      627092 :         rel->r = ba;
     174      627092 :         rel->op = op_basetable;
     175      627092 :         rel->card = CARD_MULTI;
     176      627092 :         rel->nrcols = nrcols;
     177      627092 :         return rel;
     178             : }
     179             : 
     180             : void
     181          55 : rel_base_copy(mvc *sql, sql_rel *in, sql_rel *out)
     182             : {
     183          55 :         allocator *sa = sql->sa;
     184          55 :         sql_table *t = in->l;
     185          55 :         rel_base_t *ba = in->r;
     186             : 
     187          55 :         assert(is_basetable(in->op) && is_basetable(out->op));
     188          55 :         int nrcols = ol_length(t->columns), end = nrcols + 1 + ol_length(t->idxs);
     189          55 :         size_t bsize = sizeof(rel_base_t) + sizeof(uint32_t)*USED_LEN(end);
     190          55 :         rel_base_t *nba = (rel_base_t*)sa_alloc(sa, bsize);
     191             : 
     192          55 :         memcpy(nba, ba, bsize);
     193          55 :         if (ba->name)
     194           0 :                 nba->name = sa_strdup(sa, ba->name);
     195             : 
     196          55 :         out->l = t;
     197          55 :         out->r = nba;
     198          55 : }
     199             : 
     200             : sql_rel *
     201           0 : rel_base_bind_column_( sql_rel *rel, const char *cname)
     202             : {
     203           0 :         sql_table *t = rel->l;
     204           0 :         node *n = ol_find_name(t->columns, cname);
     205           0 :         if (n)
     206           0 :                 return rel;
     207             :         return NULL;
     208             : }
     209             : 
     210             : static sql_exp *
     211     2307472 : bind_col_exp(mvc *sql, rel_base_t *ba, char *name, sql_column *c)
     212             : {
     213     2307472 :         prop *p = NULL;
     214     2307472 :         sql_exp *e = exp_column(sql->sa, name, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     215             : 
     216     2307475 :         if (e) {
     217     2307475 :                 e->nid = -(ba->basenr + c->colnr);
     218     2307475 :                 e->alias.label = e->nid;
     219             :         }
     220     2307475 :         if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     221       84709 :                 p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     222       84709 :                 p->value.pval = c->t->pkey;
     223     2222766 :         } else if (c->unique == 2) {
     224       22983 :                 p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     225       22983 :                 p->value.pval = NULL;
     226             :         }
     227     2307475 :         set_basecol(e);
     228     2307475 :         sql_column_get_statistics(sql, c, e);
     229     2307487 :         return e;
     230             : }
     231             : 
     232             : static sql_exp *
     233     1642926 : bind_col(mvc *sql, sql_rel *rel, char *name, sql_column *c )
     234             : {
     235     1642926 :         if (!c || rel_base_use(sql, rel, c->colnr)) {
     236             :                 /* error */
     237          12 :                 return NULL;
     238             :         }
     239     1642914 :         return bind_col_exp(sql, rel->r, name, c);
     240             : }
     241             : 
     242             : sql_exp *
     243         240 : rel_base_bind_colnr( mvc *sql, sql_rel *rel, int nr)
     244             : {
     245         240 :         sql_table *t = rel->l;
     246         240 :         rel_base_t *ba = rel->r;
     247         240 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, ol_fetch(t->columns, nr));
     248             : }
     249             : 
     250             : sql_exp *
     251           0 : rel_base_find_label( mvc *sql, sql_rel *rel, int label)
     252             : {
     253           0 :         sql_table *t = rel->l;
     254           0 :         rel_base_t *ba = rel->r;
     255             : 
     256           0 :         label = -label;
     257           0 :         int colnr = label - ba->basenr;
     258           0 :         if (colnr > ol_length(t->columns))
     259             :                 return NULL;
     260           0 :         return rel_base_bind_colnr(sql, rel, colnr);
     261             : }
     262             : 
     263             : sql_exp *
     264     4072212 : rel_base_bind_column( mvc *sql, sql_rel *rel, const char *cname, int no_tname)
     265             : {
     266     4072212 :         sql_table *t = rel->l;
     267     4072212 :         rel_base_t *ba = rel->r;
     268     4072212 :         (void)no_tname;
     269     4072212 :         node *n = t ? ol_find_name(t->columns, cname) : NULL;
     270     4072212 :         if (!n)
     271     3246287 :                 return NULL;
     272      825925 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, n->data);
     273             : }
     274             : 
     275             : sql_rel *
     276           0 : rel_base_bind_column2_( sql_rel *rel, const char *tname, const char *cname)
     277             : {
     278           0 :         sql_table *t = rel->l;
     279           0 :         rel_base_t *ba = rel->r;
     280             : 
     281           0 :         assert(ba);
     282           0 :         if ((ba->name && strcmp(ba->name, tname) != 0) || (!ba->name && strcmp(t->base.name, tname) != 0))
     283             :                 return NULL;
     284           0 :         node *n = ol_find_name(t->columns, cname);
     285           0 :         if (!n)
     286             :                 return NULL;
     287             :         return rel;
     288             : }
     289             : 
     290             : sql_exp *
     291     1384061 : rel_base_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname)
     292             : {
     293     1384061 :         sql_table *t = rel->l;
     294     1384061 :         rel_base_t *ba = rel->r;
     295             : 
     296     1384061 :         assert(ba);
     297     1384061 :         if ((ba->name && strcmp(ba->name, tname) != 0) || (!ba->name && strcmp(t->base.name, tname) != 0))
     298             :                 return NULL;
     299      677744 :         node *n = ol_find_name(t->columns, cname);
     300      677744 :         if (!n)
     301             :                 return NULL;
     302      677739 :         sql_column *c = n->data;
     303      677739 :         return bind_col(sql, rel, ba->name?ba->name:t->base.name, c);
     304             : }
     305             : 
     306             : sql_exp *
     307           0 : rel_base_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char *tname, const char *cname)
     308             : {
     309           0 :         sql_table *t = rel->l;
     310           0 :         if (!t->s || strcmp(t->s->base.name, sname) != 0)
     311             :                 return NULL;
     312           0 :         return rel_base_bind_column2(sql, rel, tname, cname);
     313             : }
     314             : 
     315             : list *
     316      104150 : rel_base_projection( mvc *sql, sql_rel *rel, int intern)
     317             : {
     318      104150 :         int i = 0;
     319      104150 :         sql_table *t = rel->l;
     320      104150 :         rel_base_t *ba = rel->r;
     321      104150 :         char *name = ba->name?ba->name:t->base.name;
     322      104150 :         list *exps = new_exp_list(sql->sa);
     323      104153 :         prop *p;
     324             : 
     325      768834 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     326      664673 :                 if (rel_base_is_used(ba, i)) {
     327      664564 :                         sql_exp *e = bind_col_exp(sql, ba, name, cn->data);
     328      664576 :                         append(exps, e);
     329             :                 }
     330             :         }
     331      104161 :         if ((intern && rel_base_is_used(ba, i)) || list_empty(exps)) { /* Add TID column if no column is used */
     332       79081 :                 sql_exp *e = exp_column(sql->sa, name, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     333       79081 :                 e->nid = -(ba->basenr + i);
     334       79081 :                 e->alias.label = e->nid;
     335       79081 :                 append(exps, e);
     336             :         }
     337      104160 :         i++;
     338      104160 :         if (intern) {
     339       79081 :                 int j = i;
     340      110650 :                 for (node *in = ol_first_node(t->idxs); in; in = in->next, j++) {
     341       31569 :                         if (rel_base_is_used(ba, j)) {
     342       31569 :                                 sql_idx *i = in->data;
     343       31569 :                                 sql_subtype *t = sql_bind_localtype("lng"); /* hash "lng" */
     344       31569 :                                 int has_nils = 0, unique;
     345             : 
     346       31569 :                                 if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
     347       30662 :                                         continue;
     348             : 
     349         907 :                                 if (i->type == join_idx)
     350         765 :                                         t = sql_bind_localtype("oid");
     351             : 
     352         907 :                                 char *iname = sa_strconcat( sql->sa, "%", i->base.name);
     353        1954 :                                 for (node *n = i->columns->h ; n && !has_nils; n = n->next) { /* check for NULL values */
     354        1047 :                                         sql_kc *kc = n->data;
     355             : 
     356        1047 :                                         if (kc->c->null)
     357         724 :                                                 has_nils = 1;
     358             :                                 }
     359         907 :                                 unique = list_length(i->columns) == 1 && is_column_unique(((sql_kc*)i->columns->h->data)->c);
     360         907 :                                 sql_exp *e = exp_column(sql->sa, name, iname, t, CARD_MULTI, has_nils, unique, 1);
     361         907 :                                 e->nid = -(ba->basenr + j);
     362         907 :                                 e->alias.label = e->nid;
     363         907 :                                 if (hash_index(i->type)) {
     364         142 :                                         p = e->p = prop_create(sql->sa, PROP_HASHIDX, e->p);
     365         142 :                                         p->value.pval = i;
     366             :                                 }
     367         907 :                                 if (i->type == join_idx) {
     368         765 :                                         p = e->p = prop_create(sql->sa, PROP_JOINIDX, e->p);
     369         765 :                                         p->value.pval = i;
     370             :                                 }
     371         907 :                                 append(exps, e);
     372             :                         }
     373             :                 }
     374             :         }
     375      104160 :         return exps;
     376             : }
     377             : 
     378             : list *
     379       14045 : rel_base_project_all( mvc *sql, sql_rel *rel, char *tname)
     380             : {
     381       14045 :         sql_table *t = rel->l;
     382       14045 :         rel_base_t *ba = rel->r;
     383       14045 :         char *name = ba->name?ba->name:t->base.name;
     384       14045 :         list *exps = new_exp_list(sql->sa);
     385             : 
     386       14045 :         if (!exps || strcmp(name, tname) != 0)
     387             :                 return NULL;
     388             : 
     389      153021 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next)
     390      139022 :                 append(exps, bind_col( sql, rel, name, cn->data));
     391             :         return exps;
     392             : }
     393             : 
     394             : sql_rel *
     395         511 : rel_base_add_columns( mvc *sql, sql_rel *r)
     396             : {
     397         511 :         sql_table *t = r->l;
     398         511 :         rel_base_t *ba = r->r;
     399             : 
     400         511 :         r->exps = new_exp_list(sql->sa);
     401         511 :         if(!r->exps) {
     402           0 :                 rel_destroy(r);
     403           0 :                 return NULL;
     404             :         }
     405             : 
     406         511 :         int i = 0;
     407         511 :         prop *p = NULL;
     408         511 :         node *cn;
     409         511 :         const char *tname = t->base.name;
     410         511 :         const char *atname = ba->name?ba->name:tname;
     411             : 
     412        1529 :         for (cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     413        1018 :                 sql_column *c = cn->data;
     414        1018 :                 sql_exp *e = exp_alias(sql, atname, c->base.name, tname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     415             : 
     416        1018 :                 if (e == NULL) {
     417           0 :                         rel_destroy(r);
     418           0 :                         return NULL;
     419             :                 }
     420        1018 :                 e->nid = -(ba->basenr + i);
     421        1018 :                 e->alias.label = e->nid;
     422        1018 :                 if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     423           0 :                         p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     424           0 :                         p->value.pval = c->t->pkey;
     425        1018 :                 } else if (c->unique == 2) {
     426           0 :                         p = e->p = prop_create(sql->sa, PROP_HASHCOL, e->p);
     427           0 :                         p->value.pval = NULL;
     428             :                 }
     429        1018 :                 set_basecol(e);
     430        1018 :                 sql_column_get_statistics(sql, c, e);
     431        1018 :                 append(r->exps, e);
     432             :         }
     433             :         return r;
     434             : }
     435             : 
     436             : sql_rel *
     437     2440680 : rewrite_basetable(mvc *sql, sql_rel *rel)
     438             : {
     439     2440680 :         if (is_basetable(rel->op) && !rel->exps) {
     440      453430 :                 allocator *sa = sql->sa;
     441      453430 :                 sql_table *t = rel->l;
     442      453430 :                 rel_base_t *ba = rel->r;
     443             : 
     444      453430 :                 rel->exps = new_exp_list(sa);
     445      453359 :                 if(!rel->exps) {
     446           0 :                         rel_destroy(rel);
     447           0 :                         return NULL;
     448             :                 }
     449             : 
     450      453359 :                 int i = 0;
     451      453359 :                 prop *p = NULL;
     452      453359 :                 node *cn;
     453      453359 :                 const char *tname = t->base.name;
     454      453359 :                 const char *atname = ba->name?ba->name:tname;
     455             : 
     456      453359 :                 if (isRemote(t))
     457         285 :                         tname = mapiuri_table(t->query, sql->sa, tname);
     458     3219831 :                 for (cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     459     2766265 :                         if (!rel_base_is_used(ba, i))
     460     1038275 :                                 continue;
     461             : 
     462     1727990 :                         sql_column *c = cn->data;
     463     1727990 :                         sql_exp *e = exp_alias(sql, atname, c->base.name, tname, c->base.name, &c->type, CARD_MULTI, c->null, is_column_unique(c), 0);
     464             : 
     465     1727758 :                         if (e == NULL) {
     466           0 :                                 rel_destroy(rel);
     467           0 :                                 return NULL;
     468             :                         }
     469     1727758 :                         e->nid = -(ba->basenr + i);
     470     1727758 :                         e->alias.label = e->nid;
     471     1727758 :                         if (c->t->pkey && ((sql_kc*)c->t->pkey->k.columns->h->data)->c == c) {
     472       58029 :                                 p = e->p = prop_create(sa, PROP_HASHCOL, e->p);
     473       58029 :                                 p->value.pval = c->t->pkey;
     474     1669729 :                         } else if (c->unique == 2) {
     475       12049 :                                 p = e->p = prop_create(sa, PROP_HASHCOL, e->p);
     476       12049 :                                 p->value.pval = NULL;
     477             :                         }
     478     1727758 :                         set_basecol(e);
     479     1727758 :                         sql_column_get_statistics(sql, c, e);
     480     1728751 :                         append(rel->exps, e);
     481             :                 }
     482      453566 :                 if (rel_base_is_used(ba, i) || list_empty(rel->exps)) { /* Add TID column if no column is used */
     483      453566 :                         sql_exp *e = exp_alias(sql, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     484      453432 :                         if (e == NULL) {
     485           0 :                                 rel_destroy(rel);
     486           0 :                                 return NULL;
     487             :                         }
     488      453432 :                         e->nid = -(ba->basenr + i);
     489      453432 :                         e->alias.label = e->nid;
     490      453432 :                         append(rel->exps, e);
     491             :                 }
     492      453635 :                 i++;
     493      453635 :                 int j = i;
     494      576188 :                 for (cn = ol_first_node(t->idxs); cn; cn = cn->next, j++) {
     495      122715 :                         if (!rel_base_is_used(ba, j))
     496           0 :                                 continue;
     497             : 
     498      122715 :                         sql_exp *e;
     499      122715 :                         sql_idx *i = cn->data;
     500      122715 :                         sql_subtype *t;
     501      122715 :                         char *iname = NULL;
     502      122715 :                         int has_nils = 0, unique;
     503             : 
     504             :                         /* do not include empty indices in the plan */
     505      122715 :                         if ((hash_index(i->type) && list_length(i->columns) <= 1) || !idx_has_column(i->type))
     506      104714 :                                 continue;
     507             : 
     508       18002 :                         t = (i->type == join_idx) ? sql_bind_localtype("oid") : sql_bind_localtype("lng");
     509       18002 :                         iname = sa_strconcat( sa, "%", i->base.name);
     510       39669 :                         for (node *n = i->columns->h ; n && !has_nils; n = n->next) { /* check for NULL values */
     511       21667 :                                 sql_kc *kc = n->data;
     512             : 
     513       21667 :                                 if (kc->c->null)
     514       13185 :                                         has_nils = 1;
     515             :                         }
     516       18002 :                         unique = list_length(i->columns) == 1 && is_column_unique(((sql_kc*)i->columns->h->data)->c);
     517       18002 :                         e = exp_alias(sql, atname, iname, tname, iname, t, CARD_MULTI, has_nils, unique, 1);
     518       18002 :                         if (e == NULL) {
     519           0 :                                 rel_destroy(rel);
     520           0 :                                 return NULL;
     521             :                         }
     522             :                         /* index names are prefixed, to make them independent */
     523       18002 :                         if (hash_index(i->type)) {
     524       10024 :                                 p = e->p = prop_create(sa, PROP_HASHIDX, e->p);
     525       10024 :                                 p->value.pval = i;
     526             :                         }
     527       18002 :                         if (i->type == join_idx) {
     528        7978 :                                 p = e->p = prop_create(sa, PROP_JOINIDX, e->p);
     529        7978 :                                 p->value.pval = i;
     530             :                         }
     531       18002 :                         e->nid = -(ba->basenr + j);
     532       18002 :                         e->alias.label = e->nid;
     533       18002 :                         append(rel->exps, e);
     534             :                 }
     535             :         }
     536             :         return rel;
     537             : }
     538             : 
     539             : sql_exp *
     540        1036 : basetable_get_tid_or_add_it(mvc *sql, sql_rel *rel)
     541             : {
     542        1036 :         sql_exp *res = NULL;
     543             : 
     544        1036 :         if (is_basetable(rel->op)) {
     545        1036 :                 sql_table *t = rel->l;
     546        1036 :                 rel_base_t *ba = rel->r;
     547        1036 :                 const char *tname = t->base.name;
     548        1036 :                 const char *atname = ba->name?ba->name:tname;
     549             : 
     550        1036 :                 if (isRemote(t))
     551           0 :                         tname = mapiuri_table(t->query, sql->sa, tname);
     552        1036 :                 if (!rel->exps) { /* no exps yet, just set TID */
     553        1009 :                         rel_base_use_tid(sql, rel);
     554        1009 :                         res = exp_alias(sql, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     555        1009 :                         res->nid = -(ba->basenr + ol_length(t->columns));
     556        1009 :                         res->alias.label = res->nid;
     557          27 :                 } else if (!rel_base_is_used(ba, ol_length(t->columns)) ||  /* exps set, but no TID, add it */
     558          27 :                                    !(res = exps_bind_column2(rel->exps, atname, TID, NULL))) { /* exps set with TID, but maybe rel_dce removed it */
     559           0 :                         node *n = NULL;
     560           0 :                         rel_base_use_tid(sql, rel);
     561           0 :                         res = exp_alias(sql, atname, TID, tname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1);
     562           0 :                         res->nid = -(ba->basenr + ol_length(t->columns));
     563           0 :                         res->alias.label = res->nid;
     564             : 
     565             :                         /* search for indexes */
     566           0 :                         for (node *cn = rel->exps->h; cn && !n; cn = cn->next) {
     567           0 :                                 sql_exp *e = cn->data;
     568             : 
     569           0 :                                 if (is_intern(e))
     570           0 :                                         n = cn;
     571             :                         }
     572           0 :                         if (n) { /* has indexes, insert TID before them */
     573           0 :                                 list_append_before(rel->exps, n, res);
     574             :                         } else {
     575           0 :                                 list_append(rel->exps, res);
     576             :                         }
     577             :                 }
     578             :         }
     579        1036 :         return res;
     580             : }
     581             : 
     582             : sql_rel *
     583         549 : rel_rename_part(mvc *sql, sql_rel *p, sql_rel *mt_rel, const char *mtalias)
     584             : {
     585         549 :         sql_exp *ne = NULL;
     586         549 :         sql_table *mt = rel_base_table(mt_rel), *t = rel_base_table(p);
     587         549 :         rel_base_t *mt_ba = mt_rel->r, *p_ba = p->r;
     588         549 :         p_ba->basenr = mt_ba->basenr;
     589             : 
     590         549 :         assert(!p->exps);
     591         549 :         p->exps = sa_list(sql->sa);
     592         549 :         const char *pname = t->base.name;
     593         549 :         if (isRemote(t))
     594          37 :                 pname = mapiuri_table(t->query, sql->sa, pname);
     595        1480 :         for (node *n = mt_rel->exps->h; n; n = n->next) {
     596         931 :                 sql_exp *e = n->data;
     597         931 :                 node *cn = NULL, *ci = NULL;
     598         931 :                 const char *nname = e->r;
     599             : 
     600         931 :                 if (nname[0] == '%' && strcmp(nname, TID) == 0) {
     601          53 :                         list_append(p->exps, ne=exp_alias(sql, mtalias, TID, pname, TID, sql_bind_localtype("oid"), CARD_MULTI, 0, 1, 1));
     602          53 :                         ne->nid = e->nid;
     603          53 :                         ne->alias.label = e->alias.label;
     604          53 :                         rel_base_use_tid(sql, p);
     605         878 :                 } else if (nname[0] != '%' && (cn = ol_find_name(mt->columns, nname))) {
     606         876 :                         sql_column *c = cn->data, *rc = ol_fetch(t->columns, c->colnr);
     607             : 
     608             :                         /* with name find column in merge table, with colnr find column in member */
     609         876 :                         ne = exp_alias(sql, mtalias, exp_name(e), pname, rc->base.name, &rc->type, CARD_MULTI, rc->null, is_column_unique(rc), 0);
     610         876 :                         if (rc->t->pkey && ((sql_kc*)rc->t->pkey->k.columns->h->data)->c == rc) {
     611          19 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHCOL, ne->p);
     612          19 :                                 p->value.pval = rc->t->pkey;
     613         857 :                         } else if (rc->unique == 2) {
     614           0 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHCOL, ne->p);
     615           0 :                                 p->value.pval = NULL;
     616             :                         }
     617         876 :                         set_basecol(ne);
     618         876 :                         sql_column_get_statistics(sql, c, ne);
     619         876 :                         rel_base_use(sql, p, rc->colnr);
     620         876 :                         list_append(p->exps, ne);
     621         876 :                         ne->nid = e->nid;
     622         876 :                         ne->alias.label = e->alias.label;
     623           2 :                 } else if (nname[0] == '%' && ol_length(mt->idxs) && (ci = ol_find_name(mt->idxs, nname + 1))) {
     624           2 :                         sql_idx *i = ci->data, *ri = NULL;
     625             : 
     626             :                         /* indexes don't have a number field like 'colnr', so get the index the old way */
     627           4 :                         for (node *nn = mt->idxs->l->h, *mm = t->idxs->l->h; nn && mm ; nn = nn->next, mm = mm->next) {
     628           4 :                                 sql_idx *ii = nn->data;
     629             : 
     630           4 :                                 if (ii->base.id == i->base.id) {
     631           2 :                                         ri = mm->data;
     632           2 :                                         break;
     633             :                                 }
     634             :                         }
     635             : 
     636           2 :                         assert((!hash_index(ri->type) || list_length(ri->columns) > 1) && idx_has_column(ri->type));
     637           2 :                         sql_subtype *t = (ri->type == join_idx) ? sql_bind_localtype("oid") : sql_bind_localtype("lng");
     638           2 :                         char *iname1 = sa_strconcat(sql->sa, "%", i->base.name), *iname2 = sa_strconcat(sql->sa, "%", ri->base.name);
     639             : 
     640           2 :                         ne = exp_alias(sql, mtalias, iname1, pname, iname2, t, CARD_MULTI, has_nil(e), is_unique(e), 1);
     641             :                         /* index names are prefixed, to make them independent */
     642           2 :                         if (hash_index(ri->type)) {
     643           0 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_HASHIDX, ne->p);
     644           0 :                                 p->value.pval = ri;
     645           2 :                         } else if (ri->type == join_idx) {
     646           2 :                                 prop *p = ne->p = prop_create(sql->sa, PROP_JOINIDX, ne->p);
     647           2 :                                 p->value.pval = ri;
     648             :                         }
     649           2 :                         ne->nid = e->nid;
     650           2 :                         ne->alias.label = e->alias.label;
     651           2 :                         list_append(p->exps, ne);
     652             :                 }
     653             :         }
     654         549 :         rel_base_set_mergetable(p, mt);
     655         549 :         return p;
     656             : }
     657             : 
     658             : void
     659           0 : rel_base_dump_exps( stream *fout, sql_rel *rel)
     660             : {
     661           0 :         int i = 0, comma = 0;
     662           0 :         sql_table *t = rel->l;
     663           0 :         rel_base_t *ba = rel->r;
     664           0 :         assert(ba);
     665           0 :         mnstr_printf(fout, "[ ");
     666           0 :         for (node *cn = ol_first_node(t->columns); cn; cn = cn->next, i++) {
     667           0 :                 if (rel_base_is_used(ba, i)) {
     668           0 :                         sql_column *c = cn->data;
     669           0 :                         mnstr_printf(fout, "%s\"%s\".\"%s\"", comma?", ":"", t->base.name, c->base.name);
     670           0 :                         if (ba->name)
     671           0 :                                 mnstr_printf(fout, " as \"%s\".\"%s\"", ba->name, c->base.name);
     672             :                         comma = 1;
     673             :                 }
     674             :         }
     675           0 :         if (rel_base_is_used(ba, i)) {
     676           0 :                 mnstr_printf(fout, "%s\"%s\".\"%%TID%%\"", comma?", ":"", t->base.name);
     677           0 :                 if (ba->name)
     678           0 :                         mnstr_printf(fout, " as \"%s\".\"%%TID%%\"", ba->name);
     679             :                 comma = 1;
     680             :         }
     681           0 :         i++;
     682           0 :         for (node *in = ol_first_node(t->idxs); in; in = in->next, i++) {
     683           0 :                 if (rel_base_is_used(ba, i)) {
     684           0 :                         sql_idx *i = in->data;
     685           0 :                         mnstr_printf(fout, "%s\"%s\".\"%s\"", comma?", ":"", t->base.name, i->base.name);
     686           0 :                         if (ba->name)
     687           0 :                                 mnstr_printf(fout, " as \"%s\".\"%s\"", ba->name, i->base.name);
     688             :                         comma = 1;
     689             :                 }
     690             :         }
     691           0 :         mnstr_printf(fout, " ]");
     692           0 : }
     693             : 
     694             : int
     695          72 : rel_base_has_column_privileges(mvc *sql, sql_rel *rel)
     696             : {
     697          72 :         sql_table *t = rel->l;
     698          72 :         int has = 0;
     699             : 
     700         227 :         for (node *m = ol_first_node(t->columns); m && !has; m = m->next) {
     701         155 :                 sql_column *c = m->data;
     702             : 
     703         155 :                 if (column_privs(sql, c, PRIV_SELECT))
     704          33 :                         has = 1;
     705             :         }
     706          72 :         return has;
     707             : }
     708             : 
     709             : void
     710         549 : rel_base_set_mergetable(sql_rel *rel, sql_table *mt)
     711             : {
     712         549 :         rel_base_t *ba = rel->r;
     713             : 
     714         549 :         if (ba)
     715         549 :                 ba->mt = mt;
     716         549 : }
     717             : 
     718             : sql_table *
     719      173221 : rel_base_get_mergetable(sql_rel *rel)
     720             : {
     721      173221 :         rel_base_t *ba = rel->r;
     722             : 
     723      173221 :         return ba ? ba->mt : NULL;
     724             : }

Generated by: LCOV version 1.14