LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_prelude.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 246 281 87.5 %
Date: 2024-10-03 20:03:20 Functions: 12 12 100.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             : /* Author(s) M.L. Kersten, N. Nes
      14             :  * This module takes the statically defined modules, atoms, commands and patterns
      15             :  * and populate the internal structures.
      16             :  *
      17             :  */
      18             : 
      19             : #include "monetdb_config.h"
      20             : #include "mal_import.h"
      21             : #include "mal_interpreter.h"  /* for showErrors() */
      22             : #include "mal_linker.h"                       /* for loadModuleLibrary() */
      23             : #include "mal_scenario.h"
      24             : #include "mal_parser.h"
      25             : #include "mal_authorize.h"
      26             : #include "mal_private.h"
      27             : #include "mutils.h"
      28             : 
      29             : #include "mal_prelude.h"
      30             : 
      31             : #define MAX_MAL_MODULES 128
      32             : static int mel_modules = 0, mel_modules_loaded = 0;
      33             : static struct mel_module {
      34             :         const char *name;
      35             :         mel_atom *atoms;
      36             :         mel_func *funcs;
      37             :         mel_init inits;
      38             :         const char *code;
      39             : } mel_module[MAX_MAL_MODULES];
      40             : 
      41             : int
      42         327 : mal_startup(void)
      43             : {
      44             :         /* clean up the MAL internal structures before restart */
      45         327 :         mel_modules_loaded = 0;
      46         327 :         return 0;
      47             : }
      48             : 
      49             : /* all MAL related functions register themselves
      50             :  * the order in which these registrations happen is significant
      51             :  * because there may be dependencies among the definitions.
      52             :  * For example, you better know the atoms before you use them
      53             :  */
      54             : 
      55             : void
      56        3207 : mal_module2(const char *name, mel_atom *atoms, mel_func *funcs,
      57             :                         mel_init initfunc, const char *code)
      58             : {
      59        3207 :         assert(mel_modules < MAX_MAL_MODULES);
      60        3207 :         mel_module[mel_modules].name = name;
      61        3207 :         mel_module[mel_modules].atoms = atoms;
      62        3207 :         mel_module[mel_modules].funcs = funcs;
      63        3207 :         mel_module[mel_modules].inits = initfunc;
      64        3207 :         mel_module[mel_modules].code = code;
      65        3207 :         mel_modules++;
      66        3207 : }
      67             : 
      68             : void
      69       14707 : mal_module(const char *name, mel_atom *atoms, mel_func *funcs)
      70             : {
      71       14707 :         assert(mel_modules < MAX_MAL_MODULES);
      72       14707 :         mel_module[mel_modules].name = name;
      73       14707 :         mel_module[mel_modules].atoms = atoms;
      74       14707 :         mel_module[mel_modules].funcs = funcs;
      75       14707 :         mel_module[mel_modules].inits = NULL;
      76       14707 :         mel_module[mel_modules].code = NULL;
      77       14707 :         mel_modules++;
      78       14707 : }
      79             : 
      80             : static char *
      81       15324 : initModule(Client c, const char *name, const char *initpasswd)
      82             : {
      83       15324 :         char *msg = MAL_SUCCEED;
      84             : 
      85       15324 :         if (!getName(name))
      86             :                 return msg;
      87       15324 :         if ((name = putName(name)) == NULL)
      88           0 :                 throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      89       15324 :         Module m = getModule(name);
      90       15324 :         if (m) {                                        /* run prelude */
      91       12381 :                 const char *prelude = putName("prelude");
      92       12381 :                 if (prelude == NULL)
      93           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      94       12381 :                 Symbol s = findSymbolInModule(m, prelude);
      95             : 
      96       12381 :                 if (s) {
      97         652 :                         if (s && s->kind == COMMANDsymbol && s->func && s->func->argc == 1) {
      98           0 :                                 int ret = 0;
      99             : 
     100           0 :                                 assert(s->func != NULL);
     101           0 :                                 msg = (*(str (*)(int *)) s->func->imp) (&ret);
     102           0 :                                 (void) ret;
     103         652 :                         } else if (s && s->kind == PATTERNsymbol) {
     104         652 :                                 void *mb = NULL;
     105         652 :                                 assert(s->func->fcn != NULL);
     106         652 :                                 if (strcmp(name, "sql") == 0) {
     107             :                                         /* HACK ALERT: temporarily use sqlcontext to pass
     108             :                                          * the initial password to the prelude function */
     109         327 :                                         assert(c->sqlcontext == NULL);
     110         327 :                                         c->sqlcontext = (void *) initpasswd;
     111             :                                         /* HACK ALERT: use mb (MalBlkPtr) to pass revision
     112             :                                          * string in order to check that in the callee */
     113         327 :                                         mb = (void *) mercurial_revision();
     114             :                                 }
     115         652 :                                 msg = (*(str (*)(Client, MalBlkPtr, MalStkPtr, InstrPtr)) s->func->pimp) (c, mb, NULL, NULL);
     116             :                         }
     117             :                 }
     118             :         }
     119             :         return msg;
     120             : }
     121             : 
     122             : /*
     123             :  * The statically description of the MAL structures call for a translation into
     124             :  * their underlying structure.
     125             :  */
     126             : static str
     127        2931 : addAtom(mel_atom *atoms)
     128             : {
     129        6819 :         for (; atoms && atoms->name[0]; atoms++) {
     130        3888 :                 int i = ATOMallocate(atoms->name);
     131        3888 :                 if (is_int_nil(i))
     132           0 :                         throw(TYPE, __func__, GDK_EXCEPTION);
     133        3888 :                 if (atoms->basetype[0]) {
     134        2931 :                         int tpe = ATOMindex(atoms->basetype);
     135        2931 :                         if (tpe < 0)
     136           0 :                                 throw(TYPE, __func__, TYPE_NOT_SUPPORTED);
     137        2931 :                         BATatoms[i] = BATatoms[tpe];
     138        2931 :                         strcpy_len(BATatoms[i].name, atoms->name, sizeof(BATatoms[i].name));
     139        2931 :                         BATatoms[i].storage = ATOMstorage(tpe);
     140             :                 } else {                                /* cannot overload void atoms */
     141         957 :                         BATatoms[i].storage = i;
     142         957 :                         BATatoms[i].linear = false;
     143             :                 }
     144        3888 :                 if (atoms->del)
     145         630 :                         BATatoms[i].atomDel = atoms->del;
     146        3888 :                 if (atoms->cmp) {
     147        1272 :                         BATatoms[i].atomCmp = atoms->cmp;
     148        1272 :                         BATatoms[i].linear = true;
     149             :                 }
     150        3888 :                 if (atoms->fromstr)
     151        2907 :                         BATatoms[i].atomFromStr = atoms->fromstr;
     152        3888 :                 if (atoms->tostr)
     153        2907 :                         BATatoms[i].atomToStr = atoms->tostr;
     154        3888 :                 if (atoms->heap) {
     155         630 :                         BATatoms[i].size = sizeof(var_t);
     156         630 :                         assert_shift_width(ATOMelmshift(ATOMsize(i)), ATOMsize(i));
     157         630 :                         BATatoms[i].atomHeap = atoms->heap;
     158             :                 }
     159        3888 :                 if (atoms->hash)
     160         945 :                         BATatoms[i].atomHash = atoms->hash;
     161        3888 :                 if (atoms->length)
     162         630 :                         BATatoms[i].atomLen = atoms->length;
     163        3888 :                 if (atoms->null) {
     164        1272 :                         const void *atmnull = (*atoms->null) ();
     165             : 
     166        1272 :                         BATatoms[i].atomNull = atmnull;
     167             :                 }
     168        3888 :                 if (atoms->nequal)
     169           0 :                         BATatoms[i].atomCmp = atoms->nequal;
     170        3888 :                 if (atoms->put)
     171         630 :                         BATatoms[i].atomPut = atoms->put;
     172        3888 :                 if (atoms->storage)
     173           0 :                         BATatoms[i].storage = (*atoms->storage) ();
     174        3888 :                 if (atoms->read)
     175         945 :                         BATatoms[i].atomRead = atoms->read;
     176        3888 :                 if (atoms->write)
     177         945 :                         BATatoms[i].atomWrite = atoms->write;
     178             :         }
     179             :         return MAL_SUCCEED;
     180             : }
     181             : 
     182             : static malType
     183    12738648 : makeMalType(mel_arg *a)
     184             : {
     185    12738648 :         malType tpe = TYPE_any;
     186             : 
     187    12738648 :         if (!a->type[0]) {
     188      414623 :                 a->typeid = tpe;
     189      414623 :                 if (a->isbat)
     190      327650 :                         tpe = newBatType(tpe);
     191      414623 :                 if (a->nr > 0)
     192      381932 :                         setTypeIndex(tpe, a->nr);
     193             :         } else {
     194    12324025 :                 tpe = getAtomIndex(a->type, strlen(a->type), -1);
     195    12324025 :                 a->typeid = tpe;
     196    12324025 :                 if (a->isbat)
     197     7370535 :                         tpe = newBatType(tpe);
     198             :         }
     199    12738648 :         if (a->opt == 1)
     200      154344 :                 setOptBat(tpe);
     201    12738648 :         return tpe;
     202             : }
     203             : 
     204             : void
     205      736722 : setPoly(mel_func *f, malType tpe)
     206             : {
     207      722028 :         int any = isAnyExpression(tpe) || tpe == TYPE_any || getOptBat(tpe);
     208     1270398 :     unsigned int index = 0;
     209             :         if (!any)
     210             :                 return;
     211      548370 :         if (getTypeIndex(tpe) > 0)
     212             :                 index = getTypeIndex(tpe);
     213      533676 :         if (any && (index + 1) > f->poly)
     214      304041 :                 f->poly = index + 1;
     215             : }
     216             : 
     217             : static str
     218       18267 : addFunctions(mel_func *fcn)
     219             : {
     220       18267 :         str msg = MAL_SUCCEED;
     221       18267 :         Module c;
     222       18267 :         Symbol s;
     223             : 
     224     1718607 :         for (; fcn && fcn->mod; fcn++) {
     225     1700340 :                 const char *mod = fcn->mod = putName(fcn->mod);
     226     1700340 :                 fcn->fcn = putName(fcn->fcn);
     227     1700340 :                 if (mod == NULL)
     228           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     229     1700340 :                 c = getModule(mod);
     230     1700340 :                 if (c == NULL && (c = globalModule(mod)) == NULL)
     231           0 :                         throw(LOADER, __func__, "Module %s can not be created", fcn->mod);
     232             : 
     233     2870419 :                 s = newSymbol(fcn->fcn, (fcn->command) ? COMMANDsymbol : PATTERNsymbol);
     234     1700340 :                 if (s == NULL)
     235           0 :                         throw(LOADER, __func__, "Can not create symbol for %s.%s missing", fcn->mod,
     236             :                                   fcn->fcn);
     237     1700340 :                 s->def = NULL;
     238     1700340 :                 s->func = fcn;
     239     1700340 :                 s->allocated = false;
     240             : 
     241             :                 /* add the return variables */
     242     1700340 :                 unsigned int i;
     243     3505399 :                 for (i = 0; i < fcn->retc; i++) {
     244     1805059 :                         mel_arg *a = fcn->args + i;
     245     1805059 :                         malType tpe = makeMalType(a);
     246     1805059 :                         if (a->nr > 0 || a->opt)
     247       56591 :                                 setPoly(fcn, tpe);
     248     1805059 :                         if (a->vargs) {
     249        3109 :                                 fcn->vrets = true;
     250        3109 :                                 setPoly(fcn, TYPE_any);
     251             :                         }
     252     1805059 :                         if (a->opt && fcn->command)
     253           0 :                                 throw(LOADER, __func__, "Can not have command symbol with dynamic types, ie bat vs scalar in %s.%s", fcn->mod, fcn->fcn);
     254             :                 /*
     255             :                         if (a->nr >= 2)
     256             :                                 printf("%s.%s\n", fcn->mod, fcn->fcn);
     257             :                                 */
     258             :                 }
     259             :                 /* add the arguments */
     260     6104393 :                 for (i = fcn->retc; i < fcn->argc; i++) {
     261     4404053 :                         mel_arg *a = fcn->args + i;
     262     4404053 :                         malType tpe = makeMalType(a);
     263             : 
     264     4404053 :                         if (a->nr > 0  || a->opt)
     265      445677 :                                 setPoly(fcn, tpe);
     266     4404053 :                         if (a->vargs) {
     267       11585 :                                 fcn->vargs = true;
     268       11585 :                                 setPoly(fcn, TYPE_any);
     269             :                         }
     270     4404053 :                         if (a->opt && fcn->command)
     271           0 :                                 throw(LOADER, __func__, "Can not have command symbol with dynamic types, ie bat vs scalar in %s.%s", fcn->mod, fcn->fcn);
     272             :                 /*
     273             :                         if (a->nr >= 2)
     274             :                                 printf("%s.%s\n", fcn->mod, fcn->fcn);
     275             :                                 */
     276             :                 }
     277     1700340 :                 insertSymbol(c, s);
     278             :         }
     279             :         return msg;
     280             : }
     281             : 
     282             : static void
     283     6529536 : argCopy( mel_arg *ap, mel_func_arg *a)
     284             : {
     285     6529536 :         ap->typeid = a->type;
     286     6529536 :         ap->nr = a->nr;
     287     6529536 :         ap->isbat = a->isbat;
     288     6529536 :         ap->vargs = a->vargs;
     289     6529536 :         ap->opt = a->opt;
     290     6529536 :         if (a->type != TYPE_any)
     291     6497490 :                 strcpy(ap->type, BATatoms[a->type].name);
     292             :         else
     293       32046 :                 ap->type[0] = 0;
     294     6529536 : }
     295             : 
     296             : int
     297     1628133 : melFunction(bool command, const char *mod, const char *fcn, MALfcn imp,
     298             :                         const char *fname, bool unsafe, const char *comment, int retc,
     299             :                         int argc, ...)
     300             : {
     301     1628133 :         int i;
     302     1628133 :         Module c;
     303     1628133 :         Symbol s;
     304     1628133 :         mel_func *f = NULL;
     305     1628133 :         va_list va;
     306             : 
     307     1628133 :         assert(mod && fcn);
     308     1628133 :         mod = putName(mod);
     309     1628133 :         fcn = putName(fcn);
     310     1628133 :         c = getModule(mod);
     311     1628133 :         if (c == NULL && (c = globalModule(mod)) == NULL)
     312             :                 return MEL_ERR;
     313             : 
     314     3256266 :         s = newSymbol(fcn, command ? COMMANDsymbol : PATTERNsymbol);
     315     1628133 :         if (s == NULL)
     316             :                 return MEL_ERR;
     317     1628133 :         fcn = s->name;
     318     1628133 :         s->allocated = true;
     319             : 
     320     1628133 :         f = (mel_func*)GDKmalloc(sizeof(mel_func));
     321     1628133 :         mel_arg *args = (mel_arg*)GDKmalloc(sizeof(mel_arg)*argc);
     322     1628133 :         if (!f || !args) {
     323           0 :                 if(!f) GDKfree(f);
     324           0 :                 freeSymbol(s);
     325           0 :                 return MEL_ERR;
     326             :         }
     327     1628133 :         f->mod = mod;
     328     1628133 :         f->fcn = fcn;
     329     1628133 :         f->command = command;
     330     1628133 :         f->unsafe = unsafe;
     331     1628133 :         f->vargs = 0;
     332     1628133 :         f->vrets = 0;
     333     1628133 :         f->poly = 0;
     334     1628133 :         f->retc = retc;
     335     1628133 :         f->argc = argc;
     336     1628133 :         f->args = args;
     337     1628133 :         f->imp = imp;
     338     1628133 :         f->comment = comment?GDKstrdup(comment):NULL;
     339     1628133 :         f->cname = fname?GDKstrdup(fname):NULL;
     340     1628133 :         s->def = NULL;
     341     1628133 :         s->func = f;
     342             : 
     343     1628133 :         va_start(va, argc);
     344     3265422 :         for (i = 0; i < retc; i++) {
     345     1637289 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     346     1637289 :                 mel_arg *ap = f->args+i;
     347     1637289 :                 argCopy(ap, &a);
     348     1637289 :                 malType tpe = makeMalType(ap);
     349     1637289 :                 if (a.nr > 0 || a.opt)
     350           0 :                         setPoly(f, tpe);
     351     1637289 :                 if (a.vargs) {
     352           0 :                         f->vrets = true;
     353           0 :                         setPoly(f, TYPE_any);
     354             :                 }
     355     1637289 :                 if (a.opt && f->command)
     356           0 :                         return MEL_ERR;
     357             :                 /*
     358             :                 if (a.nr >= 2)
     359             :                         printf("%s.%s\n", f->mod, f->fcn);
     360             :                         */
     361             :         }
     362             :         /* add the arguments */
     363     6520380 :         for (i = retc; i < argc; i++) {
     364     4892247 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     365     4892247 :                 mel_arg *ap = f->args+i;
     366     4892247 :                 argCopy(ap, &a);
     367     4892247 :                 malType tpe = makeMalType(ap);
     368     4892247 :                 if (a.nr > 0 || a.opt)
     369      219744 :                         setPoly(f, tpe);
     370     4892247 :                 if (a.vargs) {
     371           0 :                         f->vargs = true;
     372           0 :                         setPoly(f, TYPE_any);
     373             :                 }
     374     4892247 :                 if (a.opt && f->command)
     375           0 :                         return MEL_ERR;
     376             :                 /*
     377             :                 if (a.nr >= 2)
     378             :                         printf("%s.%s\n", f->mod, f->fcn);
     379             :                         */
     380             :         }
     381     1628133 :         insertSymbol(c, s);
     382     1628133 :         va_end(va);
     383     1628133 :         return MEL_OK;
     384             : }
     385             : 
     386             : static str
     387         327 : malPrelude(Client c, int listing, int *sql, int *mapi)
     388             : {
     389         327 :         int i;
     390         327 :         str msg = MAL_SUCCEED;
     391             : 
     392         327 :         (void) listing;
     393             :         /* Add all atom definitions */
     394       18594 :         for (i = mel_modules_loaded; i < mel_modules; i++) {
     395       18267 :                 if (mel_module[i].atoms) {
     396        2931 :                         msg = addAtom(mel_module[i].atoms);
     397        2931 :                         if (msg)
     398           0 :                                 return msg;
     399             :                 }
     400             :         }
     401             : 
     402             :         /* Add the signatures, where we now have access to all atoms */
     403       18594 :         for (i = mel_modules_loaded; i < mel_modules; i++) {
     404       18267 :                 const char *name = putName(mel_module[i].name);
     405       18267 :                 if (!malLibraryEnabled(name))
     406           0 :                         continue;
     407       18267 :                 if (mel_module[i].funcs) {
     408       18267 :                         msg = addFunctions(mel_module[i].funcs);
     409       18267 :                         if (!msg && mel_module[i].code) /* some modules may also have some function definitions */
     410           0 :                                 msg = malIncludeString(c, name, (str) mel_module[i].code, listing, NULL);
     411       18267 :                         if (msg)
     412           0 :                                 return msg;
     413             : 
     414             :                         /* mapi should be last, and sql last before mapi */
     415       18267 :                         if (strcmp(name, "sql") == 0) {
     416         327 :                                 *sql = i;
     417         327 :                                 continue;
     418             :                         }
     419       17940 :                         if (strcmp(name, "mapi") == 0) {
     420         327 :                                 *mapi = i;
     421         327 :                                 continue;
     422             :                         }
     423       17613 :                         if (!mel_module[i].inits) {
     424       14997 :                                 msg = initModule(c, name, NULL);
     425       14997 :                                 if (msg)
     426           0 :                                         return msg;
     427             :                         }
     428             :                 }
     429       17613 :                 if (mel_module[i].inits) {
     430             :                         /* mapi should be last, and sql last before mapi */
     431        2616 :                         if (strcmp(name, "sql") == 0 || strcmp(name, "mapi") == 0)
     432           0 :                                 continue;
     433        2616 :                         msg = mel_module[i].inits();
     434        2616 :                         if (msg)
     435           0 :                                 return msg;
     436             :                 }
     437             :         }
     438         327 :         mel_modules_loaded = mel_modules;
     439         327 :         return MAL_SUCCEED;
     440             : }
     441             : 
     442             : str
     443         327 : malIncludeModules(Client c, char *modules[], int listing, bool no_mapi_server,
     444             :                                   const char *initpasswd)
     445             : {
     446         327 :         str msg;
     447         327 :         int sql = -1, mapi = -1;
     448             : 
     449        3498 :         for (int i = 0; modules[i]; i++) {
     450             :                 /* load library */
     451        3171 :                 if (!malLibraryEnabled(modules[i]))
     452         923 :                         continue;
     453        2248 :                 if ((msg = loadLibrary(modules[i], listing)) != NULL)
     454           0 :                         return msg;
     455             :         }
     456             :         /* load the mal code for these modules and execute preludes */
     457         327 :         if ((msg = malPrelude(c, listing, &sql, &mapi)) != NULL)
     458             :                 return msg;
     459             :         /* mapi should be last, and sql last before mapi */
     460         327 :         if (sql >= 0) {
     461         327 :                 if (mel_module[sql].inits)
     462           0 :                         msg = mel_module[sql].inits();
     463             :                 else
     464         327 :                         msg = initModule(c, "sql", initpasswd);
     465         326 :                 if (msg)
     466             :                         return msg;
     467             :         }
     468         326 :         if (!no_mapi_server && mapi >= 0 && initpasswd == NULL) {
     469         314 :                 if (mel_module[mapi].inits)
     470         314 :                         msg = mel_module[mapi].inits();
     471             :                 else
     472           0 :                         msg = initModule(c, "mapi", NULL);
     473         314 :                 if (msg)
     474             :                         return msg;
     475             :         }
     476             :         return MAL_SUCCEED;
     477             : }

Generated by: LCOV version 1.14