LCOV - code coverage report
Current view: top level - sql/server - sql_var.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 322 395 81.5 %
Date: 2024-04-26 00:35:57 Functions: 39 40 97.5 %

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

Generated by: LCOV version 1.14