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.Kersten
10 * This optimizer prepares the code for workload-capture-replay processing
11 * by injection of the proper calls.
12 */
13#include "monetdb_config.h"
14#include "opt_wlc.h"
15
16str
17OPTwlcImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
18{ int i, j, limit, slimit, updates=0, query=1;
19 InstrPtr p, q, def = 0;
20 InstrPtr *old;
21 lng usec = GDKusec();
22 char buf[256];
23
24 (void) pci;
25 (void) cntxt;
26 (void) stk; /* to fool compilers */
27
28 if( ! WLCused() )
29 goto wrapup;
30
31 old= mb->stmt;
32 limit= mb->stop;
33 slimit = mb->ssize;
34
35 /* check if we are dealing with an update and move definition to front*/
36 for (i = 0; i < limit; i++) {
37 p = old[i];
38 if( getModuleId(p) == querylogRef && getFunctionId(p) == defineRef){
39 def = p;
40 for(j = i; j>1; j--)
41 old[j]= old[j-1];
42 old[j]= def;
43 }
44 if( getModuleId(p) == sqlcatalogRef)
45 query = 0;
46 if( getModuleId(p) == sqlRef &&
47 ( getFunctionId(p) == appendRef ||
48 getFunctionId(p) == updateRef ||
49 getFunctionId(p) == deleteRef ||
50 getFunctionId(p) == clear_tableRef ))
51 query = 0;
52 }
53 def = 0;
54
55 if(query) // nothing to log
56 return MAL_SUCCEED;
57
58 // We use a fake collection of objects to speed up the checking later.
59
60 // Now optimize the code
61 if (newMalBlkStmt(mb,mb->ssize + updates) < 0)
62 return createException(MAL, "wlcr.optimizer", SQLSTATE(HY001) MAL_MALLOC_FAIL);
63 for (i = 0; i < limit; i++) {
64 p = old[i];
65 pushInstruction(mb,p);
66 if( getModuleId(p) == querylogRef && getFunctionId(p) == defineRef){
67 if((q= copyInstruction(p)) == NULL) {
68 for(i=0; i<mb->stop; i++)
69 if( mb->stmt[i])
70 freeInstruction(mb->stmt[i]);
71 GDKfree(mb->stmt);
72 mb->stmt = old;
73 mb->stop = limit;
74 mb->ssize = slimit;
75 return createException(MAL, "wlcr.optimizer", SQLSTATE(HY001) MAL_MALLOC_FAIL);
76 }
77 setModuleId(q, wlcRef);
78 setFunctionId(q,queryRef);
79 getArg(q,0) = newTmpVariable(mb,TYPE_any);
80 pushInstruction(mb,q);
81 def = q;
82 def->argc -=2;
83 updates++;
84 } else
85 /* the catalog operations all need to be re-executed */
86 if( def && getModuleId(p) == sqlcatalogRef &&
87 strcmp( getVarConstant(mb,getArg(p,1)).val.sval, "tmp") != 0 ){
88 assert( def);// should always be there
89 setFunctionId(def,catalogRef);
90 updates++;
91 } else
92 if( def && getModuleId(p) == sqlRef && getFunctionId(p) == clear_tableRef &&
93 strcmp( getVarConstant(mb,getArg(p,1)).val.sval, "tmp") != 0 ){
94 setFunctionId(def,actionRef);
95 assert(def);
96 if((q= copyInstruction(p)) == NULL) {
97 for(i=0; i<mb->stop; i++)
98 if( mb->stmt[i])
99 freeInstruction(mb->stmt[i]);
100 GDKfree(mb->stmt);
101 mb->stmt = old;
102 mb->stop = limit;
103 mb->ssize = slimit;
104 return createException(MAL, "wlcr.optimizer", SQLSTATE(HY001) MAL_MALLOC_FAIL);
105 }
106 setModuleId(q, wlcRef);
107 for( j=0; j< p->retc; j++)
108 getArg(q,j) = newTmpVariable(mb,TYPE_any);
109 pushInstruction(mb,q);
110 updates++;
111 } else
112 if( def && getModuleId(p) == sqlRef &&
113 ( getFunctionId(p) == appendRef ||
114 getFunctionId(p) == updateRef ||
115 getFunctionId(p) == deleteRef ||
116 getFunctionId(p) == clear_tableRef ) &&
117 strcmp( getVarConstant(mb,getArg(p,2)).val.sval, "tmp") != 0 ){
118 assert( def);// should always be there, temporary tables are always ignored
119 setFunctionId(def,actionRef);
120 if((q= copyInstruction(p)) == NULL) {
121 for(i=0; i<mb->stop; i++)
122 if( mb->stmt[i])
123 freeInstruction(mb->stmt[i]);
124 GDKfree(mb->stmt);
125 mb->stmt = old;
126 mb->stop = limit;
127 mb->ssize = slimit;
128 return createException(MAL, "wlcr.optimizer", SQLSTATE(HY001) MAL_MALLOC_FAIL);
129 }
130 delArgument(q, q->retc);
131 setModuleId(q, wlcRef);
132 for( j=0; j< p->retc; j++)
133 getArg(q,j) = newTmpVariable(mb,TYPE_any);
134 pushInstruction(mb,q);
135 updates++;
136 }
137 }
138 for(; i<slimit; i++)
139 if( old[i])
140 freeInstruction(old[i]);
141 GDKfree(old);
142
143 /* Defense line against incorrect plans */
144 chkTypes(cntxt->usermodule, mb, FALSE);
145 chkFlow(mb);
146 //chkDeclarations(mb);
147 /* keep all actions taken as a post block comment */
148
149wrapup:
150 snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","wlc",updates,GDKusec() - usec);
151 newComment(mb,buf);
152 if( OPTdebug & OPTwlc){
153 fprintf(stderr, "#wlc optimizer exit\n");
154 fprintFunction(stderr, mb, 0, LIST_MAL_ALL);
155 }
156 return MAL_SUCCEED;
157}
158