LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_pipes.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 113 156 72.4 %
Date: 2021-10-13 02:24:04 Functions: 8 10 80.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * author M.L. Kersten
      11             :  * The default SQL optimizer pipeline can be set per server.  See the
      12             :  * optpipe setting in monetdb(1) when using merovingian.  During SQL
      13             :  * initialization, the optimizer pipeline is checked against the
      14             :  * dependency information maintained in the optimizer library to ensure
      15             :  * there are no conflicts and at least the pre-requisite optimizers are
      16             :  * used.  The setting of sql_optimizer can be either the list of
      17             :  * optimizers to run, or one or more variables containing the optimizer
      18             :  * pipeline to run.  The latter is provided for readability purposes
      19             :  * only.
      20             :  */
      21             : #include "monetdb_config.h"
      22             : #include "opt_pipes.h"
      23             : #include "opt_support.h"
      24             : #include "mal_client.h"
      25             : #include "mal_instruction.h"
      26             : #include "mal_function.h"
      27             : #include "mal_listing.h"
      28             : #include "mal_linker.h"
      29             : 
      30             : #define MAXOPTPIPES 64
      31             : 
      32             : static struct PIPELINES {
      33             :         char *name;
      34             :         char *def;
      35             :         char *status;
      36             :         MalBlkPtr mb;
      37             :         char builtin;
      38             : } pipes[MAXOPTPIPES] = {
      39             : /* The minimal pipeline necessary by the server to operate correctly
      40             :  *
      41             :  * NOTE:
      42             :  * If you change the minimal pipe, please also update the man page
      43             :  * (see tools/mserver/mserver5.1) accordingly!
      44             :  */
      45             :         {"minimal_pipe",
      46             :          "optimizer.inline();"
      47             :          "optimizer.remap();"
      48             :          "optimizer.bincopyfrom();"
      49             :          "optimizer.deadcode();"
      50             :          "optimizer.multiplex();"
      51             :          "optimizer.generator();"
      52             :          "optimizer.profiler();" 
      53             :          //"optimizer.candidates();" only for decoration in explain
      54             :          //"optimizer.mask();"
      55             :          "optimizer.garbageCollector();",
      56             :          "stable", NULL, 1},
      57             :         {"minimal_fast",
      58             :          "optimizer.minimalfast()",
      59             :          "stable", NULL, 1},
      60             : /* The default pipe line contains as of Feb2010
      61             :  * mitosis-mergetable-reorder, aimed at large tables and improved
      62             :  * access locality.
      63             :  *
      64             :  * NOTE:
      65             :  * If you change the default pipe, please also update the no_mitosis pipe
      66             :  * and sequential pipe (see below, as well as the man page (see
      67             :  * tools/mserver/mserver5.1) accordingly!
      68             :  */
      69             :         {"default_pipe",
      70             :          "optimizer.inline();"
      71             :          "optimizer.remap();"
      72             :          "optimizer.costModel();"
      73             :          "optimizer.coercions();"
      74             :          "optimizer.aliases();"
      75             :          "optimizer.evaluate();"
      76             :          "optimizer.emptybind();"
      77             :          "optimizer.deadcode();" /* Feb2021 update, I pushed deadcode optimizer earlier in the pipeline so it runs before mitosis, thus removing less instructions */
      78             :          "optimizer.pushselect();"
      79             :          "optimizer.aliases();"
      80             :          "optimizer.mitosis();"
      81             :          "optimizer.mergetable();"
      82             :          "optimizer.bincopyfrom();"
      83             :          "optimizer.aliases();"
      84             :          "optimizer.constants();"
      85             :          "optimizer.commonTerms();"
      86             :          "optimizer.projectionpath();"
      87             :          "optimizer.deadcode();"
      88             :          "optimizer.matpack();"
      89             :          "optimizer.reorder();"
      90             :          "optimizer.dataflow();"
      91             :          "optimizer.querylog();"
      92             :          "optimizer.multiplex();"
      93             :          "optimizer.generator();"
      94             :          "optimizer.profiler();"
      95             :          "optimizer.candidates();"
      96             :          //"optimizer.mask();"
      97             :          "optimizer.deadcode();"
      98             :          "optimizer.postfix();"
      99             : //       "optimizer.jit();" awaiting the new batcalc api
     100             :          "optimizer.wlc();"
     101             :          "optimizer.garbageCollector();",
     102             :          "stable", NULL, 1},
     103             :         {"default_fast",
     104             :          "optimizer.defaultfast()",
     105             :          "stable", NULL, 1},
     106             : /*
     107             :  * Optimistic concurreny control in general leads to more transaction failures
     108             :  * in an OLTP setting. The partial solution provided is to give out
     109             :  * advisory locks and delay updates until they are released or timeout.
     110             :  */
     111             :         {"oltp_pipe",
     112             :          "optimizer.inline();"
     113             :          "optimizer.remap();"
     114             :          "optimizer.costModel();"
     115             :          "optimizer.coercions();"
     116             :          "optimizer.evaluate();"
     117             :          "optimizer.emptybind();"
     118             :          "optimizer.deadcode();" /* Feb2021 update, I pushed deadcode optimizer earlier in the pipeline so it runs before mitosis, thus removing less instructions */
     119             :          "optimizer.pushselect();"
     120             :          "optimizer.aliases();"
     121             :          "optimizer.mitosis();"
     122             :          "optimizer.mergetable();"
     123             :          "optimizer.bincopyfrom();"
     124             :          "optimizer.aliases();"
     125             :          "optimizer.constants();"
     126             :          "optimizer.commonTerms();"
     127             :          "optimizer.projectionpath();"
     128             :          "optimizer.deadcode();"
     129             :          "optimizer.matpack();"
     130             :          "optimizer.reorder();"
     131             :          "optimizer.dataflow();"
     132             :          "optimizer.querylog();"
     133             :          "optimizer.multiplex();"
     134             :          "optimizer.generator();"
     135             :          "optimizer.profiler();"
     136             :          "optimizer.candidates();"
     137             :          //"optimizer.mask();"
     138             :          "optimizer.deadcode();"
     139             :          "optimizer.postfix();"
     140             : //       "optimizer.jit();" awaiting the new batcalc api
     141             :          "optimizer.oltp();"
     142             :          "optimizer.wlc();"
     143             :          "optimizer.garbageCollector();",
     144             :          "stable", NULL, 1},
     145             : /*
     146             :  * Volcano style execution produces a sequence of blocks from the source relation
     147             :  */
     148             :         {"volcano_pipe",
     149             :          "optimizer.inline();"
     150             :          "optimizer.remap();"
     151             :          "optimizer.costModel();"
     152             :          "optimizer.coercions();"
     153             :          "optimizer.aliases();"
     154             :          "optimizer.evaluate();"
     155             :          "optimizer.emptybind();"
     156             :          "optimizer.deadcode();" /* Feb2021 update, I pushed deadcode optimizer earlier in the pipeline so it runs before mitosis, thus removing less instructions */
     157             :          "optimizer.pushselect();"
     158             :          "optimizer.aliases();"
     159             :          "optimizer.mitosis();"
     160             :          "optimizer.mergetable();"
     161             :          "optimizer.bincopyfrom();"
     162             :          "optimizer.aliases();"
     163             :          "optimizer.constants();"
     164             :          "optimizer.commonTerms();"
     165             :          "optimizer.projectionpath();"
     166             :          "optimizer.deadcode();"
     167             :          "optimizer.matpack();"
     168             :          "optimizer.reorder();"
     169             :          "optimizer.dataflow();"
     170             :          "optimizer.querylog();"
     171             :          "optimizer.multiplex();"
     172             :          "optimizer.generator();"
     173             :          "optimizer.volcano();"
     174             :          "optimizer.profiler();"
     175             :          "optimizer.candidates();"
     176             :          //"optimizer.mask();"
     177             :          "optimizer.deadcode();"
     178             :          "optimizer.postfix();"
     179             : //       "optimizer.jit();" awaiting the new batcalc api
     180             :          "optimizer.wlc();"
     181             :          "optimizer.garbageCollector();",
     182             :          "stable", NULL, 1},
     183             : /* The no_mitosis pipe line is (and should be kept!) identical to the
     184             :  * default pipeline, except that optimizer mitosis is omitted.  It is
     185             :  * used mainly to make some tests work deterministically, and to check
     186             :  * / debug whether "unexpected" problems are related to mitosis
     187             :  * (and/or mergetable).
     188             :  *
     189             :  * NOTE:
     190             :  * If you change the no_mitosis pipe, please also update the man page
     191             :  * (see tools/mserver/mserver5.1) accordingly!
     192             :  */
     193             :         {"no_mitosis_pipe",
     194             :          "optimizer.inline();"
     195             :          "optimizer.remap();"
     196             :          "optimizer.costModel();"
     197             :          "optimizer.coercions();"
     198             :          "optimizer.aliases();"
     199             :          "optimizer.evaluate();"
     200             :          "optimizer.emptybind();"
     201             :          "optimizer.deadcode();" /* Feb2021 update, I pushed deadcode optimizer earlier in the pipeline so it runs before mitosis, thus removing less instructions */
     202             :          "optimizer.pushselect();"
     203             :          "optimizer.aliases();"
     204             :          "optimizer.mergetable();"
     205             :          "optimizer.bincopyfrom();"
     206             :          "optimizer.aliases();"
     207             :          "optimizer.constants();"
     208             :          "optimizer.commonTerms();"
     209             :          "optimizer.projectionpath();"
     210             :          "optimizer.deadcode();"
     211             :          "optimizer.matpack();"
     212             :          "optimizer.reorder();"
     213             :          "optimizer.dataflow();"
     214             :          "optimizer.querylog();"
     215             :          "optimizer.multiplex();"
     216             :          "optimizer.generator();"
     217             :          "optimizer.profiler();"
     218             :          "optimizer.candidates();"
     219             :          //"optimizer.mask();"
     220             :          "optimizer.deadcode();"
     221             :          "optimizer.postfix();"
     222             : //       "optimizer.jit();" awaiting the new batcalc api
     223             :          "optimizer.wlc();"
     224             :          "optimizer.garbageCollector();",
     225             :          "stable", NULL, 1},
     226             : /* The sequential pipe line is (and should be kept!) identical to the
     227             :  * default pipeline, except that optimizers mitosis & dataflow are
     228             :  * omitted.  It is use mainly to make some tests work
     229             :  * deterministically, i.e., avoid ambigious output, by avoiding
     230             :  * parallelism.
     231             :  *
     232             :  * NOTE:
     233             :  * If you change the sequential pipe, please also update the man page
     234             :  * (see tools/mserver/mserver5.1) accordingly!
     235             :  */
     236             :         {"sequential_pipe",
     237             :          "optimizer.inline();"
     238             :          "optimizer.remap();"
     239             :          "optimizer.costModel();"
     240             :          "optimizer.coercions();"
     241             :          "optimizer.aliases();"
     242             :          "optimizer.evaluate();"
     243             :          "optimizer.emptybind();"
     244             :          "optimizer.deadcode();" /* Feb2021 update, I pushed deadcode optimizer earlier in the pipeline so it runs before mitosis, thus removing less instructions */
     245             :          "optimizer.pushselect();"
     246             :          "optimizer.aliases();"
     247             :          "optimizer.mergetable();"
     248             :          "optimizer.bincopyfrom();"
     249             :          "optimizer.aliases();"
     250             :          "optimizer.constants();"
     251             :          "optimizer.commonTerms();"
     252             :          "optimizer.projectionpath();"
     253             :          "optimizer.deadcode();"
     254             :          "optimizer.matpack();"
     255             :          "optimizer.reorder();"
     256             :          "optimizer.querylog();"
     257             :          "optimizer.multiplex();"
     258             :          "optimizer.generator();"
     259             :          "optimizer.profiler();"
     260             :          "optimizer.candidates();"
     261             :          //"optimizer.mask();"
     262             :          "optimizer.deadcode();"
     263             :          "optimizer.postfix();"
     264             : //       "optimizer.jit();" awaiting the new batcalc api
     265             :          "optimizer.wlc();"
     266             :          "optimizer.garbageCollector();",
     267             :          "stable", NULL, 1},
     268             : /* Experimental pipelines stressing various components under
     269             :  * development.  Do not use any of these pipelines in production
     270             :  * settings!
     271             :  */
     272             : /* sentinel */
     273             :         {NULL, NULL, NULL, NULL, 0}
     274             : };
     275             : 
     276             : /*
     277             :  * Debugging the optimizer pipeline",
     278             :  * The best way is to use mdb and inspect the information gathered",
     279             :  * during the optimization phase.  Several optimizers produce more",
     280             :  * intermediate information, which may shed light on the details.  The",
     281             :  * opt_debug bitvector controls their output. It can be set to a",
     282             :  * pipeline or a comma separated list of optimizers you would like to",
     283             :  * trace. It is a server wide property and can not be set dynamically,",
     284             :  * as it is intended for internal use.",
     285             :  */
     286             : #include "optimizer_private.h"
     287             : 
     288             : static MT_Lock pipeLock = MT_LOCK_INITIALIZER(pipeLock);
     289             : 
     290             : /* the session_pipe is the one defined by the user */
     291             : str
     292          23 : addPipeDefinition(Client cntxt, const char *name, const char *pipe)
     293             : {
     294             :         int i;
     295             :         str msg;
     296             :         struct PIPELINES oldpipe;
     297             : 
     298          23 :         MT_lock_set(&pipeLock);
     299         207 :         for (i = 0; i < MAXOPTPIPES && pipes[i].name; i++)
     300         184 :                 if (strcmp(name, pipes[i].name) == 0)
     301             :                         break;
     302             : 
     303          23 :         if (i == MAXOPTPIPES) {
     304           0 :                 MT_lock_unset(&pipeLock);
     305           0 :                 throw(MAL, "optimizer.addPipeDefinition", SQLSTATE(HY013) "Out of slots");
     306             :         }
     307          23 :         if (pipes[i].name && pipes[i].builtin) {
     308           0 :                 MT_lock_unset(&pipeLock);
     309           0 :                 throw(MAL, "optimizer.addPipeDefinition", SQLSTATE(42000) "No overwrite of built in allowed");
     310             :         }
     311             : 
     312             :         /* save old value */
     313          23 :         oldpipe = pipes[i];
     314          23 :         pipes[i].name = GDKstrdup(name);
     315          23 :         pipes[i].def = GDKstrdup(pipe);
     316          23 :         pipes[i].status = GDKstrdup("experimental");
     317          23 :         if(pipes[i].name == NULL || pipes[i].def == NULL || pipes[i].status == NULL) {
     318           0 :                 GDKfree(pipes[i].name);
     319           0 :                 GDKfree(pipes[i].def);
     320           0 :                 GDKfree(pipes[i].status);
     321           0 :                 pipes[i].name = oldpipe.name;
     322           0 :                 pipes[i].def = oldpipe.def;
     323           0 :                 pipes[i].status = oldpipe.status;
     324           0 :                 MT_lock_unset(&pipeLock);
     325           0 :                 throw(MAL, "optimizer.addPipeDefinition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     326             :         }
     327          23 :         pipes[i].mb = NULL;
     328          23 :         MT_lock_unset(&pipeLock);
     329          23 :         msg = compileOptimizer(cntxt, name);
     330          23 :         if (msg) {
     331             :                 /* failed: restore old value */
     332          22 :                 MT_lock_set(&pipeLock);
     333          22 :                 GDKfree(pipes[i].name);
     334          22 :                 GDKfree(pipes[i].def);
     335          22 :                 GDKfree(pipes[i].status);
     336          22 :                 pipes[i] = oldpipe;
     337          22 :                 MT_lock_unset(&pipeLock);
     338             :         } else {
     339             :                 /* succeeded: destroy old value */
     340           1 :                 if (oldpipe.name)
     341           0 :                         GDKfree(oldpipe.name);
     342           1 :                 if (oldpipe.def)
     343           0 :                         GDKfree(oldpipe.def);
     344           1 :                 if (oldpipe.mb)
     345           0 :                         freeMalBlk(oldpipe.mb);
     346           1 :                 if (oldpipe.status)
     347           0 :                         GDKfree(oldpipe.status);
     348             :         }
     349             :         return msg;
     350             : }
     351             : 
     352             : int
     353         499 : isOptimizerPipe(const char *name)
     354             : {
     355             :         int i;
     356             : 
     357        2168 :         for (i = 0; i < MAXOPTPIPES && pipes[i].name; i++)
     358        2116 :                 if (strcmp(name, pipes[i].name) == 0)
     359             :                         return TRUE;
     360             :         return FALSE;
     361             : }
     362             : 
     363             : str
     364           0 : getPipeDefinition(str name)
     365             : {
     366             :         int i;
     367             : 
     368           0 :         for (i = 0; i < MAXOPTPIPES && pipes[i].name; i++)
     369           0 :                 if (strcmp(name, pipes[i].name) == 0)
     370           0 :                         return GDKstrdup(pipes[i].def);
     371             :         return NULL;
     372             : }
     373             : 
     374             : str
     375          96 : getPipeCatalog(bat *nme, bat *def, bat *stat)
     376             : {
     377             :         BAT *b, *bn, *bs;
     378             :         int i;
     379             : 
     380          96 :         b = COLnew(0, TYPE_str, 20, TRANSIENT);
     381          96 :         bn = COLnew(0, TYPE_str, 20, TRANSIENT);
     382          96 :         bs = COLnew(0, TYPE_str, 20, TRANSIENT);
     383          96 :         if (b == NULL || bn == NULL || bs == NULL) {
     384           0 :                 BBPreclaim(b);
     385           0 :                 BBPreclaim(bn);
     386           0 :                 BBPreclaim(bs);
     387           0 :                 throw(MAL, "optimizer.getpipeDefinition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     388             :         }
     389             : 
     390         864 :         for (i = 0; i < MAXOPTPIPES && pipes[i].name; i++) {
     391        1536 :                 if (BUNappend(b, pipes[i].name, false) != GDK_SUCCEED ||
     392        1536 :                         BUNappend(bn, pipes[i].def, false) != GDK_SUCCEED ||
     393         768 :                         BUNappend(bs, pipes[i].status, false) != GDK_SUCCEED) {
     394           0 :                         BBPreclaim(b);
     395           0 :                         BBPreclaim(bn);
     396           0 :                         BBPreclaim(bs);
     397           0 :                         throw(MAL, "optimizer.getpipeDefinition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     398             :                 }
     399             :         }
     400             : 
     401          96 :         BBPkeepref(*nme = b->batCacheid);
     402          96 :         BBPkeepref(*def = bn->batCacheid);
     403          96 :         BBPkeepref(*stat = bs->batCacheid);
     404          96 :         return MAL_SUCCEED;
     405             : }
     406             : 
     407             : static str
     408        2318 : validatePipe(MalBlkPtr mb)
     409             : {
     410             :         int mitosis = FALSE, deadcode = FALSE, mergetable = FALSE, multiplex = FALSE;
     411             :         int bincopyfrom = FALSE, garbage = FALSE, generator = FALSE, remap =  FALSE;
     412             :         int i;
     413             :         InstrPtr p;
     414             : 
     415        2318 :         if (mb == NULL )
     416           0 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "missing optimizer mal block\n");
     417        2318 :         p = getInstrPtr(mb,1);
     418             : 
     419        2318 :         if (getFunctionId(p) && (idcmp(getFunctionId(p), "defaultfast") == 0 || (idcmp(getFunctionId(p), "minimalfast") == 0)))
     420             :                 return MAL_SUCCEED;
     421             : 
     422        1744 :         if (getFunctionId(p) == NULL || idcmp(getFunctionId(p), "inline") != 0)
     423          14 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'inline' should be the first\n");
     424             : 
     425       46544 :         for (i = 1; i < mb->stop - 1; i++){
     426       44814 :                 p = getInstrPtr(mb, i);
     427       44814 :                 const char *fname = getFunctionId(p);
     428       44814 :                 if (fname != NULL) {
     429       44814 :                         if (strcmp(fname, "deadcode") == 0)
     430             :                                 deadcode = TRUE;
     431       40215 :                         else if (strcmp(fname, "remap") == 0)
     432             :                                 remap = TRUE;
     433       38492 :                         else if (strcmp(fname, "mitosis") == 0)
     434             :                                 mitosis = TRUE;
     435       37630 :                         else if (strcmp(fname, "bincopyfrom") == 0)
     436             :                                 bincopyfrom = TRUE;
     437       35907 :                         else if (strcmp(fname, "mergetable") == 0)
     438             :                                 mergetable = TRUE;
     439       34471 :                         else if (strcmp(fname, "multiplex") == 0)
     440             :                                 multiplex = TRUE;
     441       32742 :                         else if (strcmp(fname, "generator") == 0)
     442             :                                 generator = TRUE;
     443       31019 :                         else if (strcmp(fname, "garbageCollector") == 0)
     444             :                                 garbage = TRUE;
     445             :                 } else
     446           0 :                         throw(MAL, "optimizer.validate", SQLSTATE(42000) "Missing optimizer call\n");
     447             :         }
     448             : 
     449        1730 :         if (mitosis == TRUE && mergetable == FALSE)
     450           0 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'mitosis' needs 'mergetable'\n");
     451             : 
     452             :         /* several optimizer should be used */
     453        1730 :         if (multiplex == 0)
     454           1 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'multiplex' should be used\n");
     455        1729 :         if (deadcode == FALSE)
     456           1 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'deadcode' should be used at least once\n");
     457        1728 :         if (garbage == FALSE)
     458           2 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'garbageCollector' should be used as the last one\n");
     459        1726 :         if (remap == FALSE)
     460           3 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'remap' should be used\n");
     461        1723 :         if (generator == FALSE)
     462           0 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'generator' should be used\n");
     463        1723 :         if (bincopyfrom == FALSE)
     464           0 :                 throw(MAL, "optimizer.validate", SQLSTATE(42000) "'bincopyfrom' should be used\n");
     465             : 
     466             :         return MAL_SUCCEED;
     467             : }
     468             : 
     469             : static str
     470         287 : validateOptimizerPipes(void)
     471             : {
     472             :         int i;
     473             :         str msg = MAL_SUCCEED;
     474             : 
     475        2584 :         for (i = 0; i < MAXOPTPIPES && pipes[i].def; i++)
     476        2318 :                 if (pipes[i].mb) {
     477        2318 :                         msg = validatePipe(pipes[i].mb);
     478        2318 :                         if (msg != MAL_SUCCEED)
     479             :                                 break;
     480             :                 }
     481         287 :         return msg;
     482             : }
     483             : 
     484             : /*
     485             :  * Compile (the first time) an optimizer pipe string
     486             :  * then copy the statements to the end of the MAL plan
     487             : */
     488             : str
     489         288 : compileOptimizer(Client cntxt, const char *name)
     490             : {
     491             :         int i, j;
     492             :         char buf[2048];
     493             :         str msg = MAL_SUCCEED;
     494             :         Symbol fcn, compiled;
     495             : 
     496         288 :         MT_lock_set(&pipeLock);
     497        2593 :         for (i = 0; i < MAXOPTPIPES && pipes[i].name; i++)
     498        2327 :                 if (strcmp(pipes[i].name, name) == 0 && pipes[i].mb == 0) {
     499             :                         /* precompile a pipeline as MAL string */
     500        2614 :                         for (j = 0; j < MAXOPTPIPES && pipes[j].def; j++) {
     501        2327 :                                 if (pipes[j].mb == NULL) {
     502        2143 :                                         snprintf(buf,2048,"function optimizer.%s(); %s;end %s;", pipes[j].name,pipes[j].def,pipes[j].name);
     503        2143 :                                         msg = compileString(&fcn,cntxt, buf);
     504        2143 :                                         if( msg == MAL_SUCCEED){
     505        2142 :                                                 compiled = findSymbol(cntxt->usermodule,getName("optimizer"), getName(pipes[j].name));
     506        2142 :                                                 if( compiled)
     507        2142 :                                                         pipes[j].mb = compiled->def;
     508             :                                         } else break;
     509             :                                 }
     510             :                         }
     511         575 :                         if (msg != MAL_SUCCEED ||
     512         287 :                                 (msg = validateOptimizerPipes()) != MAL_SUCCEED)
     513             :                                 break;
     514             :                 }
     515         288 :         MT_lock_unset(&pipeLock);
     516         288 :         return msg;
     517             : }
     518             : 
     519             : str
     520           0 : compileAllOptimizers(Client cntxt)
     521             : {
     522             :         int i;
     523             :         str msg = MAL_SUCCEED;
     524             : 
     525           0 :         for(i=0;pipes[i].def && msg == MAL_SUCCEED; i++){
     526           0 :                 msg =compileOptimizer(cntxt,pipes[i].name);
     527             :         }
     528           0 :         return msg;
     529             : }
     530             : 
     531             : /*
     532             :  * Add a new components of the optimizer pipe to the plan
     533             :  */
     534             : str
     535      356844 : addOptimizerPipe(Client cntxt, MalBlkPtr mb, const char *name)
     536             : {
     537             :         int i, j, k;
     538             :         InstrPtr p,q;
     539             :         str msg = MAL_SUCCEED;
     540             : 
     541      356844 :         if (strcmp(name, "default_fast") == 0 && isSimpleSQL(mb)){
     542           0 :                 for (i = 0; i < MAXOPTPIPES && pipes[i].name; i++)
     543           0 :                         if (strcmp(pipes[i].name, "minimal_fast") == 0)
     544             :                                 break;
     545             :         } else {
     546     1072012 :                 for (i = 0; i < MAXOPTPIPES && pipes[i].name; i++)
     547     1072012 :                         if (strcmp(pipes[i].name, name) == 0)
     548             :                                 break;
     549             :         }
     550             : 
     551      356844 :         if (i == MAXOPTPIPES)
     552           0 :                 throw(MAL, "optimizer.addOptimizerPipe", SQLSTATE(HY013) "Out of slots");
     553             : 
     554      356844 :         if (pipes[i].mb == NULL){
     555         265 :                 if (strcmp(name, "default_fast") == 0  && isSimpleSQL(mb))
     556           0 :                         msg = compileOptimizer(cntxt, name);
     557             :                 else
     558         265 :                         msg = compileOptimizer(cntxt, "minimal_fast");
     559             :         }
     560             : 
     561      356844 :         if (pipes[i].mb && pipes[i].mb->stop) {
     562    10979206 :                 for (j = 1; j < pipes[i].mb->stop - 1; j++) {
     563    10622362 :                         q= getInstrPtr(pipes[i].mb,j);
     564    10622362 :                         if( getModuleId(q) != optimizerRef)
     565           0 :                                 continue;
     566    10622362 :                         p = copyInstruction(q);
     567    10622376 :                         if (!p)
     568           0 :                                 throw(MAL, "optimizer.addOptimizerPipe", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     569    21244739 :                         for (k = 0; k < p->argc; k++)
     570    10622376 :                                 getArg(p, k) = cloneVariable(mb, pipes[i].mb, getArg(p, k));
     571             :                         // typecheck to get its internal address typeChecker(cntxt->usermodule, mb, p, j, FALSE);
     572    10622363 :                         pushInstruction(mb, p);
     573             :                 }
     574             :         }
     575             :         return msg;
     576             : }
     577             : 
     578             : void
     579         264 : opt_pipes_reset(void)
     580             : {
     581             :         int i;
     582             : 
     583       17160 :         for (i = 0; i < MAXOPTPIPES; i++)
     584       16896 :                 pipes[i].mb = NULL;
     585         264 : }

Generated by: LCOV version 1.14