LCOV - code coverage report
Current view: top level - sql/server - sql_var.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 320 395 81.0 %
Date: 2024-11-14 20:04:02 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      349135 : destroy_sql_var(void *gdata, void *data)
      25             : {
      26      349135 :         (void)gdata;
      27      349135 :         sql_var *svar = (sql_var*) data;
      28      349135 :         VALclear(&(svar->var.data));
      29      349135 :         svar->var.data.vtype = 0;
      30      349135 :         _DELETE(svar->sname);
      31      349135 :         _DELETE(svar->name);
      32      349135 :         _DELETE(svar);
      33      349135 : }
      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      339615 : var_key(sql_var *v)
      41             : {
      42      339615 :         return hash_key(v->name);
      43             : }
      44             : 
      45             : int
      46       37735 : init_global_variables(mvc *sql)
      47             : {
      48       37735 :         sql_subtype ctype;
      49       37735 :         lng sec = 0;
      50       37735 :         ValRecord src;
      51       37735 :         const char *opt, *sname = "sys";
      52       37735 :         sql_var *var;
      53             : 
      54       37735 :         if (!(sql->global_vars = list_create(destroy_sql_var)))
      55             :                 return -1;
      56             :         /* Use hash lookup for global variables */
      57       37735 :         if (!(sql->global_vars->ht = hash_new(NULL, 16, (fkeyvalue)&var_key)))
      58             :                 return -1;
      59             : 
      60       37735 :         sql_find_subtype(&ctype, "int", 0, 0);
      61       37735 :         SQLglobal(sname, "debug", &sql->debug);
      62       37735 :         SQLglobal(sname, "sql_optimizer", &sql->sql_optimizer);
      63             : 
      64       37735 :         sql_find_subtype(&ctype,  "varchar", 1024, 0);
      65       37735 :         SQLglobal(sname, "current_schema", sname);
      66       37735 :         SQLglobal(sname, "current_user", "monetdb");
      67       37735 :         SQLglobal(sname, "current_role", "monetdb");
      68             : 
      69             :         /* inherit the optimizer from the server */
      70       37735 :         opt = GDKgetenv("sql_optimizer");
      71       37735 :         if (!opt)
      72           0 :                 opt = "default_pipe";
      73       37735 :         SQLglobal(sname, "optimizer", opt);
      74             : 
      75       37735 :         sql_find_subtype(&ctype, "sec_interval", inttype2digits(ihour, isec), 0);
      76       37735 :         SQLglobal(sname, "current_timezone", &sec);
      77             : 
      78       37735 :         sql_find_subtype(&ctype, "bigint", 0, 0);
      79       37735 :         SQLglobal(sname, "last_id", &sec);
      80       37735 :         SQLglobal(sname, "rowcnt", &sec);
      81             :         return 0;
      82             : }
      83             : 
      84             : sql_var*
      85      339615 : push_global_var(mvc *sql, const char *sname, const char *name, sql_subtype *type)
      86             : {
      87      339615 :         sql_var *svar = ZNEW(sql_var);
      88             : 
      89      339615 :         if (!svar)
      90             :                 return NULL;
      91      339615 :         if (!(svar->name = _STRDUP(name))) {
      92           0 :                 _DELETE(svar);
      93           0 :                 return NULL;
      94             :         }
      95      339615 :         if (!(svar->sname = _STRDUP(sname))) {
      96           0 :                 _DELETE(svar->name);
      97           0 :                 _DELETE(svar);
      98           0 :                 return NULL;
      99             :         }
     100      339615 :         atom_init(&(svar->var));
     101      339615 :         if (type) {
     102      339615 :                 int tpe = type->type->localtype;
     103      339615 :                 VALset(&(svar->var.data), tpe, (ptr) ATOMnilptr(tpe));
     104      339615 :                 svar->var.tpe = *type;
     105             :         }
     106      339615 :         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        9520 : frame_push_var(mvc *sql, const char *name, sql_subtype *type)
     130             : {
     131        9520 :         assert(sql->topframes > 0);
     132        9520 :         sql_frame *f = sql->frames[sql->topframes - 1];
     133        9520 :         sql_var *svar = ZNEW(sql_var);
     134             : 
     135        9520 :         if (!svar)
     136             :                 return NULL;
     137        9520 :         if (!(svar->name = _STRDUP(name))) {
     138           0 :                 _DELETE(svar);
     139           0 :                 return NULL;
     140             :         }
     141        9520 :         atom_init(&(svar->var));
     142        9520 :         if (type) {
     143        9520 :                 int tpe = type->type->localtype;
     144        9520 :                 VALset(&(svar->var.data), tpe, (ptr) ATOMnilptr(tpe));
     145        9520 :                 svar->var.tpe = *type;
     146             :         }
     147        9520 :         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        9520 :         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         119 : destroy_sql_local_table(void *gdata, void *data)
     162             : {
     163         119 :         (void)gdata;
     164         119 :         sql_local_table *slt = (sql_local_table*) data;
     165         119 :         _DELETE(slt);
     166         119 : }
     167             : 
     168             : sql_local_table*
     169         119 : frame_push_table(mvc *sql, sql_table *t)
     170             : {
     171         119 :         assert(sql->topframes > 0);
     172         119 :         sql_frame *f = sql->frames[sql->topframes - 1];
     173         119 :         sql_local_table *slt = ZNEW(sql_local_table);
     174             : 
     175         119 :         if (!slt)
     176             :                 return NULL;
     177         119 :         slt->table = t;
     178         119 :         t->s = NULL;
     179         119 :         if (!f->tables && !(f->tables = list_create(destroy_sql_local_table))) {
     180           0 :                 _DELETE(slt);
     181           0 :                 return NULL;
     182             :         }
     183         119 :         if (!list_append(f->tables, slt)) {
     184           0 :                 _DELETE(slt);
     185           0 :                 return NULL;
     186             :         }
     187             :         return slt;
     188             : }
     189             : 
     190             : static void
     191       18391 : destroy_sql_rel_view(void *gdata, void *data)
     192             : {
     193       18391 :         (void)gdata;
     194       18391 :         sql_rel_view *srv = (sql_rel_view*) data;
     195       18391 :         rel_destroy(srv->rel_view);
     196       18391 :         _DELETE(srv->name);
     197       18391 :         _DELETE(srv);
     198       18391 : }
     199             : 
     200             : sql_rel_view*
     201       18391 : stack_push_rel_view(mvc *sql, const char *name, sql_rel *var)
     202             : {
     203       18391 :         assert(sql->topframes > 0);
     204       18391 :         sql_frame *f = sql->frames[sql->topframes - 1];
     205       18391 :         sql_rel_view *srv = ZNEW(sql_rel_view);
     206             : 
     207       18391 :         if (!srv)
     208             :                 return NULL;
     209       18391 :         if (!(srv->name = _STRDUP(name))) {
     210           0 :                 _DELETE(srv);
     211           0 :                 return NULL;
     212             :         }
     213       18391 :         srv->rel_view = var;
     214       18391 :         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       18391 :         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          31 : destroy_sql_window_definition(void *gdata, void *data)
     229             : {
     230          31 :         (void)gdata;
     231          31 :         sql_window_definition *swd = (sql_window_definition*) data;
     232          31 :         _DELETE(swd->name);
     233          31 :         _DELETE(swd);
     234          31 : }
     235             : 
     236             : sql_window_definition*
     237          31 : frame_push_window_def(mvc *sql, const char *name, dlist *wdef)
     238             : {
     239          31 :         assert(sql->topframes > 0);
     240          31 :         sql_frame *f = sql->frames[sql->topframes - 1];
     241          31 :         sql_window_definition *swd = ZNEW(sql_window_definition);
     242             : 
     243          31 :         if (!swd)
     244             :                 return NULL;
     245          31 :         if (!(swd->name = _STRDUP(name))) {
     246           0 :                 _DELETE(swd);
     247           0 :                 return NULL;
     248             :         }
     249          31 :         swd->wdef = wdef;
     250          31 :         swd->visited = false;
     251          31 :         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          31 :         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         150 : destroy_sql_groupby_expression(void *gdata, void *data)
     266             : {
     267         150 :         (void)gdata;
     268         150 :         sql_groupby_expression *sge = (sql_groupby_expression*) data;
     269         150 :         _DELETE(sge);
     270         150 : }
     271             : 
     272             : sql_groupby_expression*
     273         150 : frame_push_groupby_expression(mvc *sql, symbol *def, sql_exp *exp)
     274             : {
     275         150 :         assert(sql->topframes > 0);
     276         150 :         sql_frame *f = sql->frames[sql->topframes - 1];
     277         150 :         sql_groupby_expression *sge = ZNEW(sql_groupby_expression);
     278             : 
     279         150 :         if (!sge)
     280             :                 return NULL;
     281         150 :         sge->sdef = def;
     282         150 :         sge->token = def->token;
     283         150 :         sge->exp = exp;
     284         150 :         if (!f->group_expressions && !(f->group_expressions = list_create(destroy_sql_groupby_expression))) {
     285           0 :                 _DELETE(sge);
     286           0 :                 return NULL;
     287             :         }
     288         150 :         if (!list_append(f->group_expressions, sge)) {
     289           0 :                 _DELETE(sge);
     290           0 :                 return NULL;
     291             :         }
     292             :         return sge;
     293             : }
     294             : 
     295             : dlist *
     296          64 : frame_get_window_def(mvc *sql, const char *name, int *pos)
     297             : {
     298          64 :         if (sql->topframes > 0) {
     299          64 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     300          64 :                 if (f->windows) {
     301          42 :                         int i = 0;
     302          69 :                         for (node *n = f->windows->h; n ; n = n->next, i++) {
     303          58 :                                 sql_window_definition *var = (sql_window_definition*) n->data;
     304          58 :                                 if (var->name && !strcmp(var->name, name)) {
     305          31 :                                         if (pos)
     306          30 :                                                 *pos = i;
     307          31 :                                         return var->wdef;
     308             :                                 }
     309             :                         }
     310             :                 }
     311             :         }
     312             :         return NULL;
     313             : }
     314             : 
     315             : sql_exp*
     316      105111 : frame_get_groupby_expression(mvc *sql, symbol *def)
     317             : {
     318      105111 :         if (sql->topframes > 0) {
     319      105111 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     320      105111 :                 if (f->group_expressions) {
     321         670 :                         for (node *n = f->group_expressions->h; n ; n = n->next) {
     322         398 :                                 sql_groupby_expression *var = (sql_groupby_expression*) n->data;
     323         398 :                                 if (var->token == def->token && !symbol_cmp(sql, var->sdef, def))
     324          78 :                                         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          29 : frame_set_var_visited(mvc *sql, int i)
     351             : {
     352          29 :         if (sql->topframes > 0) {
     353          29 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     354          29 :                 sql_window_definition *win;
     355             : 
     356          29 :                 if (i < 0 || i >= list_length(f->windows))
     357           0 :                         return;
     358             : 
     359          29 :                 win = (sql_window_definition*) list_fetch(f->windows, i);
     360          29 :                 win->visited = true;
     361             :         }
     362             : }
     363             : 
     364             : void
     365       17947 : frame_clear_visited_flag(mvc *sql)
     366             : {
     367       17947 :         if (sql->topframes > 0) {
     368       17940 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     369       17940 :                 if (f->windows) {
     370          62 :                         for (node *n = f->windows->h; n ; n = n->next) {
     371          39 :                                 sql_window_definition *var = (sql_window_definition*) n->data;
     372          39 :                                 var->visited = false;
     373             :                         }
     374             :                 }
     375             :         }
     376       17947 : }
     377             : 
     378             : atom *
     379      376848 : sqlvar_set(sql_var *var, ValRecord *v)
     380             : {
     381      376848 :         VALclear(&(var->var.data));
     382      376838 :         if (VALcopy(&(var->var.data), v) == NULL)
     383             :                 return NULL;
     384      376840 :         var->var.isnull = VALisnil(v);
     385      376831 :         return &(var->var);
     386             : }
     387             : 
     388             : sql_frame*
     389      419202 : stack_push_frame(mvc *sql, const char *name)
     390             : {
     391      419202 :         sql_frame *v, **nvars;
     392      419202 :         int osize = sql->sizeframes, nextsize = osize;
     393             : 
     394      419202 :         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      419202 :         if (!(v = ZNEW(sql_frame)))
     402             :                 return NULL;
     403      419203 :         if (name && !(v->name = _STRDUP(name))) {
     404           0 :                 _DELETE(v);
     405           0 :                 return NULL;
     406             :         }
     407      419203 :         v->frame_number = ++sql->frame; /* The frame number for variables on the stack start on level 1 */
     408      419203 :         sql->frames[sql->topframes++] = v;
     409      419203 :         return v;
     410             : }
     411             : 
     412             : void
     413      419202 : clear_frame(mvc *sql, sql_frame *frame)
     414             : {
     415      419202 :         list_destroy(frame->group_expressions);
     416      419193 :         list_destroy(frame->windows);
     417      419190 :         list_destroy(frame->tables);
     418      419188 :         list_destroy(frame->rel_views);
     419      419187 :         list_destroy(frame->vars);
     420      419186 :         _DELETE(frame->name);
     421      419185 :         _DELETE(frame);
     422      419201 :         sql->frame--;
     423      419201 : }
     424             : 
     425             : void
     426       37735 : stack_pop_until(mvc *sql, int frame)
     427             : {
     428       37735 :         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       37735 : }
     434             : 
     435             : void
     436      419200 : stack_pop_frame(mvc *sql)
     437             : {
     438      419200 :         sql_frame *f = sql->frames[--sql->topframes];
     439      419200 :         assert(sql->topframes >= 0);
     440      419200 :         clear_frame(sql, f);
     441      419201 : }
     442             : 
     443             : sql_table *
     444         121 : frame_find_table(mvc *sql, const char *name)
     445             : {
     446         121 :         if (sql->topframes > 0) {
     447         121 :                 sql_frame *f = sql->frames[sql->topframes - 1];
     448         121 :                 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      211776 : stack_find_table(mvc *sql, const char *name)
     461             : {
     462     4219268 :         for (int i = sql->topframes-1; i >= 0; i--) {
     463     4007702 :                 sql_frame *f = sql->frames[i];
     464     4007702 :                 if (f->tables) {
     465         306 :                         for (node *n = f->tables->h; n ; n = n->next) {
     466         258 :                                 sql_local_table *var = (sql_local_table*) n->data;
     467         258 :                                 if (!strcmp(var->table->base.name, name))
     468         210 :                                         return var->table;
     469             :                         }
     470             :                 }
     471             :         }
     472             :         return NULL;
     473             : }
     474             : 
     475             : sql_rel *
     476      115070 : stack_find_rel_view(mvc *sql, const char *name)
     477             : {
     478      257689 :         for (int i = sql->topframes-1; i >= 0; i--) {
     479      159680 :                 sql_frame *f = sql->frames[i];
     480      159680 :                 if (f->rel_views) {
     481       35268 :                         for (node *n = f->rel_views->h; n ; n = n->next) {
     482       33541 :                                 sql_rel_view *var = (sql_rel_view*) n->data;
     483       33541 :                                 assert(var->name);
     484       33541 :                                 if (!strcmp(var->name, name))
     485       17061 :                                         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       12740 : frame_find_rel_view(mvc *sql, const char *name)
     518             : {
     519       12740 :         assert(sql->topframes > 0);
     520       12740 :         sql_frame *f = sql->frames[sql->topframes - 1];
     521       12740 :         if (f->rel_views) {
     522       18276 :                 for (node *n = f->rel_views->h; n ; n = n->next) {
     523       12470 :                         sql_rel_view *var = (sql_rel_view*) n->data;
     524       12470 :                                 assert(var->name);
     525       12470 :                                 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     1231326 : find_global_var(mvc *sql, sql_schema *s, const char *name)
     553             : {
     554     1231326 :         const char *sname = s->base.name;
     555     1231326 :         int key = hash_key(name); /* Using hash lookup */
     556     1231326 :         sql_hash_e *he = sql->global_vars->ht->buckets[key&(sql->global_vars->ht->size-1)];
     557             : 
     558     1362887 :         for (; he; he = he->chain) {
     559     1358824 :                 sql_var *var = (sql_var*) he->value;
     560             : 
     561     1358824 :                 assert(var->sname && var->name);
     562     1358824 :                 if (!strcmp(var->sname, sname) && !strcmp(var->name, name))
     563     1227263 :                         return var;
     564             :         }
     565             :         return NULL;
     566             : }
     567             : 
     568             : int
     569        9495 : frame_find_var(mvc *sql, const char *name)
     570             : {
     571        9495 :         assert(sql->topframes > 0);
     572        9495 :         sql_frame *f = sql->frames[sql->topframes - 1];
     573        9495 :         if (f->vars) {
     574       14383 :                 for (node *n = f->vars->h; n ; n = n->next) {
     575        9022 :                         sql_var *var = (sql_var*) n->data;
     576        9022 :                         assert(var->name);
     577        9022 :                         if (!strcmp(var->name, name))
     578             :                                 return 1;
     579             :                 }
     580             :         }
     581             :         return 0;
     582             : }
     583             : 
     584             : sql_var*
     585      133344 : stack_find_var_frame(mvc *sql, const char *name, int *level)
     586             : {
     587      133344 :         *level = 1; /* Level 0 is for globals */
     588      301410 :         for (int i = sql->topframes-1; i >= 0; i--) {
     589      210703 :                 sql_frame *f = sql->frames[i];
     590      210703 :                 if (f->vars) {
     591      201593 :                         for (node *n = f->vars->h; n ; n = n->next) {
     592      165506 :                                 sql_var *var = (sql_var*) n->data;
     593      165506 :                                 assert(var->name);
     594      165506 :                                 if (!strcmp(var->name, name)) {
     595       42637 :                                         *level = f->frame_number;
     596       42637 :                                         return var;
     597             :                                 }
     598             :                         }
     599             :                 }
     600             :         }
     601             :         return NULL;
     602             : }
     603             : 
     604             : sql_var*
     605           0 : stack_find_var_at_level(mvc *sql, const char *name, int level)
     606             : {
     607           0 :         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         510 : stack_has_frame(mvc *sql, const char *name)
     623             : {
     624         526 :         for (int i = sql->topframes-1; i >= 0; i--) {
     625         212 :                 sql_frame *f = sql->frames[i];
     626         212 :                 if (f->name && !strcmp(f->name, name))
     627             :                         return 1;
     628             :         }
     629             :         return 0;
     630             : }
     631             : 
     632             : int
     633       23157 : stack_nr_of_declared_tables(mvc *sql)
     634             : {
     635       23157 :         int dt = 0;
     636             : 
     637       57070 :         for (int i = sql->topframes-1; i >= 0; i--) {
     638       33913 :                 sql_frame *f = sql->frames[i];
     639       33913 :                 dt += list_length(f->tables);
     640             :         }
     641       23157 :         return dt;
     642             : }
     643             : 
     644             : str
     645      111261 : sqlvar_set_string(sql_var *var, const char *val)
     646             : {
     647      111261 :         atom *a = &var->var;
     648      111261 :         str new_val = _STRDUP(val);
     649             : 
     650      111261 :         if (a != NULL && new_val != NULL) {
     651      111261 :                 ValRecord *v = &a->data;
     652             : 
     653      111261 :                 if (v->val.sval)
     654      111261 :                         _DELETE(v->val.sval);
     655      111259 :                 v->val.sval = new_val;
     656      111259 :                 return new_val;
     657             :         } else if (new_val) {
     658             :                 _DELETE(new_val);
     659             :         }
     660             :         return NULL;
     661             : }
     662             : 
     663             : str
     664      820159 : sqlvar_get_string(sql_var *var)
     665             : {
     666      820159 :         atom *a = &var->var;
     667             : 
     668      820159 :         if (!a || a->data.vtype != TYPE_str)
     669             :                 return NULL;
     670      820159 :         return a->data.val.sval;
     671             : }
     672             : 
     673             : void
     674             : #ifdef HAVE_HGE
     675      252133 : sqlvar_set_number(sql_var *var, hge val)
     676             : #else
     677             : sqlvar_set_number(sql_var *var, lng val)
     678             : #endif
     679             : {
     680      252133 :         atom *a = &var->var;
     681             : 
     682      252133 :         if (a != NULL) {
     683      252133 :                 ValRecord *v = &a->data;
     684             : #ifdef HAVE_HGE
     685      252133 :                 if (v->vtype == TYPE_hge)
     686           0 :                         v->val.hval = val;
     687             : #endif
     688      252133 :                 if (v->vtype == TYPE_lng)
     689      252133 :                         v->val.lval = val;
     690      252133 :                 if (v->vtype == TYPE_int)
     691           0 :                         v->val.lval = (int) val;
     692      252133 :                 if (v->vtype == TYPE_sht)
     693           0 :                         v->val.lval = (sht) val;
     694      252133 :                 if (v->vtype == TYPE_bte)
     695           0 :                         v->val.lval = (bte) val;
     696      252133 :                 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      252133 : }
     704             : 
     705             : #ifdef HAVE_HGE
     706             : hge
     707             : #else
     708             : lng
     709             : #endif
     710       37083 : val_get_number(const ValRecord *v)
     711             : {
     712       37083 :         if (v != NULL) {
     713             : #ifdef HAVE_HGE
     714       37083 :                 if (v->vtype == TYPE_hge)
     715           0 :                         return v->val.hval;
     716             : #endif
     717             :                 if (v->vtype == TYPE_lng)
     718       37079 :                         return v->val.lval;
     719             :                 if (v->vtype == TYPE_int)
     720           4 :                         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