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#include "monetdb_config.h"
10#include "opt_querylog.h"
11#include "mtime.h"
12#include "querylog.h"
13
14str
15OPTquerylogImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
16{
17 int i, limit, slimit;
18 InstrPtr p = 0, *old= mb->stmt, q,r;
19 int argc, io, user,nice,sys,idle,iowait,load, arg, start,finish, name;
20 int xtime=0, rtime = 0, tuples=0;
21 InstrPtr defineQuery = NULL;
22 char buf[256];
23 lng usec = GDKusec();
24 str msg = MAL_SUCCEED;
25
26
27 // query log needed?
28 if ( !QLOGisset() )
29 return MAL_SUCCEED;
30
31 (void) pci;
32 (void) stk; /* to fool compilers */
33 (void) cntxt;
34 /* gather information */
35 for (i = 1; i < mb->stop; i++) {
36 p = getInstrPtr(mb,i);
37 if ( getModuleId(p) && idcmp(getModuleId(p), "querylog") == 0 && idcmp(getFunctionId(p),"define")==0){
38 defineQuery= p;
39 getVarConstant(mb,getArg(p,3)).val.lval = GDKusec()-getVarConstant(mb,getArg(p,3)).val.lval ;
40 }
41 }
42 if ( defineQuery == NULL)
43 /* nothing to do */
44 return MAL_SUCCEED;
45
46 limit= mb->stop;
47 slimit= mb->ssize;
48 if ( newMalBlkStmt(mb, mb->ssize) < 0)
49 throw(MAL,"optimizer.querylog", SQLSTATE(HY001) MAL_MALLOC_FAIL);
50
51 pushInstruction(mb, old[0]);
52 /* run the querylog.define operation */
53 defineQuery = copyInstruction(defineQuery);
54 if( defineQuery == NULL)
55 throw(MAL,"optimizer.querylog", SQLSTATE(HY001) MAL_MALLOC_FAIL);
56
57 defineQuery->argc--; // remove MAL instruction count
58 setFunctionId(defineQuery, appendRef);
59 getArg(defineQuery,0) = newTmpVariable(mb,TYPE_any);
60 defineQuery->token = ASSIGNsymbol;
61 setModuleId(defineQuery,querylogRef);
62
63 /* collect the initial statistics */
64 q = newStmt(mb, "clients", "getUsername");
65 name= getArg(q,0)= newVariable(mb,"name",4,TYPE_str);
66 defineQuery = pushArgument(mb,defineQuery,name);
67 q = newStmt(mb, "mtime", "current_timestamp");
68 start= getArg(q,0)= newVariable(mb,"start",5,TYPE_timestamp);
69 defineQuery = pushArgument(mb,defineQuery,start);
70 pushInstruction(mb, defineQuery);
71
72 q = newStmt(mb, sqlRef, "argRecord");
73 for ( argc=1; argc < old[0]->argc; argc++)
74 q = pushArgument(mb, q, getArg(old[0],argc));
75
76 arg= getArg(q,0)= newVariable(mb,"args",4,TYPE_str);
77
78
79 q = newStmt(mb, "alarm", "usec");
80 xtime = getArg(q,0)= newVariable(mb,"xtime",5,TYPE_lng);
81 user = newVariable(mb,"user",4,TYPE_lng);
82 nice = newVariable(mb,"nice",4,TYPE_lng);
83 sys = newVariable(mb,"sys",3,TYPE_lng);
84 idle = newVariable(mb,"idle",4,TYPE_lng);
85 iowait = newVariable(mb,"iowait",6,TYPE_lng);
86 q = newStmt(mb, "profiler", "cpustats");
87 q->retc= q->argc =0;
88 q = pushReturn(mb,q,user);
89 q = pushReturn(mb,q,nice);
90 q = pushReturn(mb,q,sys);
91 q = pushReturn(mb,q,idle);
92 q = pushReturn(mb,q,iowait);
93 q = newAssignment(mb);
94 tuples= getArg(q,0) = newVariable(mb,"tuples",6,TYPE_lng);
95 (void) pushLng(mb,q,1);
96
97 for (i = 1; i < limit; i++) {
98 p = old[i];
99
100 if (getModuleId(p)==sqlRef &&
101 (idcmp(getFunctionId(p),"exportValue")==0 ||
102 idcmp(getFunctionId(p),"exportResult")==0 ) ) {
103
104 q = newStmt(mb, "alarm", "usec");
105 r = newStmt(mb, calcRef, "-");
106 r = pushArgument(mb, r, getArg(q,0));
107 r = pushArgument(mb, r, xtime);
108 getArg(r,0)=xtime;
109
110 q = newStmt(mb, "alarm", "usec");
111 rtime= getArg(q,0)= newVariable(mb,"rtime",5,TYPE_lng);
112 pushInstruction(mb,p);
113 continue;
114 }
115 if ( getModuleId(p) == sqlRef && idcmp(getFunctionId(p),"resultSet")==0 && isaBatType(getVarType(mb,getArg(p,3)))){
116 q = newStmt(mb, "aggr", "count");
117 getArg(q,0) = tuples;
118 (void) pushArgument(mb,q, getArg(p,3));
119 pushInstruction(mb,p);
120 continue;
121 }
122 if ( p->token== ENDsymbol || p->barrier == RETURNsymbol || p->barrier == YIELDsymbol){
123 if ( rtime == 0){
124 q = newStmt(mb, "alarm", "usec");
125 r = newStmt(mb, calcRef, "-");
126 r = pushArgument(mb, r, getArg(q,0));
127 r = pushArgument(mb, r, xtime);
128 getArg(r,0)=xtime;
129 q = newStmt(mb, "alarm", "usec");
130 rtime= getArg(q,0)= newVariable(mb,"rtime",5,TYPE_lng);
131 }
132 q = newStmt(mb, "alarm", "usec");
133 r = newStmt(mb, calcRef, "-");
134 r = pushArgument(mb, r, getArg(q,0));
135 r = pushArgument(mb, r, rtime);
136 getArg(r,0)=rtime;
137 /*
138 * Post execution statistics gathering
139 */
140 q = newStmt(mb, "mtime", "current_timestamp");
141 finish= getArg(q,0)= newVariable(mb,"finish",6,TYPE_any);
142
143 q = newStmt(mb, "profiler", "cpuload");
144 load = newVariable(mb,"load",4,TYPE_int);
145 getArg(q,0)= load;
146 io = newVariable(mb,"io",2,TYPE_int);
147 q= pushReturn(mb,q,io);
148 q = pushArgument(mb,q,user);
149 q = pushArgument(mb,q,nice);
150 q = pushArgument(mb,q,sys);
151 q = pushArgument(mb,q,idle);
152 q = pushArgument(mb,q,iowait);
153
154 q = newStmt(mb, querylogRef, "call");
155 q = pushArgument(mb, q, start);
156 q = pushArgument(mb, q, finish);
157 q = pushArgument(mb, q, arg);
158 q = pushArgument(mb, q, tuples);
159 q = pushArgument(mb, q, xtime);
160 q = pushArgument(mb, q, rtime);
161 q = pushArgument(mb, q, load);
162 q = pushArgument(mb, q, io);
163 pushInstruction(mb,p);
164 continue;
165 }
166
167 pushInstruction(mb,p);
168 if (p->barrier == YIELDsymbol){
169 /* the factory yield may return */
170 q = newStmt(mb, "mtime", "current_timestamp");
171 start= getArg(q,0)= newVariable(mb,"start",5,TYPE_any);
172 q = newStmt(mb, sqlRef, "argRecord");
173 for ( argc=1; argc < old[0]->argc; argc++)
174 q = pushArgument(mb, q, getArg(old[0],argc));
175 arg= getArg(q,0)= newVariable(mb,"args",4,TYPE_str);
176 q = newAssignment(mb);
177 q = pushLng(mb,q,0);
178 q = newAssignment(mb);
179 q = pushLng(mb,q,0);
180 tuples= getArg(q,0)= newVariable(mb,"tuples",6,TYPE_lng);
181 newFcnCall(mb,"profiler","setMemoryFlag");
182 q->argc--;
183 pushLng(mb,q,1);
184 q = newStmt(mb, "alarm", "usec");
185 xtime = getArg(q,0)= newVariable(mb,"xtime",5,TYPE_lng);
186 }
187 }
188
189 for( ; i<slimit; i++)
190 if(old[i])
191 freeInstruction(old[i]);
192 GDKfree(old);
193 /* Defense line against incorrect plans */
194 if( 1){
195 chkTypes(cntxt->usermodule, mb, FALSE);
196 chkFlow(mb);
197 chkDeclarations(mb);
198 }
199 /* keep all actions taken as a post block comment */
200 usec = GDKusec()- usec;
201 snprintf(buf,256,"%-20s actions= 1 time=" LLFMT " usec","querylog", usec);
202 newComment(mb,buf);
203 addtoMalBlkHistory(mb);
204 if( OPTdebug & OPTquerylog){
205 fprintf(stderr, "#QUERYLOG optimizer exit\n");
206 fprintFunction(stderr, mb, 0, LIST_MAL_ALL);
207 }
208 return msg;
209}
210