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 : #include "monetdb_config.h"
14 : #include "opt_querylog.h"
15 : #include "gdk_time.h"
16 : #include "querylog.h"
17 :
18 : str
19 498072 : OPTquerylogImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk,
20 : InstrPtr pci)
21 : {
22 498072 : int i, limit, slimit, actions = 0;
23 498072 : InstrPtr p = 0, *old = mb->stmt, q, r;
24 498072 : int argc, io, user, nice, sys, idle, iowait, load, arg, start, finish, name;
25 498072 : int xtime = 0, rtime = 0, tuples = 0;
26 498072 : InstrPtr defineQuery = NULL;
27 498072 : str msg = MAL_SUCCEED;
28 :
29 :
30 : // query log needed?
31 498072 : if (!QLOGisset())
32 498045 : goto wrapup;
33 :
34 : (void) stk; /* to fool compilers */
35 : (void) cntxt;
36 : /* gather information */
37 207 : for (i = 1; i < mb->stop; i++) {
38 202 : p = getInstrPtr(mb, i);
39 202 : if (getModuleId(p) && idcmp(getModuleId(p), "querylog") == 0
40 5 : && idcmp(getFunctionId(p), "define") == 0) {
41 5 : defineQuery = p;
42 5 : getVarConstant(mb, getArg(p, 3)).val.lval = GDKusec() - getVarConstant(mb, getArg(p, 3)).val.lval;
43 : }
44 : }
45 5 : if (defineQuery == NULL)
46 : /* nothing to do */
47 0 : goto wrapup;
48 :
49 5 : actions++;
50 5 : limit = mb->stop;
51 5 : slimit = mb->ssize;
52 5 : if (newMalBlkStmt(mb, mb->ssize) < 0)
53 0 : throw(MAL, "optimizer.querylog", SQLSTATE(HY013) MAL_MALLOC_FAIL);
54 :
55 5 : pushInstruction(mb, old[0]);
56 : /* run the querylog.define operation */
57 5 : defineQuery = copyInstruction(defineQuery);
58 5 : if (defineQuery == NULL) {
59 0 : msg = createException(MAL, "optimizer.querylog",
60 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
61 0 : goto bailout;
62 : }
63 :
64 5 : defineQuery->argc--; // remove MAL instruction count
65 5 : setFunctionId(defineQuery, appendRef);
66 5 : getArg(defineQuery, 0) = newTmpVariable(mb, TYPE_any);
67 5 : defineQuery->token = ASSIGNsymbol;
68 5 : setModuleId(defineQuery, querylogRef);
69 :
70 : /* collect the initial statistics */
71 5 : q = newStmt(mb, "clients", "getUsername");
72 5 : if (q == NULL) {
73 0 : freeInstruction(defineQuery);
74 0 : msg = createException(MAL, "optimizer.querylog",
75 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
76 0 : goto bailout;
77 : }
78 5 : name = getArg(q, 0) = newVariable(mb, "name", 4, TYPE_str);
79 5 : pushInstruction(mb, q);
80 5 : defineQuery = pushArgument(mb, defineQuery, name);
81 5 : q = newStmt(mb, mtimeRef, "current_timestamp");
82 5 : if (q == NULL) {
83 0 : freeInstruction(defineQuery);
84 0 : msg = createException(MAL, "optimizer.querylog",
85 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
86 0 : goto bailout;
87 : }
88 5 : start = getArg(q, 0) = newVariable(mb, "start", 5, TYPE_timestamp);
89 5 : pushInstruction(mb, q);
90 5 : defineQuery = pushArgument(mb, defineQuery, start);
91 5 : pushInstruction(mb, defineQuery);
92 :
93 5 : q = newStmtArgs(mb, sqlRef, "argRecord", old[0]->argc);
94 5 : if (q == NULL) {
95 0 : msg = createException(MAL, "optimizer.querylog",
96 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
97 0 : goto bailout;
98 : }
99 5 : for (argc = 1; argc < old[0]->argc; argc++)
100 0 : q = pushArgument(mb, q, getArg(old[0], argc));
101 :
102 5 : arg = getArg(q, 0) = newVariable(mb, "args", 4, TYPE_str);
103 5 : pushInstruction(mb, q);
104 :
105 :
106 5 : q = newStmt(mb, alarmRef, "usec");
107 5 : if (q == NULL) {
108 0 : msg = createException(MAL, "optimizer.querylog",
109 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
110 0 : goto bailout;
111 : }
112 5 : pushInstruction(mb, q);
113 5 : xtime = getArg(q, 0) = newVariable(mb, "xtime", 5, TYPE_lng);
114 5 : user = newVariable(mb, "user", 4, TYPE_lng);
115 5 : nice = newVariable(mb, "nice", 4, TYPE_lng);
116 5 : sys = newVariable(mb, "sys", 3, TYPE_lng);
117 5 : idle = newVariable(mb, "idle", 4, TYPE_lng);
118 5 : iowait = newVariable(mb, "iowait", 6, TYPE_lng);
119 5 : q = newStmt(mb, profilerRef, "cpustats");
120 5 : if (q == NULL) {
121 0 : msg = createException(MAL, "optimizer.querylog",
122 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
123 0 : goto bailout;
124 : }
125 5 : q->retc = q->argc = 0;
126 5 : q = pushReturn(mb, q, user);
127 5 : q = pushReturn(mb, q, nice);
128 5 : q = pushReturn(mb, q, sys);
129 5 : q = pushReturn(mb, q, idle);
130 5 : q = pushReturn(mb, q, iowait);
131 5 : pushInstruction(mb, q);
132 5 : q = newAssignment(mb);
133 5 : if (q == NULL) {
134 0 : msg = createException(MAL, "optimizer.querylog",
135 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
136 0 : goto bailout;
137 : }
138 5 : tuples = getArg(q, 0) = newVariable(mb, "tuples", 6, TYPE_lng);
139 5 : (void) pushLng(mb, q, 1);
140 5 : pushInstruction(mb, q);
141 :
142 212 : for (i = 1; i < limit; i++) {
143 202 : p = old[i];
144 :
145 202 : if (getModuleId(p) == sqlRef
146 11 : && (idcmp(getFunctionId(p), "exportValue") == 0
147 11 : || idcmp(getFunctionId(p), "exportResult") == 0)) {
148 :
149 0 : q = newStmt(mb, alarmRef, "usec");
150 0 : if (q == NULL) {
151 0 : msg = createException(MAL, "optimizer.querylog",
152 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
153 0 : break;
154 : }
155 0 : pushInstruction(mb, q);
156 0 : r = newStmt(mb, calcRef, minusRef);
157 0 : if (r == NULL) {
158 0 : msg = createException(MAL, "optimizer.querylog",
159 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
160 0 : break;
161 : }
162 0 : r = pushArgument(mb, r, getArg(q, 0));
163 0 : r = pushArgument(mb, r, xtime);
164 0 : getArg(r, 0) = xtime;
165 0 : pushInstruction(mb, r);
166 :
167 0 : q = newStmt(mb, alarmRef, "usec");
168 0 : if (q == NULL) {
169 0 : msg = createException(MAL, "optimizer.querylog",
170 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
171 0 : break;
172 : }
173 0 : rtime = getArg(q, 0) = newVariable(mb, "rtime", 5, TYPE_lng);
174 0 : pushInstruction(mb, q);
175 0 : pushInstruction(mb, p);
176 0 : continue;
177 : }
178 202 : if (getModuleId(p) == sqlRef && getFunctionId(p) == resultSetRef
179 4 : && isaBatType(getVarType(mb, getArg(p, 3)))) {
180 3 : q = newStmt(mb, aggrRef, countRef);
181 3 : if (q == NULL) {
182 0 : msg = createException(MAL, "optimizer.querylog",
183 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
184 0 : break;
185 : }
186 3 : getArg(q, 0) = tuples;
187 3 : (void) pushArgument(mb, q, getArg(p, 3));
188 3 : pushInstruction(mb, q);
189 3 : pushInstruction(mb, p);
190 3 : continue;
191 : }
192 199 : if (p->token == ENDsymbol || p->barrier == RETURNsymbol) {
193 5 : if (rtime == 0) {
194 5 : q = newStmt(mb, alarmRef, "usec");
195 5 : if (q == NULL) {
196 0 : msg = createException(MAL, "optimizer.querylog",
197 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
198 0 : break;
199 : }
200 5 : pushInstruction(mb, q);
201 5 : r = newStmt(mb, calcRef, minusRef);
202 5 : if (r == NULL) {
203 0 : msg = createException(MAL, "optimizer.querylog",
204 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
205 0 : break;
206 : }
207 5 : r = pushArgument(mb, r, getArg(q, 0));
208 5 : r = pushArgument(mb, r, xtime);
209 5 : getArg(r, 0) = xtime;
210 5 : pushInstruction(mb, r);
211 5 : q = newStmt(mb, alarmRef, "usec");
212 5 : if (q == NULL) {
213 0 : msg = createException(MAL, "optimizer.querylog",
214 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
215 0 : break;
216 : }
217 5 : rtime = getArg(q, 0) = newVariable(mb, "rtime", 5, TYPE_lng);
218 5 : pushInstruction(mb, q);
219 : }
220 5 : q = newStmt(mb, alarmRef, "usec");
221 5 : if (q == NULL) {
222 0 : msg = createException(MAL, "optimizer.querylog",
223 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
224 0 : break;
225 : }
226 5 : pushInstruction(mb, q);
227 5 : r = newStmt(mb, calcRef, minusRef);
228 5 : if (r == NULL) {
229 0 : msg = createException(MAL, "optimizer.querylog",
230 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
231 0 : break;
232 : }
233 5 : r = pushArgument(mb, r, getArg(q, 0));
234 5 : r = pushArgument(mb, r, rtime);
235 5 : getArg(r, 0) = rtime;
236 5 : pushInstruction(mb, r);
237 : /*
238 : * Post execution statistics gathering
239 : */
240 5 : q = newStmt(mb, mtimeRef, "current_timestamp");
241 5 : if (q == NULL) {
242 0 : msg = createException(MAL, "optimizer.querylog",
243 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
244 0 : break;
245 : }
246 5 : finish = getArg(q, 0) = newVariable(mb, "finish", 6, TYPE_any);
247 5 : pushInstruction(mb, q);
248 :
249 5 : q = newStmt(mb, profilerRef, "cpuload");
250 5 : if (q == NULL) {
251 0 : msg = createException(MAL, "optimizer.querylog",
252 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
253 0 : break;
254 : }
255 5 : load = newVariable(mb, "load", 4, TYPE_int);
256 5 : getArg(q, 0) = load;
257 5 : io = newVariable(mb, "io", 2, TYPE_int);
258 5 : q = pushReturn(mb, q, io);
259 5 : q = pushArgument(mb, q, user);
260 5 : q = pushArgument(mb, q, nice);
261 5 : q = pushArgument(mb, q, sys);
262 5 : q = pushArgument(mb, q, idle);
263 5 : q = pushArgument(mb, q, iowait);
264 5 : pushInstruction(mb, q);
265 :
266 5 : q = newStmtArgs(mb, querylogRef, "call", 9);
267 5 : if (q == NULL) {
268 0 : msg = createException(MAL, "optimizer.querylog",
269 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
270 0 : break;
271 : }
272 5 : q = pushArgument(mb, q, start);
273 5 : q = pushArgument(mb, q, finish);
274 5 : q = pushArgument(mb, q, arg);
275 5 : q = pushArgument(mb, q, tuples);
276 5 : q = pushArgument(mb, q, xtime);
277 5 : q = pushArgument(mb, q, rtime);
278 5 : q = pushArgument(mb, q, load);
279 5 : q = pushArgument(mb, q, io);
280 5 : pushInstruction(mb, q);
281 5 : pushInstruction(mb, p);
282 5 : continue;
283 : }
284 194 : pushInstruction(mb, p);
285 : }
286 :
287 5 : bailout:
288 1078 : for (; i < slimit; i++)
289 1073 : if (old[i])
290 0 : pushInstruction(mb, old[i]);
291 5 : GDKfree(old);
292 5 : if (msg == MAL_SUCCEED) {
293 : /* Defense line against incorrect plans */
294 5 : msg = chkTypes(cntxt->usermodule, mb, FALSE);
295 5 : if (!msg)
296 5 : msg = chkFlow(mb);
297 5 : if (!msg)
298 5 : msg = chkDeclarations(mb);
299 : }
300 : /* keep actions taken as a fake argument */
301 0 : wrapup:
302 498050 : (void) pushInt(mb, pci, actions);
303 498050 : return msg;
304 : }
|