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-07 21:21:43 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         330 : mal_startup(void)
      43             : {
      44             :         /* clean up the MAL internal structures before restart */
      45         330 :         mel_modules_loaded = 0;
      46         330 :         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        3237 : mal_module2(const char *name, mel_atom *atoms, mel_func *funcs,
      57             :                         mel_init initfunc, const char *code)
      58             : {
      59        3237 :         assert(mel_modules < MAX_MAL_MODULES);
      60        3237 :         mel_module[mel_modules].name = name;
      61        3237 :         mel_module[mel_modules].atoms = atoms;
      62        3237 :         mel_module[mel_modules].funcs = funcs;
      63        3237 :         mel_module[mel_modules].inits = initfunc;
      64        3237 :         mel_module[mel_modules].code = code;
      65        3237 :         mel_modules++;
      66        3237 : }
      67             : 
      68             : void
      69       14845 : mal_module(const char *name, mel_atom *atoms, mel_func *funcs)
      70             : {
      71       14845 :         assert(mel_modules < MAX_MAL_MODULES);
      72       14845 :         mel_module[mel_modules].name = name;
      73       14845 :         mel_module[mel_modules].atoms = atoms;
      74       14845 :         mel_module[mel_modules].funcs = funcs;
      75       14845 :         mel_module[mel_modules].inits = NULL;
      76       14845 :         mel_module[mel_modules].code = NULL;
      77       14845 :         mel_modules++;
      78       14845 : }
      79             : 
      80             : static char *
      81       15465 : initModule(Client c, const char *name, const char *initpasswd)
      82             : {
      83       15465 :         char *msg = MAL_SUCCEED;
      84             : 
      85       15465 :         if (!getName(name))
      86             :                 return msg;
      87       15465 :         if ((name = putName(name)) == NULL)
      88           0 :                 throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      89       15465 :         Module m = getModule(name);
      90       15465 :         if (m) {                                        /* run prelude */
      91       12495 :                 const char *prelude = putName("prelude");
      92       12495 :                 if (prelude == NULL)
      93           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      94       12495 :                 Symbol s = findSymbolInModule(m, prelude);
      95             : 
      96       12495 :                 if (s) {
      97         658 :                         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         658 :                         } else if (s && s->kind == PATTERNsymbol) {
     104         658 :                                 void *mb = NULL;
     105         658 :                                 assert(s->func->fcn != NULL);
     106         658 :                                 if (strcmp(name, "sql") == 0) {
     107             :                                         /* HACK ALERT: temporarily use sqlcontext to pass
     108             :                                          * the initial password to the prelude function */
     109         330 :                                         assert(c->sqlcontext == NULL);
     110         330 :                                         c->sqlcontext = (void *) initpasswd;
     111             :                                         /* HACK ALERT: use mb (MalBlkPtr) to pass revision
     112             :                                          * string in order to check that in the callee */
     113         330 :                                         mb = (void *) mercurial_revision();
     114             :                                 }
     115         658 :                                 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        2958 : addAtom(mel_atom *atoms)
     128             : {
     129        6882 :         for (; atoms && atoms->name[0]; atoms++) {
     130        3924 :                 int i = ATOMallocate(atoms->name);
     131        3924 :                 if (is_int_nil(i))
     132           0 :                         throw(TYPE, __func__, GDK_EXCEPTION);
     133        3924 :                 if (atoms->basetype[0]) {
     134        2958 :                         int tpe = ATOMindex(atoms->basetype);
     135        2958 :                         if (tpe < 0)
     136           0 :                                 throw(TYPE, __func__, TYPE_NOT_SUPPORTED);
     137        2958 :                         BATatoms[i] = BATatoms[tpe];
     138        2958 :                         strcpy_len(BATatoms[i].name, atoms->name, sizeof(BATatoms[i].name));
     139        2958 :                         BATatoms[i].storage = ATOMstorage(tpe);
     140             :                 } else {                                /* cannot overload void atoms */
     141         966 :                         BATatoms[i].storage = i;
     142         966 :                         BATatoms[i].linear = false;
     143             :                 }
     144        3924 :                 if (atoms->del)
     145         636 :                         BATatoms[i].atomDel = atoms->del;
     146        3924 :                 if (atoms->cmp) {
     147        1284 :                         BATatoms[i].atomCmp = atoms->cmp;
     148        1284 :                         BATatoms[i].linear = true;
     149             :                 }
     150        3924 :                 if (atoms->fromstr)
     151        2934 :                         BATatoms[i].atomFromStr = atoms->fromstr;
     152        3924 :                 if (atoms->tostr)
     153        2934 :                         BATatoms[i].atomToStr = atoms->tostr;
     154        3924 :                 if (atoms->heap) {
     155         636 :                         BATatoms[i].size = sizeof(var_t);
     156         636 :                         assert_shift_width(ATOMelmshift(ATOMsize(i)), ATOMsize(i));
     157         636 :                         BATatoms[i].atomHeap = atoms->heap;
     158             :                 }
     159        3924 :                 if (atoms->hash)
     160         954 :                         BATatoms[i].atomHash = atoms->hash;
     161        3924 :                 if (atoms->length)
     162         636 :                         BATatoms[i].atomLen = atoms->length;
     163        3924 :                 if (atoms->null) {
     164        1284 :                         const void *atmnull = (*atoms->null) ();
     165             : 
     166        1284 :                         BATatoms[i].atomNull = atmnull;
     167             :                 }
     168        3924 :                 if (atoms->nequal)
     169           0 :                         BATatoms[i].atomCmp = atoms->nequal;
     170        3924 :                 if (atoms->put)
     171         636 :                         BATatoms[i].atomPut = atoms->put;
     172        3924 :                 if (atoms->storage)
     173           0 :                         BATatoms[i].storage = (*atoms->storage) ();
     174        3924 :                 if (atoms->read)
     175         954 :                         BATatoms[i].atomRead = atoms->read;
     176        3924 :                 if (atoms->write)
     177         954 :                         BATatoms[i].atomWrite = atoms->write;
     178             :         }
     179             :         return MAL_SUCCEED;
     180             : }
     181             : 
     182             : static malType
     183    12861222 : makeMalType(mel_arg *a)
     184             : {
     185    12861222 :         malType tpe = TYPE_any;
     186             : 
     187    12861222 :         if (!a->type[0]) {
     188      418094 :                 a->typeid = tpe;
     189      418094 :                 if (a->isbat)
     190      330326 :                         tpe = newBatType(tpe);
     191      418094 :                 if (a->nr > 0)
     192      385106 :                         setTypeIndex(tpe, a->nr);
     193             :         } else {
     194    12443128 :                 tpe = getAtomIndex(a->type, strlen(a->type), -1);
     195    12443128 :                 a->typeid = tpe;
     196    12443128 :                 if (a->isbat)
     197     7438059 :                         tpe = newBatType(tpe);
     198             :         }
     199    12861222 :         if (a->opt == 1)
     200      155760 :                 setOptBat(tpe);
     201    12861222 :         return tpe;
     202             : }
     203             : 
     204             : void
     205      743148 : setPoly(mel_func *f, malType tpe)
     206             : {
     207      728322 :         int any = isAnyExpression(tpe) || tpe == TYPE_any || getOptBat(tpe);
     208     1281390 :     unsigned int index = 0;
     209             :         if (!any)
     210             :                 return;
     211      553068 :         if (getTypeIndex(tpe) > 0)
     212             :                 index = getTypeIndex(tpe);
     213      538242 :         if (any && (index + 1) > f->poly)
     214      306592 :                 f->poly = index + 1;
     215             : }
     216             : 
     217             : static str
     218       18435 : addFunctions(mel_func *fcn)
     219             : {
     220       18435 :         str msg = MAL_SUCCEED;
     221       18435 :         Module c;
     222       18435 :         Symbol s;
     223             : 
     224     1731771 :         for (; fcn && fcn->mod; fcn++) {
     225     1713336 :                 const char *mod = fcn->mod = putName(fcn->mod);
     226     1713336 :                 fcn->fcn = putName(fcn->fcn);
     227     1713336 :                 if (mod == NULL)
     228           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     229     1713336 :                 c = getModule(mod);
     230     1713336 :                 if (c == NULL && (c = globalModule(mod)) == NULL)
     231           0 :                         throw(LOADER, __func__, "Module %s can not be created", fcn->mod);
     232             : 
     233     2895808 :                 s = newSymbol(fcn->fcn, (fcn->command) ? COMMANDsymbol : PATTERNsymbol);
     234     1713336 :                 if (s == NULL)
     235           0 :                         throw(LOADER, __func__, "Can not create symbol for %s.%s missing", fcn->mod,
     236             :                                   fcn->fcn);
     237     1713336 :                 s->def = NULL;
     238     1713336 :                 s->func = fcn;
     239     1713336 :                 s->allocated = false;
     240             : 
     241             :                 /* add the return variables */
     242     1713336 :                 unsigned int i;
     243     3532024 :                 for (i = 0; i < fcn->retc; i++) {
     244     1818688 :                         mel_arg *a = fcn->args + i;
     245     1818688 :                         malType tpe = makeMalType(a);
     246     1818688 :                         if (a->nr > 0 || a->opt)
     247       57110 :                                 setPoly(fcn, tpe);
     248     1818688 :                         if (a->vargs) {
     249        3136 :                                 fcn->vrets = true;
     250        3136 :                                 setPoly(fcn, TYPE_any);
     251             :                         }
     252     1818688 :                         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     6166430 :                 for (i = fcn->retc; i < fcn->argc; i++) {
     261     4453094 :                         mel_arg *a = fcn->args + i;
     262     4453094 :                         malType tpe = makeMalType(a);
     263             : 
     264     4453094 :                         if (a->nr > 0  || a->opt)
     265      449436 :                                 setPoly(fcn, tpe);
     266     4453094 :                         if (a->vargs) {
     267       11690 :                                 fcn->vargs = true;
     268       11690 :                                 setPoly(fcn, TYPE_any);
     269             :                         }
     270     4453094 :                         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     1713336 :                 insertSymbol(c, s);
     278             :         }
     279             :         return msg;
     280             : }
     281             : 
     282             : static void
     283     6589440 : argCopy( mel_arg *ap, mel_func_arg *a)
     284             : {
     285     6589440 :         ap->typeid = a->type;
     286     6589440 :         ap->nr = a->nr;
     287     6589440 :         ap->isbat = a->isbat;
     288     6589440 :         ap->vargs = a->vargs;
     289     6589440 :         ap->opt = a->opt;
     290     6589440 :         if (a->type != TYPE_any)
     291     6557100 :                 strcpy(ap->type, BATatoms[a->type].name);
     292             :         else
     293       32340 :                 ap->type[0] = 0;
     294     6589440 : }
     295             : 
     296             : int
     297     1643070 : 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     1643070 :         int i;
     302     1643070 :         Module c;
     303     1643070 :         Symbol s;
     304     1643070 :         mel_func *f = NULL;
     305     1643070 :         va_list va;
     306             : 
     307     1643070 :         assert(mod && fcn);
     308     1643070 :         mod = putName(mod);
     309     1643070 :         fcn = putName(fcn);
     310     1643070 :         c = getModule(mod);
     311     1643070 :         if (c == NULL && (c = globalModule(mod)) == NULL)
     312             :                 return MEL_ERR;
     313             : 
     314     3286140 :         s = newSymbol(fcn, command ? COMMANDsymbol : PATTERNsymbol);
     315     1643070 :         if (s == NULL)
     316             :                 return MEL_ERR;
     317     1643070 :         fcn = s->name;
     318     1643070 :         s->allocated = true;
     319             : 
     320     1643070 :         f = (mel_func*)GDKmalloc(sizeof(mel_func));
     321     1643070 :         mel_arg *args = (mel_arg*)GDKmalloc(sizeof(mel_arg)*argc);
     322     1643070 :         if (!f || !args) {
     323           0 :                 if(!f) GDKfree(f);
     324           0 :                 freeSymbol(s);
     325           0 :                 return MEL_ERR;
     326             :         }
     327     1643070 :         f->mod = mod;
     328     1643070 :         f->fcn = fcn;
     329     1643070 :         f->command = command;
     330     1643070 :         f->unsafe = unsafe;
     331     1643070 :         f->vargs = 0;
     332     1643070 :         f->vrets = 0;
     333     1643070 :         f->poly = 0;
     334     1643070 :         f->retc = retc;
     335     1643070 :         f->argc = argc;
     336     1643070 :         f->args = args;
     337     1643070 :         f->imp = imp;
     338     1643070 :         f->comment = comment?GDKstrdup(comment):NULL;
     339     1643070 :         f->cname = fname?GDKstrdup(fname):NULL;
     340     1643070 :         s->def = NULL;
     341     1643070 :         s->func = f;
     342             : 
     343     1643070 :         va_start(va, argc);
     344     3295380 :         for (i = 0; i < retc; i++) {
     345     1652310 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     346     1652310 :                 mel_arg *ap = f->args+i;
     347     1652310 :                 argCopy(ap, &a);
     348     1652310 :                 malType tpe = makeMalType(ap);
     349     1652310 :                 if (a.nr > 0 || a.opt)
     350           0 :                         setPoly(f, tpe);
     351     1652310 :                 if (a.vargs) {
     352           0 :                         f->vrets = true;
     353           0 :                         setPoly(f, TYPE_any);
     354             :                 }
     355     1652310 :                 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     6580200 :         for (i = retc; i < argc; i++) {
     364     4937130 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     365     4937130 :                 mel_arg *ap = f->args+i;
     366     4937130 :                 argCopy(ap, &a);
     367     4937130 :                 malType tpe = makeMalType(ap);
     368     4937130 :                 if (a.nr > 0 || a.opt)
     369      221760 :                         setPoly(f, tpe);
     370     4937130 :                 if (a.vargs) {
     371           0 :                         f->vargs = true;
     372           0 :                         setPoly(f, TYPE_any);
     373             :                 }
     374     4937130 :                 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     1643070 :         insertSymbol(c, s);
     382     1643070 :         va_end(va);
     383     1643070 :         return MEL_OK;
     384             : }
     385             : 
     386             : static str
     387         330 : malPrelude(Client c, int listing, int *sql, int *mapi)
     388             : {
     389         330 :         int i;
     390         330 :         str msg = MAL_SUCCEED;
     391             : 
     392         330 :         (void) listing;
     393             :         /* Add all atom definitions */
     394       18765 :         for (i = mel_modules_loaded; i < mel_modules; i++) {
     395       18435 :                 if (mel_module[i].atoms) {
     396        2958 :                         msg = addAtom(mel_module[i].atoms);
     397        2958 :                         if (msg)
     398           0 :                                 return msg;
     399             :                 }
     400             :         }
     401             : 
     402             :         /* Add the signatures, where we now have access to all atoms */
     403       18765 :         for (i = mel_modules_loaded; i < mel_modules; i++) {
     404       18435 :                 const char *name = putName(mel_module[i].name);
     405       18435 :                 if (!malLibraryEnabled(name))
     406           0 :                         continue;
     407       18435 :                 if (mel_module[i].funcs) {
     408       18435 :                         msg = addFunctions(mel_module[i].funcs);
     409       18435 :                         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       18435 :                         if (msg)
     412           0 :                                 return msg;
     413             : 
     414             :                         /* mapi should be last, and sql last before mapi */
     415       18435 :                         if (strcmp(name, "sql") == 0) {
     416         330 :                                 *sql = i;
     417         330 :                                 continue;
     418             :                         }
     419       18105 :                         if (strcmp(name, "mapi") == 0) {
     420         330 :                                 *mapi = i;
     421         330 :                                 continue;
     422             :                         }
     423       17775 :                         if (!mel_module[i].inits) {
     424       15135 :                                 msg = initModule(c, name, NULL);
     425       15135 :                                 if (msg)
     426           0 :                                         return msg;
     427             :                         }
     428             :                 }
     429       17775 :                 if (mel_module[i].inits) {
     430             :                         /* mapi should be last, and sql last before mapi */
     431        2640 :                         if (strcmp(name, "sql") == 0 || strcmp(name, "mapi") == 0)
     432           0 :                                 continue;
     433        2640 :                         msg = mel_module[i].inits();
     434        2640 :                         if (msg)
     435           0 :                                 return msg;
     436             :                 }
     437             :         }
     438         330 :         mel_modules_loaded = mel_modules;
     439         330 :         return MAL_SUCCEED;
     440             : }
     441             : 
     442             : str
     443         330 : malIncludeModules(Client c, char *modules[], int listing, bool no_mapi_server,
     444             :                                   const char *initpasswd)
     445             : {
     446         330 :         str msg;
     447         330 :         int sql = -1, mapi = -1;
     448             : 
     449        3531 :         for (int i = 0; modules[i]; i++) {
     450             :                 /* load library */
     451        3201 :                 if (!malLibraryEnabled(modules[i]))
     452         932 :                         continue;
     453        2269 :                 if ((msg = loadLibrary(modules[i], listing)) != NULL)
     454           0 :                         return msg;
     455             :         }
     456             :         /* load the mal code for these modules and execute preludes */
     457         330 :         if ((msg = malPrelude(c, listing, &sql, &mapi)) != NULL)
     458             :                 return msg;
     459             :         /* mapi should be last, and sql last before mapi */
     460         330 :         if (sql >= 0) {
     461         330 :                 if (mel_module[sql].inits)
     462           0 :                         msg = mel_module[sql].inits();
     463             :                 else
     464         330 :                         msg = initModule(c, "sql", initpasswd);
     465         329 :                 if (msg)
     466             :                         return msg;
     467             :         }
     468         329 :         if (!no_mapi_server && mapi >= 0 && initpasswd == NULL) {
     469         317 :                 if (mel_module[mapi].inits)
     470         317 :                         msg = mel_module[mapi].inits();
     471             :                 else
     472           0 :                         msg = initModule(c, "mapi", NULL);
     473         317 :                 if (msg)
     474             :                         return msg;
     475             :         }
     476             :         return MAL_SUCCEED;
     477             : }

Generated by: LCOV version 1.14