LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_prelude.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 229 269 85.1 %
Date: 2024-12-19 23:10:26 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         352 : mal_startup(void)
      43             : {
      44             :         /* clean up the MAL internal structures before restart */
      45         352 :         mel_modules_loaded = 0;
      46         352 :         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       18279 : mal_module2(const char *name, mel_atom *atoms, mel_func *funcs,
      57             :                         mel_init initfunc, const char *code)
      58             : {
      59       18279 :         assert(mel_modules < MAX_MAL_MODULES);
      60       18279 :         mel_module[mel_modules].name = name;
      61       18279 :         mel_module[mel_modules].atoms = atoms;
      62       18279 :         mel_module[mel_modules].funcs = funcs;
      63       18279 :         mel_module[mel_modules].inits = initfunc;
      64       18279 :         mel_module[mel_modules].code = code;
      65       18279 :         mel_modules++;
      66       18279 : }
      67             : 
      68             : void
      69       15167 : mal_module(const char *name, mel_atom *atoms, mel_func *funcs)
      70             : {
      71       15167 :         mal_module2(name, atoms, funcs, NULL, NULL);
      72       15167 : }
      73             : 
      74             : static char *
      75       16147 : initModule(Client c, const char *name, const char *initpasswd)
      76             : {
      77       16147 :         char *msg = MAL_SUCCEED;
      78             : 
      79       16147 :         assert(getName(name) == name);
      80       16147 :         Module m = getModule(name);
      81       16147 :         if (m) {                                        /* run prelude */
      82       12979 :                 const char *prelude = putName("prelude");
      83       12979 :                 if (prelude == NULL)
      84           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      85       12979 :                 Symbol s = findSymbolInModule(m, prelude);
      86             : 
      87       12979 :                 if (s) {
      88         702 :                         if (s && s->kind == COMMANDsymbol && s->func && s->func->argc == 1) {
      89           0 :                                 int ret = 0;
      90             : 
      91           0 :                                 assert(s->func != NULL);
      92           0 :                                 msg = (*(str (*)(int *)) s->func->imp) (&ret);
      93           0 :                                 (void) ret;
      94         702 :                         } else if (s && s->kind == PATTERNsymbol) {
      95         702 :                                 void *mb = NULL;
      96         702 :                                 assert(s->func->fcn != NULL);
      97         702 :                                 if (strcmp(name, "sql") == 0) {
      98             :                                         /* HACK ALERT: temporarily use sqlcontext to pass
      99             :                                          * the initial password to the prelude function */
     100         352 :                                         assert(c->sqlcontext == NULL);
     101         352 :                                         c->sqlcontext = (void *) initpasswd;
     102             :                                         /* HACK ALERT: use mb (MalBlkPtr) to pass revision
     103             :                                          * string in order to check that in the callee */
     104         352 :                                         mb = (void *) mercurial_revision();
     105             :                                 }
     106         702 :                                 msg = (*(str (*)(Client, MalBlkPtr, MalStkPtr, InstrPtr)) s->func->pimp) (c, mb, NULL, NULL);
     107             :                         }
     108             :                 }
     109             :         }
     110             :         return msg;
     111             : }
     112             : 
     113             : /*
     114             :  * The statically description of the MAL structures call for a translation into
     115             :  * their underlying structure.
     116             :  */
     117             : static str
     118        2452 : addAtom(mel_atom *atoms)
     119             : {
     120        5596 :         for (; atoms && atoms->name[0]; atoms++) {
     121        3144 :                 int i = ATOMallocate(atoms->name);
     122        3144 :                 if (is_int_nil(i))
     123           0 :                         throw(TYPE, __func__, GDK_EXCEPTION);
     124        3144 :                 if (atoms->basetype[0]) {
     125        2452 :                         int tpe = ATOMindex(atoms->basetype);
     126        2452 :                         if (tpe < 0)
     127           0 :                                 throw(TYPE, __func__, TYPE_NOT_SUPPORTED);
     128        2452 :                         BATatoms[i] = BATatoms[tpe];
     129        2452 :                         strcpy_len(BATatoms[i].name, atoms->name, sizeof(BATatoms[i].name));
     130        2452 :                         BATatoms[i].storage = ATOMstorage(tpe);
     131             :                 } else {                                /* cannot overload void atoms */
     132         692 :                         BATatoms[i].storage = i;
     133         692 :                         BATatoms[i].linear = false;
     134             :                 }
     135        3144 :                 if (atoms->del)
     136         340 :                         BATatoms[i].atomDel = atoms->del;
     137        3144 :                 if (atoms->cmp) {
     138        1032 :                         BATatoms[i].atomCmp = atoms->cmp;
     139        1032 :                         BATatoms[i].linear = true;
     140             :                 }
     141        3144 :                 if (atoms->fromstr)
     142        2088 :                         BATatoms[i].atomFromStr = atoms->fromstr;
     143        3144 :                 if (atoms->tostr)
     144        2088 :                         BATatoms[i].atomToStr = atoms->tostr;
     145        3144 :                 if (atoms->heap) {
     146         340 :                         BATatoms[i].size = sizeof(var_t);
     147         340 :                         assert_shift_width(ATOMelmshift(ATOMsize(i)), ATOMsize(i));
     148         340 :                         BATatoms[i].atomHeap = atoms->heap;
     149             :                 }
     150        3144 :                 if (atoms->hash)
     151         680 :                         BATatoms[i].atomHash = atoms->hash;
     152        3144 :                 if (atoms->length)
     153         340 :                         BATatoms[i].atomLen = atoms->length;
     154        3144 :                 if (atoms->null) {
     155        1032 :                         const void *atmnull = (*atoms->null) ();
     156             : 
     157        1032 :                         BATatoms[i].atomNull = atmnull;
     158             :                 }
     159        3144 :                 if (atoms->nequal)
     160           0 :                         BATatoms[i].atomCmp = atoms->nequal;
     161        3144 :                 if (atoms->put)
     162         340 :                         BATatoms[i].atomPut = atoms->put;
     163        3144 :                 if (atoms->storage)
     164           0 :                         BATatoms[i].storage = (*atoms->storage) ();
     165        3144 :                 if (atoms->read)
     166         680 :                         BATatoms[i].atomRead = atoms->read;
     167        3144 :                 if (atoms->write)
     168         680 :                         BATatoms[i].atomWrite = atoms->write;
     169             :         }
     170             :         return MAL_SUCCEED;
     171             : }
     172             : 
     173             : static malType
     174    13691790 : makeMalType(mel_arg *a)
     175             : {
     176    13691790 :         malType tpe = TYPE_any;
     177             : 
     178    13691790 :         if (!a->type[0]) {
     179      446298 :                 a->typeid = tpe;
     180      446298 :                 if (a->isbat)
     181      352348 :                         tpe = newBatType(tpe);
     182      446298 :                 if (a->nr > 0)
     183      410780 :                         setTypeIndex(tpe, a->nr);
     184             :         } else {
     185    13245492 :                 tpe = getAtomIndex(a->type, strlen(a->type), -1);
     186    13245492 :                 a->typeid = tpe;
     187    13245492 :                 if (a->isbat)
     188     7921267 :                         tpe = newBatType(tpe);
     189             :         }
     190    13691790 :         if (a->opt == 1)
     191      166144 :                 setOptBat(tpe);
     192    13691790 :         return tpe;
     193             : }
     194             : 
     195             : void
     196      793022 : setPoly(mel_func *f, malType tpe)
     197             : {
     198      776876 :         if (isAnyExpression(tpe) || tpe == TYPE_any || getOptBat(tpe)) {
     199      590270 :                 unsigned int index = getTypeIndex(tpe);
     200      574124 :                 if (index + 1 > f->poly)
     201      327966 :                         f->poly = index + 1;
     202             :         }
     203      776876 : }
     204             : 
     205             : static str
     206       18611 : addFunctions(mel_func *fcn)
     207             : {
     208       18611 :         str msg = MAL_SUCCEED;
     209       18611 :         Module c;
     210       18611 :         Symbol s;
     211             : 
     212     1834127 :         for (; fcn && fcn->mod; fcn++) {
     213     1815516 :                 const char *mod = putName(fcn->mod);
     214     1815516 :                 if (mod == NULL)
     215           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     216     1815516 :                 c = getModule(mod);
     217     1815516 :                 if (c == NULL && (c = globalModule(mod)) == NULL)
     218           0 :                         throw(LOADER, __func__, "Module %s can not be created", mod);
     219             : 
     220     3077232 :                 s = newSymbol(fcn->fcn, (fcn->command) ? COMMANDsymbol : PATTERNsymbol);
     221     1815516 :                 if (s == NULL)
     222           0 :                         throw(LOADER, __func__, "Can not create symbol for %s.%s missing", mod,
     223             :                                   fcn->fcn);
     224     1815516 :                 s->def = NULL;
     225     1815516 :                 s->func = fcn;
     226     1815516 :                 s->allocated = false;
     227             : 
     228             :                 /* add the return variables */
     229     1815516 :                 unsigned int i;
     230     3743424 :                 for (i = 0; i < fcn->retc; i++) {
     231     1927908 :                         mel_arg *a = fcn->args + i;
     232     1927908 :                         malType tpe = makeMalType(a);
     233     1927908 :                         if (a->nr > 0 || a->opt)
     234       60916 :                                 setPoly(fcn, tpe);
     235     1927908 :                         if (a->vargs) {
     236        3334 :                                 fcn->vrets = true;
     237        3334 :                                 setPoly(fcn, TYPE_any);
     238             :                         }
     239     1927908 :                         if (a->opt && fcn->command)
     240           0 :                                 throw(LOADER, __func__, "Can not have command symbol with dynamic types, ie bat vs scalar in %s.%s", mod, fcn->fcn);
     241             :                 /*
     242             :                         if (a->nr >= 2)
     243             :                                 printf("%s.%s\n", mod, fcn->fcn);
     244             :                                 */
     245             :                 }
     246             :                 /* add the arguments */
     247     6550662 :                 for (i = fcn->retc; i < fcn->argc; i++) {
     248     4735146 :                         mel_arg *a = fcn->args + i;
     249     4735146 :                         malType tpe = makeMalType(a);
     250             : 
     251     4735146 :                         if (a->nr > 0  || a->opt)
     252      479400 :                                 setPoly(fcn, tpe);
     253     4735146 :                         if (a->vargs) {
     254       12812 :                                 fcn->vargs = true;
     255       12812 :                                 setPoly(fcn, TYPE_any);
     256             :                         }
     257     4735146 :                         if (a->opt && fcn->command)
     258           0 :                                 throw(LOADER, __func__, "Can not have command symbol with dynamic types, ie bat vs scalar in %s.%s", mod, fcn->fcn);
     259             :                 /*
     260             :                         if (a->nr >= 2)
     261             :                                 printf("%s.%s\n", mod, fcn->fcn);
     262             :                                 */
     263             :                 }
     264     1815516 :                 insertSymbol(c, s);
     265             :         }
     266             :         return msg;
     267             : }
     268             : 
     269             : static void
     270     7028736 : argCopy( mel_arg *ap, mel_func_arg *a)
     271             : {
     272     7028736 :         ap->typeid = a->type;
     273     7028736 :         ap->nr = a->nr;
     274     7028736 :         ap->isbat = a->isbat;
     275     7028736 :         ap->vargs = a->vargs;
     276     7028736 :         ap->opt = a->opt;
     277     7028736 :         if (a->type != TYPE_any)
     278     6994240 :                 strcpy(ap->type, BATatoms[a->type].name);
     279             :         else
     280       34496 :                 ap->type[0] = 0;
     281     7028736 : }
     282             : 
     283             : int
     284     1752608 : melFunction(bool command, const char *mod, const char *fcn, MALfcn imp,
     285             :                         const char *fname, bool unsafe, const char *comment, int retc,
     286             :                         int argc, ...)
     287             : {
     288     1752608 :         int i;
     289     1752608 :         Module c;
     290     1752608 :         Symbol s;
     291     1752608 :         mel_func *f = NULL;
     292     1752608 :         va_list va;
     293             : 
     294     1752608 :         assert(mod && fcn);
     295     1752608 :         mod = putName(mod);
     296     1752608 :         fcn = putName(fcn);
     297     1752608 :         c = getModule(mod);
     298     1752608 :         if (c == NULL && (c = globalModule(mod)) == NULL)
     299             :                 return MEL_ERR;
     300             : 
     301     3505216 :         s = newSymbol(fcn, command ? COMMANDsymbol : PATTERNsymbol);
     302     1752608 :         if (s == NULL)
     303             :                 return MEL_ERR;
     304     1752608 :         fcn = s->name;
     305     1752608 :         s->allocated = true;
     306             : 
     307     1752608 :         f = (mel_func*)GDKmalloc(sizeof(mel_func));
     308     1752608 :         mel_arg *args = (mel_arg*)GDKmalloc(sizeof(mel_arg)*argc);
     309     1752608 :         if (!f || !args) {
     310           0 :                 GDKfree(f);
     311           0 :                 GDKfree(args);
     312           0 :                 freeSymbol(s);
     313           0 :                 return MEL_ERR;
     314             :         }
     315     3505216 :         *f = (mel_func) {
     316             :                 .mod = mod,
     317             :                 .fcn = fcn,
     318             :                 .command = command,
     319             :                 .unsafe = unsafe,
     320             :                 .vargs = 0,
     321             :                 .vrets = 0,
     322             :                 .poly = 0,
     323             :                 .retc = retc,
     324             :                 .argc = argc,
     325             :                 .args = args,
     326             :                 .imp = imp,
     327     1752608 :                 .comment = comment ? GDKstrdup(comment) : NULL,
     328     1752608 :                 .cname = fname ? GDKstrdup(fname) : NULL,
     329             :         };
     330     1752608 :         s->def = NULL;
     331     1752608 :         s->func = f;
     332             : 
     333     1752608 :         va_start(va, argc);
     334     3515072 :         for (i = 0; i < retc; i++) {
     335     1762464 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     336     1762464 :                 mel_arg *ap = f->args+i;
     337     1762464 :                 argCopy(ap, &a);
     338     1762464 :                 malType tpe = makeMalType(ap);
     339     1762464 :                 if (a.nr > 0 || a.opt)
     340           0 :                         setPoly(f, tpe);
     341     1762464 :                 if (a.vargs) {
     342           0 :                         f->vrets = true;
     343           0 :                         setPoly(f, TYPE_any);
     344             :                 }
     345     1762464 :                 if (a.opt && f->command) {
     346           0 :                         va_end(va);
     347           0 :                         freeSymbol(s);          /* also frees f and args */
     348           0 :                         return MEL_ERR;
     349             :                 }
     350             :                 /*
     351             :                 if (a.nr >= 2)
     352             :                         printf("%s.%s\n", f->mod, f->fcn);
     353             :                         */
     354             :         }
     355             :         /* add the arguments */
     356     7018880 :         for (i = retc; i < argc; i++) {
     357     5266272 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     358     5266272 :                 mel_arg *ap = f->args+i;
     359     5266272 :                 argCopy(ap, &a);
     360     5266272 :                 malType tpe = makeMalType(ap);
     361     5266272 :                 if (a.nr > 0 || a.opt)
     362      236544 :                         setPoly(f, tpe);
     363     5266272 :                 if (a.vargs) {
     364           0 :                         f->vargs = true;
     365           0 :                         setPoly(f, TYPE_any);
     366             :                 }
     367     5266272 :                 if (a.opt && f->command) {
     368           0 :                         va_end(va);
     369           0 :                         freeSymbol(s);          /* also frees f and args */
     370           0 :                         return MEL_ERR;
     371             :                 }
     372             :                 /*
     373             :                 if (a.nr >= 2)
     374             :                         printf("%s.%s\n", f->mod, f->fcn);
     375             :                         */
     376             :         }
     377     1752608 :         insertSymbol(c, s);
     378     1752608 :         va_end(va);
     379     1752608 :         return MEL_OK;
     380             : }
     381             : 
     382             : static str
     383         352 : malPrelude(Client c, int listing, int *sql, int *mapi)
     384             : {
     385         352 :         int i;
     386         352 :         str msg = MAL_SUCCEED;
     387             : 
     388         352 :         (void) listing;
     389             :         /* Add all atom definitions */
     390       18963 :         for (i = mel_modules_loaded; i < mel_modules; i++) {
     391       18611 :                 if (mel_module[i].atoms) {
     392        2452 :                         msg = addAtom(mel_module[i].atoms);
     393        2452 :                         if (msg)
     394           0 :                                 return msg;
     395             :                 }
     396             :         }
     397             : 
     398             :         /* Add the signatures, where we now have access to all atoms */
     399       18963 :         for (i = mel_modules_loaded; i < mel_modules; i++) {
     400       18611 :                 const char *name = putName(mel_module[i].name);
     401       18611 :                 if (name == NULL)
     402           0 :                         throw(LOADER, __func__, MAL_MALLOC_FAIL);
     403       18611 :                 if (!malLibraryEnabled(name))
     404           0 :                         continue;
     405       18611 :                 if (mel_module[i].funcs) {
     406       18611 :                         msg = addFunctions(mel_module[i].funcs);
     407       18611 :                         if (!msg && mel_module[i].code) /* some modules may also have some function definitions */
     408           0 :                                 msg = malIncludeString(c, name, (str) mel_module[i].code, listing, NULL);
     409       18611 :                         if (msg)
     410           0 :                                 return msg;
     411             : 
     412             :                         /* mapi should be last, and sql last before mapi */
     413       18611 :                         if (name == sqlRef) {
     414         352 :                                 *sql = i;
     415         352 :                                 continue;
     416             :                         }
     417       18259 :                         if (name == mapiRef) {
     418         352 :                                 *mapi = i;
     419         352 :                                 continue;
     420             :                         }
     421       17907 :                         if (!mel_module[i].inits) {
     422       15795 :                                 msg = initModule(c, name, NULL);
     423       15795 :                                 if (msg)
     424           0 :                                         return msg;
     425             :                         }
     426             :                 }
     427       17907 :                 if (mel_module[i].inits) {
     428             :                         /* mapi should be last, and sql last before mapi */
     429        2112 :                         if (name == sqlRef || name == mapiRef)
     430           0 :                                 continue;
     431        2112 :                         msg = mel_module[i].inits();
     432        2112 :                         if (msg)
     433           0 :                                 return msg;
     434             :                 }
     435             :         }
     436         352 :         mel_modules_loaded = mel_modules;
     437         352 :         return MAL_SUCCEED;
     438             : }
     439             : 
     440             : str
     441         352 : malIncludeModules(Client c, char *modules[], int listing, bool no_mapi_server,
     442             :                                   const char *initpasswd)
     443             : {
     444         352 :         str msg;
     445         352 :         int sql = -1, mapi = -1;
     446             : 
     447        3773 :         for (int i = 0; modules[i]; i++) {
     448             :                 /* load library */
     449        3421 :                 if (!malLibraryEnabled(modules[i]))
     450         998 :                         continue;
     451        2423 :                 if ((msg = loadLibrary(modules[i], listing)) != NULL)
     452           0 :                         return msg;
     453             :         }
     454             :         /* load the mal code for these modules and execute preludes */
     455         352 :         if ((msg = malPrelude(c, listing, &sql, &mapi)) != NULL)
     456             :                 return msg;
     457             :         /* mapi should be last, and sql last before mapi */
     458         352 :         if (sql >= 0) {
     459         352 :                 if (mel_module[sql].inits)
     460           0 :                         msg = mel_module[sql].inits();
     461             :                 else
     462         352 :                         msg = initModule(c, sqlRef, initpasswd);
     463         351 :                 if (msg)
     464             :                         return msg;
     465             :         }
     466         351 :         if (!no_mapi_server && mapi >= 0 && initpasswd == NULL) {
     467         339 :                 if (mel_module[mapi].inits)
     468         339 :                         msg = mel_module[mapi].inits();
     469             :                 else
     470           0 :                         msg = initModule(c, mapiRef, NULL);
     471         339 :                 if (msg)
     472             :                         return msg;
     473             :         }
     474             :         return MAL_SUCCEED;
     475             : }

Generated by: LCOV version 1.14