LCOV - code coverage report
Current view: top level - sql/server - sql_var.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 321 396 81.1 %
Date: 2024-11-11 20:03:36 Functions: 38 40 95.0 %

          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 "sql_mvc.h"
      15             : #include "sql_scan.h"
      16             : #include "sql_list.h"
      17             : #include "sql_types.h"
      18             : #include "sql_catalog.h"
      19             : #include "sql_datetime.h"
      20             : #include "sql_atom.h"
      21             : #include "rel_rel.h"
      22             : 
      23             : static void
      24      386970 : destroy_sql_var(void *gdata, void *data)
      25             : {
      26      386970 :         (void)gdata;
      27      386970 :         sql_var *svar = (sql_var*) data;
      28      386970 :         VALclear(&(svar->var.data));
      29      386970 :         svar->var.data.vtype = 0;
      30      386970 :         _DELETE(svar->sname);
      31      386970 :         _DELETE(svar->name);
      32      386970 :         _DELETE(svar);
      33      386970 : }
      34             : 
      35             : #define SQL_GLOBAL(sname, name, val)                                                                    \
      36             :         if (!(var = push_global_var(sql, sname, name, &ctype)) ||                   \
      37             :                 !sqlvar_set(var, VALset(&src, ctype.type->localtype, (char*)(val)))) \
      38             :                 return -1;
      39             : 
      40             : static int
      41      377450 : var_key(sql_var *v)
      42             : {
      43      377450 :         return hash_key(v->name);
      44             : }
      45             : 
      46             : int
      47       37745 : init_global_variables(mvc *sql)
      48             : {
      49       37745 :         sql_subtype ctype;
      50       37745 :         lng sec = 0;
      51       37745 :         ValRecord src;
      52       37745 :         const char *mal_optimizer, *sname = "sys";
      53       37745 :         sql_var *var;
      54             : 
      55       37745 :         if (!(sql->global_vars = list_create(destroy_sql_var)))
      56             :                 return -1;
      57       37745 :         if (!(sql->global_vars->ht = hash_new(NULL, 16, (fkeyvalue)&var_key)))
      58             :                 return -1;
      59             : 
      60       37745 :         sql_find_subtype(&ctype, "int", 0, 0);
      61       37745 :         SQL_GLOBAL(sname, "debug", &sql->debug);
      62       37745 :         SQL_GLOBAL(sname, "sql_optimizer", &sql->sql_optimizer);
      63       37745 :         SQL_GLOBAL(sname, "division_min_scale", &sql->div_min_scale);
      64             : 
      65       37745 :         sql_find_subtype(&ctype, "varchar", 1024, 0);
      66       37745 :         SQL_GLOBAL(sname, "current_schema", sname);
      67       37745 :         SQL_GLOBAL(sname, "current_user", "monetdb");
      68       37745 :         SQL_GLOBAL(sname, "current_role", "monetdb");
      69             : 
      70             :         /* TODO: GDKenv var sql_optimizer change to mal_optimizer */
      71       37745 :         mal_optimizer = GDKgetenv("sql_optimizer");
      72       37745 :         if (!mal_optimizer)
      73           0 :                 mal_optimizer = "default_pipe";
      74             :         /* TODO: Change optmizer to mal_optimizer */
      75       37745 :         SQL_GLOBAL(sname, "optimizer", mal_optimizer);
      76             : 
      77       37745 :         sql_find_subtype(&ctype, "sec_interval", inttype2digits(ihour, isec), 0);
      78       37745 :         SQL_GLOBAL(sname, "current_timezone", &sec);
      79             : 
      80       37745 :         sql_find_subtype(&ctype, "bigint", 0, 0);
      81       37745 :         SQL_GLOBAL(sname, "last_id", &sec);
      82       37745 :         SQL_GLOBAL(sname, "rowcnt", &sec);
      83             : 
      84             :         return 0;
      85             : }
      86             : 
      87             : sql_var*
      88      377450 : push_global_var(mvc *sql, const char *sname, const char *name, sql_subtype *type)
      89             : {
      90      377450 :         sql_var *svar = ZNEW(sql_var);
      91             : 
      92      377450 :         if (!svar)
      93             :                 return NULL;
      94      377450 :         if (!(svar->name = _STRDUP(name))) {
      95           0 :                 _DELETE(svar);
      96           0 :                 return NULL;
      97             :         }
      98      377450 :         if (!(svar->sname = _STRDUP(sname))) {
      99           0 :                 _DELETE(svar->name);
     100           0 :                 _DELETE(svar);
     101           0 :                 return NULL;
     102             :         }
     103      377450 :         atom_init(&(svar->var));
     104      377450 :         if (type) {
     105      377450 :                 int tpe = type->type->localtype;
     106      377450 :                 VALset(&(svar->var.data), tpe, (ptr) ATOMnilptr(tpe));
     107      377450 :                 svar->var.tpe = *type;
     108             :         }
     109      377450 :         if (!list_append(sql->global_vars, svar)) {
     110           0 :                 _DELETE(svar->name);
     111           0 :                 _DELETE(svar->sname);
     112           0 :                 _DELETE(svar);
     113           0 :                 return NULL;
     114             :         }
     115             :         return svar;
     116             : }
     117             : 
     118             : int
     119           0 : remove_global_var(mvc *sql, sql_schema *s, const char *name)
     120             : {
     121           0 :         sql_var *v = find_global_var(sql, s, name);
     122             : 
     123           0 :         if (v) {
     124           0 :                 list_remove_data(sql->global_vars, NULL, v);
     125           0 :                 return 0;
     126             :         } else {
     127             :                 return -1;
     128             :         }
     129             : }
     130             : 
     131             : sql_var*
     132        9520 : frame_push_var(mvc *sql, const char *name, sql_subtype *type)
     133             : {
     134        9520 :         assert(sql->topframes > 0);
     135        9520 :         sql_frame *f = sql->frames[sql->topframes - 1];
     136        9520 :         sql_var *svar = ZNEW(sql_var);
     137             : 
     138        9520 :         if (!svar)
     139             :                 return NULL;
     140        9520 :         if (!(svar->name = _STRDUP(name))) {
     141           0 :                 _DELETE(svar);
     142           0 :                 return NULL;
     143             :         }
     144        9520 :         atom_init(&(svar->var));
     145        9520 :         if (type) {
     146        9520 :                 int tpe = type->type->localtype;
     147        9520 :                 VALset(&(svar->var.data), tpe, (ptr) ATOMnilptr(tpe));
     148        9520 :                 svar->var.tpe = *type;
     149             :         }
     150        9520 :         if (!f->vars && !(f->vars = list_create(destroy_sql_var))) {
     151           0 :                 _DELETE(svar->name);
     152           0 :                 _DELETE(svar);
     153           0 :                 return NULL;
     154             :         }
     155        9520 :         if (!list_append(f->vars, svar)) {
     156           0 :                 _DELETE(svar->name);
     157           0 :                 _DELETE(svar);
     158           0 :                 return NULL;
     159             :         }
     160             :         return svar;
     161             : }
     162             : 
     163             : static void
     164         119 : destroy_sql_local_table(void *gdata, void *data)
     165             : {
     166         119 :         (void)gdata;
     167         119 :         sql_local_table *slt = (sql_local_table*) data;
     168         119 :         _DELETE(slt);
     169         119 : }
     170             : 
     171             : sql_local_table*
     172         119 : frame_push_table(mvc *sql, sql_table *t)
     173             : {
     174         119 :         assert(sql->topframes > 0);
     175         119 :         sql_frame *f = sql->frames[sql->topframes - 1];
     176         119 :         sql_local_table *slt = ZNEW(sql_local_table);
     177             : 
     178         119 :         if (!slt)
     179             :                 return NULL;
     180         119 :         slt->table = t;
     181         119 :         t->s = NULL;
     182         119 :         if (!f->tables && !(f->tables = list_create(destroy_sql_local_table))) {
     183           0 :                 _DELETE(slt);
     184           0 :                 return NULL;
     185             :         }
     186         119 :         if (!list_append(f->tables, slt)) {
     187           0 :                 _DELETE(slt);
     188           0 :                 return NULL;
     189             :         }
     190             :         return slt;
     191             : }
     192             : 
     193             : static void
     194       18391 : destroy_sql_rel_view(void *gdata, void *data)
     195             : {
     196       18391 :         (void)gdata;
     197       18391 :         sql_rel_view *srv = (sql_rel_view*) data;
     198       18391 :         rel_destroy(srv->rel_view);
     199       18391 :         _DELETE(srv->name);
     200       18391 :         _DELETE(srv);
     201       18391 : }
     202             : 
     203             : sql_rel_view*
     204       18391 : stack_push_rel_view(mvc *sql, const char *name, sql_rel *var)
     205             : {
     206       18391 :         assert(sql->topframes > 0);
     207       18391 :         sql_frame *f = sql->frames[sql->topframes - 1];
     208       18391 :         sql_rel_view *srv = ZNEW(sql_rel_view);
     209             : 
     210       18391 :         if (!srv)
     211             :                 return NULL;
     212       18391 :         if (!(srv->name = _STRDUP(name))) {
     213           0 :                 _DELETE(srv);
     214           0 :                 return NULL;
     215             :         }
     216       18391 :         srv->rel_view = var;
     217       18391 :         if (!f->rel_views && !(f->rel_views = list_create(destroy_sql_rel_view))) {
     218           0 :                 _DELETE(srv->name);
     219           0 :                 _DELETE(srv);
     220           0 :                 return NULL;
     221             :         }
     222       18391 :         if (!list_append(f->rel_views, srv)) {
     223           0 :                 _DELETE(srv->name);
     224           0 :                 _DELETE(srv);
     225           0 :                 return NULL;
     226             :         }
     227             :         return srv;
     228             : }
     229             : 
     230             : static void
     231          31 : destroy_sql_window_definition(void *gdata, void *data)
     232             : {
     233          31 :         (void)gdata;
     234          31 :         sql_window_definition *swd = (sql_window_definition*) data;
     235          31 :         _DELETE(swd->name);
     236          31 :         _DELETE(swd);
     237          31 : }
     238             : 
     239             : sql_window_definition*
     240          31 : frame_push_window_def(mvc *sql, const char *name, dlist *wdef)
     241             : {
     242          31 :         assert(sql->topframes > 0);
     243          31 :         sql_frame *f = sql->frames[sql->topframes - 1];
     244          31 :         sql_window_definition *swd = ZNEW(sql_window_definition);
     245             : 
     246          31 :         if (!swd)
     247             :                 return NULL;
     248          31 :         if (!(swd->name = _STRDUP(name))) {
     249           0 :                 _DELETE(swd);
     250           0 :                 return NULL;
     251             :         }
     252          31 :         swd->wdef = wdef;
     253          31 :         swd->visited = false;
     254          31 :         if (!f->windows && !(f->windows = list_create(destroy_sql_window_definition))) {
     255           0 :                 _DELETE(swd->name);
     256           0 :                 _DELETE(swd);
     257           0 :                 return NULL;
     258             :         }
     259          31 :         if (!list_append(f->windows, swd)) {
     260           0 :                 _DELETE(swd->name);
     261           0 :                 _DELETE(swd);
     262           0 :                 return NULL;
     263             :         }
     264             :         return swd;
     265             : }
     266             : 
     267             : static void
     268         150 : destroy_sql_groupby_expression(void *gdata, void *data)
     269             : {
     270         150 :         (void)gdata;
     271         150 :         sql_groupby_expression *sge = (sql_groupby_expression*) data;
     272         150 :         _DELETE(sge);
     273         150 : }
     274             : 
     275             : sql_groupby_expression*
     276         150 : frame_push_groupby_expression(mvc *sql, symbol *def, sql_exp *exp)
     277             : {
     278         150 :         assert(sql->topframes > 0);
     279         150 :         sql_frame *f = sql->frames[sql->topframes - 1];
     280         150 :         sql_groupby_expression *sge = ZNEW(sql_groupby_expression);
     281             : 
     282         150 :         if (!sge)
     283             :                 return NULL;
     284         150 :         sge->sdef = def;
     285         150 :         sge->token = def->token;
     286         150 :         sge->exp = exp;
     287         150 :         if (!f->group_expressions && !(f->group_expressions = list_create(destroy_sql_groupby_expression))) {
     288           0 :                 _DELETE(sge);
     289           0 :                 return NULL;
     290             :         }
     291         150 :         if (!list_append(f->group_expressions, sge)) {
     292           0 :                 _DELETE(sge);
     293           0 :                 return NULL;
     294             :         }
     295             :         return sge;
     296             : }
     297             : 
     298             : dlist *
     299          64 : frame_get_window_def(mvc *sql, const char *name, int *pos)
     300             : {
     301          64 :         if (sql->topframes > 0) {
     302          64 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     303          64 :                 if (f->windows) {
     304          42 :                         int i = 0;
     305          69 :                         for (node *n = f->windows->h; n ; n = n->next, i++) {
     306          58 :                                 sql_window_definition *var = (sql_window_definition*) n->data;
     307          58 :                                 if (var->name && !strcmp(var->name, name)) {
     308          31 :                                         if (pos)
     309          30 :                                                 *pos = i;
     310          31 :                                         return var->wdef;
     311             :                                 }
     312             :                         }
     313             :                 }
     314             :         }
     315             :         return NULL;
     316             : }
     317             : 
     318             : sql_exp*
     319      105111 : frame_get_groupby_expression(mvc *sql, symbol *def)
     320             : {
     321      105111 :         if (sql->topframes > 0) {
     322      105111 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     323      105111 :                 if (f->group_expressions) {
     324         670 :                         for (node *n = f->group_expressions->h; n ; n = n->next) {
     325         398 :                                 sql_groupby_expression *var = (sql_groupby_expression*) n->data;
     326         398 :                                 if (var->token == def->token && !symbol_cmp(sql, var->sdef, def))
     327          78 :                                         return var->exp;
     328             :                         }
     329             :                 }
     330             :         }
     331             :         return NULL;
     332             : }
     333             : 
     334             : /* There could a possibility that this is vulnerable to a time-of-check, time-of-use race condition.
     335             :  * However this should never happen in the SQL compiler */
     336             : bool
     337          15 : frame_check_var_visited(mvc *sql, int i)
     338             : {
     339          15 :         if (sql->topframes > 0) {
     340          15 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     341          15 :                 sql_window_definition *win;
     342             : 
     343          15 :                 if (i < 0 || i >= list_length(f->windows))
     344           0 :                         return false;
     345             : 
     346          15 :                 win = (sql_window_definition*) list_fetch(f->windows, i);
     347          15 :                 return win->visited;
     348             :         }
     349             :         return false;
     350             : }
     351             : 
     352             : void
     353          29 : frame_set_var_visited(mvc *sql, int i)
     354             : {
     355          29 :         if (sql->topframes > 0) {
     356          29 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     357          29 :                 sql_window_definition *win;
     358             : 
     359          29 :                 if (i < 0 || i >= list_length(f->windows))
     360           0 :                         return;
     361             : 
     362          29 :                 win = (sql_window_definition*) list_fetch(f->windows, i);
     363          29 :                 win->visited = true;
     364             :         }
     365             : }
     366             : 
     367             : void
     368       17947 : frame_clear_visited_flag(mvc *sql)
     369             : {
     370       17947 :         if (sql->topframes > 0) {
     371       17940 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     372       17940 :                 if (f->windows) {
     373          62 :                         for (node *n = f->windows->h; n ; n = n->next) {
     374          39 :                                 sql_window_definition *var = (sql_window_definition*) n->data;
     375          39 :                                 var->visited = false;
     376             :                         }
     377             :                 }
     378             :         }
     379       17947 : }
     380             : 
     381             : atom *
     382      414687 : sqlvar_set(sql_var *var, ValRecord *v)
     383             : {
     384      414687 :         VALclear(&(var->var.data));
     385      414674 :         if (VALcopy(&(var->var.data), v) == NULL)
     386             :                 return NULL;
     387      414671 :         var->var.isnull = VALisnil(v);
     388      414661 :         return &(var->var);
     389             : }
     390             : 
     391             : sql_frame*
     392      420598 : stack_push_frame(mvc *sql, const char *name)
     393             : {
     394      420598 :         sql_frame *v, **nvars;
     395      420598 :         int osize = sql->sizeframes, nextsize = osize;
     396             : 
     397      420598 :         if (sql->topframes == nextsize) {
     398          12 :                 nextsize <<= 1;
     399          24 :                 if (!(nvars = SA_RENEW_ARRAY(sql->pa, sql_frame*, sql->frames, nextsize, osize)))
     400             :                         return NULL;
     401          12 :                 sql->frames = nvars;
     402          12 :                 sql->sizeframes = nextsize;
     403             :         }
     404      420598 :         if (!(v = ZNEW(sql_frame)))
     405             :                 return NULL;
     406      420598 :         if (name && !(v->name = _STRDUP(name))) {
     407           0 :                 _DELETE(v);
     408           0 :                 return NULL;
     409             :         }
     410      420598 :         v->frame_number = ++sql->frame; /* The frame number for variables on the stack start on level 1 */
     411      420598 :         sql->frames[sql->topframes++] = v;
     412      420598 :         return v;
     413             : }
     414             : 
     415             : void
     416      420598 : clear_frame(mvc *sql, sql_frame *frame)
     417             : {
     418      420598 :         list_destroy(frame->group_expressions);
     419      420594 :         list_destroy(frame->windows);
     420      420592 :         list_destroy(frame->tables);
     421      420590 :         list_destroy(frame->rel_views);
     422      420591 :         list_destroy(frame->vars);
     423      420590 :         _DELETE(frame->name);
     424      420592 :         _DELETE(frame);
     425      420598 :         sql->frame--;
     426      420598 : }
     427             : 
     428             : void
     429       37745 : stack_pop_until(mvc *sql, int frame)
     430             : {
     431       37745 :         while (sql->topframes > frame) {
     432           0 :                 assert(sql->topframes >= 0);
     433           0 :                 sql_frame *f = sql->frames[--sql->topframes];
     434           0 :                 clear_frame(sql, f);
     435             :         }
     436       37745 : }
     437             : 
     438             : void
     439      420597 : stack_pop_frame(mvc *sql)
     440             : {
     441      420597 :         sql_frame *f = sql->frames[--sql->topframes];
     442      420597 :         assert(sql->topframes >= 0);
     443      420597 :         clear_frame(sql, f);
     444      420598 : }
     445             : 
     446             : sql_table *
     447         121 : frame_find_table(mvc *sql, const char *name)
     448             : {
     449         121 :         if (sql->topframes > 0) {
     450         121 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     451         121 :                 if (f->tables) {
     452           5 :                         for (node *n = f->tables->h; n ; n = n->next) {
     453           3 :                                 sql_local_table *var = (sql_local_table*) n->data;
     454           3 :                                 if (!strcmp(var->table->base.name, name))
     455           1 :                                         return var->table;
     456             :                         }
     457             :                 }
     458             :         }
     459             :         return NULL;
     460             : }
     461             : 
     462             : sql_table *
     463      211934 : stack_find_table(mvc *sql, const char *name)
     464             : {
     465     4219530 :         for (int i = sql->topframes-1; i >= 0; i--) {
     466     4007806 :                 sql_frame *f = sql->frames[i];
     467     4007806 :                 if (f->tables) {
     468         306 :                         for (node *n = f->tables->h; n ; n = n->next) {
     469         258 :                                 sql_local_table *var = (sql_local_table*) n->data;
     470         258 :                                 if (!strcmp(var->table->base.name, name))
     471         210 :                                         return var->table;
     472             :                         }
     473             :                 }
     474             :         }
     475             :         return NULL;
     476             : }
     477             : 
     478             : sql_rel *
     479      115174 : stack_find_rel_view(mvc *sql, const char *name)
     480             : {
     481      257897 :         for (int i = sql->topframes-1; i >= 0; i--) {
     482      159784 :                 sql_frame *f = sql->frames[i];
     483      159784 :                 if (f->rel_views) {
     484       35268 :                         for (node *n = f->rel_views->h; n ; n = n->next) {
     485       33541 :                                 sql_rel_view *var = (sql_rel_view*) n->data;
     486       33541 :                                 assert(var->name);
     487       33541 :                                 if (!strcmp(var->name, name))
     488       17061 :                                         return rel_dup(var->rel_view);
     489             :                         }
     490             :                 }
     491             :         }
     492             :         return NULL;
     493             : }
     494             : 
     495             : int
     496          13 : stack_find_rel_view_projection_columns(mvc *sql, const char *name, sql_rel **res)
     497             : {
     498          13 :         *res = NULL;
     499             : 
     500          43 :         for (int i = sql->topframes-1; i >= 0; i--) {
     501          31 :                 sql_frame *f = sql->frames[i];
     502          31 :                 if (f->rel_views) {
     503          18 :                         for (node *n = f->rel_views->h; n ; n = n->next) {
     504          10 :                                 sql_rel_view *var = (sql_rel_view*) n->data;
     505             : 
     506          10 :                                 assert(var->name);
     507             :                                  /* trigger views are basetables relations, so those may conflict */
     508          10 :                                 if (is_base(var->rel_view->op) && rel_bind_column(sql, var->rel_view, name, 0, 0)) {
     509          10 :                                         if (*res)
     510             :                                                 return -1;
     511           9 :                                         *res = var->rel_view;
     512             :                                 }
     513             :                         }
     514             :                 }
     515             :         }
     516             :         return 0;
     517             : }
     518             : 
     519             : sql_rel *
     520       12740 : frame_find_rel_view(mvc *sql, const char *name)
     521             : {
     522       12740 :         assert(sql->topframes > 0);
     523       12740 :         sql_frame *f = sql->frames[sql->topframes - 1];
     524       12740 :         if (f->rel_views) {
     525       18276 :                 for (node *n = f->rel_views->h; n ; n = n->next) {
     526       12470 :                         sql_rel_view *var = (sql_rel_view*) n->data;
     527       12470 :                                 assert(var->name);
     528       12470 :                                 if (!strcmp(var->name, name))
     529           1 :                                         return var->rel_view;
     530             :                 }
     531             :         }
     532             :         return NULL;
     533             : }
     534             : 
     535             : void
     536           6 : stack_update_rel_view(mvc *sql, const char *name, sql_rel *view)
     537             : {
     538           6 :         for (int i = sql->topframes-1; i >= 0; i--) {
     539           6 :                 sql_frame *f = sql->frames[i];
     540           6 :                 if (f->rel_views) {
     541           9 :                         for (node *n = f->rel_views->h; n ; n = n->next) {
     542           9 :                                 sql_rel_view *var = (sql_rel_view*) n->data;
     543           9 :                                 assert(var->name);
     544           9 :                                 if (!strcmp(var->name, name)) {
     545           6 :                                         rel_destroy(var->rel_view);
     546           6 :                                         var->rel_view = view;
     547           6 :                                         return;
     548             :                                 }
     549             :                         }
     550             :                 }
     551             :         }
     552             : }
     553             : 
     554             : sql_var*
     555     1254699 : find_global_var(mvc *sql, sql_schema *s, const char *name)
     556             : {
     557     1254699 :         const char *sname = s->base.name;
     558     1254699 :         int key = hash_key(name); /* Using hash lookup */
     559     1254699 :         sql_hash_e *he = sql->global_vars->ht->buckets[key&(sql->global_vars->ht->size-1)];
     560             : 
     561     1386369 :         for (; he; he = he->chain) {
     562     1382224 :                 sql_var *var = (sql_var*) he->value;
     563             : 
     564     1382224 :                 assert(var->sname && var->name);
     565     1382224 :                 if (!strcmp(var->sname, sname) && !strcmp(var->name, name))
     566     1250554 :                         return var;
     567             :         }
     568             :         return NULL;
     569             : }
     570             : 
     571             : int
     572        9495 : frame_find_var(mvc *sql, const char *name)
     573             : {
     574        9495 :         assert(sql->topframes > 0);
     575        9495 :         sql_frame *f = sql->frames[sql->topframes - 1];
     576        9495 :         if (f->vars) {
     577       14383 :                 for (node *n = f->vars->h; n ; n = n->next) {
     578        9022 :                         sql_var *var = (sql_var*) n->data;
     579        9022 :                         assert(var->name);
     580        9022 :                         if (!strcmp(var->name, name))
     581             :                                 return 1;
     582             :                 }
     583             :         }
     584             :         return 0;
     585             : }
     586             : 
     587             : sql_var*
     588      133381 : stack_find_var_frame(mvc *sql, const char *name, int *level)
     589             : {
     590      133381 :         *level = 1; /* Level 0 is for globals */
     591      301477 :         for (int i = sql->topframes-1; i >= 0; i--) {
     592      210733 :                 sql_frame *f = sql->frames[i];
     593      210733 :                 if (f->vars) {
     594      201593 :                         for (node *n = f->vars->h; n ; n = n->next) {
     595      165506 :                                 sql_var *var = (sql_var*) n->data;
     596      165506 :                                 assert(var->name);
     597      165506 :                                 if (!strcmp(var->name, name)) {
     598       42637 :                                         *level = f->frame_number;
     599       42637 :                                         return var;
     600             :                                 }
     601             :                         }
     602             :                 }
     603             :         }
     604             :         return NULL;
     605             : }
     606             : 
     607             : sql_var*
     608           0 : stack_find_var_at_level(mvc *sql, const char *name, int level)
     609             : {
     610           0 :         for (int i = sql->topframes-1; i >= 0; i--) {
     611           0 :                 sql_frame *f = sql->frames[i];
     612           0 :                 if (f->frame_number == level && f->vars) {
     613           0 :                         for (node *n = f->vars->h; n ; n = n->next) {
     614           0 :                                 sql_var *var = (sql_var*) n->data;
     615           0 :                                 assert(var->name);
     616           0 :                                 if (!strcmp(var->name, name))
     617           0 :                                         return var;
     618             :                         }
     619             :                 }
     620             :         }
     621             :         return NULL;
     622             : }
     623             : 
     624             : int
     625         516 : stack_has_frame(mvc *sql, const char *name)
     626             : {
     627         532 :         for (int i = sql->topframes-1; i >= 0; i--) {
     628         212 :                 sql_frame *f = sql->frames[i];
     629         212 :                 if (f->name && !strcmp(f->name, name))
     630             :                         return 1;
     631             :         }
     632             :         return 0;
     633             : }
     634             : 
     635             : int
     636       23157 : stack_nr_of_declared_tables(mvc *sql)
     637             : {
     638       23157 :         int dt = 0;
     639             : 
     640       57070 :         for (int i = sql->topframes-1; i >= 0; i--) {
     641       33913 :                 sql_frame *f = sql->frames[i];
     642       33913 :                 dt += list_length(f->tables);
     643             :         }
     644       23157 :         return dt;
     645             : }
     646             : 
     647             : str
     648      111273 : sqlvar_set_string(sql_var *var, const char *val)
     649             : {
     650      111273 :         atom *a = &var->var;
     651      111273 :         str new_val = _STRDUP(val);
     652             : 
     653      111272 :         if (a != NULL && new_val != NULL) {
     654      111272 :                 ValRecord *v = &a->data;
     655             : 
     656      111272 :                 if (v->val.sval)
     657      111272 :                         _DELETE(v->val.sval);
     658      111273 :                 v->val.sval = new_val;
     659      111273 :                 return new_val;
     660             :         } else if (new_val) {
     661             :                 _DELETE(new_val);
     662             :         }
     663             :         return NULL;
     664             : }
     665             : 
     666             : str
     667      832602 : sqlvar_get_string(sql_var *var)
     668             : {
     669      832602 :         atom *a = &var->var;
     670             : 
     671      832602 :         if (!a || a->data.vtype != TYPE_str)
     672             :                 return NULL;
     673      832602 :         return a->data.val.sval;
     674             : }
     675             : 
     676             : void
     677             : #ifdef HAVE_HGE
     678      262991 : sqlvar_set_number(sql_var *var, hge val)
     679             : #else
     680             : sqlvar_set_number(sql_var *var, lng val)
     681             : #endif
     682             : {
     683      262991 :         atom *a = &var->var;
     684             : 
     685      262991 :         if (a != NULL) {
     686      262991 :                 ValRecord *v = &a->data;
     687             : #ifdef HAVE_HGE
     688      262991 :                 if (v->vtype == TYPE_hge)
     689           0 :                         v->val.hval = val;
     690             : #endif
     691      262991 :                 if (v->vtype == TYPE_lng)
     692      262991 :                         v->val.lval = val;
     693      262991 :                 if (v->vtype == TYPE_int)
     694           0 :                         v->val.lval = (int) val;
     695      262991 :                 if (v->vtype == TYPE_sht)
     696           0 :                         v->val.lval = (sht) val;
     697      262991 :                 if (v->vtype == TYPE_bte)
     698           0 :                         v->val.lval = (bte) val;
     699      262991 :                 if (v->vtype == TYPE_bit) {
     700           0 :                         if (val)
     701           0 :                                 v->val.btval = 1;
     702             :                         else
     703           0 :                                 v->val.btval = 0;
     704             :                 }
     705             :         }
     706      262991 : }
     707             : 
     708             : #ifdef HAVE_HGE
     709             : hge
     710             : #else
     711             : lng
     712             : #endif
     713       37088 : val_get_number(const ValRecord *v)
     714             : {
     715       37088 :         if (v != NULL) {
     716             : #ifdef HAVE_HGE
     717       37088 :                 if (v->vtype == TYPE_hge)
     718           0 :                         return v->val.hval;
     719             : #endif
     720             :                 if (v->vtype == TYPE_lng)
     721       37084 :                         return v->val.lval;
     722             :                 if (v->vtype == TYPE_int)
     723           4 :                         return v->val.ival;
     724             :                 if (v->vtype == TYPE_sht)
     725           0 :                         return v->val.shval;
     726             :                 if (v->vtype == TYPE_bte)
     727           0 :                         return v->val.btval;
     728             :                 if (v->vtype == TYPE_bit)
     729           0 :                         if (v->val.btval)
     730             :                                 return 1;
     731           0 :                 return 0;
     732             :         }
     733             :         return 0;
     734             : }

Generated by: LCOV version 1.14