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

Generated by: LCOV version 1.14