1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // CegoProcBlock.cc
4 // ----------------
5 // Cego proc block class implementation
6 //
7 // Design and Implementation by Bjoern Lemke
8 //
9 // (C)opyright 2000-2019 Bjoern Lemke
10 //
11 // IMPLEMENTATION MODULE
12 //
13 // Class: CegoProcBlock
14 //
15 // Description: Stored procedure block container class
16 //
17 // Status: CLEAN
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20
21 // CEGO INCLUDES
22 #include "CegoProcBlock.h"
23 #include "CegoSelect.h"
24 #include "CegoProcException.h"
25
26 #include "CegoDatabaseFormater.h"
27
CegoProcBlock(CegoProcBlock * pParentBlock)28 CegoProcBlock::CegoProcBlock(CegoProcBlock *pParentBlock)
29 {
30 _pParentBlock = pParentBlock;
31 _pTriggerValueList = 0;
32 }
33
~CegoProcBlock()34 CegoProcBlock::~CegoProcBlock()
35 {
36 CegoProcStmt **pStmt = _stmtList.First();
37 while (pStmt)
38 {
39 delete (*pStmt);
40 pStmt = _stmtList.Next();
41 }
42 CegoProcCursor **pCur = _cursorList.First();
43 while ( pCur )
44 {
45 delete (*pCur);
46 pCur = _cursorList.Next();
47 }
48 CegoProcException **pExcep = _exceptionList.First();
49 while ( pExcep )
50 {
51 delete *pExcep;
52 pExcep = _exceptionList.Next();
53 }
54 }
55
setVarList(const ListT<CegoProcVar> & varList)56 void CegoProcBlock::setVarList(const ListT<CegoProcVar>& varList)
57 {
58 _varList = varList;
59 }
60
getVarList()61 ListT<CegoProcVar>& CegoProcBlock::getVarList()
62 {
63 return _varList;
64 }
65
addCursor(const Chain & cursorName,CegoSelect * pSelect)66 void CegoProcBlock::addCursor(const Chain& cursorName, CegoSelect *pSelect)
67 {
68 CegoProcCursor **pCur = _cursorList.First();
69 while ( pCur )
70 {
71 if ( (*pCur)->getName() == cursorName )
72 {
73 Chain msg = Chain("Cursor ") + cursorName + Chain(" already defined");
74 throw Exception(EXLOC, msg);
75 }
76 pCur = _cursorList.Next();
77 }
78
79 _cursorList.Insert(new CegoProcCursor(cursorName, pSelect));
80 return;
81 }
82
getCursor(const Chain & cursorName)83 CegoProcCursor* CegoProcBlock::getCursor(const Chain &cursorName)
84 {
85 CegoProcCursor **pCur = _cursorList.First();
86 while ( pCur )
87 {
88 if ( (*pCur)->getName() == cursorName )
89 {
90 return *pCur;
91 }
92 pCur = _cursorList.Next();
93 }
94
95 if ( _pParentBlock )
96 {
97 return _pParentBlock->getCursor(cursorName);
98 }
99 else
100 {
101 Chain msg = Chain("Unknown cursor ") + cursorName;
102 throw Exception(EXLOC, msg);
103 }
104 }
105
setParentBlock(CegoProcBlock * pParentBlock)106 void CegoProcBlock::setParentBlock(CegoProcBlock* pParentBlock)
107 {
108 _pParentBlock = pParentBlock;
109 }
110
getParentBlock()111 CegoProcBlock* CegoProcBlock::getParentBlock()
112 {
113 return _pParentBlock;
114 }
115
setValue(const Chain & varName,const CegoFieldValue & fv)116 void CegoProcBlock::setValue(const Chain& varName, const CegoFieldValue& fv)
117 {
118 CegoProcVar *pVar = _varList.Find(CegoProcVar(varName));
119 if ( pVar )
120 {
121 pVar->setValue(fv);
122 }
123 else
124 {
125 if ( _pParentBlock )
126 {
127 _pParentBlock->setValue(varName, fv);
128 }
129 else
130 {
131 Chain msg = Chain("Unknown variable ") + varName;
132 throw Exception(EXLOC, msg);
133 }
134 }
135 }
136
getValue(const Chain & varName)137 CegoFieldValue CegoProcBlock::getValue(const Chain& varName)
138 {
139 if ( varName == Chain(EXCEPINFO))
140 return CegoFieldValue(VARCHAR_TYPE, _exceptionMsg);
141
142 CegoProcVar *pVar = _varList.Find(CegoProcVar(varName));
143 CegoFieldValue fv;
144 if ( pVar )
145 {
146 return pVar->getValue();
147 }
148 else
149 {
150 if ( _pParentBlock )
151 {
152 return _pParentBlock->getValue(varName);
153 }
154 else
155 {
156 Chain msg = Chain("Unknown variable ") + varName;
157 throw Exception(EXLOC, msg);
158 }
159 }
160 }
161
addStatement(CegoProcStmt * pS)162 void CegoProcBlock::addStatement(CegoProcStmt* pS)
163 {
164 _stmtList.Insert(pS);
165 }
166
addException(CegoProcException * pE)167 void CegoProcBlock::addException(CegoProcException* pE)
168 {
169 _exceptionList.Insert(pE);
170 }
171
execute(ListT<CegoField> * pFVL)172 CegoException CegoProcBlock::execute(ListT<CegoField> *pFVL)
173 {
174 CegoProcStmt **pStmt = _stmtList.First();
175
176 while (pStmt)
177 {
178 try
179 {
180 CegoException excep;
181
182 if ( ( excep = (*pStmt)->execute() ) != NONE_EXCEP )
183 {
184 if ( excep == RETURN_EXCEP )
185 {
186 closeBlock();
187 return excep;
188 }
189 CegoProcException **pException = _exceptionList.First();
190 while ( pException )
191 {
192 if ( (*pException)->getException() == excep || (*pException)->getException() == ANY_EXCEP )
193 {
194 CegoProcBlock *pBlock = (*pException)->getBlock();
195 pBlock->setExceptionMsg( getExceptionMsg() );
196 if ( pBlock->execute() == RETURN_EXCEP )
197 return RETURN_EXCEP;
198 excep = NONE_EXCEP;
199 }
200 pException = _exceptionList.Next();
201 }
202 // propagate exception to parent block
203 if ( excep != NONE_EXCEP && _pParentBlock )
204 _pParentBlock->setExceptionMsg( getExceptionMsg() );
205 closeBlock();
206 return excep;
207 }
208 }
209 catch ( Exception e )
210 {
211 Chain errMsg;
212 e.pop(errMsg);
213 Chain plainStmt;
214 (*pStmt)->toChain().replaceAll(Chain("\n"), Chain(" "), plainStmt);
215 Chain msg = Chain("Procedure block error at stmt <") + plainStmt + Chain("> : ") + errMsg;
216 closeBlock();
217
218 throw Exception(EXLOC, msg);
219
220 }
221 pStmt = _stmtList.Next();
222 }
223
224 closeBlock();
225
226 return NONE_EXCEP;
227 }
228
cleanBlock()229 void CegoProcBlock::cleanBlock()
230 {
231 CegoProcCursor **pCur = _cursorList.First();
232 while ( pCur )
233 {
234 (*pCur)->reset();
235 pCur = _cursorList.Next();
236 }
237 }
238
closeBlock()239 void CegoProcBlock::closeBlock()
240 {
241 CegoProcCursor **pCur = _cursorList.First();
242 while ( pCur )
243 {
244 (*pCur)->close();
245 pCur = _cursorList.Next();
246 }
247 }
248
setRetVal(const CegoFieldValue & retVal)249 void CegoProcBlock::setRetVal(const CegoFieldValue& retVal)
250 {
251 if ( _pParentBlock )
252 _pParentBlock->setRetVal(retVal);
253 else
254 _retVal = retVal;
255 }
256
getRetVal()257 CegoFieldValue& CegoProcBlock::getRetVal()
258 {
259 return _retVal;
260 }
261
setExceptionMsg(const Chain msg)262 void CegoProcBlock::setExceptionMsg(const Chain msg)
263 {
264 _exceptionMsg = msg;
265 }
266
getExceptionMsg() const267 Chain CegoProcBlock::getExceptionMsg() const
268 {
269 return _exceptionMsg;
270 }
271
getStmtList()272 ListT<CegoProcStmt*>& CegoProcBlock::getStmtList()
273 {
274 return _stmtList;
275 }
276
getExceptionList() const277 const ListT<CegoProcException*>& CegoProcBlock::getExceptionList() const
278 {
279 return _exceptionList;
280 }
281
toChain(const Chain & indent) const282 Chain CegoProcBlock::toChain(const Chain& indent) const
283 {
284 Chain s;
285 CegoProcVar *pVar = _varList.First();
286 while ( pVar )
287 {
288 if ( pVar->getVarType() == CegoProcVar::BLOCKVAR )
289 {
290 s += indent + Chain("var ");
291 s += pVar->getName();
292 switch ( pVar->getType() )
293 {
294 case INT_TYPE:
295 s += Chain(" int;\n");
296 break;
297 case LONG_TYPE:
298 s += Chain(" long;\n");
299 break;
300 case VARCHAR_TYPE:
301 s += Chain(" string(") + Chain(pVar->getLength()) + Chain(");\n");
302 break;
303 case BIGINT_TYPE:
304 s += Chain(" bigint(") + Chain(pVar->getLength()) + Chain(");\n");
305 break;
306 case DECIMAL_TYPE:
307 s += Chain(" decimal(") + Chain(pVar->getLength()) + Chain(");\n");
308 break;
309 case FIXED_TYPE:
310 s += Chain(" fixed(") + Chain(pVar->getLength()) + Chain(");\n");
311 break;
312 case BOOL_TYPE:
313 s += Chain(" bool;\n");
314 break;
315 case DATETIME_TYPE:
316 s += Chain(" datetime;\n");
317 break;
318 case FLOAT_TYPE:
319 s += Chain(" float;\n");
320 break;
321 case DOUBLE_TYPE:
322 s += Chain(" double;\n");
323 break;
324 case SMALLINT_TYPE:
325 s += Chain(" smallint;\n");
326 break;
327 case TINYINT_TYPE:
328 s += Chain(" tinyint;\n");
329 break;
330 case NULL_TYPE:
331 s += Chain(" null;\n");
332 break;
333 case BLOB_TYPE:
334 s += Chain(" blob;\n");
335 break;
336 case CLOB_TYPE:
337 s += Chain(" clob;\n");
338 break;
339 case PAGEID_TYPE:
340 break;
341 }
342 }
343
344 pVar = _varList.Next();
345 }
346
347 CegoProcStmt **pStmt = _stmtList.First();
348 while (pStmt)
349 {
350 s += (*pStmt)->toChain(indent) + Chain(";\n");
351 pStmt = _stmtList.Next();
352 }
353
354 CegoProcException **pException = _exceptionList.First();
355 while ( pException )
356 {
357 s += Chain("exception when ") + (*pException)->toChain() + Chain("\nthen\n");
358 s += (*pException)->getBlock()->toChain(indent + Chain(DEFAULTINDENT));
359 pException = _exceptionList.Next();
360 }
361
362 return s;
363 }
364
dbFormat(CegoDatabaseFormater * pForm) const365 Chain CegoProcBlock::dbFormat(CegoDatabaseFormater *pForm) const
366 {
367 return pForm->formatProcBlock(_varList, _stmtList, _exceptionList);
368 }
369
setTriggerValueList(ListT<CegoField> * pTriggerValueList)370 void CegoProcBlock::setTriggerValueList(ListT<CegoField>* pTriggerValueList)
371 {
372 _pTriggerValueList = pTriggerValueList;
373 }
374
getTriggerValueList()375 ListT<CegoField>* CegoProcBlock::getTriggerValueList()
376 {
377 return _pTriggerValueList;
378 }
379