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 M.L. Kersten
14 : * The optimizer wrapper code is the interface to the MAL optimizer calls.
15 : *
16 : * Before an optimizer is finished, it should leave a clean state behind.
17 : * Moreover, some information of the optimization step is saved for
18 : * debugging and analysis.
19 : */
20 :
21 : #include "monetdb_config.h"
22 : #include "mal_listing.h"
23 :
24 : /*
25 : * The optimizer used so far
26 : */
27 : #include "opt_aliases.h"
28 : #include "opt_coercion.h"
29 : #include "opt_commonTerms.h"
30 : #include "opt_candidates.h"
31 : #include "opt_constants.h"
32 : #include "opt_costModel.h"
33 : #include "opt_dataflow.h"
34 : #include "opt_deadcode.h"
35 : #include "opt_emptybind.h"
36 : #include "opt_evaluate.h"
37 : #include "opt_garbageCollector.h"
38 : #include "opt_generator.h"
39 : #include "opt_inline.h"
40 : #include "opt_projectionpath.h"
41 : #include "opt_matpack.h"
42 : #include "opt_postfix.h"
43 : #include "opt_for.h"
44 : #include "opt_dict.h"
45 : #include "opt_mergetable.h"
46 : #include "opt_mitosis.h"
47 : #include "opt_multiplex.h"
48 : #include "opt_profiler.h"
49 : #include "opt_pushselect.h"
50 : #include "opt_querylog.h"
51 : #include "opt_reduce.h"
52 : #include "opt_remap.h"
53 : #include "opt_remoteQueries.h"
54 : #include "opt_reorder.h"
55 : #include "opt_fastpath.h"
56 : #include "optimizer_private.h"
57 :
58 : // keep the optimizer list sorted
59 : static struct {
60 : str nme;
61 : str (*fcn)(Client, MalBlkPtr, MalStkPtr, InstrPtr);
62 : int calls;
63 : lng timing;
64 : } codes[] = {
65 : {"aliases", &OPTaliasesImplementation, 0, 0},
66 : {"candidates", &OPTcandidatesImplementation, 0, 0},
67 : {"coercions", &OPTcoercionImplementation, 0, 0},
68 : {"commonTerms", &OPTcommonTermsImplementation, 0, 0},
69 : {"constants", &OPTconstantsImplementation, 0, 0},
70 : {"costModel", &OPTcostModelImplementation, 0, 0},
71 : {"dataflow", &OPTdataflowImplementation, 0, 0},
72 : {"deadcode", &OPTdeadcodeImplementation, 0, 0},
73 : {"defaultfast", &OPTdefaultfastImplementation, 0, 0},
74 : {"dict", &OPTdictImplementation, 0, 0},
75 : {"emptybind", &OPTemptybindImplementation, 0, 0},
76 : {"evaluate", &OPTevaluateImplementation, 0, 0},
77 : {"for", &OPTforImplementation, 0, 0},
78 : {"garbageCollector", &OPTgarbageCollectorImplementation, 0, 0},
79 : {"generator", &OPTgeneratorImplementation, 0, 0},
80 : {"inline", &OPTinlineImplementation, 0, 0},
81 : {"matpack", &OPTmatpackImplementation, 0, 0},
82 : {"mergetable", &OPTmergetableImplementation, 0, 0},
83 : {"minimalfast", &OPTminimalfastImplementation, 0, 0},
84 : {"mitosis", &OPTmitosisImplementation, 0, 0},
85 : {"multiplex", &OPTmultiplexImplementation, 0, 0},
86 : {"postfix", &OPTpostfixImplementation, 0, 0},
87 : {"profiler", &OPTprofilerImplementation, 0, 0},
88 : {"projectionpath", &OPTprojectionpathImplementation, 0, 0},
89 : {"pushselect", &OPTpushselectImplementation, 0, 0},
90 : {"querylog", &OPTquerylogImplementation, 0, 0},
91 : {"reduce", &OPTreduceImplementation, 0, 0},
92 : {"remap", &OPTremapImplementation, 0, 0},
93 : {"remoteQueries", &OPTremoteQueriesImplementation, 0, 0},
94 : {"reorder", &OPTreorderImplementation, 0, 0},
95 : {0, 0, 0, 0}
96 : };
97 :
98 : static MT_Lock codeslock = MT_LOCK_INITIALIZER(codeslock);
99 :
100 : str
101 13079695 : OPTwrapper(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
102 : {
103 13079695 : str modnme = "optimizer";
104 13079695 : const char *fcnnme;
105 13079695 : Symbol s = NULL;
106 13079695 : int i;
107 13079695 : str msg = MAL_SUCCEED;
108 13079695 : lng clk;
109 :
110 : // no optimizer starts with a null byte, initialization sets a zero
111 13079695 : if (cntxt->mode == FINISHCLIENT)
112 0 : throw(MAL, "optimizer", SQLSTATE(42000) "prematurely stopped client");
113 :
114 13079695 : if (p == NULL)
115 0 : throw(MAL, "opt_wrapper",
116 : SQLSTATE(HY002) "missing optimizer statement");
117 :
118 13079695 : if (mb->errors) {
119 0 : msg = mb->errors;
120 0 : mb->errors = NULL;
121 0 : return msg;
122 : }
123 13079695 : fcnnme = getFunctionId(p);
124 :
125 13079695 : if (p && p->argc > 1) {
126 87 : if (getArgType(mb, p, 1) != TYPE_str
127 87 : || getArgType(mb, p, 2) != TYPE_str
128 87 : || !isVarConstant(mb, getArg(p, 1))
129 87 : || !isVarConstant(mb, getArg(p, 2)))
130 0 : throw(MAL, getFunctionId(p), SQLSTATE(42000) ILLARG_CONSTANTS);
131 :
132 87 : if (stk != NULL) {
133 0 : modnme = *getArgReference_str(stk, p, 1);
134 0 : fcnnme = *getArgReference_str(stk, p, 2);
135 : } else {
136 87 : modnme = getArgDefault(mb, p, 1);
137 87 : fcnnme = getArgDefault(mb, p, 2);
138 : }
139 : //removeInstruction(mb, p);
140 87 : p->token = REMsymbol;
141 87 : s = findSymbol(cntxt->usermodule, putName(modnme), putName(fcnnme));
142 :
143 87 : if (s == NULL)
144 0 : throw(MAL, getFunctionId(p),
145 : SQLSTATE(HY002) RUNTIME_OBJECT_UNDEFINED "%s.%s", modnme,
146 : fcnnme);
147 87 : mb = s->def;
148 87 : stk = NULL;
149 13079608 : } else if (p) {
150 13079608 : p->token = REMsymbol;
151 : }
152 :
153 13079695 : clk = GDKusec();
154 13079685 : const char *id = getFunctionId(p);
155 173467705 : for (i = 0; codes[i].nme != NULL; i++) {
156 173468326 : if (strcmp(codes[i].nme, id) == 0) {
157 13080306 : msg = (*codes[i].fcn) (cntxt, mb, stk, p);
158 13079872 : clk = GDKusec() - clk;
159 13079843 : MT_lock_set(&codeslock);
160 13080533 : codes[i].timing += clk;
161 13080533 : codes[i].calls++;
162 13080533 : MT_lock_unset(&codeslock);
163 13080529 : p = pushLng(mb, p, clk);
164 13079632 : if (msg || mb->errors) {
165 : /* we can only return one or the other */
166 : if (msg)
167 0 : freeException(mb->errors);
168 : else
169 : msg = mb->errors;
170 0 : mb->errors = NULL;
171 0 : str newmsg = createException(MAL, getFunctionId(p),
172 : SQLSTATE(42000)
173 : "Error in optimizer %s: %s",
174 : getFunctionId(p), msg);
175 0 : freeException(msg);
176 0 : return newmsg;
177 : }
178 : break;
179 : }
180 : }
181 13079011 : if (codes[i].nme == 0)
182 0 : throw(MAL, fcnnme,
183 : SQLSTATE(HY002) "Optimizer implementation '%s' missing", fcnnme);
184 :
185 : return MAL_SUCCEED;
186 : }
187 :
188 : str
189 0 : OPTstatistics(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
190 : {
191 0 : bat *nme = getArgReference_bat(stk, p, 0);
192 0 : bat *cnt = getArgReference_bat(stk, p, 1);
193 0 : bat *time = getArgReference_bat(stk, p, 2);
194 0 : BAT *n, *c, *t;
195 0 : int i;
196 :
197 0 : (void) cntxt;
198 0 : (void) mb;
199 0 : n = COLnew(0, TYPE_str, 256, TRANSIENT);
200 0 : c = COLnew(0, TYPE_int, 256, TRANSIENT);
201 0 : t = COLnew(0, TYPE_lng, 256, TRANSIENT);
202 0 : if (n == NULL || c == NULL || t == NULL) {
203 0 : BBPreclaim(n);
204 0 : BBPreclaim(c);
205 0 : BBPreclaim(t);
206 0 : throw(MAL, "optimizer.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
207 : }
208 0 : MT_lock_set(&codeslock);
209 0 : for (i = 0; codes[i].nme; i++) {
210 0 : if (BUNappend(n, codes[i].nme, false) != GDK_SUCCEED
211 0 : || BUNappend(c, &codes[i].calls, false) != GDK_SUCCEED
212 0 : || BUNappend(t, &codes[i].timing, false) != GDK_SUCCEED) {
213 0 : MT_lock_unset(&codeslock);
214 0 : BBPreclaim(n);
215 0 : BBPreclaim(c);
216 0 : BBPreclaim(t);
217 0 : throw(MAL, "optimizer.statistics", SQLSTATE(HY013) MAL_MALLOC_FAIL);
218 : }
219 : }
220 0 : MT_lock_unset(&codeslock);
221 0 : *nme = n->batCacheid;
222 0 : BBPkeepref(n);
223 0 : *cnt = c->batCacheid;
224 0 : BBPkeepref(c);
225 0 : *time = t->batCacheid;
226 0 : BBPkeepref(t);
227 0 : return MAL_SUCCEED;
228 : }
|