| 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 - 2019 MonetDB B.V. |
| 7 | */ |
| 8 | |
| 9 | /* author M.L. Kersten |
| 10 | * The optimizer wrapper code is the interface to the MAL optimizer calls. |
| 11 | * |
| 12 | * Before an optimizer is finished, it should leave a clean state behind. |
| 13 | * Moreover, some information of the optimization step is saved for |
| 14 | * debugging and analysis. |
| 15 | */ |
| 16 | |
| 17 | #include "monetdb_config.h" |
| 18 | #include "mal_listing.h" |
| 19 | |
| 20 | /* |
| 21 | * The optimizer used so far |
| 22 | */ |
| 23 | #include "opt_aliases.h" |
| 24 | #include "opt_coercion.h" |
| 25 | #include "opt_commonTerms.h" |
| 26 | #include "opt_candidates.h" |
| 27 | #include "opt_constants.h" |
| 28 | #include "opt_costModel.h" |
| 29 | #include "opt_dataflow.h" |
| 30 | #include "opt_deadcode.h" |
| 31 | #include "opt_emptybind.h" |
| 32 | #include "opt_evaluate.h" |
| 33 | #include "opt_garbageCollector.h" |
| 34 | #include "opt_generator.h" |
| 35 | #include "opt_inline.h" |
| 36 | #include "opt_jit.h" |
| 37 | #include "opt_projectionpath.h" |
| 38 | #include "opt_matpack.h" |
| 39 | #include "opt_json.h" |
| 40 | #include "opt_oltp.h" |
| 41 | #include "opt_postfix.h" |
| 42 | #include "opt_mergetable.h" |
| 43 | #include "opt_mitosis.h" |
| 44 | #include "opt_multiplex.h" |
| 45 | #include "opt_profiler.h" |
| 46 | #include "opt_pushselect.h" |
| 47 | #include "opt_querylog.h" |
| 48 | #include "opt_reduce.h" |
| 49 | #include "opt_remap.h" |
| 50 | #include "opt_remoteQueries.h" |
| 51 | #include "opt_reorder.h" |
| 52 | #include "opt_volcano.h" |
| 53 | #include "opt_wlc.h" |
| 54 | |
| 55 | struct{ |
| 56 | str nme; |
| 57 | str (*fcn)(); |
| 58 | int calls; |
| 59 | lng timing; |
| 60 | } codes[] = { |
| 61 | {"aliases" , &OPTaliasesImplementation,0,0}, |
| 62 | {"candidates" , &OPTcandidatesImplementation,0,0}, |
| 63 | {"coercions" , &OPTcoercionImplementation,0,0}, |
| 64 | {"commonTerms" , &OPTcommonTermsImplementation,0,0}, |
| 65 | {"constants" , &OPTconstantsImplementation,0,0}, |
| 66 | {"costModel" , &OPTcostModelImplementation,0,0}, |
| 67 | {"dataflow" , &OPTdataflowImplementation,0,0}, |
| 68 | {"deadcode" , &OPTdeadcodeImplementation,0,0}, |
| 69 | {"emptybind" , &OPTemptybindImplementation,0,0}, |
| 70 | {"evaluate" , &OPTevaluateImplementation,0,0}, |
| 71 | {"garbageCollector" , &OPTgarbageCollectorImplementation,0,0}, |
| 72 | {"generator" , &OPTgeneratorImplementation,0,0}, |
| 73 | {"inline" , &OPTinlineImplementation,0,0}, |
| 74 | {"jit" , &OPTjitImplementation,0,0}, |
| 75 | {"json" , &OPTjsonImplementation,0,0}, |
| 76 | {"matpack" , &OPTmatpackImplementation,0,0}, |
| 77 | {"mergetable" , &OPTmergetableImplementation,0,0}, |
| 78 | {"mitosis" , &OPTmitosisImplementation,0,0}, |
| 79 | {"multiplex" , &OPTmultiplexImplementation,0,0}, |
| 80 | {"oltp" , &OPToltpImplementation,0,0}, |
| 81 | {"postfix" , &OPTpostfixImplementation,0,0}, |
| 82 | {"profiler" , &OPTprofilerImplementation,0,0}, |
| 83 | {"projectionpath" , &OPTprojectionpathImplementation,0,0}, |
| 84 | {"pushselect" , &OPTpushselectImplementation,0,0}, |
| 85 | {"querylog" , &OPTquerylogImplementation,0,0}, |
| 86 | {"reduce" , &OPTreduceImplementation,0,0}, |
| 87 | {"remap" , &OPTremapImplementation,0,0}, |
| 88 | {"remoteQueries" , &OPTremoteQueriesImplementation,0,0}, |
| 89 | {"reorder" , &OPTreorderImplementation,0,0}, |
| 90 | {"volcano" , &OPTvolcanoImplementation,0,0}, |
| 91 | {"wlc" , &OPTwlcImplementation,0,0}, |
| 92 | {0,0,0,0} |
| 93 | }; |
| 94 | mal_export str OPTwrapper(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p); |
| 95 | |
| 96 | str OPTwrapper (Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){ |
| 97 | str modnme = "(NONE)" ; |
| 98 | str fcnnme = "(NONE)" ; |
| 99 | Symbol s= NULL; |
| 100 | int i; |
| 101 | char optimizer[256]; |
| 102 | str msg = MAL_SUCCEED; |
| 103 | lng clk; |
| 104 | |
| 105 | if (cntxt->mode == FINISHCLIENT) |
| 106 | throw(MAL, "optimizer" , SQLSTATE(42000) "prematurely stopped client" ); |
| 107 | |
| 108 | if( p == NULL) |
| 109 | throw(MAL, "opt_wrapper" , SQLSTATE(HY002) "missing optimizer statement" ); |
| 110 | |
| 111 | if( mb->errors) |
| 112 | throw(MAL, "opt_wrapper" , SQLSTATE(42000) "MAL block contains errors" ); |
| 113 | snprintf(optimizer,256,"%s" , fcnnme = getFunctionId(p)); |
| 114 | |
| 115 | if( p && p->argc > 1 ){ |
| 116 | if( getArgType(mb,p,1) != TYPE_str || |
| 117 | getArgType(mb,p,2) != TYPE_str || |
| 118 | !isVarConstant(mb,getArg(p,1)) || |
| 119 | !isVarConstant(mb,getArg(p,2)) |
| 120 | ) |
| 121 | throw(MAL, optimizer, SQLSTATE(42000) ILLARG_CONSTANTS); |
| 122 | |
| 123 | if( stk != 0){ |
| 124 | modnme= *getArgReference_str(stk,p,1); |
| 125 | fcnnme= *getArgReference_str(stk,p,2); |
| 126 | } else { |
| 127 | modnme= getArgDefault(mb,p,1); |
| 128 | fcnnme= getArgDefault(mb,p,2); |
| 129 | } |
| 130 | removeInstruction(mb, p); |
| 131 | s= findSymbol(cntxt->usermodule, putName(modnme),putName(fcnnme)); |
| 132 | |
| 133 | if( s == NULL) |
| 134 | throw(MAL, optimizer, SQLSTATE(HY002) RUNTIME_OBJECT_UNDEFINED ":%s.%s" , modnme, fcnnme); |
| 135 | mb = s->def; |
| 136 | stk= 0; |
| 137 | } else if( p ) |
| 138 | removeInstruction(mb, p); |
| 139 | |
| 140 | for (i=0; codes[i].nme; i++) |
| 141 | if (strcmp(codes[i].nme, optimizer) == 0){ |
| 142 | clk = GDKusec(); |
| 143 | msg = (str)(*(codes[i].fcn))(cntxt, mb, stk, 0); |
| 144 | codes[i].timing += GDKusec() - clk; |
| 145 | codes[i].calls++; |
| 146 | if (msg) |
| 147 | throw(MAL, optimizer, SQLSTATE(42000) "Error in optimizer %s" , optimizer); |
| 148 | break; |
| 149 | } |
| 150 | if (codes[i].nme == 0) |
| 151 | throw(MAL, optimizer, SQLSTATE(HY002) "Optimizer implementation '%s' missing" , fcnnme); |
| 152 | |
| 153 | if ( mb->errors) |
| 154 | throw(MAL, optimizer, SQLSTATE(42000) PROGRAM_GENERAL ":%s.%s %s" , modnme, fcnnme, mb->errors); |
| 155 | return MAL_SUCCEED; |
| 156 | } |
| 157 | |
| 158 | mal_export str OPTstatistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p); |
| 159 | |
| 160 | str |
| 161 | OPTstatistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) |
| 162 | { |
| 163 | bat *nme = (bat*) getArgReference_bat(stk, p, 0); |
| 164 | bat *cnt = (bat*) getArgReference_bat(stk, p, 1); |
| 165 | bat *time = (bat*) getArgReference_bat(stk, p, 2); |
| 166 | BAT *n, *c, *t; |
| 167 | int i; |
| 168 | |
| 169 | (void) cntxt; |
| 170 | (void) mb; |
| 171 | n = COLnew(0, TYPE_str, 256, TRANSIENT); |
| 172 | c = COLnew(0, TYPE_int, 256, TRANSIENT); |
| 173 | t = COLnew(0, TYPE_lng, 256, TRANSIENT); |
| 174 | if( n == NULL || c == NULL || t == NULL){ |
| 175 | BBPreclaim(n); |
| 176 | BBPreclaim(c); |
| 177 | BBPreclaim(t); |
| 178 | throw(MAL,"optimizer.statistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 179 | } |
| 180 | for( i= 0; codes[i].nme; i++){ |
| 181 | if (BUNappend(n, codes[i].nme, false) != GDK_SUCCEED || |
| 182 | BUNappend(c, &codes[i].calls, false) != GDK_SUCCEED || |
| 183 | BUNappend(t, &codes[i].timing, false) != GDK_SUCCEED) { |
| 184 | BBPreclaim(n); |
| 185 | BBPreclaim(c); |
| 186 | BBPreclaim(t); |
| 187 | throw(MAL,"optimizer.statistics" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 188 | } |
| 189 | } |
| 190 | BBPkeepref( *nme = n->batCacheid); |
| 191 | BBPkeepref( *cnt = c->batCacheid); |
| 192 | BBPkeepref( *time = t->batCacheid); |
| 193 | return MAL_SUCCEED; |
| 194 | } |
| 195 | |