1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // CegoTableManager.cc
4 // -------------------
5 // Cego table manager 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: CegoTableManager
14 //
15 // Description: The table manager provides are required methods for local tableset operations
16 //
17 // Status: CLEAN
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20
21 // base includes
22 #include <lfcbase/Sleeper.h>
23 #include <lfcbase/Exception.h>
24 #include <lfcbase/Timer.h>
25 #include <lfcbase/SetT.h>
26 #include <lfcbase/Datetime.h>
27
28 // cego includes
29 #include "CegoDefs.h"
30 #include "CegoTableManager.h"
31 #include "CegoTransactionManager.h"
32 #include "CegoBufferPage.h"
33 #include "CegoObject.h"
34 #include "CegoAVLIndexManager.h"
35 #include "CegoAVLIndexEntry.h"
36 #include "CegoAVLIndexCursor.h"
37 #include "CegoBTreeCursor.h"
38 #include "CegoBTreeManager.h"
39 #include "CegoTableCursor.h"
40 #include "CegoAttrCond.h"
41 #include "CegoXMLdef.h"
42 #include "CegoTypeConverter.h"
43 #include "CegoCheckObject.h"
44 #include "CegoSelect.h"
45 #include "CegoDbThreadPool.h"
46
47 #include <string.h>
48 #include <stdlib.h>
49
CegoTableManager(CegoDatabaseManager * pDBMng)50 CegoTableManager::CegoTableManager(CegoDatabaseManager *pDBMng) : CegoSystemObject(pDBMng)
51 {
52 _pTM = new CegoTransactionManager(this);
53 for ( int i=0;i<TABMNG_MAXTABSET; i++)
54 {
55 _tid[i]=0;
56 _tastep[i]=0;
57 }
58
59 _encBufLen=0;
60 _pEncBuf=0;
61
62 _isAborted = false;
63 _autoCommit = true;
64 _doAppend = true;
65 _isolationLevel = CegoTableManager::READ_COMMITTED;
66 _modId = pDBMng->getModId("CegoTableManager");
67 _pPool = 0;
68 }
69
~CegoTableManager()70 CegoTableManager::~CegoTableManager()
71 {
72 if ( _pEncBuf )
73 {
74 free ( _pEncBuf);
75 }
76 delete _pTM;
77 }
78
setThreadId(unsigned long long tid)79 void CegoTableManager::setThreadId(unsigned long long tid)
80 {
81 _threadId = tid;
82 }
83
getThreadId() const84 unsigned long long CegoTableManager::getThreadId() const
85 {
86 return _threadId;
87 }
88
setPoolSyncInfo(CegoDbThreadPool * pPool,int thrIdx)89 void CegoTableManager::setPoolSyncInfo(CegoDbThreadPool *pPool, int thrIdx)
90 {
91 _pPool = pPool;
92 _thrIdx = thrIdx;
93 }
94
setAppend(bool doAppend)95 void CegoTableManager::setAppend(bool doAppend)
96 {
97 _doAppend = doAppend;
98 }
99
createBasicTableSet(const Chain & tableSet)100 void CegoTableManager::createBasicTableSet(const Chain& tableSet)
101 {
102 _pDBMng->log(_modId, Logger::NOTICE, Chain("Creating basic tableset files ..."));
103
104 int tabSetId =_pDBMng->getTabSetId(tableSet);
105 int sysSize = _pDBMng->getSysSize(tableSet);
106 int tmpFileId = _pDBMng->getTmpFid(tableSet);
107 int tmpSize = _pDBMng->getTmpSize(tableSet);
108 Chain dbSysFileName = _pDBMng->getSysFileName(tableSet);
109
110 if ( sysSize < TABMNG_HASHSIZE )
111 {
112 Chain msg = Chain("System space must be at least ") + Chain(TABMNG_HASHSIZE) + Chain(" pages ");
113 throw Exception(EXLOC, msg);
114 }
115
116 if ( tmpSize < TABMNG_HASHSIZE )
117 {
118 Chain msg = Chain("Tmp space must be at least ") + Chain(TABMNG_HASHSIZE) + Chain(" pages ");
119 throw Exception(EXLOC, msg);
120 }
121
122 _pDBMng->log(_modId, Logger::NOTICE, Chain("Initializing sysfile ") + dbSysFileName + Chain(" ..."));
123
124 PageIdType pageOffset;
125
126 pageOffset = _pDBMng->getNextPageOffset(sysSize);
127 _pDBMng->initDataFile(tabSetId, dbSysFileName, tabSetId, sysSize, pageOffset, CegoFileHandler::SYSTEMFILE);
128
129 _pDBMng->setSysPageOffset(tabSetId, pageOffset);
130
131 _pDBMng->log(_modId, Logger::NOTICE, Chain("Registrating sysfile ") + dbSysFileName + Chain(" ..."));
132 _pDBMng->regDataFile(tabSetId, dbSysFileName, tabSetId, _pLockHandle);
133
134 for ( PageIdType i = 0 ; i < TABMNG_HASHSIZE ; i++ )
135 {
136 _pDBMng->claimPage(pageOffset + i, _pLockHandle);
137 }
138
139 Chain dbTempFileName = _pDBMng->getTmpFileName(tableSet);
140
141 _pDBMng->log(_modId, Logger::NOTICE, Chain("Initializing tempfile ") + dbTempFileName + Chain(" ..."));
142 pageOffset = _pDBMng->getNextPageOffset(tmpSize);
143 _pDBMng->initDataFile(tabSetId, dbTempFileName, tmpFileId, tmpSize, pageOffset, CegoFileHandler::TEMP);
144
145 _pDBMng->setTempPageOffset(tabSetId, pageOffset);
146
147 _pDBMng->log(_modId, Logger::NOTICE, Chain("Registrating tempfile ") + dbTempFileName + Chain(" ..."));
148 _pDBMng->regDataFile(tabSetId, dbTempFileName, tmpFileId, _pLockHandle);
149
150 for ( PageIdType i = 0 ; i < TABMNG_HASHSIZE ; i++ )
151 {
152 _pDBMng->claimPage(pageOffset + i, _pLockHandle);
153 }
154
155 _pDBMng->initLogFiles(tableSet, false);
156 _pDBMng->setCommittedLSN(tableSet, 0);
157
158 ListT<Chain> dfList;
159 ListT<int> fidList;
160 ListT<int> sizeList;
161
162 _pDBMng->getDataFileInfo(tableSet, Chain(XML_APPFILE_VALUE), dfList, fidList, sizeList);
163
164 Chain *pFileName = dfList.First();
165 int *pFid = fidList.First();
166 int *pSize = sizeList.First();
167
168 while ( pFileName && pFid && pSize )
169 {
170 _pDBMng->log(_modId, Logger::NOTICE, Chain("Init datafile ") + *pFileName + Chain(" ..."));
171
172 pageOffset = _pDBMng->getNextPageOffset(*pSize);
173 _pDBMng->initDataFile(tabSetId, *pFileName, *pFid, *pSize, pageOffset, CegoFileHandler::DATAFILE);
174 _pDBMng->regDataFile(tabSetId, *pFileName, *pFid, _pLockHandle);
175
176 pFileName = dfList.Next();
177 pFid = fidList.Next();
178 pSize = sizeList.Next();
179 }
180
181 dfList.Empty();
182 fidList.Empty();
183 sizeList.Empty();
184
185 _pDBMng->getDataFileInfo(tableSet, Chain(XML_SYSFILE_VALUE), dfList, fidList, sizeList);
186
187 pFileName = dfList.First();
188 pFid = fidList.First();
189 pSize = sizeList.First();
190
191 while ( pFileName && pFid && pSize )
192 {
193
194 _pDBMng->log(_modId, Logger::NOTICE, Chain("Init sysfile ") + *pFileName + Chain(" ..."));
195
196 pageOffset = _pDBMng->getNextPageOffset(*pSize);
197 _pDBMng->initDataFile(tabSetId, *pFileName, *pFid, *pSize, pageOffset, CegoFileHandler::SYSTEMFILE);
198 _pDBMng->regDataFile(tabSetId, *pFileName, *pFid, _pLockHandle);
199
200 pFileName = dfList.Next();
201 pFid = fidList.Next();
202 pSize = sizeList.Next();
203
204 }
205
206 dfList.Empty();
207 fidList.Empty();
208 sizeList.Empty();
209
210 _pDBMng->getDataFileInfo(tableSet, Chain(XML_TEMPFILE_VALUE), dfList, fidList, sizeList);
211
212 pFileName = dfList.First();
213 pFid = fidList.First();
214 pSize = sizeList.First();
215
216 while ( pFileName && pFid && pSize )
217 {
218 _pDBMng->log(_modId, Logger::NOTICE, Chain("Init tempfile ") + *pFileName + Chain(" ..."));
219
220 pageOffset = _pDBMng->getNextPageOffset(*pSize);
221 _pDBMng->initDataFile(tabSetId, *pFileName, *pFid, *pSize, pageOffset, CegoFileHandler::TEMP);
222 _pDBMng->regDataFile(tabSetId, *pFileName, *pFid, _pLockHandle);
223
224 pFileName = dfList.Next();
225 pFid = fidList.Next();
226 pSize = sizeList.Next();
227 }
228
229 _pDBMng->setTableSetRunState(tableSet, XML_OFFLINE_VALUE);
230
231 _pDBMng->doc2Xml();
232
233 _pDBMng->log(_modId, Logger::NOTICE, Chain("Tableset ") + tableSet + Chain(" created succesful"));
234 }
235
dropTableSet(const Chain & tableSet)236 void CegoTableManager::dropTableSet(const Chain& tableSet)
237 {
238 Chain status = _pDBMng->getTableSetRunState(tableSet);
239
240 if ( status == Chain(XML_OFFLINE_VALUE) || status == Chain(XML_CHECKPOINT_VALUE) )
241 {
242 Chain dbSysFileName = _pDBMng->getSysFileName(tableSet);
243 Chain dbTempFileName = _pDBMng->getTmpFileName(tableSet);
244
245 int tabSetId = _pDBMng->getTabSetId(tableSet);
246 _pDBMng->writeAndRemoveTabSet(tabSetId, _pLockHandle);
247
248 File dbSysFile(dbSysFileName);
249
250 try
251 {
252 dbSysFile.remove();
253 }
254 catch ( Exception e )
255 {
256 _pDBMng->log(_modId, Logger::NOTICE, Chain("System file ") + dbSysFileName + Chain(" does not exist ( Ignored )"));
257 }
258
259 File dbTempFile(dbTempFileName);
260
261 try
262 {
263 dbTempFile.remove();
264 }
265 catch ( Exception e )
266 {
267 _pDBMng->log(_modId, Logger::NOTICE, Chain("Temp file ") + dbTempFileName + Chain(" does not exist ( Ignored )"));
268 }
269
270 ListT<Chain> lfList;
271 ListT<int> lfsizeList;
272 ListT<Chain> statusList;
273
274 _pDBMng->getLogFileInfo(tableSet, lfList, lfsizeList, statusList);
275
276 Chain *pLog = lfList.First();
277
278 while ( pLog )
279 {
280 File logFile(*pLog);
281 try
282 {
283 logFile.remove();
284 }
285 catch ( Exception e )
286 {
287 _pDBMng->log(_modId, Logger::NOTICE, Chain("Log file ") + *pLog + Chain(" does not exist ( Ignored )"));
288 }
289
290 pLog = lfList.Next();
291 }
292
293 ListT<Chain> dfList;
294 ListT<int> fidList;
295 ListT<int> dfsizeList;
296
297 _pDBMng->getDataFileInfo(tableSet, Chain(XML_APPFILE_VALUE), dfList, fidList, dfsizeList);
298
299 Chain *pFileName = dfList.First();
300
301 while ( pFileName )
302 {
303 File dataFile(*pFileName);
304
305 try
306 {
307 dataFile.remove();
308 }
309 catch ( Exception e )
310 {
311 _pDBMng->log(_modId, Logger::NOTICE, Chain("Data file ") + *pFileName + Chain(" does not exist ( Ignored )"));
312 }
313
314 pFileName = dfList.Next();
315 }
316
317 dfList.Empty();
318 fidList.Empty();
319 dfsizeList.Empty();
320
321 _pDBMng->getDataFileInfo(tableSet, Chain(XML_TEMPFILE_VALUE), dfList, fidList, dfsizeList);
322
323 pFileName = dfList.First();
324
325 while ( pFileName )
326 {
327 File dataFile(*pFileName);
328
329 try
330 {
331 dataFile.remove();
332 }
333 catch ( Exception e )
334 {
335 _pDBMng->log(_modId, Logger::NOTICE, Chain("Temp file ") + *pFileName + Chain(" does not exist ( Ignored )"));
336 }
337
338 pFileName = dfList.Next();
339 }
340
341 dfList.Empty();
342 fidList.Empty();
343 dfsizeList.Empty();
344
345 _pDBMng->getDataFileInfo(tableSet, Chain(XML_SYSFILE_VALUE), dfList, fidList, dfsizeList);
346
347 pFileName = dfList.First();
348
349 while ( pFileName )
350 {
351 File dataFile(*pFileName);
352
353 try
354 {
355 dataFile.remove();
356 }
357 catch ( Exception e )
358 {
359 _pDBMng->log(_modId, Logger::NOTICE, Chain("Sys file ") + *pFileName + Chain(" does not exist ( Ignored )"));
360 }
361
362 pFileName = dfList.Next();
363 }
364
365 // dropping counters
366 ListT<Chain> counterList;
367 _pDBMng->getCounterList(tabSetId, counterList);
368 Chain* pCounter = counterList.First();
369 while ( pCounter )
370 {
371 _pDBMng->removeCounter(tabSetId, *pCounter);
372 pCounter = counterList.Next();
373 }
374
375 _pDBMng->setCurrentLSN(tabSetId, 0);
376 _pDBMng->setTableSetRunState(tableSet,XML_DEFINED_VALUE);
377 _pDBMng->doc2Xml();
378
379 _pDBMng->log(_modId, Logger::NOTICE, Chain("Tableset ") + tableSet + Chain(" dropped"));
380 }
381 else
382 {
383 throw Exception(EXLOC, Chain("Tableset must be in status offline to drop"));
384 }
385 }
386
reorgTableSet(const Chain & tableSet)387 void CegoTableManager::reorgTableSet(const Chain& tableSet)
388 {
389 int tabSetId = _pDBMng->getTabSetId(tableSet);
390 _pTM->reorgSystemSpace(tabSetId);
391 }
392
stopTableSet(const Chain & tableSet,bool archComplete)393 void CegoTableManager::stopTableSet(const Chain& tableSet, bool archComplete)
394 {
395 _pDBMng->log(_modId, Logger::NOTICE, Chain("Stopping tableset ") + tableSet + Chain(" ..."));
396
397 int tabSetId = _pDBMng->getTabSetId(tableSet);
398
399 if ( _pDBMng->hasLogConnection(tabSetId) )
400 {
401 _pDBMng->releaseLogConnection(tabSetId);
402 }
403 else
404 {
405 unsigned long long lsn = _pDBMng->getCurrentLSN(tabSetId);
406 _pDBMng->setCommittedLSN(tabSetId, lsn);
407 _pDBMng->writeCheckPoint(tableSet, true, archComplete, _pLockHandle);
408 }
409
410 _pTM->release(tabSetId);
411
412 _pDBMng->writeAndRemoveTabSet(tabSetId, _pLockHandle);
413
414 _pDBMng->stopLog(tabSetId);
415
416 _pDBMng->setTableSetRunState(tableSet, XML_OFFLINE_VALUE);
417
418 _pDBMng->doc2Xml();
419
420 _pDBMng->log(_modId, Logger::NOTICE, Chain("Tableset ") + tableSet + Chain(" stopped"));
421 }
422
resetTableSet(const Chain & tableSet)423 void CegoTableManager::resetTableSet(const Chain& tableSet)
424 {
425 _pDBMng->log(_modId, Logger::NOTICE, Chain("Resetting tableset ") + tableSet + Chain(" ..."));
426
427 int tabSetId = _pDBMng->getTabSetId(tableSet);
428
429 if ( _pDBMng->hasLogConnection(tabSetId) )
430 {
431 _pDBMng->releaseLogConnection(tabSetId);
432 }
433 else
434 {
435 unsigned long long lsn = _pDBMng->getCurrentLSN(tabSetId);
436 _pDBMng->setCommittedLSN(tabSetId, lsn);
437 _pDBMng->writeCheckPoint(tableSet, false, false, _pLockHandle);
438 }
439
440 _pTM->release(tabSetId);
441
442 if ( _pDBMng->getTableSetRunState(tableSet) == Chain(XML_BACKUP_VALUE) )
443 {
444 endBackup(tableSet, Chain("Tableset reset"), false);
445 }
446
447 if ( _pDBMng->getTableSetRunState(tableSet) == Chain(XML_ONLINE_VALUE) )
448 {
449 _pDBMng->writeAndRemoveTabSet(tabSetId, _pLockHandle);
450 }
451
452 Chain primary = _pDBMng->getPrimary(tableSet);
453 _pDBMng->setSecondary(tableSet, primary);
454
455 _pDBMng->setTableSetRunState(tableSet, XML_OFFLINE_VALUE);
456 _pDBMng->setTableSetSyncState(tableSet, XML_SYNCHED_VALUE);
457
458 _pDBMng->log(_modId, Logger::NOTICE, Chain("Tableset ") + tableSet + Chain(" reset"));
459 }
460
beginBackup(const Chain & tableSet,const Chain & msg)461 void CegoTableManager::beginBackup(const Chain& tableSet, const Chain& msg)
462 {
463 if ( _pDBMng->getTableSetRunState(tableSet) != Chain(XML_ONLINE_VALUE) )
464 {
465 Chain msg = Chain("Tableset ") + tableSet + Chain(" must be in runstate ONLINE to begin backup mode");
466 throw Exception(EXLOC, msg);
467 }
468
469 if ( _pDBMng->isArchiveMode(tableSet) == false )
470 {
471 Chain msg = Chain("Archive not enabled for tableset ") + tableSet;
472 throw Exception(EXLOC, msg);
473 }
474
475 _pDBMng->log(_modId, Logger::NOTICE, Chain("Begin backup for tableset ") + tableSet);
476
477 _pDBMng->writeCheckPoint(tableSet, true, false, _pLockHandle);
478
479 Chain tsTicketName = _pDBMng->getTSTicket(tableSet);
480
481 File tsTicket(tsTicketName);
482 if ( tsTicket.exists())
483 throw Exception(EXLOC, Chain("Backup tableset ticket exists"));
484
485 XMLSuite xml;
486 Chain tsTicketData;
487
488 Document *pDoc = new Document;
489
490 try
491 {
492 pDoc->setAttribute(XML_VERSION_ATTR, XML_VERSION_VALUE);
493 pDoc->setDocType(XML_TSTICKET_DOC);
494
495 xml.setDocument(pDoc);
496
497 Element *pRoot = _pDBMng->getTableSetInfo(tableSet);
498 pDoc->setRootElement(pRoot);
499
500 xml.getXMLChain( tsTicketData );
501
502 delete pDoc;
503 }
504 catch ( Exception e )
505 {
506 delete pDoc;
507 Chain msg;
508 e.pop(msg);
509 throw Exception(EXLOC, Chain("Cannot write ticket data") + msg);
510 }
511
512 tsTicket.open(File::WRITE);
513 tsTicket.writeChain(tsTicketData);
514 tsTicket.close();
515
516 _pDBMng->setTableSetRunState(tableSet, XML_BACKUP_VALUE);
517
518 int tabSetId =_pDBMng->getTabSetId(tableSet);
519 _pDBMng->setBackup(tabSetId, true);
520 int tmpFileId = _pDBMng->getTmpFid(tableSet);
521 _pDBMng->setBackup(tmpFileId, true);
522
523 ListT<Chain> dfList;
524 ListT<int> fidList;
525 ListT<int> sizeList;
526
527 _pDBMng->getDataFileInfo(tableSet, Chain(XML_APPFILE_VALUE), dfList, fidList, sizeList);
528
529 int *pFid = fidList.First();
530
531 while ( pFid )
532 {
533 _pDBMng->setBackup(*pFid, true);
534 pFid = fidList.Next();
535 }
536
537 dfList.Empty();
538 fidList.Empty();
539 sizeList.Empty();
540
541 _pDBMng->getDataFileInfo(tableSet, Chain(XML_TEMPFILE_VALUE), dfList, fidList, sizeList);
542
543 pFid = fidList.First();
544
545 while ( pFid )
546 {
547 _pDBMng->setBackup(*pFid, true);
548 pFid = fidList.Next();
549 }
550
551 addBUStat(tabSetId, Chain("BEGIN BACKUP"), msg);
552 }
553
endBackup(const Chain & tableSet,const Chain & msg,bool keepTicket)554 void CegoTableManager::endBackup(const Chain& tableSet, const Chain& msg, bool keepTicket)
555 {
556 if ( _pDBMng->getTableSetRunState(tableSet) != Chain(XML_BACKUP_VALUE) )
557 {
558 Chain msg = Chain("Tableset ") + tableSet + Chain(" must be in runstate BACKUP to end backup mode");
559 throw Exception(EXLOC, msg);
560 }
561
562 if ( _pDBMng->isArchiveMode(tableSet) == false )
563 {
564 Chain msg = Chain("Archive not enabled for tableset ") + tableSet;
565 throw Exception(EXLOC, msg);
566 }
567
568 _pDBMng->log(_modId, Logger::NOTICE, Chain("End backup for tableset ") + tableSet);
569
570 int tabSetId =_pDBMng->getTabSetId(tableSet);
571 _pDBMng->setBackup(tabSetId, false);
572 int tmpFileId = _pDBMng->getTmpFid(tableSet);
573 _pDBMng->setBackup(tmpFileId, false);
574
575 ListT<Chain> dfList;
576 ListT<int> fidList;
577 ListT<int> sizeList;
578
579 _pDBMng->getDataFileInfo(tableSet, Chain(XML_APPFILE_VALUE), dfList, fidList, sizeList);
580
581 int *pFid = fidList.First();
582
583 while ( pFid )
584 {
585 _pDBMng->setBackup(*pFid, false);
586 pFid = fidList.Next();
587 }
588
589 dfList.Empty();
590 fidList.Empty();
591 sizeList.Empty();
592
593 _pDBMng->getDataFileInfo(tableSet, Chain(XML_TEMPFILE_VALUE), dfList, fidList, sizeList);
594
595 pFid = fidList.First();
596
597 while ( pFid )
598 {
599 _pDBMng->setBackup(*pFid, false);
600 pFid = fidList.Next();
601 }
602
603 CegoLogRecord logRec;
604 CegoLogRecord lr;
605 lr.setAction(CegoLogRecord::LOGREC_BUFIN);
606 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
607
608 _pDBMng->writeCheckPoint(tableSet, true, false, _pLockHandle);
609
610 if ( keepTicket == false)
611 {
612 Chain tsTicketName = _pDBMng->getTSTicket(tableSet);
613 File tsTicket(tsTicketName);
614 tsTicket.remove();
615 }
616 _pDBMng->setTableSetRunState(tableSet, XML_ONLINE_VALUE);
617
618 addBUStat(tabSetId, Chain("END BACKUP"), msg);
619 }
620
resetBUStat(const Chain & tableSet)621 void CegoTableManager::resetBUStat(const Chain& tableSet)
622 {
623 int tabSetId =_pDBMng->getTabSetId(tableSet);
624 truncateObject(tabSetId, Chain(SYSTAB_BUSTAT_ID), CegoObject::SYSTEM);
625 }
626
syncTableSet(const Chain & tableSet,const Chain & msg,const Chain & escCmd,int timeout)627 void CegoTableManager::syncTableSet(const Chain& tableSet, const Chain& msg, const Chain& escCmd, int timeout)
628 {
629 if ( _pDBMng->getTableSetRunState(tableSet) != Chain(XML_ONLINE_VALUE) )
630 {
631 Chain msg = Chain("Tableset ") + tableSet + Chain(" must be in runstate ONLINE to perform sync");
632 throw Exception(EXLOC, msg);
633 }
634
635 _pDBMng->writeCheckPoint(tableSet, true, true, _pLockHandle, escCmd, timeout);
636 int tabSetId =_pDBMng->getTabSetId(tableSet);
637 addBUStat(tabSetId, Chain("EXTERNAL SYNC"), msg);
638 }
639
logTo(const Chain & tableSet,const Chain & secondary)640 void CegoTableManager::logTo(const Chain& tableSet, const Chain& secondary)
641 {
642 Chain dbHost;
643 _pDBMng->getDBHost(dbHost);
644
645 int tabSetId = _pDBMng->getTabSetId(tableSet);
646
647 _pDBMng->releaseLogConnection(tabSetId);
648
649 if ( secondary != dbHost )
650 {
651 int logPort;
652 _pDBMng->getLogPort(logPort);
653
654 Chain logUser = _pDBMng->getTSLogUser(tableSet);
655 Chain logPwd = _pDBMng->getUserPwd(logUser);
656
657 _pDBMng->allocateLogConnection(tabSetId, tableSet, secondary, logPort, logUser, logPwd);
658 }
659 else
660 {
661 _pDBMng->setActiveLogFile(tableSet);
662 }
663
664 unsigned long long cplsn = _pDBMng->getCommittedLSN(tableSet);
665
666 _pDBMng->setCurrentLSN(tabSetId, cplsn);
667 _pDBMng->startLog(tabSetId);
668 }
669
addDataFile(const Chain & tableSet,const Chain & type,int fileId,const Chain & dataFile,int fileSize)670 void CegoTableManager::addDataFile(const Chain& tableSet, const Chain& type, int fileId, const Chain& dataFile, int fileSize)
671 {
672 int tabSetId = _pDBMng->getTabSetId(tableSet);
673
674 _pDBMng->log(_modId, Logger::NOTICE, Chain("Initializing datafile ") + dataFile + Chain(" ..."));
675
676 PageIdType pageOffset;
677 pageOffset = _pDBMng->getNextPageOffset(fileSize);
678
679 if ( type == Chain(XML_APPFILE_VALUE) )
680 {
681 _pDBMng->initDataFile(tabSetId, dataFile, fileId, fileSize, pageOffset, CegoFileHandler::DATAFILE);
682 }
683 else if ( type == Chain(XML_TEMPFILE_VALUE) )
684 {
685 _pDBMng->initDataFile(tabSetId, dataFile, fileId, fileSize, pageOffset, CegoFileHandler::TEMP);
686 }
687 else if ( type == Chain(XML_SYSFILE_VALUE) )
688 {
689 _pDBMng->initDataFile(tabSetId, dataFile, fileId, fileSize, pageOffset, CegoFileHandler::SYSTEMFILE);
690 }
691
692 _pDBMng->regDataFile(tabSetId, dataFile, fileId, _pLockHandle);
693 }
694
setIsolationLevel(IsolationLevel level)695 void CegoTableManager::setIsolationLevel(IsolationLevel level)
696 {
697 _isolationLevel = level;
698 }
699
getIsolationLevel() const700 CegoTableManager::IsolationLevel CegoTableManager::getIsolationLevel() const
701 {
702 return _isolationLevel;
703 }
704
setAutoCommit(bool autoCommit)705 void CegoTableManager::setAutoCommit(bool autoCommit)
706 {
707 _autoCommit = autoCommit;
708 }
709
getAutoCommit() const710 bool CegoTableManager::getAutoCommit() const
711 {
712 return _autoCommit;
713 }
714
lockTable(int tabSetId,const Chain & tableName)715 void CegoTableManager::lockTable(int tabSetId, const Chain& tableName)
716 {
717 _pDBMng->useObject(tabSetId, tableName, CegoObject::TABLE, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
718 }
719
unlockTable(int tabSetId,const Chain & tableName)720 void CegoTableManager::unlockTable(int tabSetId, const Chain& tableName)
721 {
722 _pDBMng->unuseObject(tabSetId, tableName, CegoObject::TABLE, _threadId);
723 }
724
beginTransaction(int tabSetId,bool doLog)725 void CegoTableManager::beginTransaction(int tabSetId, bool doLog)
726 {
727 if (_tid[tabSetId] == 0)
728 {
729 _tid[tabSetId]=_pDBMng->nextTID(tabSetId);
730 _tastep[tabSetId]=0;
731
732 if ( doLog )
733 {
734 // create log entry
735 CegoLogRecord lr;
736 lr.setAction(CegoLogRecord::LOGREC_BEGIN);
737 lr.setTID(_tid[tabSetId]);
738 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
739 }
740 }
741 else
742 {
743 Chain msg = Chain("Already active transaction on tableset ") + Chain(tabSetId);
744 throw Exception(EXLOC, msg);
745 }
746 }
747
getTransactionAffectedTables(int tabSetId,SetT<Chain> & tableList)748 void CegoTableManager::getTransactionAffectedTables(int tabSetId, SetT<Chain>& tableList)
749 {
750 unsigned long long ctid = _tid[tabSetId];
751 if ( ctid > 0 )
752 _pTM->getTransactionAffectedTables(tabSetId, ctid, tableList);
753 }
754
commitTransactionSynced(int tabSetId)755 unsigned long long CegoTableManager::commitTransactionSynced(int tabSetId)
756 {
757 unsigned long long numCommitOp=0;
758
759 SetT<Chain> tableList;
760
761 getTransactionAffectedTables(tabSetId, tableList);
762
763 Chain *pTable;
764
765 pTable = tableList.First();
766 while ( pTable )
767 {
768 _pDBMng->useObject(tabSetId, *pTable, CegoObject::TABLE, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
769 pTable = tableList.Next();
770 }
771
772 try
773 {
774 numCommitOp = commitTransaction(tabSetId, true);
775 }
776 catch ( Exception e )
777 {
778 pTable = tableList.First();
779 while ( pTable )
780 {
781 _pDBMng->unuseObject(tabSetId, *pTable, CegoObject::TABLE);
782 pTable = tableList.Next();
783 }
784 }
785 pTable = tableList.First();
786 while ( pTable )
787 {
788 _pDBMng->unuseObject(tabSetId, *pTable, CegoObject::TABLE);
789 pTable = tableList.Next();
790 }
791
792 return numCommitOp;
793 }
794
commitTransaction(int tabSetId,bool doLog)795 unsigned long long CegoTableManager::commitTransaction(int tabSetId, bool doLog)
796 {
797 if (_tid[tabSetId] != 0)
798 {
799 unsigned long long ctid = _tid[tabSetId];
800 _tid[tabSetId] = 0;
801 _tastep[tabSetId] = 0;
802
803 unsigned long long n = _pTM->commitTransaction(tabSetId, ctid);
804
805 if ( doLog )
806 {
807 // create log entry
808 CegoLogRecord lr;
809 lr.setAction(CegoLogRecord::LOGREC_COMMIT);
810 lr.setTID(ctid);
811 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
812 }
813
814 return n;
815 }
816 else
817 {
818 // nothing to do
819 return 0;
820 }
821 }
822
rollbackTransactionSynced(int tabSetId)823 unsigned long long CegoTableManager::rollbackTransactionSynced(int tabSetId)
824 {
825 unsigned long long numRollbackOp=0;
826
827 SetT<Chain> tableList;
828 getTransactionAffectedTables(tabSetId, tableList);
829
830 Chain *pTable;
831
832 pTable = tableList.First();
833 while ( pTable )
834 {
835 _pDBMng->useObject(tabSetId, *pTable, CegoObject::TABLE, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
836 pTable = tableList.Next();
837 }
838
839 try
840 {
841 numRollbackOp = rollbackTransaction(tabSetId, true);
842 }
843 catch ( Exception e )
844 {
845 pTable = tableList.First();
846 while ( pTable )
847 {
848 _pDBMng->unuseObject(tabSetId, *pTable, CegoObject::TABLE);
849 pTable = tableList.Next();
850 }
851 }
852 pTable = tableList.First();
853 while ( pTable )
854 {
855 _pDBMng->unuseObject(tabSetId, *pTable, CegoObject::TABLE);
856 pTable = tableList.Next();
857 }
858
859 return numRollbackOp;
860 }
861
rollbackTransaction(int tabSetId,bool doLog)862 unsigned long long CegoTableManager::rollbackTransaction(int tabSetId, bool doLog)
863 {
864 if (_tid[tabSetId] != 0)
865 {
866 unsigned long long ctid = _tid[tabSetId];
867 _tid[tabSetId] = 0;
868
869 unsigned long long n = _pTM->rollbackTransaction(tabSetId, ctid);
870
871 if ( doLog )
872 {
873 // create log entry
874 CegoLogRecord lr;
875 lr.setAction(CegoLogRecord::LOGREC_ABORT);
876 lr.setTID(_tid[tabSetId]);
877 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
878 }
879
880 return n;
881 }
882 else
883 {
884 // nothing to do
885 return 0;
886 }
887 }
888
getTID(int tabSetId)889 unsigned long long CegoTableManager::getTID(int tabSetId)
890 {
891 return(_tid[tabSetId]);
892 }
893
setTAStep(int tabSetId,unsigned long long tastep)894 void CegoTableManager::setTAStep(int tabSetId, unsigned long long tastep)
895 {
896 _tastep[tabSetId]=tastep;
897 }
898
getTAStep(int tabSetId)899 unsigned long long CegoTableManager::getTAStep(int tabSetId)
900 {
901 return(_tastep[tabSetId]);
902 }
903
setTID(int tabSetId,unsigned long long tid)904 void CegoTableManager::setTID(int tabSetId, unsigned long long tid)
905 {
906 _tid[tabSetId] = tid;
907 }
908
setTupleInfo(int tabSetId,const CegoDataPointer dp,unsigned long long tid,unsigned long long tastep,CegoTupleState ts)909 void CegoTableManager::setTupleInfo(int tabSetId, const CegoDataPointer dp, unsigned long long tid, unsigned long long tastep, CegoTupleState ts)
910 {
911 char *pc;
912 int len;
913
914 CegoBufferPage bp;
915 claimDataPtrUnlocked(tabSetId, CegoBufferPool::SYNC, dp, pc, len, bp);
916
917 CegoQueryHelper::encodeTupleHeader(tid, tastep, ts, pc);
918
919 releaseDataPtrUnlocked(bp, true);
920 }
921
getTupleInfo(int tabSetId,const CegoDataPointer dp,unsigned long long & tid,unsigned long long & tastep,CegoTupleState & ts)922 void CegoTableManager::getTupleInfo(int tabSetId, const CegoDataPointer dp, unsigned long long& tid, unsigned long long& tastep, CegoTupleState& ts)
923 {
924 char *pc;
925 int len;
926
927 CegoBufferPage bp;
928 claimDataPtrUnlocked(tabSetId, CegoBufferPool::SYNC, dp, pc, len, bp);
929
930 CegoQueryHelper::decodeTupleHeader(tid, tastep, ts, pc);
931
932 releaseDataPtrUnlocked(bp, true);
933 }
934
createDataTable(int tabSetId,const Chain & tableName,CegoObject::ObjectType type,const ListT<CegoField> & fl,bool useColumnId)935 CegoTableObject CegoTableManager::createDataTable(int tabSetId, const Chain& tableName, CegoObject::ObjectType type, const ListT<CegoField>& fl, bool useColumnId)
936 {
937 if ( type != CegoObject::RBSEG && getTID(tabSetId > 0 ) )
938 {
939 Chain msg = Chain("create data table in a transaction not allowed");
940 throw Exception(EXLOC, msg);
941 }
942
943 // check duplicate column names
944
945 ListT<CegoField> cfl = fl;
946 CegoField* pF = fl.First();
947 while (pF)
948 {
949 int count=0;
950 CegoField* pCF = cfl.First();
951 while ( pCF )
952 {
953 if ( pCF->getAttrName() == pF->getAttrName() )
954 count++;
955 pCF = cfl.Next();
956 }
957
958 if ( count > 1 )
959 {
960 Chain msg = Chain("Column ") + pF->getAttrName() + Chain(" multiple defined");
961 throw Exception(EXLOC, msg);
962 }
963
964 pF = fl.Next();
965 }
966
967 // define field id's
968 int id=1;
969
970 if ( useColumnId == false )
971 {
972 CegoField* pF = fl.First();
973 while (pF)
974 {
975 pF->setId(id);
976 pF = fl.Next();
977 if ( pF )
978 id++;
979 }
980 }
981 else
982 {
983 // for plain export and import, we read complete record chunks with id information
984 // so for tableimport, we have to restore the previous exported id configuration
985 CegoField* pF = fl.First();
986 while (pF)
987 {
988 if ( id < pF->getId() )
989 id = pF->getId();
990 pF = fl.Next();
991 }
992 }
993
994
995 CegoLogRecord lr;
996 if ( type != CegoObject::RBSEG )
997 {
998 lr.setLSN(_pDBMng->nextLSN(tabSetId));
999 }
1000
1001 CegoTableObject oe(tabSetId, type, tableName, fl, tableName);
1002 oe.setMaxFid(id);
1003 createTableObject(oe);
1004
1005 if ( type != CegoObject::RBSEG )
1006 {
1007 // create log entry
1008 lr.setObjectInfo(oe.getName(), oe.getType());
1009 lr.setAction(CegoLogRecord::LOGREC_CREATE);
1010
1011 char *buf;
1012 buf = (char*)malloc(oe.getEntrySize());
1013 if (buf == NULL)
1014 {
1015 throw Exception(EXLOC, Chain("malloc system error"));
1016 }
1017 oe.encode(buf);
1018 lr.setData(buf);
1019 lr.setDataLen(oe.getEntrySize());
1020
1021 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle);
1022 free(buf);
1023 }
1024
1025 return oe;
1026 }
1027
alterDataTableSynced(CegoTableObject & oe,const ListT<CegoAlterDesc> & alterList)1028 void CegoTableManager::alterDataTableSynced(CegoTableObject& oe, const ListT<CegoAlterDesc>& alterList)
1029 {
1030 _pDBMng->useObject(oe.getTabSetId(), oe.getName(), CegoObject::TABLE, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
1031
1032 try
1033 {
1034 alterDataTable(oe.getTabSetId(), oe.getName(), CegoObject::TABLE, alterList);
1035 }
1036 catch ( Exception e )
1037 {
1038 _pDBMng->unuseObject(oe.getTabSetId(), oe.getName(), CegoObject::TABLE);
1039 throw e;
1040 }
1041
1042 _pDBMng->unuseObject(oe.getTabSetId(), oe.getName(), CegoObject::TABLE);
1043 }
1044
alterDataTable(int tabSetId,const Chain & tableName,CegoObject::ObjectType type,const ListT<CegoAlterDesc> & alterList)1045 void CegoTableManager::alterDataTable(int tabSetId, const Chain& tableName, CegoObject::ObjectType type, const ListT<CegoAlterDesc>& alterList)
1046 {
1047 if ( getTID(tabSetId) > 0 )
1048 {
1049 Chain msg = Chain("alter data table in a transaction not allowed");
1050 throw Exception(EXLOC, msg);
1051 }
1052
1053
1054
1055 ListT<CegoTableObject> idxList;
1056 ListT<CegoBTreeObject> btreeList;
1057 ListT<CegoKeyObject> keyList;
1058 ListT<CegoCheckObject> checkList;
1059 ListT<CegoTriggerObject> triggerList;
1060 ListT<CegoAliasObject> aliasList;
1061 int numInvalid;
1062
1063 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
1064
1065 if ( numInvalid > 0 )
1066 {
1067 throw Exception(EXLOC, Chain("Invalid index detected, must be valid for table alter"));
1068 }
1069
1070 // TODO : handle trigger, check and alias objects for table alter operations
1071 // for now, we deny altering
1072
1073 if ( checkList.Size() > 0 )
1074 {
1075 throw Exception(EXLOC, Chain("Check object detected, must be dropped before table alter"));
1076 }
1077 if ( triggerList.Size() > 0 )
1078 {
1079 throw Exception(EXLOC, Chain("Trigger object detected, must be dropped before table alter"));
1080 }
1081 if ( aliasList.Size() > 0 )
1082 {
1083 throw Exception(EXLOC, Chain("Alias object detected, must be dropped before table alter"));
1084 }
1085
1086 CegoTableObject oe;
1087 getObject(tabSetId, tableName, type, oe);
1088
1089 ListT<CegoKeyObject> keyAlterList;
1090 ListT<CegoTableObject> idxAlterList;
1091 ListT<CegoBTreeObject> btreeAlterList;
1092
1093 ListT<CegoKeyObject> keyDropList;
1094 ListT<CegoTableObject> idxDropList;
1095 ListT<CegoBTreeObject> btreeDropList;
1096
1097
1098
1099 ListT<CegoField> alterSchema = oe.getSchema();
1100
1101 // getting max id
1102 int maxFid = oe.getMaxFid();
1103
1104 CegoAlterDesc* pAD = alterList.First();
1105 while (pAD)
1106 {
1107 switch ( pAD->getType() )
1108 {
1109 case CegoAlterDesc::ADD:
1110 {
1111 CegoField* pSF = alterSchema.Find(CegoField(tableName, pAD->getAttrName()));
1112 if (pSF)
1113 {
1114 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain(" already exists");
1115 throw Exception(EXLOC, msg);
1116 }
1117 else
1118 {
1119 if ( pAD->getField().isNullable() == false )
1120 {
1121 CegoObjectCursor *pOC = getObjectCursor(tabSetId, tableName, tableName, type);
1122 int len;
1123 CegoDataPointer dp;
1124 if ( pOC->getFirst(len, dp) )
1125 {
1126 delete pOC;
1127 throw Exception(EXLOC, Chain("Column ") + pAD->getAttrName() + Chain(" cannot be added as not nullable to non-empty table"));
1128 }
1129 delete pOC;
1130 }
1131
1132 maxFid++;
1133 pAD->getField().setId(maxFid);
1134 alterSchema.Insert(pAD->getField());
1135 }
1136 break;
1137 }
1138 case CegoAlterDesc::DROP:
1139 {
1140 getKeyAndIdxRef(tabSetId, tableName, pAD->getAttrName(), keyDropList, idxDropList, btreeDropList);
1141
1142 CegoField* pSF = alterSchema.Find(CegoField(tableName, pAD->getAttrName()));
1143 if (pSF)
1144 {
1145 alterSchema.Remove(*pSF);
1146 }
1147 else
1148 {
1149 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain(" does not exist");
1150 throw Exception(EXLOC, msg);
1151 }
1152 break;
1153 }
1154 case CegoAlterDesc::MODIFY_COLUMN:
1155 {
1156 ListT<CegoKeyObject> keyList;
1157 ListT<CegoTableObject> idxList;
1158 ListT<CegoBTreeObject> btreeList;
1159
1160 if ( pAD->getField().isNullable() == false )
1161 {
1162 CegoField* pF = alterSchema.Find(pAD->getField());
1163 if ( pF )
1164 {
1165 pAD->getField().setId(pF->getId());
1166 if ( checkNullValue(tabSetId, tableName, pAD->getField()) )
1167 {
1168 Chain msg = Chain("Null values exist for column ") + pAD->getAttrName();
1169 throw Exception(EXLOC, msg);
1170 }
1171 }
1172 }
1173
1174 getKeyAndIdxRef(tabSetId, tableName, pAD->getAttrName(), keyList, idxList, btreeList);
1175
1176 // check if any constraints or index object are defined
1177
1178 // check key objects
1179 CegoKeyObject* pKey = keyList.First();
1180 while ( pKey )
1181 {
1182 if ( (Chain)pKey->getTabName() == (Chain)tableName )
1183 {
1184 CegoField *pF = pKey->getKeySchema().First();
1185 while ( pF )
1186 {
1187 if ( pF->getAttrName() == pAD->getAttrName() )
1188 {
1189 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain(" with foreign key cannot be altered");
1190 throw Exception(EXLOC, msg);
1191 }
1192 pF = pKey->getKeySchema().Next();
1193 }
1194 }
1195 else if ( (Chain)pKey->getRefTable() == (Chain)tableName )
1196 {
1197 CegoField *pF = pKey->getRefSchema().First();
1198 while ( pF )
1199 {
1200 if ( pF->getAttrName() == pAD->getAttrName() )
1201 {
1202 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain(" with foreign key cannot be altered");
1203 throw Exception(EXLOC, msg);
1204 }
1205 pF = pKey->getRefSchema().Next();
1206 }
1207 }
1208 pKey = keyList.Next();
1209 }
1210
1211 // columns with avl trees can be modified, so we don't have to check for it
1212
1213 // check btree objects
1214 CegoBTreeObject* pBTree = btreeList.First();
1215 while ( pBTree )
1216 {
1217 CegoField *pF = pBTree->getSchema().First();
1218 while ( pF )
1219 {
1220 if ( pF->getAttrName() == pAD->getAttrName() )
1221 {
1222 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain(" with btree cannot be altered");
1223 throw Exception(EXLOC, msg);
1224 }
1225 pF = pBTree->getSchema().Next();
1226 }
1227 pBTree = btreeList.Next();
1228 }
1229
1230 CegoField* pSF = alterSchema.Find(CegoField(tableName, pAD->getAttrName()));
1231 if (pSF)
1232 {
1233 int id = pSF->getId();
1234
1235 // check if field data type could be converted
1236 if ( pSF->getType() == pAD->getField().getType() )
1237 {
1238 *pSF = pAD->getField();
1239 pSF->setId(id);
1240 }
1241 else
1242 {
1243 Chain msg = Chain("Cannot change column ") + pSF->getAttrName() + Chain(" from type ") + CEGO_TYPE_MAP[pSF->getType()] + Chain(" to ") + CEGO_TYPE_MAP[pAD->getField().getType()];
1244 throw Exception(EXLOC, msg);
1245 }
1246 if ( pSF->getLength() > pAD->getField().getLength() )
1247 {
1248 Chain msg = Chain("Cannot shrink column size for ") + pSF->getAttrName() + Chain(" from size ") + Chain(pSF->getLength()) + Chain(" to ") + Chain(pAD->getField().getLength());
1249 throw Exception(EXLOC, msg);
1250 }
1251 }
1252 else
1253 {
1254 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain(" does not exist");
1255 throw Exception(EXLOC, msg);
1256 }
1257 break;
1258 }
1259 case CegoAlterDesc::MODIFY_DEFAULT:
1260 {
1261 CegoField* pSF = alterSchema.Find(CegoField(tableName, pAD->getAttrName()));
1262 if (pSF)
1263 {
1264 CegoFieldValue fv = pAD->getField().getValue();
1265
1266 if ( fv.castTo(pSF->getType(), pSF->getDim()) == false )
1267 throw Exception(EXLOC, Chain("Cannot cast from <")
1268 + CEGO_TYPE_MAP[fv.getType()]
1269 + Chain("> to <")
1270 + CEGO_TYPE_MAP[pSF->getType()]
1271 + Chain(">"));
1272
1273 pSF->setValue( fv );
1274 }
1275 else
1276 {
1277 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain(" does not exist");
1278 throw Exception(EXLOC, msg);
1279 }
1280 break;
1281 }
1282 case CegoAlterDesc::RENAME:
1283 {
1284 CegoField* pCF = alterSchema.Find(CegoField(tableName, pAD->getAttrName()));
1285 if ( pCF )
1286 {
1287 throw Exception(EXLOC, Chain("Attribute ") + pCF->getAttrName() + Chain(" already defined"));
1288 }
1289
1290 ListT<CegoKeyObject> keyList;
1291 ListT<CegoTableObject> idxList;
1292 ListT<CegoBTreeObject> btreeList;
1293
1294 getKeyAndIdxRef(tabSetId, tableName, pAD->getOldAttrName(), keyList, idxList, btreeList);
1295
1296 CegoKeyObject* pKey = keyList.First();
1297 while ( pKey )
1298 {
1299 if ( (Chain)pKey->getTabName() == (Chain)tableName )
1300 {
1301 CegoField *pF = pKey->getKeySchema().First();
1302 while ( pF )
1303 {
1304 if ( pF->getAttrName() == pAD->getOldAttrName() )
1305 {
1306 pF->setAttrName(pAD->getAttrName());
1307 }
1308 pF = pKey->getKeySchema().Next();
1309 }
1310 }
1311 else if ( (Chain)pKey->getRefTable() == (Chain)tableName )
1312 {
1313 CegoField *pF = pKey->getRefSchema().First();
1314 while ( pF )
1315 {
1316 if ( pF->getAttrName() == pAD->getOldAttrName() )
1317 {
1318 pF->setAttrName(pAD->getAttrName());
1319 }
1320 pF = pKey->getRefSchema().Next();
1321 }
1322 }
1323 pKey = keyList.Next();
1324 }
1325
1326 CegoTableObject* pIdx = idxList.First();
1327 while ( pIdx )
1328 {
1329 CegoField *pF = pIdx->getSchema().First();
1330 while ( pF )
1331 {
1332 if ( pF->getAttrName() == pAD->getOldAttrName() )
1333 {
1334 pF->setAttrName(pAD->getAttrName());
1335 }
1336 pF = pIdx->getSchema().Next();
1337 }
1338 pIdx = idxList.Next();
1339 }
1340
1341 CegoBTreeObject* pBTree = btreeList.First();
1342 while ( pBTree )
1343 {
1344 CegoField *pF = pBTree->getSchema().First();
1345 while ( pF )
1346 {
1347 if ( pF->getAttrName() == pAD->getOldAttrName() )
1348 {
1349 pF->setAttrName(pAD->getAttrName());
1350 }
1351 pF = pBTree->getSchema().Next();
1352 }
1353 pBTree = btreeList.Next();
1354 }
1355
1356 keyAlterList += keyList;
1357 idxAlterList += idxList;
1358 btreeAlterList += btreeList;
1359
1360 CegoField* pSF = alterSchema.Find(CegoField(tableName, pAD->getOldAttrName()));
1361 if (pSF)
1362 {
1363 pSF->setAttrName(pAD->getField().getAttrName());
1364 }
1365 else
1366 {
1367 Chain msg = Chain("Column ") + pAD->getAttrName() + Chain("does not exist");
1368 throw Exception(EXLOC, msg);
1369 }
1370 break;
1371 }
1372 }
1373 pAD = alterList.Next();
1374 }
1375
1376 CegoKeyObject* pDropKey = keyDropList.First();
1377 while ( pDropKey )
1378 {
1379
1380 CegoLogRecord lr;
1381 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1382
1383 removeObject(tabSetId, pDropKey->getName(), pDropKey->getType());
1384
1385 // create log entry
1386 lr.setObjectInfo(pDropKey->getName(), pDropKey->getType());
1387 lr.setAction(CegoLogRecord::LOGREC_DROP);
1388 lr.setData(0);
1389 lr.setDataLen(0);
1390 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1391
1392
1393 pDropKey = keyDropList.Next();
1394 }
1395
1396 CegoTableObject* pDropIdx = idxDropList.First();
1397 while ( pDropIdx )
1398 {
1399 CegoLogRecord lr;
1400 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1401
1402 removeObject(tabSetId, pDropIdx->getName(), pDropIdx->getType());
1403
1404 // create log entry
1405 lr.setObjectInfo(pDropIdx->getName(), pDropIdx->getType());
1406 lr.setAction(CegoLogRecord::LOGREC_DROP);
1407 lr.setData(0);
1408 lr.setDataLen(0);
1409 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1410
1411 pDropIdx = idxDropList.Next();
1412 }
1413
1414 CegoBTreeObject* pDropBTree = btreeDropList.First();
1415 while ( pDropBTree )
1416 {
1417 CegoLogRecord lr;
1418 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1419
1420 removeObject(tabSetId, pDropBTree->getName(), pDropBTree->getType());
1421
1422 // create log entry
1423 lr.setObjectInfo(pDropBTree->getName(), pDropBTree->getType());
1424 lr.setAction(CegoLogRecord::LOGREC_DROP);
1425 lr.setData(0);
1426 lr.setDataLen(0);
1427 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1428
1429 pDropBTree = btreeDropList.Next();
1430 }
1431
1432 CegoKeyObject* pKey = keyAlterList.First();
1433 while ( pKey )
1434 {
1435 CegoLogRecord lr;
1436 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1437
1438 alterKeyObject(tabSetId, tableName, *pKey);
1439
1440 // create log entry
1441 lr.setObjectInfo(pKey->getName(), pKey->getType());
1442 lr.setAction(CegoLogRecord::LOGREC_ALTER);
1443
1444 char *buf;
1445 buf = (char*)malloc(pKey->getEntrySize());
1446 if (buf == NULL)
1447 {
1448 throw Exception(EXLOC, Chain("malloc system error"));
1449 }
1450
1451 pKey->encode(buf);
1452 lr.setData(buf);
1453 lr.setDataLen(pKey->getEntrySize());
1454
1455 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1456
1457 free(buf);
1458
1459 pKey = keyAlterList.Next();
1460 }
1461
1462 CegoTableObject* pIdx = idxAlterList.First();
1463 while ( pIdx )
1464 {
1465 CegoLogRecord lr;
1466 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1467
1468 alterTableObject(tabSetId, pIdx->getName(), pIdx->getType(), *pIdx);
1469
1470 // create log entry
1471 lr.setObjectInfo(pIdx->getName(), pIdx->getType());
1472 lr.setAction(CegoLogRecord::LOGREC_ALTER);
1473
1474 char *buf;
1475 buf = (char*)malloc(pIdx->getEntrySize());
1476 if (buf == NULL)
1477 {
1478 throw Exception(EXLOC, Chain("malloc system error"));
1479 }
1480
1481 pIdx->encode(buf);
1482 lr.setData(buf);
1483 lr.setDataLen(pIdx->getEntrySize());
1484
1485 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1486
1487 free(buf);
1488
1489 pIdx = idxAlterList.Next();
1490 }
1491
1492 CegoBTreeObject* pBTree = btreeAlterList.First();
1493 while ( pBTree )
1494 {
1495 CegoLogRecord lr;
1496 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1497
1498 alterBTreeObject(tabSetId, pBTree->getName(), pBTree->getType(), *pBTree);
1499
1500 // create log entry
1501 lr.setObjectInfo(pBTree->getName(), pBTree->getType());
1502 lr.setAction(CegoLogRecord::LOGREC_ALTER);
1503
1504 char *buf;
1505 buf = (char*)malloc(pBTree->getEntrySize());
1506 if (buf == NULL)
1507 {
1508 throw Exception(EXLOC, Chain("malloc system error"));
1509 }
1510
1511 pBTree->encode(buf);
1512 lr.setData(buf);
1513 lr.setDataLen(pBTree->getEntrySize());
1514
1515 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1516
1517 free(buf);
1518
1519 pBTree = btreeAlterList.Next();
1520 }
1521
1522 CegoTableObject aoe(tabSetId, type, tableName, alterSchema, tableName);
1523 aoe.setMaxFid(maxFid);
1524
1525 CegoLogRecord lr;
1526 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1527
1528 alterTableObject(tabSetId, tableName, type, aoe);
1529
1530 // create log entry
1531 lr.setObjectInfo(aoe.getName(), aoe.getType());
1532 lr.setAction(CegoLogRecord::LOGREC_ALTER);
1533
1534 char *buf;
1535 buf = (char*)malloc(aoe.getEntrySize());
1536 if (buf == NULL)
1537 {
1538 throw Exception(EXLOC, Chain("malloc system error"));
1539 }
1540
1541 aoe.encode(buf);
1542 lr.setData(buf);
1543 lr.setDataLen(aoe.getEntrySize());
1544
1545 _pDBMng->logIt(aoe.getTabSetId(), lr, _pLockHandle);
1546
1547 free(buf);
1548 }
1549
renameObject(int tabSetId,const Chain & objName,CegoObject::ObjectType type,const Chain & newObjName)1550 void CegoTableManager::renameObject(int tabSetId, const Chain& objName, CegoObject::ObjectType type, const Chain& newObjName)
1551 {
1552 switch ( type )
1553 {
1554 case CegoObject::TABLE:
1555 {
1556 renameTable(tabSetId, objName, newObjName);
1557 break;
1558 }
1559 case CegoObject::AVLTREE:
1560 case CegoObject::UAVLTREE:
1561 case CegoObject::PAVLTREE:
1562 {
1563 renameIndex(tabSetId, objName, type, newObjName);
1564 break;
1565 }
1566 case CegoObject::BTREE:
1567 case CegoObject::UBTREE:
1568 case CegoObject::PBTREE:
1569 {
1570 renameBTree(tabSetId, objName, type, newObjName);
1571 break;
1572 }
1573 case CegoObject::FKEY:
1574 {
1575 renameKey(tabSetId, objName, newObjName);
1576 break;
1577 }
1578 case CegoObject::PROCEDURE:
1579 {
1580 renameProcedure(tabSetId, objName, newObjName);
1581 break;
1582 }
1583 case CegoObject::VIEW:
1584 {
1585 renameView(tabSetId, objName, newObjName);
1586 break;
1587 }
1588 case CegoObject::CHECK:
1589 {
1590 renameCheck(tabSetId, objName, newObjName);
1591 break;
1592 }
1593 case CegoObject::RBSEG:
1594 {
1595 renameRBO(tabSetId, objName, newObjName);
1596 break;
1597 }
1598 case CegoObject::TRIGGER:
1599 {
1600 renameTrigger(tabSetId, objName, newObjName);
1601 break;
1602 }
1603 case CegoObject::SYSTEM:
1604 case CegoObject::JOIN:
1605 case CegoObject::ALIAS:
1606 case CegoObject::UNDEFINED:
1607 throw Exception(EXLOC, Chain("Cannot rename object"));
1608 }
1609 }
1610
renameTable(int tabSetId,const Chain & tableName,const Chain & newTableName)1611 void CegoTableManager::renameTable(int tabSetId, const Chain& tableName, const Chain& newTableName)
1612 {
1613 CegoTableObject oe;
1614 getObject(tabSetId, tableName, CegoObject::TABLE, oe);
1615
1616 CegoObject::ObjectType type = oe.getType();
1617 oe.setName(newTableName);
1618 oe.setTabName(newTableName);
1619
1620 ListT<CegoTableObject> idxList;
1621 ListT<CegoBTreeObject> btreeList;
1622 ListT<CegoKeyObject> keyList;
1623 ListT<CegoCheckObject> checkList;
1624 ListT<CegoTriggerObject> triggerList;
1625 ListT<CegoAliasObject> aliasList;
1626 int numInvalid;
1627
1628 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
1629
1630 if ( numInvalid > 0 )
1631 {
1632 throw Exception(EXLOC, Chain("Invalid index detected, must be valid for table renaming"));
1633 }
1634
1635 CegoTableObject *pIO = idxList.First();
1636 while ( pIO )
1637 {
1638 if ( pIO->getType() == CegoObject::AVLTREE
1639 || pIO->getType() == CegoObject::UAVLTREE
1640 || pIO->getType() == CegoObject::PAVLTREE )
1641 {
1642
1643 CegoTableObject idx;
1644 getObject(tabSetId, pIO->getName(), pIO->getType(), idx);
1645 idx.setTabName( newTableName );
1646
1647 alterTableObject(tabSetId, pIO->getName(), pIO->getType(), idx);
1648
1649 }
1650 pIO = idxList.Next();
1651 }
1652
1653 CegoBTreeObject *pBTO = btreeList.First();
1654 while ( pBTO )
1655 {
1656 if ( pBTO->getType() == CegoObject::BTREE
1657 || pBTO->getType() == CegoObject::UBTREE
1658 || pBTO->getType() == CegoObject::PBTREE )
1659 {
1660
1661 CegoBTreeObject btree;
1662 getObject(tabSetId, pBTO->getName(), pBTO->getType(), btree);
1663 btree.setTabName( newTableName );
1664
1665 alterBTreeObject(tabSetId, pBTO->getName(), pBTO->getType(), btree);
1666
1667 }
1668 pBTO = btreeList.Next();
1669 }
1670
1671 CegoKeyObject *pKO = keyList.First();
1672 while ( pKO )
1673 {
1674 CegoKeyObject keyObj;
1675 getObject(tabSetId, pKO->getName(), pKO->getType(), keyObj);
1676 keyObj.setTabName( newTableName );
1677
1678 alterKeyObject(tabSetId, pKO->getName(), keyObj);
1679
1680 pKO = keyList.Next();
1681 }
1682
1683 CegoCheckObject *pCO = checkList.First();
1684 while ( pCO )
1685 {
1686 CegoCheckObject checkObj;
1687 getObject(tabSetId, pCO->getName(), pCO->getType(), checkObj);
1688 checkObj.setTabName( newTableName );
1689
1690 alterCheckObject(tabSetId, pCO->getName(), checkObj);
1691
1692 pCO = checkList.Next();
1693 }
1694
1695 CegoTriggerObject *pTO = triggerList.First();
1696 while ( pTO )
1697 {
1698 CegoTriggerObject triggerObj;
1699 getObject(tabSetId, pTO->getName(), pTO->getType(), triggerObj);
1700 triggerObj.setTabName( newTableName );
1701
1702 alterTriggerObject(tabSetId, pTO->getName(), triggerObj);
1703
1704 pTO = triggerList.Next();
1705 }
1706
1707
1708 CegoLogRecord lr;
1709 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1710
1711 alterTableObject(tabSetId, tableName, type, oe);
1712
1713 // create log entry
1714 lr.setObjectInfo(tableName, type);
1715 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1716
1717 lr.setData((char*)newTableName);
1718 lr.setDataLen(newTableName.length());
1719
1720 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle);
1721 }
1722
renameIndex(int tabSetId,const Chain & idxName,CegoObject::ObjectType type,const Chain & newIdxName)1723 void CegoTableManager::renameIndex(int tabSetId, const Chain& idxName, CegoObject::ObjectType type, const Chain& newIdxName)
1724 {
1725 if ( type != CegoObject::PAVLTREE && type != CegoObject::UAVLTREE && type != CegoObject::AVLTREE )
1726 throw Exception(EXLOC, Chain("Invalid index type"));
1727
1728 CegoTableObject oe;
1729 getObject(tabSetId, idxName, type, oe);
1730
1731 oe.setName(newIdxName);
1732
1733 CegoLogRecord lr;
1734 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1735
1736 alterTableObject(tabSetId, idxName, type, oe);
1737
1738 // create log entry
1739 lr.setObjectInfo(idxName, type);
1740 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1741 lr.setData((char*)newIdxName);
1742 lr.setDataLen(newIdxName.length());
1743
1744 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle);
1745 }
1746
renameBTree(int tabSetId,const Chain & btreeName,CegoObject::ObjectType type,const Chain & newBTreeName)1747 void CegoTableManager::renameBTree(int tabSetId, const Chain& btreeName, CegoObject::ObjectType type, const Chain& newBTreeName)
1748 {
1749 if ( type != CegoObject::PBTREE && type != CegoObject::UBTREE && type != CegoObject::BTREE )
1750 throw Exception(EXLOC, Chain("Invalid btree type"));
1751
1752 CegoBTreeObject btoe;
1753 getObject(tabSetId, btreeName, type, btoe);
1754
1755 btoe.setName(newBTreeName);
1756
1757 CegoLogRecord lr;
1758 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1759
1760 alterBTreeObject(tabSetId, btreeName, type, btoe);
1761
1762 // create log entry
1763 lr.setObjectInfo(btreeName, type);
1764 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1765 lr.setData((char*)newBTreeName);
1766 lr.setDataLen(newBTreeName.length());
1767
1768 _pDBMng->logIt(btoe.getTabSetId(), lr, _pLockHandle);
1769 }
1770
renameKey(int tabSetId,const Chain & keyName,const Chain & newKeyName)1771 void CegoTableManager::renameKey(int tabSetId, const Chain& keyName, const Chain& newKeyName)
1772 {
1773 CegoKeyObject oe;
1774 getObject(tabSetId, keyName, CegoObject::FKEY, oe);
1775
1776 oe.setName(newKeyName);
1777
1778 CegoLogRecord lr;
1779 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1780
1781 alterKeyObject(tabSetId, keyName, oe);
1782
1783 // create log entry
1784 lr.setObjectInfo(keyName, CegoObject::FKEY);
1785 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1786
1787 lr.setData((char*)newKeyName);
1788 lr.setDataLen(newKeyName.length());
1789
1790 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1791 }
1792
renameRBO(int tabSetId,const Chain & rboName,const Chain & newRboName)1793 void CegoTableManager::renameRBO(int tabSetId, const Chain& rboName, const Chain& newRboName)
1794 {
1795 CegoTableObject rbo;
1796 getObject(tabSetId, rboName, CegoObject::RBSEG, rbo);
1797
1798 rbo.setName(newRboName);
1799
1800 alterTableObject(tabSetId, rboName, CegoObject::RBSEG, rbo);
1801
1802 // no need to create log entry
1803 }
1804
renameProcedure(int tabSetId,const Chain & procName,const Chain & newProcName)1805 void CegoTableManager::renameProcedure(int tabSetId, const Chain& procName, const Chain& newProcName)
1806 {
1807 CegoProcObject oe;
1808 getObject(tabSetId, procName, CegoObject::FKEY, oe);
1809
1810 oe.setName(newProcName);
1811
1812 CegoLogRecord lr;
1813 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1814
1815 alterProcObject(tabSetId, procName, oe);
1816
1817 // create log entry
1818 lr.setObjectInfo(procName, CegoObject::FKEY);
1819 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1820 lr.setData((char*)newProcName);
1821 lr.setDataLen(newProcName.length());
1822
1823 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1824 }
1825
renameView(int tabSetId,const Chain & viewName,const Chain & newViewName)1826 void CegoTableManager::renameView(int tabSetId, const Chain& viewName, const Chain& newViewName)
1827 {
1828 CegoViewObject oe;
1829 getObject(tabSetId, viewName, CegoObject::VIEW, oe);
1830
1831 oe.setName(newViewName);
1832
1833 CegoLogRecord lr;
1834 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1835
1836 alterViewObject(tabSetId, viewName, oe);
1837
1838 // create log entry
1839 lr.setObjectInfo(viewName, CegoObject::VIEW);
1840 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1841 lr.setData((char*)newViewName);
1842 lr.setDataLen(newViewName.length());
1843
1844 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1845 }
1846
renameCheck(int tabSetId,const Chain & checkName,const Chain & newCheckName)1847 void CegoTableManager::renameCheck(int tabSetId, const Chain& checkName, const Chain& newCheckName)
1848 {
1849 CegoCheckObject oe;
1850 getObject(tabSetId, checkName, CegoObject::CHECK, oe);
1851
1852 oe.setName(newCheckName);
1853
1854 CegoLogRecord lr;
1855 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1856
1857 alterCheckObject(tabSetId, checkName, oe);
1858
1859 // create log entry
1860 lr.setObjectInfo(checkName, CegoObject::CHECK);
1861 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1862 lr.setData((char*)newCheckName);
1863 lr.setDataLen(newCheckName.length());
1864
1865 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1866 }
1867
renameTrigger(int tabSetId,const Chain & triggerName,const Chain & newTriggerName)1868 void CegoTableManager::renameTrigger(int tabSetId, const Chain& triggerName, const Chain& newTriggerName)
1869 {
1870 CegoTriggerObject to;
1871 getObject(tabSetId, triggerName, CegoObject::TRIGGER, to);
1872
1873 to.setName(newTriggerName);
1874
1875 CegoLogRecord lr;
1876 lr.setLSN(_pDBMng->nextLSN(tabSetId));
1877
1878 alterTriggerObject(tabSetId, triggerName, to);
1879
1880 // create log entry
1881 lr.setObjectInfo(triggerName, CegoObject::TRIGGER);
1882 lr.setAction(CegoLogRecord::LOGREC_RENAME);
1883 lr.setData((char*)newTriggerName);
1884 lr.setDataLen(newTriggerName.length());
1885
1886 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
1887 }
1888
1889
reorgObjectSynced(int tabSetId,const Chain & objName,CegoObject::ObjectType type)1890 void CegoTableManager::reorgObjectSynced(int tabSetId, const Chain& objName, CegoObject::ObjectType type)
1891 {
1892 _pDBMng->useObject(tabSetId, objName, type, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
1893
1894 try
1895 {
1896 reorgObject(tabSetId, objName, type);
1897 }
1898 catch ( Exception e )
1899 {
1900 _pDBMng->unuseObject(tabSetId, objName, type);
1901 }
1902 _pDBMng->unuseObject(tabSetId, objName, type);
1903 }
1904
reorgTable(int tabSetId,const Chain & tableName)1905 void CegoTableManager::reorgTable(int tabSetId, const Chain& tableName)
1906 {
1907 reorgObject(tabSetId, tableName, CegoObject::TABLE);
1908 }
1909
invalidateIndexForTable(int tabSetId,const Chain & tableName)1910 void CegoTableManager::invalidateIndexForTable(int tabSetId, const Chain& tableName)
1911 {
1912 ListT<CegoTableObject> idxList;
1913 ListT<CegoBTreeObject> btreeList;
1914 ListT<CegoKeyObject> keyList;
1915 ListT<CegoCheckObject> checkList;
1916 ListT<CegoTriggerObject> triggerList;
1917 ListT<CegoAliasObject> aliasList;
1918 int numInvalid;
1919
1920 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
1921
1922 CegoTableObject *pIdx = idxList.First();
1923 while ( pIdx )
1924 {
1925 invalidateObject(tabSetId, pIdx->getName(), pIdx->getType());
1926 pIdx = idxList.Next();
1927 }
1928
1929 CegoBTreeObject *pBTree = btreeList.First();
1930 while ( pBTree )
1931 {
1932 invalidateObject(tabSetId, pBTree->getName(), pBTree->getType());
1933 pBTree = btreeList.Next();
1934 }
1935 }
1936
insertDataTable(CegoTableObject & oe,ListT<CegoField> & fvl,CegoDataPointer & dp,bool doLogging,bool flushLog)1937 void CegoTableManager::insertDataTable(CegoTableObject& oe, ListT<CegoField>& fvl, CegoDataPointer& dp, bool doLogging, bool flushLog)
1938 {
1939 // nextTAStep
1940 // if ( getTID(oe.getTabSetId()) != 0 )
1941 // _tastep[oe.getTabSetId()]++;
1942
1943 ListT<CegoTableObject> idxList;
1944 ListT<CegoBTreeObject> btreeList;
1945 ListT<CegoKeyObject> keyList;
1946 ListT<CegoCheckObject> checkList;
1947 ListT<CegoTriggerObject> triggerList;
1948 ListT<CegoAliasObject> aliasList;
1949 int numInvalid;
1950
1951 bool doAppend;
1952
1953 if ( oe.getType() == CegoObject::TABLE )
1954 {
1955 getObjectListByTable(oe.getTabSetId(), oe.getName(), idxList, btreeList, keyList,
1956 checkList, triggerList, aliasList, numInvalid);
1957 if ( numInvalid > 0 )
1958 {
1959 // for ongoing transactions, we don't support online index build up
1960 if ( getTID(oe.getTabSetId() != 0 ))
1961 {
1962 throw Exception(EXLOC, Chain("Invalid index detected, must be valid for transactions"));
1963 }
1964 doAppend = true;
1965 }
1966 else
1967 {
1968 doAppend = _doAppend;
1969 }
1970 }
1971
1972 CegoDataPointer sysEntry;
1973 Chain virginIndex;
1974 insertDataTable(oe, fvl, idxList, btreeList, keyList, checkList, sysEntry, virginIndex, dp, doLogging, doAppend, true, flushLog);
1975 }
1976
insertDataTable(CegoTableObject & oe,ListT<CegoField> & nfvl,const ListT<CegoTableObject> & idxList,const ListT<CegoBTreeObject> & btreeList,const ListT<CegoKeyObject> & keyList,const ListT<CegoCheckObject> & checkList,const CegoDataPointer & sysEntry,const Chain & virginIndex,CegoDataPointer & dp,bool doLogging,bool doAppend,bool increaseStep,bool flushLog)1977 void CegoTableManager::insertDataTable(CegoTableObject& oe, ListT<CegoField>& nfvl,
1978 const ListT<CegoTableObject>& idxList,
1979 const ListT<CegoBTreeObject>& btreeList,
1980 const ListT<CegoKeyObject>& keyList,
1981 const ListT<CegoCheckObject>& checkList,
1982 const CegoDataPointer& sysEntry,
1983 const Chain& virginIndex,
1984 CegoDataPointer& dp, bool doLogging, bool doAppend, bool increaseStep, bool flushLog)
1985 {
1986
1987 CegoLogRecord lr;
1988
1989 // we have to create log seq number at the beginning BEFORE performing the opertion.
1990 // The reason is, a sync point might happen during the operation and the operation then is
1991 // written after the sync point. For this we have to ensure a log seqnr < lsn(syncpoint) to catch this operation
1992 // during recovery
1993
1994 if ( oe.getType() == CegoObject::TABLE && doLogging == true )
1995 {
1996 lr.setLSN(_pDBMng->nextLSN(oe.getTabSetId()));
1997 }
1998
1999 // nextTAStep, just done for explicit insert ( disabled for use by updateTuple method, since TA step is already increased by embedding update method )
2000 if ( increaseStep )
2001 {
2002 if ( getTID(oe.getTabSetId()) != 0 )
2003 _tastep[oe.getTabSetId()]++;
2004 }
2005
2006 CegoDataPointer nil;
2007
2008 dp = nil;
2009
2010 unsigned long long tid = 0;
2011 unsigned long long tastep = 0;
2012 CegoTupleState ts = COMMITTED;
2013
2014 int idxInsertCount=0;
2015 int btreeInsertCount=0;
2016
2017 /////////////////////////////////////////////
2018 // Step 1 : Setting ids and check null values
2019 /////////////////////////////////////////////
2020 // after setting ids, the fvl must be sorted in terms of the id
2021
2022 CegoField* pF = nfvl.First();
2023 while (pF)
2024 {
2025
2026 CegoField* pSF = oe.getSchema().Find(CegoField(oe.getName(), pF->getAttrName()));
2027
2028 // check for allowed null values
2029 if ( pF->getValue().getType() == NULL_TYPE && pSF->isNullable() == false )
2030 {
2031 throw Exception(EXLOC, Chain("Invalid null value"));
2032 }
2033
2034 if ( pSF )
2035 {
2036 pF->setId(pSF->getId());
2037 }
2038
2039 pF = nfvl.Next();
2040 }
2041
2042 ListT<CegoField> fvl;
2043
2044 pF = nfvl.First();
2045 int maxId=0;
2046 while ( pF )
2047 {
2048 if ( pF->getId() > maxId )
2049 maxId = pF->getId();
2050 pF = nfvl.Next();
2051 }
2052
2053 for ( int id=0; id<=maxId; id++ )
2054 {
2055 CegoField *pF = nfvl.First();
2056 while ( pF )
2057 {
2058 if ( pF->getId() == id )
2059 {
2060 fvl.Insert(*pF);
2061 pF = 0;
2062 }
2063 else
2064 {
2065 pF = nfvl.Next();
2066 }
2067 }
2068 }
2069
2070 unsigned long long cpCount = _pDBMng->getCPCount();
2071
2072 int encLen;
2073
2074 try
2075 {
2076 /////////////////////////////////////////////
2077 // Step 2 : Insert table data
2078 /////////////////////////////////////////////
2079
2080 if ( oe.getType() == CegoObject::TABLE )
2081 {
2082 tid = getTID(oe.getTabSetId());
2083 tastep = getTAStep(oe.getTabSetId());
2084 if ( tid > 0 )
2085 ts = INSERTED;
2086 }
2087
2088
2089 // cout << "Encode FVL with tid = " << tid << " tastep=" << tastep << "ts = " << ts << endl;
2090
2091 encLen = CegoQueryHelper::encodeFVL(tid, tastep, ts, fvl, _pEncBuf, _encBufLen);
2092
2093 int numTries=0;
2094 while ( dp == nil )
2095 {
2096 try
2097 {
2098 if ( sysEntry == nil )
2099 {
2100 dp = insertData(oe, _pEncBuf, encLen, doAppend);
2101 }
2102 else
2103 {
2104 dp = insertData(sysEntry, oe, _pEncBuf, encLen, doAppend);
2105 }
2106 }
2107 catch ( Exception e)
2108 {
2109 Chain msg;
2110 e.pop(msg);
2111 _pDBMng->log(_modId, Logger::NOTICE, Chain("Retry insert after : ") + msg);
2112
2113 if ( numTries == LCKMNG_NUMLOCKTRIES )
2114 {
2115 throw Exception(EXLOC, msg);
2116 }
2117 numTries++;
2118 }
2119 }
2120
2121 ///////////////////////////////////
2122 // Step 3 : check key contraints //
2123 ///////////////////////////////////
2124
2125 // Note: since fkeys can refer to a primary key inside the same table and the same row,
2126 // this must be done as the second step
2127
2128 if ( ! keyList.isEmpty() )
2129 {
2130 CegoKeyObject* pKey = keyList.First();
2131 while ( pKey )
2132 {
2133 if ( (Chain)pKey->getTabName() == (Chain)oe.getName() )
2134 {
2135 Chain idxName = pKey->getRefTable() + Chain(TABMNG_PBTREE_SUFFIX);
2136 bool hasBTree = true;
2137 ListT<CegoField> rfl;
2138 ListT<CegoField> ifl;
2139
2140 try
2141 {
2142 if ( objectExists(oe.getTabSetId(), idxName, CegoObject::PBTREE ))
2143 {
2144 CegoBTreeObject pbt;
2145 getObject(oe.getTabSetId(), idxName, CegoObject::PBTREE, pbt);
2146 rfl = pbt.getSchema();
2147 ifl = pbt.getSchema();
2148 }
2149 else
2150 {
2151 idxName = pKey->getRefTable() + Chain(TABMNG_PIDX_SUFFIX);
2152 hasBTree = false;
2153
2154 CegoTableObject poe;
2155 getObject(oe.getTabSetId(), idxName, CegoObject::PAVLTREE, poe);
2156 rfl = poe.getSchema();
2157 ifl = poe.getSchema();
2158 }
2159 }
2160 catch ( Exception e )
2161 {
2162 Chain msg = Chain("Primary index or btree required for insert operation");
2163 throw Exception(EXLOC, msg);
2164 }
2165
2166 ListT<CegoField> kfl = pKey->getKeySchema();
2167 CegoField *pKF = kfl.First();
2168 while ( pKF )
2169 {
2170 CegoField *pDF = fvl.Find(*pKF);
2171 if ( pDF )
2172 {
2173 pKF->setValue(pDF->getValue());
2174 }
2175 else
2176 {
2177 Chain msg = Chain("Cannot access key attribute <") + pKF->getAttrName() + Chain(">");
2178 throw Exception(EXLOC, msg);
2179 }
2180 pKF = kfl.Next();
2181 }
2182
2183 CegoField *pRF = rfl.First();
2184 pKF = kfl.First();
2185
2186 CegoAttrCond ac;
2187
2188 while ( pKF && pRF )
2189 {
2190 // cout << "Adding search cond " << pRF->getTableAlias() << " ." << pRF->getAttrName() << " = " << pKF->getValue() << endl;
2191 ac.add(CegoAttrComp(pRF->getTableAlias(), pRF->getAttrName(), EQUAL, pKF->getValue()));
2192 pRF = rfl.Next();
2193 pKF = kfl.Next();
2194 }
2195
2196 bool hasTuple;
2197
2198 if ( hasBTree )
2199 {
2200 CegoBTreeCursor btc(this, oe.getTabSetId(), idxName, CegoObject::PBTREE, &ac, false, false);
2201 CegoDataPointer dp;
2202 hasTuple = btc.getFirst(ifl, dp);
2203 }
2204 else
2205 {
2206 CegoAVLIndexCursor ic(this, oe.getTabSetId(), idxName, CegoObject::PAVLTREE, &ac, false, false);
2207 CegoDataPointer dp;
2208 hasTuple = ic.getFirst(ifl, dp);
2209 }
2210
2211 if ( hasTuple == false )
2212 {
2213 // check for self refering tables, if the new inserted tuple can satisfy the constraint
2214
2215 if ( (Chain)pKey->getTabName() == (Chain)pKey->getRefTable() )
2216 {
2217 bool keyMatch = true;
2218 pKF = kfl.First();
2219 pRF = rfl.First();
2220 while ( pKF && keyMatch )
2221 {
2222 CegoField *pF = nfvl.Find(CegoField(Chain(), pRF->getAttrName()));
2223 if ( pF )
2224 {
2225 // cout << "Comparing " << pKF->getValue() << " and " << pF->getValue() << endl;
2226 if ( ! ( (CegoFieldValue)pKF->getValue() == (CegoFieldValue)pF->getValue()) )
2227 {
2228 keyMatch=false;
2229 }
2230 }
2231 else
2232 {
2233 Chain msg = Chain("Cannot access key attribute <") + pRF->getAttrName() + Chain(">");
2234 throw Exception(EXLOC, msg);
2235 }
2236 pKF = kfl.Next();
2237 pRF = rfl.Next();
2238 }
2239
2240 if ( keyMatch == false )
2241 {
2242 Chain msg = Chain("Missing foreign key value in reference btree <") + idxName + Chain(">");
2243 throw Exception(EXLOC, msg);
2244 }
2245 }
2246 else
2247 {
2248 Chain msg = Chain("Missing foreign key value in reference btree <") + idxName + Chain(">");
2249 throw Exception(EXLOC, msg);
2250 }
2251 }
2252 }
2253 pKey = keyList.Next();
2254 }
2255 }
2256
2257 ///////////////////////////////////
2258 // Step 4 : Check check constraints
2259 ///////////////////////////////////
2260
2261 if ( ! checkList.isEmpty() )
2262 {
2263 CegoCheckObject* pCheck = checkList.First();
2264 while ( pCheck )
2265 {
2266 // cout << "======= Check Constraint .." << endl;
2267 pCheck->getPredDesc()->clearAttrCache();
2268 // cout << "after clear attr cache" << endl;
2269
2270 // we need to create an additional reference to call evalPredicate
2271 ListT<CegoField>* xfl[2];
2272 xfl[0] = &fvl;
2273 xfl[1] = 0;
2274
2275 if ( CegoQueryHelper::evalPredicate(0, 0, xfl, 0, pCheck->getPredDesc(), 0) == false )
2276 {
2277 Chain msg = Chain("Check constraint ") + pCheck->getName() + Chain(" violated");
2278 throw Exception(EXLOC, msg);
2279 }
2280
2281 pCheck = checkList.Next();
2282 }
2283 }
2284
2285 ///////////////////////////////////
2286 // Step 5: Add index ref //
2287 ///////////////////////////////////
2288
2289 CegoTableObject* pOE = idxList.First();
2290
2291 idxInsertCount=0;
2292 while (pOE)
2293 {
2294 if (pOE->getName() != virginIndex &&
2295 pOE->isValid() &&
2296 ( pOE->getType() == CegoObject::AVLTREE
2297 || pOE->getType() == CegoObject::UAVLTREE
2298 || pOE->getType() == CegoObject::PAVLTREE ) )
2299 {
2300 char p[TABMNG_MAXINDEXVALUE];
2301 int len = TABMNG_MAXINDEXVALUE;
2302 int idxLen;
2303 CegoDataPointer ritp;
2304
2305 extractIndexValue(fvl, pOE->getSchema(), p, len, idxLen);
2306
2307 CegoDataPointer nil;
2308
2309 CegoAVLIndexManager idxMng(this);
2310 idxMng.insertNativeIndexTable(*pOE,
2311 nil,
2312 dp,
2313 p,
2314 idxLen,
2315 getTID(oe.getTabSetId()),
2316 doAppend,
2317 ritp);
2318 idxInsertCount++;
2319 }
2320 pOE = idxList.Next();
2321 }
2322
2323 ///////////////////////////////////
2324 // Step 6: Add btree ref //
2325 ///////////////////////////////////
2326
2327 CegoBTreeObject* pBTO = btreeList.First();
2328
2329 btreeInsertCount=0;
2330 while (pBTO)
2331 {
2332 if (pBTO->getName() != virginIndex &&
2333 pBTO->isValid() &&
2334 ( pBTO->getType() == CegoObject::BTREE
2335 || pBTO->getType() == CegoObject::UBTREE
2336 || pBTO->getType() == CegoObject::PBTREE ) )
2337 {
2338 CegoBTreeValue iv;
2339
2340 iv.valueFromSchema(fvl, pBTO->getSchema());
2341
2342 CegoBTreeManager btreeMng(this, pBTO);
2343
2344 // cout << "############ BEFORE INSERT ##################" << endl;
2345 // btreeMng.dumpBTree();
2346
2347
2348 btreeMng.insertBTreeWithCommit(dp,
2349 iv,
2350 getTID(oe.getTabSetId()));
2351 btreeInsertCount++;
2352
2353 // cout << "############ AFTER INSERT ##################" << endl;
2354 // btreeMng.dumpBTree();
2355 }
2356
2357 pBTO = btreeList.Next();
2358 }
2359
2360 /////////////////////////////////
2361 // Step 7: Make rollback entry //
2362 /////////////////////////////////
2363 // any exceptions also have to be catched ( e.g. temp space expired )
2364 // to rollback the complete insert operation
2365
2366 if (oe.getType() == CegoObject::TABLE && getTID(oe.getTabSetId()) != 0)
2367 {
2368 _pTM->newRBEntry(oe.getTabSetId(), getTID(oe.getTabSetId()), dp.getPageId(), dp.getOffset(), oe.getName());
2369 }
2370 }
2371 catch ( Exception e)
2372 {
2373 if ( dp != nil )
2374 {
2375 deleteData(oe.getType(), oe.getTabSetId(), dp);
2376
2377 /* if a checkpoint has occured during teh insert procedure, we have to sync again
2378 to have consistent data on disk */
2379
2380 if ( _pDBMng->getCPCount() > cpCount )
2381 {
2382 _pDBMng->log(_modId, Logger::NOTICE, Chain("Forced checkpoint by insertDataTable"));
2383 _pDBMng->writeCheckPoint(oe.getTabSetId(), true, Chain(""), 0, _pLockHandle);
2384 }
2385
2386 int i=0;
2387 CegoTableObject* pOE = idxList.First();
2388 while (pOE && i < idxInsertCount)
2389 {
2390 if (pOE->getName() != virginIndex &&
2391 pOE->isValid() &&
2392 ( pOE->getType() == CegoObject::AVLTREE
2393 || pOE->getType() == CegoObject::UAVLTREE
2394 || pOE->getType() == CegoObject::PAVLTREE ) )
2395 {
2396 char p[TABMNG_MAXINDEXVALUE];
2397 int len = TABMNG_MAXINDEXVALUE;
2398 int idxLen;
2399
2400 extractIndexValue(fvl, pOE->getSchema(), p, len, idxLen);
2401
2402 try
2403 {
2404 // cout << "Deleting index for " << pOE->getName() << " of len " << idxLen << endl;
2405 CegoAVLIndexManager idxMng(this);
2406 idxMng.deleteIndexTable(oe.getTabSetId(), oe.getName(), oe.getType(),
2407 pOE->getName(), pOE->getType(), pOE->getSchema(), dp, p, idxLen);
2408 }
2409 catch ( Exception e )
2410 {
2411 Chain msg;
2412 e.pop(msg);
2413 throw Exception(EXLOC, Chain("Cannot delete index row : ") + msg);
2414 }
2415 i++;
2416 }
2417 pOE = idxList.Next();
2418 }
2419
2420 CegoBTreeObject* pBTO = btreeList.First();
2421
2422 i=0;
2423 while (pBTO && i < btreeInsertCount )
2424 {
2425 if (pBTO->getName() != virginIndex &&
2426 pBTO->isValid() &&
2427 ( pBTO->getType() == CegoObject::BTREE
2428 || pBTO->getType() == CegoObject::UBTREE
2429 || pBTO->getType() == CegoObject::PBTREE ) )
2430 {
2431 CegoBTreeValue btv;
2432 btv.valueFromSchema(fvl, pBTO->getSchema());
2433
2434 try
2435 {
2436 CegoBTreeManager btreeMng(this, pBTO);
2437 btreeMng.deleteBTree(btv, dp, getTID(oe.getTabSetId()));
2438 }
2439 catch ( Exception e )
2440 {
2441 Chain msg;
2442 e.pop(msg);
2443 throw Exception(EXLOC, Chain("Cannot delete btree row : ") + msg);
2444 }
2445 i++;
2446 }
2447
2448 pBTO = btreeList.Next();
2449 }
2450 }
2451
2452 throw e;
2453 }
2454
2455 // increase lob refs here
2456
2457 pF = fvl.First();
2458 while (pF)
2459 {
2460 if ( pF->getValue().getType() == BLOB_TYPE )
2461 {
2462 PageIdType pageId;
2463 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
2464
2465 increaseBlobRef(oe.getTabSetId(), pageId);
2466 }
2467 else if ( pF->getValue().getType() == CLOB_TYPE )
2468 {
2469 PageIdType pageId;
2470 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
2471
2472 increaseClobRef(oe.getTabSetId(), pageId);
2473 }
2474
2475 pF = fvl.Next();
2476 }
2477
2478 if (oe.getType() == CegoObject::TABLE && doLogging == true)
2479 {
2480
2481 ListT<CegoBlob> blobList;
2482 getBlobs(oe.getTabSetId(), fvl, blobList);
2483
2484 ListT<CegoClob> clobList;
2485 getClobs(oe.getTabSetId(), fvl, clobList);
2486
2487 if ( blobList.Size() > 0 || clobList.Size() > 0 )
2488 {
2489
2490 encLen = CegoQueryHelper::encodeFVL(tid, tastep, ts, fvl, blobList, clobList, _pEncBuf, _encBufLen);
2491
2492 CegoBlob *pBlob = blobList.First();
2493 while ( pBlob )
2494 {
2495 pBlob->release();
2496 pBlob = blobList.Next();
2497 }
2498 CegoClob *pClob = clobList.First();
2499 while ( pClob )
2500 {
2501 pClob->release();
2502 pClob = clobList.Next();
2503 }
2504 }
2505
2506 lr.setObjectInfo(oe.getName(), CegoObject::TABLE);
2507
2508 lr.setAction(CegoLogRecord::LOGREC_INSERT);
2509 lr.setData(_pEncBuf);
2510 lr.setDataLen(encLen);
2511
2512 lr.setTID(getTID(oe.getTabSetId()));
2513 if ( getTID(oe.getTabSetId()) > 0 )
2514 lr.setTAStep(_tastep[oe.getTabSetId()]);
2515 else
2516 lr.setTAStep(0);
2517
2518 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle, flushLog);
2519 }
2520 }
2521
updateDataTable(int tabSetId,const Chain & tableName,const Chain & tableAlias,CegoPredDesc * pPred,const ListT<CegoField> & updList,ListT<CegoExpr * > & exprList,bool returnOnFirst,ListT<CegoField> & returnList,CegoProcBlock * pBlock)2522 unsigned long long CegoTableManager::updateDataTable(int tabSetId, const Chain& tableName, const Chain& tableAlias,
2523 CegoPredDesc* pPred, const ListT<CegoField>& updList,
2524 ListT<CegoExpr*>& exprList, bool returnOnFirst, ListT<CegoField>& returnList,
2525 CegoProcBlock* pBlock)
2526 {
2527 ListT<CegoTableObject> idxList;
2528 ListT<CegoBTreeObject> btreeList;
2529 ListT<CegoKeyObject> keyList;
2530 ListT<CegoCheckObject> checkList;
2531 ListT<CegoTriggerObject> triggerList;
2532 ListT<CegoAliasObject> aliasList;
2533 int numInvalid;
2534
2535 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
2536
2537 if ( numInvalid > 0 )
2538 {
2539 throw Exception(EXLOC, Chain("Invalid index detected, must be valid for update operations"));
2540 }
2541
2542 unsigned long long updCount = updateDataTable(tabSetId, tableName, tableAlias,
2543 idxList, btreeList, keyList, checkList,
2544 pPred, updList, exprList, returnOnFirst, returnList, pBlock);
2545
2546 return updCount;
2547 }
2548
updateDataTable(int tabSetId,const Chain & tableName,const Chain & tableAlias,const ListT<CegoTableObject> & idxList,const ListT<CegoBTreeObject> & btreeList,const ListT<CegoKeyObject> & keyList,const ListT<CegoCheckObject> & checkList,CegoPredDesc * pPred,const ListT<CegoField> & updList,ListT<CegoExpr * > & exprList,bool returnOnFirst,ListT<CegoField> & returnList,CegoProcBlock * pBlock)2549 unsigned long long CegoTableManager::updateDataTable(int tabSetId, const Chain& tableName, const Chain& tableAlias,
2550 const ListT<CegoTableObject>& idxList,
2551 const ListT<CegoBTreeObject>& btreeList,
2552 const ListT<CegoKeyObject>& keyList,
2553 const ListT<CegoCheckObject>& checkList,
2554 CegoPredDesc* pPred,
2555 const ListT<CegoField>& updList,
2556 ListT<CegoExpr*>& exprList,
2557 bool returnOnFirst,
2558 ListT<CegoField>& returnList,
2559 CegoProcBlock* pBlock)
2560 {
2561
2562 unsigned long long updCount = 0;
2563
2564 unsigned long long tid = getTID(tabSetId);
2565
2566 CegoLogRecord lr;
2567 lr.setObjectInfo(tableName, CegoObject::TABLE);
2568 lr.setAction(CegoLogRecord::LOGREC_UPDATE);
2569
2570 // increase tastep to filter out modifications for this step for any cursor
2571 if ( tid != 0 )
2572 _tastep[tabSetId]++;
2573
2574 lr.setTID(tid);
2575 if ( tid > 0 )
2576 lr.setTAStep(_tastep[tabSetId]);
2577 else
2578 lr.setTAStep(0);
2579
2580 CegoTableObject oe;
2581 CegoBufferPage bp;
2582 getObjectWithFix(tabSetId, tableName, CegoObject::TABLE, oe, bp);
2583
2584 // make log entry first
2585
2586 ListT<CegoBlob> blobList;
2587 getBlobs(oe.getTabSetId(), exprList, pBlock, blobList);
2588
2589 ListT<CegoClob> clobList;
2590 getClobs(oe.getTabSetId(), exprList, pBlock, clobList);
2591
2592
2593 char *pLogBuf = 0;
2594 int logBuflen = 0;
2595
2596 CegoQueryHelper::encodeUpdRec(tableAlias, pPred, updList, exprList, blobList, clobList, returnOnFirst, pBlock, pLogBuf, logBuflen);
2597
2598 lr.setData(pLogBuf);
2599 lr.setDataLen(logBuflen);
2600
2601 try
2602 {
2603 CegoDataPointer sysEntry(bp.getPageId(), bp.getEntryPos());
2604
2605 ListT<CegoField> fl = oe.getSchema();
2606
2607 // init returnlist with empty schema
2608 returnList = fl;
2609
2610 if ( tableName != tableAlias )
2611 {
2612 // set up the defined alias for attribute evaluation
2613 CegoField *pF = fl.First();
2614 while (pF)
2615 {
2616 pF->setTableAlias(tableAlias);
2617 pF = fl.Next();
2618 }
2619 }
2620
2621 if (pPred == 0)
2622 {
2623 #ifdef CGDEBUG
2624 _pDBMng->log(_modId, Logger::DEBUG, Chain("Updating ") + oe.getTabName() + Chain(" with fulltablescan"));
2625 #endif
2626
2627 CegoTableCursor* pTC = new CegoTableCursor(this, tabSetId, oe.getTabName(), true);
2628
2629 try
2630 {
2631 bool moreTuple;
2632
2633 CegoDataPointer dp;
2634
2635 checkTypes(fl, updList);
2636
2637 moreTuple = pTC->getFirst(fl, dp);
2638
2639 while ( moreTuple && _isAborted == false && ( returnOnFirst == false || ( returnOnFirst == true && updCount == 0)) )
2640 {
2641
2642 /*
2643 Since we are inside a transaction and use ObjectCursor,
2644 we don't have to reset the Tablecursor to the beginning after modifying the
2645 */
2646
2647 Chain virginIndex;
2648 if ( updateTuple(oe, sysEntry, dp, fl, updList, exprList, returnList, idxList, btreeList, keyList, checkList, virginIndex, _doAppend, pBlock) )
2649 updCount++;
2650
2651 moreTuple = pTC->getNext(fl, dp);
2652 }
2653 }
2654 catch ( Exception e )
2655 {
2656 delete pTC;
2657 throw e;
2658 }
2659
2660 delete pTC;
2661
2662 if ( _isAborted )
2663 {
2664 throw Exception(EXLOC, Chain("Update aborted by user"));
2665 }
2666 }
2667 else
2668 {
2669 ListT<CegoField>* xfl[3];
2670 xfl[0] = &fl;
2671 if ( pBlock )
2672 xfl[1] = pBlock->getTriggerValueList();
2673 else
2674 xfl[1] = 0;
2675 xfl[2] = 0; // terminate in any case
2676
2677 ListT<CegoSelect*> queryList;
2678 pPred->getSelectQueryList(queryList);
2679 CegoSelect **pSelect = queryList.First();
2680 while ( pSelect )
2681 {
2682 (*pSelect)->setParentJoinBuf(xfl);
2683 pSelect = queryList.Next();
2684 }
2685 pPred->analyzeSelect();
2686
2687 CegoAttrCond ac;
2688 CegoQueryHelper::AttrCondMatch m = CegoQueryHelper::checkAttrCond(ac, pPred, fl, &fl,1, pBlock);
2689
2690 if ( m == CegoQueryHelper::COMPLETE )
2691 {
2692 bool isAffected = false;
2693
2694 CegoAttrComp *pAC = 0;
2695 pAC = ac.getAttrCompSet().First();
2696
2697 while ( pAC )
2698 {
2699 CegoField *pF = updList.First();
2700 while ( pF && isAffected == false )
2701 {
2702 if ( pF->getAttrName() == pAC->getAttrName() )
2703 {
2704 isAffected = true;
2705 }
2706 else
2707 {
2708 pF = updList.Next();
2709 }
2710 }
2711
2712 pAC = ac.getAttrCompSet().Next();
2713
2714 }
2715 if ( isAffected == true )
2716 m = CegoQueryHelper::INAPP;
2717 }
2718
2719
2720 if ( m == CegoQueryHelper::INAPP )
2721 {
2722 #ifdef CGDEBUG
2723 _pDBMng->log(_modId, Logger::DEBUG, Chain("Updating ") + oe.getTabName() + Chain(" with fulltablescan"));
2724 #endif
2725
2726 CegoTableCursor* pTC = new CegoTableCursor(this, tabSetId, oe.getTabName(), true);
2727
2728 try
2729 {
2730 bool moreTuple;
2731
2732 CegoDataPointer dp;
2733
2734 checkTypes(fl, updList);
2735
2736 moreTuple = pTC->getFirst(fl, dp);
2737
2738 while ( moreTuple && _isAborted == false && ( returnOnFirst == false || ( returnOnFirst == true && updCount == 0 ) ) )
2739 {
2740 pPred->clearAttrCache();
2741
2742 if ( CegoQueryHelper::evalPredicate(0, 0, xfl, 0, pPred, pBlock))
2743 {
2744 Chain virginIndex;
2745
2746 if ( updateTuple(oe, sysEntry, dp, fl, updList, exprList, returnList, idxList, btreeList, keyList, checkList, virginIndex, _doAppend, pBlock) )
2747 updCount++;
2748
2749 moreTuple = pTC->getNext(fl, dp);
2750 }
2751 else
2752 {
2753 moreTuple = pTC->getNext(fl, dp);
2754 }
2755 }
2756 }
2757 catch ( Exception e )
2758 {
2759 // now we can release the index root page
2760 delete pTC;
2761 throw e;
2762 }
2763
2764 delete pTC;
2765
2766 if ( _isAborted )
2767 {
2768 throw Exception(EXLOC, Chain("Update aborted by user"));
2769 }
2770 }
2771 else
2772 {
2773 #ifdef CGDEBUG
2774 _pDBMng->log(_modId, Logger::DEBUG, Chain("Updating ") + oe.getTabName() + Chain(" using AttrCond ") + ac.toChain());
2775 #endif
2776
2777 CegoTableCursor *pTC = new CegoTableCursor(this, tabSetId, oe.getTabName(), true);
2778 Chain virginIndex;
2779
2780 try
2781 {
2782 checkTypes(fl, updList);
2783
2784 CegoAttrCond::IndexMatch indexMatch = pTC->setup(ac);
2785
2786
2787 CegoObject::ObjectType virginType;
2788
2789 if ( indexMatch == CegoAttrCond::FULL || indexMatch == CegoAttrCond::PART )
2790 {
2791 virginIndex = pTC->getIndexName();
2792 virginType = pTC->getIndexType();
2793 }
2794
2795 #ifdef CGDEBUG
2796 _pDBMng->log(_modId, Logger::DEBUG, Chain("Virgin index is ") + virginIndex);
2797 #endif
2798
2799 bool moreTuple;
2800 CegoDataPointer dp;
2801
2802 moreTuple = pTC->getFirst(fl, dp);
2803
2804 while ( moreTuple && _isAborted == false && ( returnOnFirst == false || ( returnOnFirst == true && updCount == 0 ) ) )
2805 {
2806 #ifdef CGDEBUG
2807 _pDBMng->log(_modId, Logger::DEBUG, Chain("Checking pred for update ..."));
2808 #endif
2809 pPred->clearAttrCache();
2810 if ( CegoQueryHelper::evalPredicate(0, 0, xfl, 0, pPred, pBlock))
2811 {
2812 #ifdef CGDEBUG
2813 _pDBMng->log(_modId, Logger::DEBUG, Chain("Updating tuple..."));
2814 #endif
2815
2816 if ( updateTuple(oe, sysEntry, dp, fl, updList, exprList, returnList, idxList, btreeList, keyList, checkList, virginIndex, _doAppend, pBlock) )
2817 updCount++;
2818
2819 moreTuple = pTC->getNext(fl, dp);
2820 }
2821 else
2822 {
2823 moreTuple = pTC->getNext(fl, dp);
2824 }
2825 }
2826 #ifdef CGDEBUG
2827 _pDBMng->log(_modId, Logger::DEBUG, Chain("Commiting update "));
2828 #endif
2829
2830 if ( virginIndex != Chain() )
2831 _pTM->commitUpdate(tabSetId, virginIndex, virginType, getTID(tabSetId), _doAppend);
2832 }
2833 catch ( Exception e )
2834 {
2835 if ( virginIndex != Chain() )
2836 {
2837 _pTM->abortUpdate(tabSetId, getTID(tabSetId));
2838 }
2839
2840 delete pTC;
2841 throw e;
2842 }
2843
2844 delete pTC;
2845
2846 if ( _isAborted )
2847 {
2848 throw Exception(EXLOC, Chain("Update aborted by user"));
2849 }
2850 }
2851 }
2852 }
2853 catch ( Exception e )
2854 {
2855 if ( logBuflen > 0 )
2856 free ( pLogBuf );
2857
2858 // now we can release the index root page
2859 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
2860 throw e;
2861 }
2862
2863 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
2864
2865 #ifdef CGDEBUG
2866 _pDBMng->log(_modId, Logger::DEBUG, Chain("Update finished, updCount = ") + Chain(updCount));
2867 #endif
2868
2869
2870 /*
2871 for the update operation, we have to get the LSN AFTER successful operation
2872 otherwise, it may occur, that a checkpoint happens during the update with a higher LSN
2873 and so the operation is lost
2874 */
2875
2876 // log update record
2877 lr.setLSN(_pDBMng->nextLSN(tabSetId));
2878 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle);
2879 if ( logBuflen > 0 )
2880 free ( pLogBuf );
2881
2882 return updCount;
2883 }
2884
updateTuple(CegoTableObject & oe,const CegoDataPointer & sysEntry,const CegoDataPointer & dp,ListT<CegoField> & fl,const ListT<CegoField> & nfvl,ListT<CegoExpr * > & exprList,ListT<CegoField> & updSchema,const ListT<CegoTableObject> & idxList,const ListT<CegoBTreeObject> & btreeList,const ListT<CegoKeyObject> & keyList,const ListT<CegoCheckObject> & checkList,const Chain & virginIndex,bool doAppend,CegoProcBlock * pBlock)2885 bool CegoTableManager::updateTuple(CegoTableObject& oe, const CegoDataPointer& sysEntry, const CegoDataPointer& dp,
2886 ListT<CegoField>& fl,
2887 const ListT<CegoField>& nfvl,
2888 ListT<CegoExpr*>& exprList,
2889 ListT<CegoField>& updSchema,
2890 const ListT<CegoTableObject>& idxList,
2891 const ListT<CegoBTreeObject>& btreeList,
2892 const ListT<CegoKeyObject>& keyList,
2893 const ListT<CegoCheckObject>& checkList,
2894 const Chain& virginIndex,
2895 bool doAppend,
2896 CegoProcBlock* pBlock)
2897 {
2898 #ifdef CGDEBUG
2899 _pDBMng->log(_modId, Logger::DEBUG, Chain("Updating tuple for ") + oe.getTabName());
2900 #endif
2901
2902 CegoField* pFV = nfvl.First();
2903 CegoExpr** pExpr = exprList.First();
2904
2905 while ( pFV && pExpr)
2906 {
2907 ListT<CegoField>* fla[3];
2908 fla[0] = &fl;
2909 if ( pBlock )
2910 fla[1] = pBlock->getTriggerValueList();
2911 else
2912 fla[1] = 0;
2913 fla[2] = 0;// terminate in any case
2914
2915 (*pExpr)->setFieldListArray(fla);
2916 // set block must be set after setFieldListArray, since in CegoFactor, sub queries are prepared
2917 // for preparation, field list array is needed
2918 (*pExpr)->setBlock(pBlock);
2919
2920 (*pExpr)->clearAttrCache();
2921
2922 CegoFieldValue fv = (*pExpr)->evalFieldValue();
2923
2924 CegoQueryHelper::prepareFieldValue(pFV, fv, this, oe.getTabSetId());
2925
2926 pFV->setValue(fv);
2927 pFV = nfvl.Next();
2928 pExpr = exprList.Next();
2929 }
2930
2931 if ( pFV || pExpr )
2932 {
2933 throw Exception(EXLOC, Chain("Mismatched argument count for value list"));
2934 }
2935
2936 // ListT<CegoField> updSchema = nfvl;
2937 updSchema = nfvl;
2938
2939 // complete updSchema
2940 CegoField* pUF = fl.First();
2941 while ( pUF )
2942 {
2943 if ( ! updSchema.Find( *pUF ) )
2944 {
2945 updSchema.Insert( *pUF );
2946 }
2947 pUF = fl.Next();
2948 }
2949
2950 bool updateDone=false;
2951 unsigned long long recLock = 0;
2952
2953 try
2954 {
2955 recLock = _pLockHandle->lockRecord(dp, CegoLockHandler::WRITE);
2956
2957 checkIntegrity( oe.getTabSetId(), oe.getTabName(), idxList, btreeList, keyList, checkList, dp, fl, updSchema);
2958
2959 /* the update operation is devided into a delete and an insert operation */
2960 /* We dont have to write dedicated redo log entries, since a log entry for update is already done => logging = false */
2961
2962 // cout << "Deleting .." << endl;
2963 if ( deleteDataTableEntry(oe.getTabSetId(), oe.getTabName(), oe.getType(), dp, fl, idxList, btreeList, keyList, false) )
2964 {
2965 CegoDataPointer ndp;
2966
2967 bool increaseStep = false;
2968 bool flushLog = true;
2969 insertDataTable(oe, updSchema, idxList, btreeList, keyList, checkList, sysEntry, virginIndex, ndp, false, doAppend, increaseStep, flushLog);
2970
2971 if ( virginIndex != Chain() )
2972 {
2973 _pTM->recordUpdate(oe.getTabSetId(), getTID(oe.getTabSetId()), ndp);
2974 }
2975
2976 updateDone = true;
2977 }
2978 else
2979 {
2980 // if delete failed, we have to cleanup lob data
2981 CegoField* pF = updSchema.First();
2982 while ( pF)
2983 {
2984 if ( pF->getValue().getType() == BLOB_TYPE && pF->getValue().getValue() != 0 )
2985 {
2986 PageIdType pageId;
2987 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
2988
2989 decreaseBlobRef(oe.getTabSetId(), pageId);
2990 }
2991
2992 if ( pF->getValue().getType() == CLOB_TYPE && pF->getValue().getValue() != 0 )
2993 {
2994 PageIdType pageId;
2995 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
2996
2997 decreaseClobRef(oe.getTabSetId(), pageId);
2998 }
2999
3000 pF = updSchema.Next();
3001 }
3002 }
3003
3004 _pLockHandle->unlockRecord(recLock);
3005 return updateDone;
3006 }
3007 catch ( Exception e )
3008 {
3009 if ( recLock )
3010 _pLockHandle->unlockRecord(recLock);
3011 throw e;
3012 }
3013 }
3014
getKeyAndIdxRef(int tabSetId,const Chain & tableName,const Chain & attrName,ListT<CegoKeyObject> & refKeyList,ListT<CegoTableObject> & refIdxList,ListT<CegoBTreeObject> & refBTreeList)3015 void CegoTableManager::getKeyAndIdxRef(int tabSetId, const Chain& tableName, const Chain& attrName,
3016 ListT<CegoKeyObject>& refKeyList,
3017 ListT<CegoTableObject>& refIdxList,
3018 ListT<CegoBTreeObject>& refBTreeList)
3019 {
3020 ListT<CegoTableObject> idxList;
3021 ListT<CegoBTreeObject> btreeList;
3022 ListT<CegoKeyObject> keyList;
3023 ListT<CegoCheckObject> checkList;
3024 ListT<CegoTriggerObject> triggerList;
3025 ListT<CegoAliasObject> aliasList;
3026 int numInvalid;
3027
3028 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
3029
3030 if ( ! keyList.isEmpty() )
3031 {
3032 CegoKeyObject* pKey = keyList.First();
3033 while ( pKey )
3034 {
3035 if ( (Chain)pKey->getTabName() == (Chain)tableName )
3036 {
3037 CegoField *pF = pKey->getKeySchema().First();
3038 while ( pF )
3039 {
3040 if ( pF->getAttrName() == attrName )
3041 {
3042 refKeyList.Insert(*pKey);
3043 }
3044 pF = pKey->getKeySchema().Next();
3045 }
3046 }
3047 else if ( (Chain)pKey->getRefTable() == (Chain)tableName )
3048 {
3049 CegoField *pF = pKey->getRefSchema().First();
3050 while ( pF )
3051 {
3052 if ( pF->getAttrName() == attrName )
3053 {
3054 refKeyList.Insert(*pKey);
3055 }
3056 pF = pKey->getRefSchema().Next();
3057 }
3058 }
3059 pKey = keyList.Next();
3060 }
3061 }
3062 if ( ! idxList.isEmpty() )
3063 {
3064 CegoTableObject* pIdx = idxList.First();
3065 while ( pIdx )
3066 {
3067 CegoField *pF = pIdx->getSchema().First();
3068 while ( pF )
3069 {
3070 if ( pF->getAttrName() == attrName )
3071 {
3072 refIdxList.Insert(*pIdx);
3073 // return true;
3074 }
3075 pF = pIdx->getSchema().Next();
3076 }
3077 pIdx = idxList.Next();
3078 }
3079 }
3080
3081 if ( ! btreeList.isEmpty() )
3082 {
3083 CegoBTreeObject* pBTree = btreeList.First();
3084 while ( pBTree )
3085 {
3086 CegoField *pF = pBTree->getSchema().First();
3087 while ( pF )
3088 {
3089 if ( pF->getAttrName() == attrName )
3090 {
3091 refBTreeList.Insert(*pBTree);
3092 // return true;
3093 }
3094 pF = pBTree->getSchema().Next();
3095 }
3096 pBTree = btreeList.Next();
3097 }
3098 }
3099
3100 return;
3101 }
3102
keyReferenceExists(int tabSetId,const Chain & tableName,const ListT<CegoField> & fl,const ListT<CegoKeyObject> & keyList)3103 bool CegoTableManager::keyReferenceExists(int tabSetId, const Chain& tableName, const ListT<CegoField>& fl, const ListT<CegoKeyObject>& keyList)
3104 {
3105 if ( ! keyList.isEmpty() )
3106 {
3107 CegoKeyObject* pKey = keyList.First();
3108 while ( pKey )
3109 {
3110 if ( (Chain)pKey->getRefTable() == (Chain)tableName )
3111 {
3112 CegoTableCursor tc(this, tabSetId, pKey->getTabName());
3113
3114 CegoField *pKF = pKey->getKeySchema().First();
3115 CegoField *pRF = pKey->getRefSchema().First();
3116
3117 CegoAttrCond ac;
3118
3119 while ( pKF && pRF )
3120 {
3121 CegoField *pF = fl.Find(*pRF);
3122 // cout << "Setting up " << pKF->getAttrName() << " = " << pF->getValue() << endl;
3123 ac.add(CegoAttrComp(pKF->getTableAlias(), pKF->getAttrName(), EQUAL, pF->getValue()));
3124
3125 pKF = pKey->getKeySchema().Next();
3126 pRF = pKey->getRefSchema().Next();
3127 }
3128
3129 CegoTableObject oe;
3130 getObject(tabSetId, pKey->getTabName(), CegoObject::TABLE, oe);
3131
3132 ListT<CegoField> kfl = oe.getSchema();
3133
3134 pKF = kfl.First();
3135 while ( pKF )
3136 {
3137 pKF->setTableName(pKey->getTabName());
3138 pKF->setTableAlias(pKey->getTabName());
3139
3140 CegoField *pF = fl.Find(CegoField(pKF->getTableAlias(), pKF->getAttrName()));
3141 if ( pF )
3142 {
3143 pKF->setId(pF->getId());
3144 }
3145 pKF = kfl.Next();
3146 }
3147 CegoDataPointer dp;
3148
3149 CegoAttrCond::IndexMatch indexMatch = tc.setup(ac);
3150 bool moreTuple = tc.getFirst(kfl, dp);
3151
3152 if ( indexMatch == CegoAttrCond::FULL )
3153 {
3154 if ( moreTuple )
3155 {
3156 // treat self refering tables
3157 if ( pKey->getRefTable() == pKey->getTabName() )
3158 {
3159 pRF = pKey->getRefSchema().First();
3160 while ( pRF )
3161 {
3162 // we just search for attrname, since must be unique and tablename could be setup with alias
3163 CegoField *pF = fl.Find(CegoField(Chain(), pRF->getAttrName()));
3164 if ( pF )
3165 {
3166 CegoField *pKFV = kfl.Find(*pRF);
3167 if ( pKFV )
3168 {
3169 if ( ! ( (CegoFieldValue)pF->getValue() == (CegoFieldValue)pKFV->getValue()) )
3170 {
3171 // cursor tuple is not the to-deleted tuple, so we really found a key reference
3172 return true;
3173 }
3174 }
3175 else
3176 {
3177 Chain msg = Chain("Unknown key attribute <" ) + pRF->getAttrName() + Chain(">");
3178 throw Exception(EXLOC, msg);
3179 }
3180 }
3181 pRF = pKey->getRefSchema().Next();
3182 }
3183 }
3184 else
3185 {
3186 return true;
3187 }
3188 }
3189 }
3190 else
3191 {
3192 while ( moreTuple )
3193 {
3194 bool isMatch = true;
3195 pKF = pKey->getKeySchema().First();
3196 pRF = pKey->getRefSchema().First();
3197 while ( pKF && pRF && isMatch)
3198 {
3199 // we just search for attrname, since must be unique and tablename could be setup with alias
3200 CegoField *pF = fl.Find(CegoField(Chain(), pRF->getAttrName()));
3201 if ( pF )
3202 {
3203 CegoField *pKFV = kfl.Find(*pKF);
3204 if ( ! ( (CegoFieldValue)pF->getValue() == (CegoFieldValue)pKFV->getValue()) )
3205 {
3206 isMatch=false;
3207 }
3208 }
3209 else
3210 {
3211 Chain msg = Chain("Unknown key attribute <" ) + pKF->getAttrName() + Chain(">");
3212 throw Exception(EXLOC, msg);
3213 }
3214 pRF = pKey->getRefSchema().Next();
3215 pKF = pKey->getKeySchema().Next();
3216 }
3217 if ( isMatch )
3218 {
3219 // for self refering keys, we still have to check primary key, if cursor tuple != delete tuple
3220
3221 if ( pKey->getRefTable() == pKey->getTabName() )
3222 {
3223 pRF = pKey->getRefSchema().First();
3224 while ( pRF )
3225 {
3226 // we just search for attrname, since must be unique and tablename could be setup with alias
3227 CegoField *pF = fl.Find(CegoField(Chain(), pRF->getAttrName()));
3228 if ( pF )
3229 {
3230 CegoField *pKFV = kfl.Find(*pRF);
3231 if ( pKFV )
3232 {
3233 if ( ! ( (CegoFieldValue)pF->getValue() == (CegoFieldValue)pKFV->getValue()) )
3234 {
3235 // cursor tuple is not the to-deleted tuple, so we really found a key reference
3236 return true;
3237 }
3238 }
3239 else
3240 {
3241 Chain msg = Chain("Unknown key attribute <" ) + pRF->getAttrName() + Chain(">");
3242 throw Exception(EXLOC, msg);
3243 }
3244 }
3245 pRF = pKey->getRefSchema().Next();
3246 }
3247 }
3248 else
3249 {
3250 return true;
3251 }
3252 }
3253 moreTuple = tc.getNext(kfl, dp);
3254 }
3255 }
3256 }
3257 pKey = keyList.Next();
3258 }
3259 }
3260 return false;
3261 }
3262
checkIntegrity(int tabSetId,const Chain & tableName,const ListT<CegoTableObject> & idxList,const ListT<CegoBTreeObject> & btreeList,const ListT<CegoKeyObject> & keyList,const ListT<CegoCheckObject> & checkList,const CegoDataPointer & dp,const ListT<CegoField> & fvl,const ListT<CegoField> & nfvl)3263 void CegoTableManager::checkIntegrity(int tabSetId,
3264 const Chain& tableName,
3265 const ListT<CegoTableObject>& idxList,
3266 const ListT<CegoBTreeObject>& btreeList,
3267 const ListT<CegoKeyObject>& keyList,
3268 const ListT<CegoCheckObject>& checkList,
3269 const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl)
3270 {
3271 /*
3272 if ( ! idxList.isEmpty() )
3273 {
3274 if ( checkIndexIntegrity(idxList, tabSetId, dp, fvl, nfvl) == false )
3275 throw Exception(EXLOC, Chain("Constraint violation on unique index"));
3276 }
3277 */
3278
3279 /*
3280 if ( ! btreeList.isEmpty() )
3281 {
3282 if ( checkBTreeIntegrity(btreeList, tabSetId, dp, fvl, nfvl) == false )
3283 throw Exception(EXLOC, Chain("Constraint violation on unique btree"));
3284 }
3285 */
3286
3287 /*
3288 if ( ! keyList.isEmpty() )
3289 {
3290 if ( checkKeyIntegrity(keyList, tabSetId, tableName, fvl, nfvl) == false )
3291 throw Exception(EXLOC, Chain("Constraint violation on foreign key"));
3292 }
3293 */
3294
3295 checkIndexIntegrity(idxList, tabSetId, dp, fvl, nfvl);
3296 checkBTreeIntegrity(btreeList, tabSetId, dp, fvl, nfvl);
3297 checkKeyIntegrity(keyList, tabSetId, tableName, fvl, nfvl);
3298 checkCheckIntegrity(checkList, nfvl);
3299
3300 }
3301
checkKeyIntegrity(const ListT<CegoKeyObject> & keyList,int tabSetId,const Chain & tableName,const ListT<CegoField> & fvl,const ListT<CegoField> & nfvl)3302 void CegoTableManager::checkKeyIntegrity(const ListT<CegoKeyObject>& keyList, int tabSetId, const Chain& tableName, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl)
3303 {
3304 CegoKeyObject* pKey = keyList.First();
3305 while ( pKey )
3306 {
3307 if ( (Chain)pKey->getRefTable() == (Chain)tableName )
3308 {
3309 CegoTableCursor tc(this, tabSetId, pKey->getTabName());
3310 CegoField *pRF, *pKF;
3311
3312 // get reference key value from old tuple value
3313 ListT<CegoField> rfl = pKey->getRefSchema();
3314 pRF = rfl.First();
3315 while ( pRF )
3316 {
3317 CegoField *pF = fvl.Find(*pRF);
3318 if ( pF )
3319 {
3320 pRF->setValue(pF->getValue());
3321 }
3322 else
3323 {
3324 Chain msg = Chain("Unknown reference attribute <" ) + pRF->getAttrName() + Chain(">");
3325 throw Exception(EXLOC, msg);
3326 }
3327
3328 pRF = rfl.Next();
3329 }
3330
3331 CegoAttrCond ac;
3332 pKF = pKey->getKeySchema().First();
3333 pRF = rfl.First();
3334 while ( pKF && pRF )
3335 {
3336 ac.add(CegoAttrComp(pKey->getTabName(), pKF->getAttrName(), EQUAL, pRF->getValue()));
3337
3338 pKF = pKey->getKeySchema().Next();
3339 pRF = rfl.Next();
3340 }
3341
3342 CegoAttrCond::IndexMatch indexMatch = tc.setup(ac);
3343
3344 CegoTableObject oe;
3345 getObject(tabSetId, pKey->getTabName(), CegoObject::TABLE, oe);
3346
3347 ListT<CegoField> kfl = pKey->getKeySchema();
3348 pKF = kfl.First();
3349 while ( pKF )
3350 {
3351 pKF->setTableName(pKey->getTabName());
3352 pKF->setTableAlias(pKey->getTabName());
3353
3354 CegoField *pF = oe.getSchema().Find(CegoField(pKey->getTabName(), pKF->getAttrName()));
3355 if ( pF )
3356 {
3357 pKF->setId(pF->getId());
3358 pKF = kfl.Next();
3359 }
3360 }
3361
3362 CegoDataPointer dp;
3363 bool moreTuple = tc.getFirst(kfl, dp);
3364
3365 if ( indexMatch == CegoAttrCond::FULL )
3366 {
3367 if ( moreTuple )
3368 {
3369 bool keyMatch=true;
3370 pKF = kfl.First();
3371 pRF = rfl.First();
3372 while ( pKF && pRF && keyMatch)
3373 {
3374 // we must search for undefined tablename, since for update opertions, also an alias could be setup
3375 CegoField *pNF = nfvl.Find(CegoField(Chain(), pRF->getAttrName()));
3376 if ( pNF )
3377 {
3378 if ( ! ( (CegoFieldValue)pNF->getValue() == (CegoFieldValue)pKF->getValue()) )
3379 {
3380 keyMatch=false;
3381 }
3382 }
3383 pKF = kfl.Next();
3384 }
3385 if ( keyMatch == false )
3386 {
3387 Chain msg = Chain("Foreign key " ) + pKey->getName() + Chain(" violated");
3388 throw Exception(EXLOC, msg);
3389
3390 // return false;
3391 }
3392 return; // true;
3393 }
3394 return; // true;
3395 }
3396 else
3397 {
3398 while ( moreTuple )
3399 {
3400 bool isMatch = true;
3401 pKF = kfl.First();
3402 pRF = rfl.First();
3403 while ( pKF && pRF && isMatch)
3404 {
3405 // we must search for undefined tablename, since for update opertions, also an alias could be setup
3406 CegoField *pF = fvl.Find(CegoField(Chain(), pRF->getAttrName()));
3407 if ( pF )
3408 {
3409 if ( ! ( (CegoFieldValue)pF->getValue() == (CegoFieldValue)pKF->getValue()) )
3410 {
3411 isMatch=false;
3412 }
3413 }
3414 else
3415 {
3416 Chain msg = Chain("Unknown key attribute <" ) + pKF->getAttrName() + Chain(">");
3417 throw Exception(EXLOC, msg);
3418 }
3419 pRF = rfl.Next();
3420 pKF = kfl.Next();
3421 }
3422 if ( isMatch )
3423 {
3424 bool keyMatch=true;
3425 pKF = kfl.First();
3426 pRF = rfl.First();
3427 while ( pKF && pRF && keyMatch)
3428 {
3429 // we must search for undefined tablename, since for update opertions, also an alias could be setup
3430 CegoField *pNF = nfvl.Find(CegoField(Chain(), pRF->getAttrName()));
3431 if ( pNF )
3432 {
3433 if ( ! ( (CegoFieldValue)pNF->getValue() == (CegoFieldValue)pKF->getValue()) )
3434 {
3435 keyMatch=false;
3436 }
3437 }
3438 else
3439 {
3440 Chain msg = Chain("Unknown reference attribute <" ) + pRF->getAttrName() + Chain(">");
3441 throw Exception(EXLOC, msg);
3442 }
3443 pRF = rfl.Next();
3444 pKF = kfl.Next();
3445 }
3446 if ( keyMatch == false )
3447 {
3448 Chain msg = Chain("Foreign key " ) + pKey->getName() + Chain(" violated");
3449 throw Exception(EXLOC, msg);
3450 // return false;
3451 }
3452
3453 }
3454 moreTuple = tc.getNext(kfl, dp);
3455 }
3456
3457 return; // true;
3458 }
3459 }
3460 pKey = keyList.Next();
3461 }
3462 return; // true;
3463 }
3464
checkIndexIntegrity(const ListT<CegoTableObject> & idxList,int tabSetId,const CegoDataPointer & dp,const ListT<CegoField> & fvl,const ListT<CegoField> & nfvl)3465 void CegoTableManager::checkIndexIntegrity(const ListT<CegoTableObject>& idxList, int tabSetId, const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl)
3466 {
3467 CegoTableObject* pOE = idxList.First();
3468
3469 while (pOE)
3470 {
3471 if ( pOE->getType() == CegoObject::UAVLTREE
3472 || pOE->getType() == CegoObject::PAVLTREE )
3473 {
3474 CegoFieldValue fv = getIndexSearchValue(pOE->getSchema(), nfvl);
3475
3476 CegoField *pF = pOE->getSchema().First();
3477
3478 CegoAttrCond ac;
3479 ac.add(CegoAttrComp( pF->getTableAlias(), pF->getAttrName(), EQUAL, fv));
3480
3481 CegoAVLIndexCursor ic(this, tabSetId, pOE->getName(), pOE->getType(), &ac, false, true);
3482
3483 CegoDataPointer ndp;
3484 bool attrMatch = ic.getFirst(pOE->getSchema(), ndp);
3485
3486 while ( attrMatch )
3487 {
3488 CegoField *pIF = pOE->getSchema().First();
3489 while ( pIF && attrMatch )
3490 {
3491 CegoField *pNF = nfvl.Find(*pIF);
3492
3493 if ( pNF )
3494 {
3495 if ( pNF->getValue() != pIF->getValue() )
3496 attrMatch = false;
3497 else
3498 pIF = pOE->getSchema().Next();
3499 }
3500 else
3501 {
3502 pIF = pOE->getSchema().Next();
3503 }
3504 }
3505
3506 if ( ndp != dp && attrMatch )
3507 {
3508 ic.abort();
3509
3510 Chain msg = Chain("Duplicate entry for index " ) + pOE->getName();
3511 throw Exception(EXLOC, msg);
3512
3513 // return false;
3514 }
3515
3516 attrMatch = ic.getNext(pOE->getSchema(), ndp);
3517 }
3518 }
3519 pOE = idxList.Next();
3520 }
3521 return; // true;
3522 }
3523
checkBTreeIntegrity(const ListT<CegoBTreeObject> & btreeList,int tabSetId,const CegoDataPointer & dp,const ListT<CegoField> & fvl,const ListT<CegoField> & nfvl)3524 void CegoTableManager::checkBTreeIntegrity(const ListT<CegoBTreeObject>& btreeList, int tabSetId, const CegoDataPointer& dp, const ListT<CegoField>& fvl, const ListT<CegoField>& nfvl)
3525 {
3526 CegoBTreeObject* pOE = btreeList.First();
3527
3528 while (pOE)
3529 {
3530 if ( pOE->getType() == CegoObject::UBTREE
3531 || pOE->getType() == CegoObject::PBTREE )
3532 {
3533 CegoFieldValue fv = getIndexSearchValue(pOE->getSchema(), nfvl);
3534
3535 CegoField *pF = pOE->getSchema().First();
3536
3537 CegoAttrCond ac;
3538 ac.add(CegoAttrComp( pF->getTableAlias(), pF->getAttrName(), EQUAL, fv));
3539
3540 CegoBTreeCursor btc(this, tabSetId, pOE->getName(), pOE->getType(), &ac, false, true);
3541
3542 CegoDataPointer ndp;
3543 bool attrMatch = btc.getFirst(pOE->getSchema(), ndp);
3544
3545 while ( attrMatch )
3546 {
3547 CegoField *pIF = pOE->getSchema().First();
3548 while ( pIF && attrMatch )
3549 {
3550 CegoField *pNF = nfvl.Find(*pIF);
3551
3552 if ( pNF )
3553 {
3554 if ( pNF->getValue() != pIF->getValue() )
3555 attrMatch = false;
3556 else
3557 pIF = pOE->getSchema().Next();
3558 }
3559 else
3560 {
3561 pIF = pOE->getSchema().Next();
3562 }
3563 }
3564
3565 if ( ndp != dp && attrMatch )
3566 {
3567 // we still have to check the tuple state, it might be that the found entry
3568 // was made by another transaction and is still not commited
3569
3570 unsigned long long tid;
3571 unsigned long long tastep;
3572 CegoTupleState ts;
3573
3574 getTupleInfo(tabSetId, ndp, tid, tastep, ts);
3575
3576 if ( ts == COMMITTED )
3577 {
3578 // just if the tuple state is commited,
3579 // we have detected a duplicate
3580
3581 btc.abort();
3582
3583 Chain msg = Chain("Dupliate entry for btree " ) + pOE->getName();
3584 throw Exception(EXLOC, msg);
3585
3586
3587 // return false;
3588 }
3589 }
3590
3591 attrMatch = btc.getNext(pOE->getSchema(), ndp);
3592 }
3593
3594 }
3595 pOE = btreeList.Next();
3596 }
3597 return; // true;
3598 }
3599
checkCheckIntegrity(const ListT<CegoCheckObject> & checkList,const ListT<CegoField> & nfvl)3600 void CegoTableManager::checkCheckIntegrity(const ListT<CegoCheckObject>& checkList, const ListT<CegoField>& nfvl)
3601 {
3602 if ( ! checkList.isEmpty() )
3603 {
3604 // we need to make a copy, since nvfl ist const
3605 ListT<CegoField> fvl = nfvl;
3606
3607 CegoCheckObject* pCheck = checkList.First();
3608 while ( pCheck )
3609 {
3610 pCheck->getPredDesc()->clearAttrCache();
3611
3612 ListT<CegoField>* xfl[2];
3613 xfl[0] = &fvl;
3614 xfl[1] = 0;
3615
3616 if ( CegoQueryHelper::evalPredicate(0, 0, xfl, 0, pCheck->getPredDesc(), 0) == false )
3617 {
3618 Chain msg = Chain("Check constraint ") + pCheck->getName() + Chain(" violated");
3619 throw Exception(EXLOC, msg);
3620 }
3621
3622 pCheck = checkList.Next();
3623 }
3624 }
3625 return; // true;
3626 }
3627
checkNullValue(int tabSetId,const Chain & tableName,const CegoField & f)3628 bool CegoTableManager::checkNullValue(int tabSetId, const Chain& tableName, const CegoField& f)
3629 {
3630 CegoTableCursor *pTC = new CegoTableCursor(this, tabSetId, tableName);
3631 CegoAttrCond attrCond;
3632 CegoFieldValue nullValue;
3633
3634 bool hasNullValue = false;
3635
3636 attrCond.add(CegoAttrComp(f.getTableAlias(), f.getAttrName(), EQUAL, nullValue));
3637 CegoAttrCond::IndexMatch m = pTC->setup(attrCond);
3638 CegoDataPointer dp;
3639 ListT<CegoField> fl;
3640 CegoField *pF;
3641
3642 if ( m == CegoAttrCond::INAPP )
3643 {
3644 fl.Insert(f);
3645 if ( pTC->getFirst(fl, dp) )
3646 {
3647 pF = fl.First();
3648 if ( pF )
3649 {
3650 if ( pF->getValue() == nullValue )
3651 {
3652 hasNullValue = true;
3653 }
3654 else
3655 {
3656 while ( pTC->getNext(fl, dp) && hasNullValue == false)
3657 {
3658 pF = fl.First();
3659 if ( pF )
3660 {
3661 if ( pF->getValue() == nullValue )
3662 {
3663 hasNullValue = true;
3664 }
3665 }
3666 }
3667 }
3668 }
3669 }
3670 }
3671 else
3672 {
3673 fl.Insert(f);
3674 if ( pTC->getFirst(fl, dp) )
3675 {
3676 hasNullValue = true;
3677 }
3678 }
3679 pTC->abort();
3680 delete pTC;
3681
3682 return hasNullValue;
3683 }
3684
checkTypes(const ListT<CegoField> & fl,const ListT<CegoField> & nfl)3685 void CegoTableManager::checkTypes(const ListT<CegoField>& fl, const ListT<CegoField>& nfl)
3686 {
3687 CegoField *pF = fl.First();
3688 while ( pF )
3689 {
3690 CegoField *pD = nfl.Find(*pF);
3691 if ( pD )
3692 {
3693 if ( pD->getType() != pF->getType() )
3694 {
3695 throw Exception(EXLOC, Chain("Mismatched data type <")
3696 + CEGO_TYPE_MAP[(int)(pD->getType())]
3697 + Chain("> for attribute ") + pF->getAttrName()
3698 + Chain(", expected type <")
3699 + CEGO_TYPE_MAP[(int)(pF->getType())]
3700 + Chain(">"));
3701
3702 }
3703 }
3704 pF = fl.Next();
3705 }
3706 }
3707
getIndexSearchValue(const ListT<CegoField> & idxSchema,const ListT<CegoField> & nfvl)3708 const CegoFieldValue& CegoTableManager::getIndexSearchValue(const ListT<CegoField>& idxSchema, const ListT<CegoField>& nfvl)
3709 {
3710 CegoField *pSF = idxSchema.First();
3711
3712 CegoField *pVF = nfvl.First();
3713 while ( pVF )
3714 {
3715 if ( (Chain)pSF->getAttrName() == (Chain)pVF->getAttrName() )
3716 return pVF->getValue();
3717 pVF = nfvl.Next();
3718 }
3719
3720 throw Exception(EXLOC, Chain("No index value found"));
3721 }
3722
deleteDataTable(CegoTableObject & oe,CegoPredDesc * pPred,CegoProcBlock * pBlock,bool isSynced)3723 unsigned long long CegoTableManager::deleteDataTable(CegoTableObject& oe, CegoPredDesc* pPred, CegoProcBlock* pBlock, bool isSynced)
3724 {
3725 ListT<CegoTableObject> idxList;
3726 ListT<CegoBTreeObject> btreeList;
3727 ListT<CegoKeyObject> keyList;
3728 ListT<CegoCheckObject> checkList;
3729 ListT<CegoTriggerObject> triggerList;
3730 ListT<CegoAliasObject> aliasList;
3731 int numInvalid;
3732
3733 getObjectListByTable(oe.getTabSetId(), oe.getTabName(), idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
3734
3735 if ( numInvalid > 0 )
3736 {
3737 throw Exception(EXLOC, Chain("Invalid index detected, must be valid for delete opertions"));
3738 }
3739
3740 return deleteDataTable(oe, idxList, btreeList, keyList, pPred, pBlock, isSynced);
3741 }
3742
deleteDataTable(CegoTableObject & oe,const ListT<CegoTableObject> & idxList,const ListT<CegoBTreeObject> & btreeList,const ListT<CegoKeyObject> & keyList,CegoPredDesc * pPred,CegoProcBlock * pBlock,bool isSynced)3743 unsigned long long CegoTableManager::deleteDataTable(CegoTableObject& oe,
3744 const ListT<CegoTableObject>& idxList,
3745 const ListT<CegoBTreeObject>& btreeList,
3746 const ListT<CegoKeyObject>& keyList,
3747 CegoPredDesc* pPred, CegoProcBlock* pBlock, bool isSynced)
3748 {
3749 unsigned long tid = getTID(oe.getTabSetId());
3750
3751 // prepare log entry first
3752 CegoLogRecord lr;
3753 lr.setObjectInfo(oe.getName(), oe.getType());
3754 lr.setAction(CegoLogRecord::LOGREC_DELETE);
3755 lr.setTID(tid);
3756
3757 if ( tid != 0 )
3758 _tastep[oe.getTabSetId()]++;
3759
3760 if ( tid > 0 )
3761 lr.setTAStep(_tastep[oe.getTabSetId()]);
3762 else
3763 lr.setTAStep(0);
3764
3765 unsigned long long delCount = 0;
3766
3767 if (pPred == 0)
3768 {
3769 CegoTableCursor* pTC = new CegoTableCursor(this, oe.getTabSetId(), oe.getTabName(), true);
3770
3771 try
3772 {
3773 bool moreTuple;
3774
3775 CegoDataPointer dp;
3776 ListT<CegoField> fl = oe.getSchema();
3777
3778 moreTuple = pTC->getFirst(fl, dp);
3779
3780 while (moreTuple && _isAborted == false )
3781 {
3782 ListT<CegoField> nfl = oe.getSchema();
3783 CegoDataPointer ndp;
3784 moreTuple = pTC->getNext(nfl, ndp);
3785
3786 deleteDataTableEntrySynced(oe.getTabSetId(), oe.getTabName(), CegoObject::TABLE, dp, fl, idxList, btreeList, keyList, true, false, isSynced);
3787
3788 delCount++;
3789
3790 if ( moreTuple )
3791 {
3792 dp = ndp;
3793 fl = nfl;
3794 }
3795 }
3796
3797 delete pTC;
3798 }
3799 catch ( Exception e)
3800 {
3801 delete pTC;
3802 throw e;
3803 }
3804 }
3805 else
3806 {
3807 if ( oe.getTabName() != oe.getTabAlias() )
3808 {
3809 // set up the defined alias for attribute evaluation
3810 CegoField *pF = oe.getSchema().First();
3811 while (pF)
3812 {
3813 pF->setTableAlias(oe.getTabAlias());
3814 pF = oe.getSchema().Next();
3815 }
3816 }
3817
3818 ListT<CegoField> fl = oe.getSchema();
3819
3820 // we need to create an additional reference to use the setFieldListArray method
3821 ListT<CegoField>* xfl[3];
3822 xfl[0] = &fl;
3823 if ( pBlock )
3824 xfl[1] = pBlock->getTriggerValueList();
3825 else
3826 xfl[1] = 0;
3827 xfl[2] = 0; // terminate in any case
3828
3829 ListT<CegoSelect*> queryList;
3830 pPred->getSelectQueryList(queryList);
3831 CegoSelect **pSelect = queryList.First();
3832 while ( pSelect )
3833 {
3834 (*pSelect)->setParentJoinBuf(xfl);
3835 pSelect = queryList.Next();
3836 }
3837
3838 pPred->analyzeSelect();
3839
3840 // we have to resolve external references in a second step, since they are handled with lower priority
3841 pSelect = queryList.First();
3842 while ( pSelect )
3843 {
3844 // before evaluating external table references, we have to prepare to resolve native query attributes first
3845 (*pSelect)->prepare();
3846
3847 (*pSelect)->evalExtTableReferences(&oe, fl);
3848 pSelect = queryList.Next();
3849 }
3850
3851 CegoAttrCond ac;
3852 CegoQueryHelper::AttrCondMatch m = CegoQueryHelper::checkAttrCond(ac, pPred, fl, &fl, 1, pBlock);
3853
3854 CegoTableCursor *pTC = new CegoTableCursor(this, oe.getTabSetId(), oe.getTabName(), true);
3855
3856 try
3857 {
3858 CegoAttrCond::IndexMatch idxMatch = CegoAttrCond::INAPP;
3859
3860 if ( m != CegoQueryHelper::INAPP )
3861 idxMatch = pTC->setup(ac);
3862
3863 if ( idxMatch == CegoAttrCond::INAPP )
3864 {
3865 ListT<CegoField> ufl = (ListT<CegoField>)oe.getSchema();
3866
3867 // we need to create an additional reference for evalPredicate method
3868 ListT<CegoField>* xufl[3];
3869 xufl[0] = &ufl;
3870 if ( pBlock )
3871 xufl[1] = pBlock->getTriggerValueList();
3872 else
3873 xufl[1] = 0;
3874 xufl[2] = 0; // terminate in any case
3875
3876 CegoDataPointer dp;
3877 bool moreTuple;
3878 moreTuple = pTC->getFirst(ufl, dp);
3879 while (moreTuple && _isAborted == false)
3880 {
3881 pPred->clearAttrCache();
3882 if ( CegoQueryHelper::evalPredicate(0, 0, xufl, 0, pPred, pBlock))
3883 {
3884 if ( tid == 0 )
3885 {
3886 // before deleting, we first have to skip to next valid tuple
3887 ListT<CegoField> nfl = oe.getSchema();
3888 CegoDataPointer ndp;
3889 moreTuple = pTC->getNext(nfl, ndp);
3890
3891 deleteDataTableEntrySynced(oe.getTabSetId(), oe.getTabName(), CegoObject::TABLE, dp, ufl, idxList, btreeList, keyList, true, false, isSynced);
3892 delCount++;
3893
3894 if ( moreTuple )
3895 {
3896 dp = ndp;
3897 ufl = nfl;
3898 }
3899 }
3900 else
3901 {
3902 deleteDataTableEntrySynced(oe.getTabSetId(), oe.getTabName(), CegoObject::TABLE, dp, ufl, idxList, btreeList, keyList, true, false, isSynced);
3903 delCount++;
3904 moreTuple = pTC->getNext(ufl, dp);
3905 }
3906 }
3907 else
3908 {
3909 moreTuple = pTC->getNext(ufl, dp);
3910 }
3911 }
3912 }
3913 else
3914 {
3915 ListT<CegoField> ufl = (ListT<CegoField>)oe.getSchema();
3916
3917 // we need to create an additional reference for evalPredicate method
3918 ListT<CegoField>* xufl[2];
3919 xufl[0] = &ufl;
3920 xufl[1] = 0;
3921
3922 bool moreTuple;
3923
3924 CegoDataPointer dp;
3925
3926 moreTuple = pTC->getFirst(ufl, dp);
3927
3928 while (moreTuple && _isAborted == false)
3929 {
3930 pPred->clearAttrCache();
3931
3932 if ( CegoQueryHelper::evalPredicate(0, 0, xufl, 0, pPred, pBlock))
3933 {
3934 if ( tid == 0 )
3935 {
3936 /* if we are not inside a transaction, the index or btree object for the delete condition
3937 was modified and we have to reset the cursor */
3938
3939 pTC->abort();
3940
3941 // cout << "Deleting data table with index cursor ..." << dp << endl;
3942 deleteDataTableEntrySynced(oe.getTabSetId(), oe.getTabName(), CegoObject::TABLE, dp, ufl, idxList, btreeList, keyList, true, false, isSynced);
3943 delCount++;
3944
3945 moreTuple = pTC->getFirst(ufl, dp);
3946 }
3947 else
3948 {
3949 deleteDataTableEntrySynced(oe.getTabSetId(), oe.getTabName(), CegoObject::TABLE, dp, ufl, idxList, btreeList, keyList, true, false, isSynced);
3950 delCount++;
3951 moreTuple = pTC->getNext(ufl, dp);
3952 }
3953 }
3954 else
3955 {
3956 moreTuple = pTC->getNext(ufl, dp);
3957 }
3958 }
3959 }
3960 }
3961 catch ( Exception e )
3962 {
3963 delete pTC;
3964 throw e;
3965 }
3966
3967 delete pTC;
3968
3969 if ( _isAborted )
3970 {
3971 throw Exception(EXLOC, Chain("Delete aborted by user"));
3972 }
3973
3974
3975 }
3976
3977 #ifdef CGDEBUG
3978 _pDBMng->log(_modId, Logger::DEBUG, Chain("Delete finished, delCount = ") + Chain(delCount));
3979 #endif
3980
3981 // commit delete record
3982
3983 char *pLogBuf = 0;
3984 int logBuflen = 0;
3985
3986 CegoQueryHelper::encodeDelRec(oe.getTabAlias(), pPred, pBlock, pLogBuf, logBuflen);
3987
3988 /*
3989 for the delete operation, we have to get the LSN AFTER successful operation
3990 otherwise, it may occur, that a checkpoint happens during the delete with a higher LSN
3991 and so the operation is lost
3992 */
3993
3994 lr.setLSN(_pDBMng->nextLSN(oe.getTabSetId()));
3995 lr.setData(pLogBuf);
3996 lr.setDataLen(logBuflen);
3997
3998 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle);
3999
4000 if ( logBuflen > 0 )
4001 free ( pLogBuf );
4002
4003 return delCount;
4004 }
4005
deleteDataTableEntrySynced(int tabSetId,const Chain & tableName,CegoObject::ObjectType type,const CegoDataPointer & dp,const ListT<CegoField> & fvl,const ListT<CegoTableObject> & idxList,const ListT<CegoBTreeObject> & btreeList,const ListT<CegoKeyObject> & keyList,bool doCheckKey,bool doIgnoreIndexError,bool isSynced)4006 void CegoTableManager::deleteDataTableEntrySynced(int tabSetId, const Chain& tableName, CegoObject::ObjectType type,
4007 const CegoDataPointer& dp, const ListT<CegoField>& fvl,
4008 const ListT<CegoTableObject>& idxList,
4009 const ListT<CegoBTreeObject>& btreeList,
4010 const ListT<CegoKeyObject>& keyList,
4011 bool doCheckKey, bool doIgnoreIndexError, bool isSynced)
4012 {
4013
4014 unsigned long long recLock = 0;
4015
4016 try
4017 {
4018 recLock = _pLockHandle->lockRecord(dp, CegoLockHandler::WRITE);
4019
4020 deleteDataTableEntry(tabSetId, tableName, type, dp, fvl, idxList, btreeList, keyList, doCheckKey, doIgnoreIndexError);
4021
4022 _pLockHandle->unlockRecord(recLock);
4023
4024 }
4025 catch ( Exception e )
4026 {
4027 if ( recLock )
4028 _pLockHandle->unlockRecord(recLock);
4029 throw e;
4030 }
4031 }
4032
deleteDataTableEntry(int tabSetId,const Chain & tableName,CegoObject::ObjectType type,const CegoDataPointer & dp,const ListT<CegoField> & fvl,const ListT<CegoTableObject> & idxList,const ListT<CegoBTreeObject> & btreeList,const ListT<CegoKeyObject> & keyList,bool doCheckKey,bool doIgnoreIndexError)4033 bool CegoTableManager::deleteDataTableEntry(int tabSetId, const Chain& tableName,
4034 CegoObject::ObjectType type,
4035 const CegoDataPointer& dp,
4036 const ListT<CegoField>& fvl,
4037 const ListT<CegoTableObject>& idxList,
4038 const ListT<CegoBTreeObject>& btreeList,
4039 const ListT<CegoKeyObject>& keyList,
4040 bool doCheckKey, bool doIgnoreIndexError)
4041 {
4042 if ( doCheckKey )
4043 if ( keyReferenceExists(tabSetId, tableName, fvl, keyList) )
4044 throw Exception(EXLOC, Chain("Constraint violation on foreign key"));
4045
4046 // we just delete entries on committed tuples
4047 if ( getTID(tabSetId) == 0 )
4048 {
4049 // delete index entries
4050
4051 CegoTableObject* pOE = idxList.First();
4052 while (pOE)
4053 {
4054 if ( pOE->isValid()
4055 && ( pOE->getType() == CegoObject::AVLTREE
4056 || pOE->getType() == CegoObject::UAVLTREE
4057 || pOE->getType() == CegoObject::PAVLTREE ) )
4058 {
4059 char p[TABMNG_MAXINDEXVALUE];
4060 int len = TABMNG_MAXINDEXVALUE;
4061 int idxLen;
4062
4063 extractIndexValue(fvl, pOE->getSchema(), p, len, idxLen);
4064
4065 try
4066 {
4067 CegoAVLIndexManager idxMng(this);
4068 idxMng.deleteIndexTable(tabSetId, tableName, type, pOE->getName(), pOE->getType(), pOE->getSchema(), dp, p, idxLen, true);
4069 }
4070 catch ( Exception e )
4071 {
4072 if ( doIgnoreIndexError == false )
4073 throw e;
4074 }
4075 }
4076 pOE = idxList.Next();
4077 }
4078
4079 // delete btree entries
4080
4081 CegoBTreeObject* pBTO = btreeList.First();
4082 while (pBTO)
4083 {
4084 if (pBTO->getType() == CegoObject::BTREE
4085 || pBTO->getType() == CegoObject::UBTREE
4086 || pBTO->getType() == CegoObject::PBTREE )
4087
4088 {
4089 CegoBTreeValue btv;
4090 btv.valueFromSchema(fvl, pBTO->getSchema());
4091
4092 try
4093 {
4094 CegoBTreeManager btreeMng(this, pBTO);
4095 btreeMng.deleteBTree(btv, dp, getTID(tabSetId));
4096 }
4097 catch ( Exception e )
4098 {
4099 if ( doIgnoreIndexError == false )
4100 throw e;
4101 }
4102 }
4103 pBTO = btreeList.Next();
4104 }
4105
4106 // delete blob and clob entries
4107 CegoField *pF = fvl.First();
4108
4109 while ( pF)
4110 {
4111 if ( pF->getValue().getType() == BLOB_TYPE && pF->getValue().getValue() != 0 )
4112 {
4113 PageIdType pageId;
4114 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
4115
4116 decreaseBlobRef(tabSetId, pageId);
4117 }
4118
4119 if ( pF->getValue().getType() == CLOB_TYPE && pF->getValue().getValue() != 0 )
4120 {
4121 PageIdType pageId;
4122 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
4123
4124 decreaseClobRef(tabSetId, pageId);
4125 }
4126
4127 pF = fvl.Next();
4128 }
4129
4130 int numTries=0;
4131 bool isDeleted=false;
4132 while ( isDeleted == false )
4133 {
4134 try
4135 {
4136 #ifdef CGDEBUG
4137 _pDBMng->log(_modId, Logger::DEBUG, Chain("Deleting tuple"));
4138 #endif
4139 deleteData(type, tabSetId, dp);
4140 isDeleted=true;
4141 }
4142 catch ( Exception e )
4143 {
4144 Chain msg;
4145 e.pop(msg);
4146 _pDBMng->log(_modId, Logger::NOTICE, Chain("Retry delete after : ") + msg);
4147
4148 if ( numTries == LCKMNG_NUMLOCKTRIES )
4149 {
4150 throw Exception(EXLOC, msg);
4151 }
4152 numTries++;
4153 }
4154 }
4155
4156 return true;
4157 }
4158 else // getTID(tabSetId) != 0
4159 {
4160 unsigned long long tid;
4161 unsigned long long tastep;
4162 CegoTupleState ts;
4163
4164 bool tupleTouched = false;
4165
4166 getTupleInfo(tabSetId, dp, tid, tastep, ts);
4167
4168 // is tuple untouched or already modified by the same transaction
4169 if ( getTID(tabSetId) == tid || tid == 0 )
4170 {
4171 _pTM->newRBEntry(tabSetId, getTID(tabSetId), dp.getPageId(), dp.getOffset(), tableName);
4172
4173 if ( ts == INSERTED )
4174 setTupleInfo(tabSetId, dp, getTID(tabSetId), getTAStep(tabSetId), OBSOLETE);
4175 else
4176 setTupleInfo(tabSetId, dp, getTID(tabSetId), getTAStep(tabSetId), DELETED);
4177
4178 tupleTouched = true;
4179 }
4180
4181 return tupleTouched;
4182 }
4183 }
4184
truncateTable(int tabSetId,const Chain & tableName)4185 void CegoTableManager::truncateTable(int tabSetId, const Chain& tableName)
4186 {
4187
4188 #ifdef CGDEBUG
4189 _pDBMng->log(_modId, Logger::DEBUG, Chain("Start of call truncateTable(") + Chain(tabSetId)
4190 + Chain(",") + tableName + Chain(")"));
4191
4192 #endif
4193
4194 if ( getTID(tabSetId) > 0 )
4195 {
4196 Chain msg = Chain("Truncate in a transaction not allowed");
4197 throw Exception(EXLOC, msg);
4198 }
4199
4200 if ( _pTM->hasOpenTransaction(tabSetId, tableName) )
4201 {
4202 Chain msg = Chain("Table ") + tableName + Chain(" still has open transactions");
4203 throw Exception(EXLOC, msg);
4204 }
4205
4206 ListT<CegoTableObject> idxList;
4207 ListT<CegoBTreeObject> btreeList;
4208 ListT<CegoKeyObject> keyList;
4209 ListT<CegoCheckObject> checkList;
4210 ListT<CegoTriggerObject> triggerList;
4211 ListT<CegoAliasObject> aliasList;
4212
4213 int numInvalid;
4214
4215 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
4216
4217 CegoKeyObject *pKey = keyList.First();
4218 while ( pKey )
4219 {
4220 if ( pKey->getRefTable() == tableName )
4221 {
4222
4223 CegoTableCursor* pTC = new CegoTableCursor(this, tabSetId, pKey->getTabName(), true);
4224
4225 try
4226 {
4227 bool moreTuple;
4228 CegoDataPointer dp;
4229 ListT<CegoField> fl;
4230 moreTuple = pTC->getFirst(fl, dp);
4231
4232 if (moreTuple)
4233 {
4234 throw Exception(EXLOC, Chain("Cannnot truncate key reference table with existing references"));
4235 }
4236
4237 delete pTC;
4238 }
4239 catch ( Exception e )
4240 {
4241 delete pTC;
4242 throw e;
4243 }
4244 }
4245 pKey = keyList.Next();
4246 }
4247
4248 CegoTableObject *pIO = idxList.First();
4249 while ( pIO )
4250 {
4251 #ifdef CGDEBUG
4252 _pDBMng->log(_modId, Logger::DEBUG, Chain("Truncating index ") + pIO->getName() + Chain(" ..."));
4253 #endif
4254
4255 truncateObject(tabSetId, pIO->getName(), pIO->getType());
4256 pIO = idxList.Next();
4257 }
4258
4259 CegoBTreeObject *pBTO = btreeList.First();
4260 while ( pBTO )
4261 {
4262 #ifdef CGDEBUG
4263 _pDBMng->log(_modId, Logger::DEBUG, Chain("Truncating btree ") + pBTO->getName() + Chain(" ..."));
4264 #endif
4265
4266 truncateObject(tabSetId, pBTO->getName(), pBTO->getType());
4267
4268 pBTO = btreeList.Next();
4269 }
4270
4271 // check for blobs and remove
4272
4273 CegoTableObject oe;
4274 getObject(tabSetId, tableName, CegoObject::TABLE, oe);
4275 ListT<CegoField> fl = oe.getSchema();
4276
4277 bool hasXlobField = false;
4278 CegoField *pF = fl.First();
4279 while ( pF )
4280 {
4281 if ( pF->getType() == BLOB_TYPE || pF->getType() == CLOB_TYPE )
4282 hasXlobField = true;
4283 pF = fl.Next();
4284 }
4285
4286 if ( hasXlobField )
4287 {
4288 CegoTableCursor* pTC = new CegoTableCursor(this, tabSetId, tableName, true);
4289
4290 try
4291 {
4292 bool moreTuple;
4293 CegoDataPointer dp;
4294 moreTuple = pTC->getFirst(fl, dp);
4295
4296 while (moreTuple)
4297 {
4298 CegoField *pF = fl.First();
4299 while ( pF )
4300 {
4301 if ( pF->getType() == BLOB_TYPE && pF->getValue().getValue() != 0 )
4302 {
4303 PageIdType pageId;
4304 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
4305
4306 #ifdef CGDEBUG
4307 _pDBMng->log(_modId, Logger::DEBUG, Chain("Releasing blob [") + Chain(pageId) + Chain("]"));
4308 #endif
4309
4310 decreaseBlobRef(tabSetId, pageId);
4311 }
4312
4313 if ( pF->getType() == CLOB_TYPE && pF->getValue().getValue() != 0 )
4314 {
4315 PageIdType pageId;
4316 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
4317
4318 #ifdef CGDEBUG
4319 _pDBMng->log(_modId, Logger::DEBUG, Chain("Releasing clob [") + Chain(pageId) + Chain("]"));
4320 #endif
4321
4322 decreaseClobRef(tabSetId, pageId);
4323 }
4324
4325 pF = fl.Next();
4326 }
4327 moreTuple = pTC->getNext(fl, dp);
4328 }
4329 delete pTC;
4330 }
4331 catch ( Exception e )
4332 {
4333 delete pTC;
4334 throw e;
4335 }
4336 }
4337
4338 #ifdef CGDEBUG
4339 _pDBMng->log(_modId, Logger::DEBUG, Chain("Truncating table ") + tableName + Chain(" ..."));
4340 #endif
4341
4342 CegoLogRecord lr;
4343 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4344
4345 truncateObject(tabSetId, tableName, CegoObject::TABLE);
4346
4347 // create log entry
4348 lr.setObjectInfo(tableName, CegoObject::TABLE);
4349 lr.setAction(CegoLogRecord::LOGREC_TRUNCATE);
4350 lr.setData(0);
4351 lr.setDataLen(0);
4352
4353 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4354
4355 }
4356
dropObjectSynced(int tabSetId,const Chain & objName,CegoObject::ObjectType type)4357 void CegoTableManager::dropObjectSynced(int tabSetId, const Chain& objName, CegoObject::ObjectType type)
4358 {
4359 Chain useName;
4360 CegoObject::ObjectType useType;
4361
4362 if ( type == CegoObject::AVLTREE
4363 || type == CegoObject::UAVLTREE
4364 || type == CegoObject::PAVLTREE )
4365 {
4366 CegoTableObject io;
4367 getObject(tabSetId, objName, type, io);
4368 useName = io.getTabName();
4369 useType=CegoObject::TABLE;
4370
4371
4372 // We still have to check, if any foreign key reference exists
4373 // If so, we do not allow to remove
4374 if ( io.getType() == CegoObject::PAVLTREE )
4375 {
4376 ListT<CegoTableObject> checkIdxList;
4377 ListT<CegoBTreeObject> checkBTreeList;
4378 ListT<CegoKeyObject> checkKeyList;
4379 ListT<CegoCheckObject> checkList;
4380 ListT<CegoTriggerObject> triggerList;
4381 ListT<CegoAliasObject> aliasList;
4382 int numInvalid;
4383
4384 getObjectListByTable(tabSetId, useName, checkIdxList, checkBTreeList, checkKeyList, checkList, triggerList, aliasList, numInvalid);
4385 CegoKeyObject *pKey = checkKeyList.First();
4386 while ( pKey )
4387 {
4388 if ( pKey->getRefTable() == useName )
4389 {
4390 throw Exception(EXLOC, Chain("Cannnot drop primary avltree with existing key reference"));
4391 }
4392 pKey = checkKeyList.Next();
4393 }
4394 }
4395 }
4396 else if ( type == CegoObject::BTREE
4397 || type == CegoObject::UBTREE
4398 || type == CegoObject::PBTREE )
4399 {
4400 CegoBTreeObject bto;
4401 getObject(tabSetId, objName, type, bto);
4402 useName = bto.getTabName();
4403 useType=CegoObject::TABLE;
4404
4405 // We still have to check, if any foreign key reference exists
4406 // If so, we do not allow to remove
4407 if ( bto.getType() == CegoObject::PBTREE )
4408 {
4409 ListT<CegoTableObject> checkIdxList;
4410 ListT<CegoBTreeObject> checkBTreeList;
4411 ListT<CegoKeyObject> checkKeyList;
4412 ListT<CegoCheckObject> checkList;
4413 ListT<CegoTriggerObject> triggerList;
4414 ListT<CegoAliasObject> aliasList;
4415 int numInvalid;
4416
4417 getObjectListByTable(tabSetId, useName, checkIdxList, checkBTreeList, checkKeyList, checkList, triggerList, aliasList, numInvalid);
4418 CegoKeyObject *pKey = checkKeyList.First();
4419 while ( pKey )
4420 {
4421 if ( pKey->getRefTable() == useName )
4422 {
4423 throw Exception(EXLOC, Chain("Cannnot drop primary btree with existing key reference"));
4424 }
4425 pKey = checkKeyList.Next();
4426 }
4427 }
4428 }
4429 else if ( type == CegoObject::TABLE )
4430 {
4431 useName = objName;
4432 useType=type;
4433 }
4434 else if ( type == CegoObject::PROCEDURE
4435 || type == CegoObject::VIEW )
4436 {
4437 useName = objName;
4438 useType=type;
4439 }
4440 else if ( type == CegoObject::FKEY )
4441 {
4442 CegoKeyObject ko;
4443 getObject(tabSetId, objName, type, ko);
4444 useName = ko.getTabName();
4445 useType=CegoObject::TABLE;
4446 }
4447 else if ( type == CegoObject::CHECK )
4448 {
4449 CegoCheckObject co;
4450 getObject(tabSetId, objName, type, co);
4451 useName = co.getTabName();
4452 useType=CegoObject::TABLE;
4453 }
4454 else if ( type == CegoObject::TRIGGER )
4455 {
4456 CegoTriggerObject to;
4457 getObject(tabSetId, objName, type, to);
4458 useName = to.getTabName();
4459 useType=CegoObject::TABLE;
4460 }
4461 else if ( type == CegoObject::ALIAS )
4462 {
4463 // CegoAliasObject ao;
4464 // getObject(tabSetId, objName, type, ao);
4465 // useName = ao.getTabName();
4466 // useType=CegoObject::TABLE;
4467
4468 // for alias objects, we allow drop without synching with corresponding table
4469 useName = objName;
4470 useType=type;
4471 }
4472
4473 else
4474 {
4475 throw Exception(EXLOC, Chain("Invalid object type"));
4476 }
4477
4478 _pDBMng->useObject(tabSetId, useName, useType, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
4479
4480 try
4481 {
4482 switch ( type )
4483 {
4484 case CegoObject::TABLE:
4485 dropTable(tabSetId, objName);
4486 break;
4487 case CegoObject::AVLTREE:
4488 case CegoObject::UAVLTREE:
4489 case CegoObject::PAVLTREE:
4490 dropIndex(tabSetId, objName);
4491 break;
4492 case CegoObject::BTREE:
4493 case CegoObject::UBTREE:
4494 case CegoObject::PBTREE:
4495 dropBTree(tabSetId, objName);
4496 break;
4497 case CegoObject::VIEW:
4498 dropView(tabSetId, objName);
4499 break;
4500 case CegoObject::PROCEDURE:
4501 dropProcedure(tabSetId, objName);
4502 break;
4503 case CegoObject::FKEY:
4504 dropFKey(tabSetId, objName);
4505 break;
4506 case CegoObject::CHECK:
4507 dropCheck(tabSetId, objName);
4508 break;
4509 case CegoObject::TRIGGER:
4510 dropTrigger(tabSetId, objName);
4511 break;
4512 case CegoObject::ALIAS:
4513 dropAlias(tabSetId, objName);
4514 break;
4515 case CegoObject::SYSTEM:
4516 case CegoObject::RBSEG:
4517 case CegoObject::JOIN:
4518 case CegoObject::UNDEFINED:
4519 throw Exception(EXLOC, "Invalid object type for drop");
4520 }
4521 }
4522 catch ( Exception e )
4523 {
4524
4525 _pDBMng->unuseObject(tabSetId, useName, useType);
4526 throw e;
4527 }
4528
4529
4530 // _pDBMng->printObjectList();
4531
4532 // cout << "Removing object " << objName << " of type " << type << endl;
4533
4534 _pDBMng->removeObject(tabSetId, objName, type);
4535
4536 // _pDBMng->printObjectList();
4537
4538 if ( useName != objName )
4539 _pDBMng->unuseObject(tabSetId, useName, useType);
4540 }
4541
dropTable(int tabSetId,const Chain & tableName)4542 void CegoTableManager::dropTable(int tabSetId,
4543 const Chain& tableName)
4544 {
4545 #ifdef CGDEBUG
4546 _pDBMng->log(_modId, Logger::DEBUG, Chain("Start of call dropTable(") + Chain(tabSetId)
4547 + Chain(",") + tableName + Chain(")"));
4548
4549 #endif
4550
4551 if ( getTID(tabSetId) > 0 )
4552 {
4553 Chain msg = Chain("Drop in a transaction not allowed");
4554 throw Exception(EXLOC, msg);
4555 }
4556
4557 if ( _pTM->hasOpenTransaction(tabSetId, tableName) )
4558 {
4559 Chain msg = Chain("Table ") + tableName + Chain(" still has open transactions");
4560 throw Exception(EXLOC, msg);
4561 }
4562
4563 ListT<CegoTableObject> idxList;
4564 ListT<CegoBTreeObject> btreeList;
4565 ListT<CegoKeyObject> keyList;
4566 ListT<CegoCheckObject> checkList;
4567 ListT<CegoTriggerObject> triggerList;
4568 ListT<CegoAliasObject> aliasList;
4569 int numInvalid;
4570
4571 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
4572
4573 CegoKeyObject *pKey = keyList.First();
4574 while ( pKey )
4575 {
4576 if ( pKey->getRefTable() == tableName && pKey->getTabName() != tableName )
4577 {
4578 throw Exception(EXLOC, Chain("Cannnot drop table with existing foreign key reference"));
4579 }
4580 pKey = keyList.Next();
4581 }
4582
4583 CegoTableObject *pIO = idxList.First();
4584 while ( pIO )
4585 {
4586 if ( pIO->getType() == CegoObject::AVLTREE
4587 || pIO->getType() == CegoObject::UAVLTREE
4588 || pIO->getType() == CegoObject::PAVLTREE )
4589 {
4590 #ifdef CGDEBUG
4591 _pDBMng->log(_modId, Logger::DEBUG, Chain("Dropping index ") + pIO->getName() + Chain(" ..."));
4592 #endif
4593
4594 removeObject(tabSetId, pIO->getName(), pIO->getType());
4595 _pDBMng->removeObject(tabSetId, pIO->getName(), pIO->getType());
4596
4597
4598 }
4599 pIO = idxList.Next();
4600 }
4601
4602 CegoBTreeObject *pBTO = btreeList.First();
4603 while ( pBTO )
4604 {
4605 if ( pBTO->getType() == CegoObject::BTREE
4606 || pBTO->getType() == CegoObject::UBTREE
4607 || pBTO->getType() == CegoObject::PBTREE )
4608 {
4609 #ifdef CGDEBUG
4610 _pDBMng->log(_modId, Logger::DEBUG, Chain("Dropping btree ") + pBTO->getName() + Chain(" ..."));
4611 #endif
4612
4613 removeObject(tabSetId, pBTO->getName(), pBTO->getType());
4614 _pDBMng->removeObject(tabSetId, pBTO->getName(), pBTO->getType());
4615
4616 }
4617 pBTO = btreeList.Next();
4618 }
4619
4620 CegoKeyObject *pKO = keyList.First();
4621 while ( pKO )
4622 {
4623 #ifdef CGDEBUG
4624 _pDBMng->log(_modId, Logger::DEBUG, Chain("Dropping key ") + pKO->getName() + Chain(" ..."));
4625 #endif
4626 removeObject(tabSetId, pKO->getName(), pKO->getType());
4627 _pDBMng->removeObject(tabSetId, pKO->getName(), pKO->getType());
4628
4629
4630 pKO = keyList.Next();
4631 }
4632
4633 CegoCheckObject *pCO = checkList.First();
4634 while ( pCO )
4635 {
4636 #ifdef CGDEBUG
4637 _pDBMng->log(_modId, Logger::DEBUG, Chain("Dropping check ") + pCO->getName() + Chain(" ..."));
4638 #endif
4639
4640 removeObject(tabSetId, pCO->getName(), pCO->getType());
4641 _pDBMng->removeObject(tabSetId, pCO->getName(), pCO->getType());
4642
4643 pCO = checkList.Next();
4644 }
4645
4646 CegoTriggerObject *pTO = triggerList.First();
4647 while ( pTO )
4648 {
4649 #ifdef CGDEBUG
4650 _pDBMng->log(_modId, Logger::DEBUG, Chain("Dropping trigger ") + pTO->getName() + Chain(" ..."));
4651 #endif
4652
4653 removeObject(tabSetId, pTO->getName(), pTO->getType());
4654 _pDBMng->removeObject(tabSetId, pTO->getName(), pTO->getType());
4655
4656 pTO = triggerList.Next();
4657 }
4658
4659 CegoAliasObject *pAO = aliasList.First();
4660 while ( pAO )
4661 {
4662 #ifdef CGDEBUG
4663 _pDBMng->log(_modId, Logger::DEBUG, Chain("Dropping alias ") + pAO->getName() + Chain(" ..."));
4664 #endif
4665
4666 removeObject(tabSetId, pAO->getName(), pAO->getType());
4667 _pDBMng->removeObject(tabSetId, pAO->getName(), pAO->getType());
4668
4669 pAO = aliasList.Next();
4670 }
4671
4672 // check for blobs and remove
4673
4674 CegoTableObject oe;
4675 getObject(tabSetId, tableName, CegoObject::TABLE, oe);
4676 ListT<CegoField> fl = oe.getSchema();
4677
4678 bool hasXlobField = false;
4679 CegoField *pF = fl.First();
4680 while ( pF )
4681 {
4682 if ( pF->getType() == BLOB_TYPE || pF->getType() == CLOB_TYPE )
4683 hasXlobField = true;
4684 pF = fl.Next();
4685 }
4686
4687 if ( hasXlobField )
4688 {
4689 CegoTableCursor* pTC = new CegoTableCursor(this, tabSetId, tableName, true);
4690
4691 try
4692 {
4693 bool moreTuple;
4694 CegoDataPointer dp;
4695 moreTuple = pTC->getFirst(fl, dp);
4696
4697 while (moreTuple)
4698 {
4699 CegoField *pF = fl.First();
4700 while ( pF )
4701 {
4702 if ( pF->getType() == BLOB_TYPE && pF->getValue().getValue() != 0 )
4703 {
4704 PageIdType pageId;
4705 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
4706
4707 #ifdef CGDEBUG
4708 _pDBMng->log(_modId, Logger::DEBUG, Chain("Releasing blob [") + Chain(pageId) + Chain("]"));
4709 #endif
4710
4711 decreaseBlobRef(tabSetId, pageId);
4712 }
4713
4714 if ( pF->getType() == CLOB_TYPE && pF->getValue().getValue() != 0 )
4715 {
4716 PageIdType pageId;
4717 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
4718
4719 #ifdef CGDEBUG
4720 _pDBMng->log(_modId, Logger::DEBUG, Chain("Releasing clob [") + Chain(pageId) + Chain("]"));
4721 #endif
4722
4723 decreaseClobRef(tabSetId, pageId);
4724 }
4725
4726 pF = fl.Next();
4727 }
4728 moreTuple = pTC->getNext(fl, dp);
4729 }
4730 delete pTC;
4731 }
4732 catch ( Exception e )
4733 {
4734 delete pTC;
4735 throw e;
4736 }
4737 }
4738
4739 #ifdef CGDEBUG
4740 _pDBMng->log(_modId, Logger::DEBUG, Chain("Dropping table ") + tableName + Chain(" ..."));
4741 #endif
4742
4743 CegoLogRecord lr;
4744 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4745
4746 removeObject(tabSetId, tableName, CegoObject::TABLE);
4747
4748 // create log entry
4749 lr.setObjectInfo(tableName, CegoObject::TABLE);
4750 lr.setAction(CegoLogRecord::LOGREC_DROP);
4751 lr.setData(0);
4752 lr.setDataLen(0);
4753 // lr.setTID(0);
4754
4755 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4756
4757 }
4758
dropIndex(int tabSetId,const Chain & idxName)4759 void CegoTableManager::dropIndex(int tabSetId, const Chain& idxName)
4760 {
4761 if ( getTID(tabSetId) > 0 )
4762 {
4763 Chain msg = Chain("Drop in a transaction not allowed");
4764 throw Exception(EXLOC, msg);
4765 }
4766
4767 CegoObject::ObjectType idxType = CegoObject::AVLTREE;
4768
4769 if ( ! objectExists(tabSetId, idxName, idxType ) )
4770 {
4771 Chain msg = "Unknown index " + idxName;
4772 throw Exception(EXLOC, msg);
4773 }
4774
4775 CegoLogRecord lr;
4776 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4777
4778 removeObject(tabSetId, idxName, idxType);
4779
4780 // create log entry
4781 lr.setObjectInfo(idxName, idxType);
4782 lr.setAction(CegoLogRecord::LOGREC_DROP);
4783 lr.setData(0);
4784 lr.setDataLen(0);
4785 // lr.setTID(0);
4786
4787 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4788 }
4789
dropBTree(int tabSetId,const Chain & btreeName)4790 void CegoTableManager::dropBTree(int tabSetId, const Chain& btreeName)
4791 {
4792 if ( getTID(tabSetId) > 0 )
4793 {
4794 Chain msg = Chain("Drop in a transaction not allowed");
4795 throw Exception(EXLOC, msg);
4796 }
4797
4798 CegoObject::ObjectType btType = CegoObject::BTREE;
4799
4800 if ( ! objectExists(tabSetId, btreeName, btType ) )
4801 {
4802 Chain msg = "Unknown btree " + btreeName;
4803 throw Exception(EXLOC, msg);
4804 }
4805
4806 CegoLogRecord lr;
4807 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4808
4809 removeObject(tabSetId, btreeName, btType);
4810
4811 // create log entry
4812 lr.setObjectInfo(btreeName, btType);
4813 lr.setAction(CegoLogRecord::LOGREC_DROP);
4814 lr.setData(0);
4815 lr.setDataLen(0);
4816 // lr.setTID(0);
4817
4818 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4819
4820 }
4821
dropView(int tabSetId,const Chain & viewName)4822 void CegoTableManager::dropView(int tabSetId, const Chain& viewName)
4823 {
4824 if ( getTID(tabSetId) > 0 )
4825 {
4826 Chain msg = Chain("drop in a transaction not allowed");
4827 throw Exception(EXLOC, msg);
4828 }
4829
4830 CegoLogRecord lr;
4831 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4832
4833 removeObject(tabSetId, viewName, CegoObject::VIEW);
4834
4835 // create log entry
4836 lr.setObjectInfo(viewName, CegoObject::VIEW);
4837 lr.setAction(CegoLogRecord::LOGREC_DROP);
4838 lr.setData(0);
4839 lr.setDataLen(0);
4840 // lr.setTID(0);
4841
4842 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4843 }
4844
dropProcedure(int tabSetId,const Chain & procName)4845 void CegoTableManager::dropProcedure(int tabSetId, const Chain& procName)
4846 {
4847 if ( getTID(tabSetId) > 0 )
4848 {
4849 Chain msg = Chain("drop in a transaction not allowed");
4850 throw Exception(EXLOC, msg);
4851 }
4852
4853 CegoLogRecord lr;
4854 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4855
4856 removeObject(tabSetId, procName, CegoObject::PROCEDURE);
4857
4858 // create log entry
4859 lr.setObjectInfo(procName, CegoObject::PROCEDURE);
4860 lr.setAction(CegoLogRecord::LOGREC_DROP);
4861 lr.setData(0);
4862 lr.setDataLen(0);
4863 // lr.setTID(0);
4864 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4865 }
4866
dropFKey(int tabSetId,const Chain & fkey)4867 void CegoTableManager::dropFKey(int tabSetId, const Chain& fkey)
4868 {
4869 if ( getTID(tabSetId) > 0 )
4870 {
4871 Chain msg = Chain("drop in a transaction not allowed");
4872 throw Exception(EXLOC, msg);
4873 }
4874
4875 CegoLogRecord lr;
4876 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4877
4878 removeObject(tabSetId, fkey, CegoObject::FKEY);
4879
4880 // create log entry
4881 lr.setObjectInfo(fkey, CegoObject::FKEY);
4882 lr.setAction(CegoLogRecord::LOGREC_DROP);
4883 lr.setData(0);
4884 lr.setDataLen(0);
4885 // lr.setTID(0);
4886 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4887 }
4888
dropCheck(int tabSetId,const Chain & check)4889 void CegoTableManager::dropCheck(int tabSetId, const Chain& check)
4890 {
4891 if ( getTID(tabSetId) > 0 )
4892 {
4893 Chain msg = Chain("drop in a transaction not allowed");
4894 throw Exception(EXLOC, msg);
4895 }
4896
4897 CegoLogRecord lr;
4898 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4899
4900 removeObject(tabSetId, check, CegoObject::CHECK);
4901
4902 // create log entry
4903 lr.setObjectInfo(check, CegoObject::CHECK);
4904 lr.setAction(CegoLogRecord::LOGREC_DROP);
4905 lr.setData(0);
4906 lr.setDataLen(0);
4907 // lr.setTID(0);
4908 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4909 }
4910
dropTrigger(int tabSetId,const Chain & trigger)4911 void CegoTableManager::dropTrigger(int tabSetId, const Chain& trigger)
4912 {
4913 if ( getTID(tabSetId) > 0 )
4914 {
4915 Chain msg = Chain("drop in a transaction not allowed");
4916 throw Exception(EXLOC, msg);
4917 }
4918
4919 CegoLogRecord lr;
4920 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4921
4922 removeObject(tabSetId, trigger, CegoObject::TRIGGER);
4923
4924 // create log entry
4925 lr.setObjectInfo(trigger, CegoObject::TRIGGER);
4926 lr.setAction(CegoLogRecord::LOGREC_DROP);
4927 lr.setData(0);
4928 lr.setDataLen(0);
4929 // lr.setTID(0);
4930 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4931 }
4932
dropAlias(int tabSetId,const Chain & aliasName)4933 void CegoTableManager::dropAlias(int tabSetId, const Chain& aliasName)
4934 {
4935 if ( getTID(tabSetId) > 0 )
4936 {
4937 Chain msg = Chain("drop in a transaction not allowed");
4938 throw Exception(EXLOC, msg);
4939 }
4940
4941 CegoLogRecord lr;
4942 lr.setLSN(_pDBMng->nextLSN(tabSetId));
4943
4944 removeObject(tabSetId, aliasName, CegoObject::ALIAS);
4945
4946 // create log entry
4947 lr.setObjectInfo(aliasName, CegoObject::ALIAS);
4948 lr.setAction(CegoLogRecord::LOGREC_DROP);
4949 lr.setData(0);
4950 lr.setDataLen(0);
4951 // lr.setTID(0);
4952 _pDBMng->logIt(tabSetId, lr, _pLockHandle);
4953 }
4954
4955
correctTableSet(int tabSetId,bool doSync)4956 void CegoTableManager::correctTableSet(int tabSetId, bool doSync)
4957 {
4958 ListT<Chain> tabList;
4959 getObjectList(tabSetId, CegoObject::TABLE, tabList);
4960
4961 Chain *pTableName = tabList.First();
4962 while ( pTableName )
4963 {
4964 correctIndexForTable(tabSetId, *pTableName, doSync, false);
4965
4966 pTableName = tabList.Next();
4967 }
4968 }
4969
correctIndexForTable(int tabSetId,const Chain & tableName,bool doSync,bool doForce)4970 void CegoTableManager::correctIndexForTable(int tabSetId, const Chain& tableName, bool doSync, bool doForce)
4971 {
4972 ListT<CegoTableObject> idxList;
4973 ListT<CegoBTreeObject> btreeList;
4974 ListT<CegoKeyObject> keyList;
4975 ListT<CegoCheckObject> checkList;
4976 ListT<CegoTriggerObject> triggerList;
4977 ListT<CegoAliasObject> aliasList;
4978 int numInvalid;
4979
4980 setIgnoreInvalid(false);
4981 getObjectListByTable(tabSetId, tableName, idxList, btreeList, keyList, checkList, triggerList, aliasList, numInvalid);
4982
4983 // correct indexes
4984 CegoTableObject *pIdx = idxList.First();
4985 while ( pIdx )
4986 {
4987 if ( pIdx->isValid() == false || doForce )
4988 {
4989 dropIndex(tabSetId, pIdx->getName());
4990 bool isCached=false;
4991 createIndexTable(tabSetId, pIdx->getName(), pIdx->getTabName(), pIdx->getSchema(), pIdx->getType(), isCached);
4992 _pDBMng->log(_modId, Logger::NOTICE, Chain("Index ") + pIdx->getName() + Chain(" was corrected"));
4993 }
4994
4995 pIdx = idxList.Next();
4996 }
4997
4998 // correct btrees
4999 CegoBTreeObject *pBTree = btreeList.First();
5000 while ( pBTree )
5001 {
5002 if ( pBTree->isValid() == false || doForce )
5003 {
5004 dropBTree(tabSetId, pBTree->getName());
5005 // to be defensive, we don't use btree cache for correction
5006 bool isCached = false;
5007 createBTree(tabSetId, pBTree->getName(), pBTree->getTabName(), pBTree->getSchema(), pBTree->getType(), doSync, isCached);
5008 _pDBMng->log(_modId, Logger::NOTICE, Chain("Btree ") + pBTree->getName() + Chain(" was corrected"));
5009 }
5010 pBTree = btreeList.Next();
5011 }
5012 }
5013
cleanTableSet(int tabSetId)5014 int CegoTableManager::cleanTableSet(int tabSetId)
5015 {
5016 ListT<Chain> tabList;
5017 getObjectList(tabSetId, CegoObject::TABLE, tabList);
5018
5019 int traceCount = 0;
5020 Chain *pTableName = tabList.First();
5021 while ( pTableName )
5022 {
5023 traceCount += traceObject(tabSetId, *pTableName, CegoObject::TABLE);
5024
5025 CegoTableObject oe;
5026 getObject(tabSetId, *pTableName, CegoObject::TABLE, oe);
5027
5028 bool traceLob = false;
5029 CegoField *pF = oe.getSchema().First();
5030 while ( pF && traceLob == false)
5031 {
5032 if ( pF->getType() == CLOB_TYPE || pF->getType() == BLOB_TYPE )
5033 {
5034 traceLob=true;
5035 }
5036 pF = oe.getSchema().Next();
5037 }
5038
5039 if ( traceLob )
5040 {
5041 CegoTableCursor tc(this, tabSetId, *pTableName);
5042 ListT<CegoField> fl = oe.getSchema();
5043 CegoDataPointer dp;
5044
5045 if ( tc.getFirst(fl, dp) )
5046 {
5047 do
5048 {
5049 CegoField *pF = fl.First();
5050 while ( pF )
5051 {
5052 if ( pF->getValue().getType() == BLOB_TYPE
5053 || pF->getValue().getType() == CLOB_TYPE )
5054 {
5055 PageIdType pageId;
5056 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
5057 traceCount += traceObjectPages(tabSetId, pageId);
5058 }
5059 pF = fl.Next();
5060 }
5061 }
5062 while ( tc.getNext(fl, dp) );
5063 }
5064 }
5065
5066 pTableName = tabList.Next();
5067 }
5068
5069 ListT<Chain> avlList;
5070 getObjectList(tabSetId, CegoObject::AVLTREE, avlList);
5071
5072 Chain *pAVL = avlList.First();
5073 while ( pAVL )
5074 {
5075 traceCount += traceObject(tabSetId, *pAVL, CegoObject::AVLTREE);
5076 pAVL = avlList.Next();
5077 }
5078
5079 ListT<Chain> btreeList;
5080 getObjectList(tabSetId, CegoObject::BTREE, btreeList);
5081
5082 Chain *pBTree = btreeList.First();
5083 while ( pBTree )
5084 {
5085 traceCount += traceObject(tabSetId, *pBTree, CegoObject::BTREE);
5086 pBTree = btreeList.Next();
5087 }
5088
5089 return _pDBMng->cleanPages(_pLockHandle);
5090 }
5091
getFirstTuple(CegoObjectCursor * pC,ListT<CegoField> & fl,CegoDataPointer & dp)5092 bool CegoTableManager::getFirstTuple(CegoObjectCursor* pC, ListT<CegoField>& fl, CegoDataPointer& dp)
5093 {
5094 int len;
5095
5096 char* pc = (char*)pC->getFirst(len, dp);
5097
5098 if ( pc && len > 0 )
5099 {
5100 unsigned long long tid;
5101 unsigned long long tastep;
5102 CegoTupleState ts;
5103
5104 int toff = CegoQueryHelper::decodeTupleHeader(tid, tastep, ts, pc);
5105
5106 char* tp = pc + toff;
5107 int tlen = len - toff;
5108
5109 if ( tid != 0 )
5110 {
5111 if ( ( ts == INSERTED && tid == getTID(pC->getTabSetId()) )
5112 || ( ts == DELETED && tid != getTID(pC->getTabSetId()) ) )
5113 {
5114 CegoQueryHelper::decodeFVL(fl, tp, tlen);
5115 }
5116 else
5117 {
5118 return getNextTuple(pC, fl, dp);
5119 }
5120 }
5121 else
5122 {
5123 CegoQueryHelper::decodeFVL(fl, tp, tlen);
5124 }
5125
5126 return true;
5127 }
5128 return false;
5129 }
5130
getNextTuple(CegoObjectCursor * pC,ListT<CegoField> & fl,CegoDataPointer & dp)5131 bool CegoTableManager::getNextTuple(CegoObjectCursor* pC, ListT<CegoField>& fl, CegoDataPointer& dp)
5132 {
5133
5134 do
5135 {
5136 int len;
5137 char* pc = (char*)pC->getNext(len, dp);
5138
5139 if ( pc && len > 0 )
5140 {
5141 unsigned long long tid;
5142 unsigned long long tastep;
5143 CegoTupleState ts;
5144
5145 int toff = CegoQueryHelper::decodeTupleHeader(tid, tastep, ts, pc);
5146
5147 char* tp = pc + toff;
5148 int tlen = len - toff;
5149
5150 if ( tid != 0 )
5151 {
5152 if ( ( ts == INSERTED && tid == getTID(pC->getTabSetId()) )
5153 || ( ts == DELETED && tid == getTID(pC->getTabSetId()) ) )
5154 {
5155 CegoQueryHelper::decodeFVL(fl, tp, tlen);
5156 return true;
5157 }
5158 }
5159 else
5160 {
5161 CegoQueryHelper::decodeFVL(fl, tp, tlen);
5162 return true;
5163 }
5164 }
5165 else
5166 {
5167 return false;
5168 }
5169
5170 } while ( 1 ) ;
5171 }
5172
createIndexTableSynced(int tabSetId,const Chain & indexName,const Chain & tableName,CegoObject::ObjectType type,ListT<CegoField> & idxList,bool isCached)5173 void CegoTableManager::createIndexTableSynced(int tabSetId, const Chain& indexName, const Chain& tableName, CegoObject::ObjectType type, ListT<CegoField>& idxList, bool isCached)
5174 {
5175 if ( type == CegoObject::PAVLTREE
5176 || type == CegoObject::UAVLTREE
5177 || type == CegoObject::AVLTREE )
5178 {
5179 if ( isCached )
5180 {
5181 Chain msg = "Cache option not supported for AVL tree";
5182 throw Exception(EXLOC, msg);
5183 }
5184
5185 _pDBMng->useObject(tabSetId, tableName, CegoObject::TABLE, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
5186
5187 try
5188 {
5189 createAVLIndexTable(tabSetId, indexName, tableName, idxList, type);
5190 }
5191 catch ( Exception e )
5192 {
5193 _pDBMng->unuseObject(tabSetId, tableName, CegoObject::TABLE);
5194 throw Exception(e);
5195 }
5196 _pDBMng->unuseObject(tabSetId, tableName, CegoObject::TABLE);
5197 }
5198 else if ( type == CegoObject::PBTREE
5199 || type == CegoObject::UBTREE
5200 || type == CegoObject::BTREE )
5201 {
5202 createBTree(tabSetId, indexName, tableName, idxList, type, true, isCached);
5203 }
5204
5205 _pDBMng->addObject(tabSetId, indexName, type);
5206 }
5207
createPrimaryIndexTable(int tabSetId,const Chain & indexName,const Chain & tableName,ListT<CegoField> & schema)5208 void CegoTableManager::createPrimaryIndexTable(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema)
5209 {
5210 CegoObject::ObjectType type = CegoObject::PBTREE;
5211 bool isCached=false;
5212 createIndexTable(tabSetId, indexName, tableName, schema, type, isCached);
5213 }
5214
createIndexTable(int tabSetId,const Chain & indexName,const Chain & tableName,ListT<CegoField> & schema,CegoObject::ObjectType type,bool isCached)5215 void CegoTableManager::createIndexTable(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema, CegoObject::ObjectType type, bool isCached)
5216 {
5217 if ( type == CegoObject::PAVLTREE
5218 || type == CegoObject::UAVLTREE
5219 || type == CegoObject::AVLTREE )
5220 {
5221 if ( isCached )
5222 {
5223 Chain msg = "Cache option not supported for AVL tree";
5224 throw Exception(EXLOC, msg);
5225 }
5226
5227 createAVLIndexTable(tabSetId, indexName, tableName, schema, type);
5228 }
5229 else if ( type == CegoObject::PBTREE
5230 || type == CegoObject::UBTREE
5231 || type == CegoObject::BTREE )
5232 {
5233 createBTree(tabSetId, indexName, tableName, schema, type, false, isCached);
5234 }
5235 else
5236 {
5237 throw Exception(EXLOC, Chain("Unknown index type"));
5238 }
5239 }
5240
createBTree(int tabSetId,const Chain & btreeName,const Chain & tableName,ListT<CegoField> & schema,CegoObject::ObjectType type,bool doSync,bool isCached)5241 void CegoTableManager::createBTree(int tabSetId, const Chain& btreeName, const Chain& tableName, ListT<CegoField>& schema, CegoObject::ObjectType type, bool doSync, bool isCached)
5242 {
5243 if ( getTID(tabSetId) > 0 )
5244 {
5245 Chain msg = Chain("create btree in a transaction not allowed");
5246 throw Exception(EXLOC, msg);
5247 }
5248
5249 CegoLogRecord lr;
5250 lr.setLSN(_pDBMng->nextLSN(tabSetId));
5251
5252 CegoTableObject toe;
5253
5254 getObject(tabSetId, tableName, CegoObject::TABLE, toe);
5255
5256
5257 CegoField* pF;
5258
5259 // first we create a tableschema with the required attribute in the appropriate order
5260 ListT<CegoField> tableSchema;
5261 pF = toe.getSchema().First();
5262 while ( pF )
5263 {
5264 if ( schema.Find(CegoField(tableName, pF->getAttrName())))
5265 tableSchema.Insert(*pF);
5266 pF = toe.getSchema().Next();
5267 }
5268
5269
5270 pF = schema.First();
5271 while (pF)
5272 {
5273 CegoField* pSF = toe.getSchema().Find(CegoField(tableName, pF->getAttrName()));
5274
5275 if ( pSF )
5276 {
5277 pF->setType(pSF->getType());
5278 pF->setLength(pSF->getLength());
5279 pF->setId(pSF->getId());
5280 }
5281 else
5282 {
5283 Chain msg = "Unknown field <" + pF->getAttrName() + ">";
5284 throw Exception(EXLOC, msg);
5285 }
5286
5287 if ( type == CegoObject::PBTREE && pSF->isNullable() )
5288 {
5289 Chain msg = "Primary btree attribute must be not nullable";
5290 throw Exception(EXLOC, msg);
5291 }
5292
5293 pF = schema.Next();
5294 }
5295
5296 if ( doSync )
5297 _pDBMng->useObject(tabSetId, tableName, CegoObject::TABLE, CegoDatabaseManager::SHARED, _threadId);
5298
5299 CegoBTreeObject btoe(tabSetId, type, btreeName, schema, tableName);
5300 CegoDataPointer sysEntry;
5301
5302 try
5303 {
5304 createBTreeObject(btoe);
5305 }
5306 catch ( Exception e )
5307 {
5308 if ( doSync )
5309 _pDBMng->unuseObject(tabSetId, tableName, CegoObject::TABLE);
5310
5311 Chain msg;
5312 e.pop(msg);
5313 throw Exception(EXLOC, Chain("Create of btree failed (") + msg + + Chain(")"));
5314 }
5315
5316 // building up index
5317
5318 CegoObjectCursor* pC = 0;
5319 CegoBufferPage bp;
5320 CegoBTreeManager* pBTreeMng = 0;
5321
5322 try
5323 {
5324 // we have to keep the index object in buffer pool
5325 getObjectWithFix(tabSetId, btreeName, type, btoe, bp);
5326 sysEntry = CegoDataPointer(bp.getPageId(), bp.getEntryPos());
5327
5328 // create root node
5329
5330 CegoBufferPage rootPage;
5331 getNewFilePage(rootPage, btoe.getTabSetId(), btoe.getType());
5332
5333 rootPage.setType(CegoBufferPage::BTREE_LEAF);
5334 CegoBTreeNode rootNode;
5335 rootNode.setPtr(rootPage.getChunkEntry(), rootPage.getChunkLen());
5336 rootNode.initNode();
5337
5338 PageIdType dataPageId = rootPage.getPageId();
5339
5340 btoe.setDataPageId(dataPageId);
5341
5342 _pDBMng->bufferUnfix(rootPage, true, _pLockHandle);
5343
5344 CegoDataPointer dp;
5345 pC = getObjectCursor(tabSetId, tableName, tableName, CegoObject::TABLE);
5346 bool moreTuple = getFirstTuple(pC, tableSchema, dp);
5347
5348 pBTreeMng = new CegoBTreeManager(this, &btoe);
5349
5350 if ( isCached )
5351 {
5352 pBTreeMng->createCache();
5353 }
5354
5355 while (moreTuple && _isAborted == false)
5356 {
5357 CegoBTreeValue iv;
5358
5359 iv.valueFromSchema(tableSchema, schema);
5360
5361 unsigned long long tid = 0;
5362 pBTreeMng->insertBTree(dp, iv, tid);
5363
5364 moreTuple = getNextTuple(pC, tableSchema, dp);
5365 }
5366
5367 // we also can release the object cursor
5368 pC->abort();
5369 delete pC;
5370 pC = 0;
5371
5372 if ( _isAborted )
5373 {
5374 throw Exception(EXLOC, Chain("Btree creation aborted by user"));
5375 }
5376 }
5377 catch ( Exception e )
5378 {
5379 if ( bp.isFixed() )
5380 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
5381
5382 if ( pC )
5383 {
5384 pC->abort();
5385 delete pC;
5386 }
5387 if ( pBTreeMng )
5388 {
5389 pBTreeMng->rollback();
5390 delete pBTreeMng;
5391 }
5392
5393 dropBTree(tabSetId, btreeName);
5394
5395 if ( doSync )
5396 _pDBMng->unuseObject(tabSetId, tableName, CegoObject::TABLE);
5397
5398 Chain msg;
5399 e.pop(msg);
5400
5401 throw Exception(EXLOC, Chain("Create of btree failed (") + msg + Chain(")"));
5402
5403 }
5404
5405 if ( doSync )
5406 {
5407 _pDBMng->unuseObject(tabSetId, tableName, CegoObject::TABLE);
5408 _pDBMng->useObject(tabSetId, tableName, CegoObject::TABLE, CegoDatabaseManager::EXCLUSIVE_WRITE, _threadId);
5409 }
5410
5411 pBTreeMng->commit(sysEntry);
5412
5413 if ( doSync )
5414 {
5415 _pDBMng->unuseObject(tabSetId, tableName, CegoObject::TABLE);
5416 }
5417
5418 // now we can release the index root page
5419 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
5420
5421 delete pBTreeMng;
5422
5423 // create log entry
5424
5425 lr.setObjectInfo(btoe.getName(), btoe.getType());
5426 lr.setAction(CegoLogRecord::LOGREC_CREATE);
5427
5428 char *buf;
5429 buf = (char*)malloc(btoe.getEntrySize());
5430
5431 btoe.encode(buf);
5432 lr.setData(buf);
5433 lr.setDataLen(btoe.getEntrySize());
5434 // lr.setTID(0);
5435
5436 _pDBMng->logIt(btoe.getTabSetId(), lr, _pLockHandle);
5437
5438 free(buf);
5439 }
5440
createAVLIndexTable(int tabSetId,const Chain & indexName,const Chain & tableName,ListT<CegoField> & schema,CegoObject::ObjectType type)5441 void CegoTableManager::createAVLIndexTable(int tabSetId, const Chain& indexName, const Chain& tableName, ListT<CegoField>& schema, CegoObject::ObjectType type)
5442 {
5443 if ( getTID(tabSetId) > 0 )
5444 {
5445 Chain msg = Chain("create avl index in a transaction not allowed");
5446 throw Exception(EXLOC, msg);
5447 }
5448
5449 CegoLogRecord lr;
5450 lr.setLSN(_pDBMng->nextLSN(tabSetId));
5451
5452 CegoTableObject toe;
5453
5454 getObject(tabSetId, tableName, CegoObject::TABLE, toe);
5455
5456 CegoField* pF = schema.First();
5457 while (pF)
5458 {
5459 CegoField* pSF = toe.getSchema().Find(CegoField(tableName, pF->getAttrName()));
5460
5461 if ( pSF )
5462 {
5463 pF->setType(pSF->getType());
5464 pF->setLength(pSF->getLength());
5465 pF->setId(pSF->getId());
5466 }
5467 else
5468 {
5469 Chain msg = "Unknown field <" + pF->getAttrName() + ">";
5470 throw Exception(EXLOC, msg);
5471 }
5472
5473 if ( type == CegoObject::PAVLTREE && pSF->isNullable() )
5474 {
5475 Chain msg = "Primary index attribute must be not nullable";
5476 throw Exception(EXLOC, msg);
5477 }
5478
5479 pF = schema.Next();
5480 }
5481
5482 CegoTableObject ioe(tabSetId, type, indexName, schema, tableName);
5483
5484 createTableObject(ioe);
5485
5486 CegoAVLIndexEntry base;
5487 CegoDataPointer nil;
5488
5489 base.initEntry(nil);
5490
5491 base.setLeftBranch(nil);
5492 base.setParent(nil);
5493 base.setRightBranch(nil);
5494
5495 CegoDataPointer dp = insertData(ioe, (char*)base.getPtr(), base.getLen(), true);
5496
5497 CegoBufferPage zp;
5498 // unsigned long recLock = _pLockHandle->lockRecord(zp, dp, CegoLockHandler::WRITE);
5499
5500 // building up index
5501
5502 CegoObjectCursor* pC = 0;
5503 CegoBufferPage bp;
5504
5505 CegoAVLIndexManager idxMng(this);
5506
5507 try
5508 {
5509 pC = getObjectCursor(tabSetId, tableName, tableName, CegoObject::TABLE);
5510
5511 // we have to keep the index object in buffer pool
5512 getObjectWithFix(tabSetId, indexName, type, ioe, bp);
5513
5514 CegoDataPointer dp;
5515 unsigned long long tid = 0;
5516
5517 char idxBuf[TABMNG_MAXINDEXVALUE];
5518
5519 bool moreTuple = getFirstTuple(pC, schema, dp);
5520
5521 bool isFirst = true;
5522 CegoDataPointer ritp;
5523
5524 CegoDataPointer sysEntry(bp.getPageId(), bp.getEntryPos());
5525
5526 while (moreTuple && _isAborted == false)
5527 {
5528 // get Index len
5529 int idxLen = 0;
5530 CegoField* pF = schema.First();
5531 while (pF)
5532 {
5533 idxLen += pF->getValue().getLength() + sizeof(int);
5534 pF = schema.Next();
5535 }
5536
5537 char* idxPtr = idxBuf;
5538 pF = schema.First();
5539 while (pF)
5540 {
5541 int len = pF->getValue().getLength();
5542 memcpy(idxPtr, &len, sizeof(int));
5543 idxPtr+=sizeof(int);
5544 if ( len > 0 )
5545 {
5546 memcpy(idxPtr, pF->getValue().getValue(), len);
5547 idxPtr += len;
5548 }
5549 pF = schema.Next();
5550 }
5551
5552 if ( isFirst )
5553 {
5554 // since we have locked the index root page in bufferpool, we can call with no resolution of object entry
5555 idxMng.insertNativeIndexTable(ioe, sysEntry, dp, idxBuf, idxLen, tid, true, ritp);
5556 isFirst=false;
5557 }
5558 else
5559 {
5560 bool isUnique = false;
5561 if ( type == CegoObject::UAVLTREE || type == CegoObject::PAVLTREE )
5562 isUnique = true;
5563
5564 idxMng.insertIndexTable(ioe, sysEntry, ritp, isUnique, dp, idxBuf, idxLen, tid, true, true);
5565 }
5566
5567 moreTuple = getNextTuple(pC, schema, dp);
5568 }
5569
5570 if ( _isAborted )
5571 {
5572 throw Exception(EXLOC, Chain("Index creation aborted by user"));
5573 }
5574 }
5575 catch ( Exception e )
5576 {
5577 if ( bp.isFixed() )
5578 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
5579 if ( pC )
5580 pC->abort();
5581
5582 // _pLockHandle->unlockRecord(recLock);
5583
5584 delete pC;
5585 dropIndex(tabSetId, indexName);
5586
5587 Chain msg;
5588 e.pop(msg);
5589 throw Exception(EXLOC, Chain("Create of index failed (") + msg + Chain(")"));
5590 }
5591
5592 // now we can release the index root page
5593 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
5594 // _pLockHandle->unlockRecord(recLock);
5595
5596 // we also can release the object cursor
5597 pC->abort();
5598
5599 delete pC;
5600
5601 // create log entry
5602 lr.setObjectInfo(ioe.getName(), ioe.getType());
5603 lr.setAction(CegoLogRecord::LOGREC_CREATE);
5604
5605 char *buf;
5606 buf = (char*)malloc(ioe.getEntrySize());
5607
5608 ioe.encode(buf);
5609 lr.setData(buf);
5610 lr.setDataLen(ioe.getEntrySize());
5611 // lr.setTID(0);
5612
5613 _pDBMng->logIt(ioe.getTabSetId(), lr, _pLockHandle);
5614
5615 free(buf);
5616 }
5617
createForeignKey(int tabSetId,const Chain & fkey,const Chain & tableName,const ListT<CegoField> & keyList,const Chain & refTable,const ListT<CegoField> & refList)5618 void CegoTableManager::createForeignKey(int tabSetId, const Chain& fkey, const Chain& tableName, const ListT<CegoField>& keyList, const Chain& refTable, const ListT<CegoField>& refList)
5619 {
5620 if ( getTID(tabSetId) > 0 )
5621 {
5622 Chain msg = Chain("create foreign key in a transaction not allowed");
5623 throw Exception(EXLOC, msg);
5624 }
5625
5626 CegoLogRecord lr;
5627 lr.setLSN(_pDBMng->nextLSN(tabSetId));
5628
5629 CegoObjectCursor* pC = 0;
5630
5631 try
5632 {
5633 // check if key references primary key
5634
5635 ListT<CegoTableObject> checkIdxList;
5636 ListT<CegoBTreeObject> checkBTreeList;
5637 ListT<CegoKeyObject> checkKeyList;
5638 ListT<CegoCheckObject> checkList;
5639 ListT<CegoTriggerObject> triggerList;
5640 ListT<CegoAliasObject> aliasList;
5641 int numInvalid;
5642
5643 getObjectListByTable(tabSetId, refTable, checkIdxList, checkBTreeList, checkKeyList, checkList, triggerList, aliasList, numInvalid);
5644 if ( numInvalid > 0 )
5645 {
5646 throw Exception(EXLOC, Chain("Cannot create foreign key on table with invalid index"));
5647 }
5648
5649 CegoTableObject *pIO = checkIdxList.First();
5650 bool idxFound = false;
5651 while ( pIO && idxFound == false)
5652 {
5653 if ( pIO->getType() == CegoObject::PAVLTREE )
5654 {
5655 if ( pIO->getSchema().Size() == keyList.Size() )
5656 {
5657 CegoField *pK = refList.First();
5658 idxFound = true;
5659 while ( pK && idxFound )
5660 {
5661 if ( pIO->getSchema().Find(*pK) )
5662 {
5663 pK = refList.Next();
5664 }
5665 else
5666 {
5667 idxFound = false;
5668 }
5669 }
5670 }
5671 // just one primary index can be found
5672 pIO = 0;
5673 }
5674 else
5675 {
5676 pIO = checkIdxList.Next();
5677 }
5678 }
5679 if ( idxFound == false )
5680 {
5681 CegoBTreeObject *pBTO = checkBTreeList.First();
5682 while ( pBTO && idxFound == false)
5683 {
5684 if ( pBTO->getType() == CegoObject::PBTREE )
5685 {
5686 if ( pBTO->getSchema().Size() == keyList.Size() )
5687 {
5688 CegoField *pK = refList.First();
5689 idxFound = true;
5690 while ( pK && idxFound )
5691 {
5692 if ( pBTO->getSchema().Find(*pK) )
5693 {
5694 pK = refList.Next();
5695 }
5696 else
5697 {
5698 idxFound = false;
5699 }
5700 }
5701 }
5702
5703 // just one primary btree can be found
5704 pBTO = 0;
5705 }
5706 else
5707 {
5708 pBTO = checkBTreeList.Next();
5709 }
5710 }
5711 }
5712
5713 if ( idxFound == false )
5714 throw Exception(EXLOC, Chain("Primary index or btree not found"));
5715
5716 CegoTableObject toe;
5717 getObject(tabSetId, tableName, CegoObject::TABLE, toe);
5718
5719 ListT<CegoField> schema = toe.getSchema();
5720
5721 CegoField *pDF = keyList.First();
5722 while ( pDF )
5723 {
5724 CegoField *pF = schema.Find(*pDF);
5725 if ( pF == 0 )
5726 {
5727 Chain msg = Chain("Unknown key attribute ") + pDF->getAttrName();
5728 throw Exception(EXLOC, msg);
5729 }
5730 pDF = keyList.Next();
5731 }
5732
5733 pC = getObjectCursor(tabSetId, tableName, tableName, CegoObject::TABLE);
5734
5735 CegoDataPointer dp;
5736
5737 bool moreTuple = getFirstTuple(pC, schema, dp);
5738
5739 while ( moreTuple && _isAborted == false)
5740 {
5741 CegoTableCursor tc(this, tabSetId, refTable);
5742
5743 CegoAttrCond ac;
5744
5745 CegoField *pDF = keyList.First();
5746 while ( pDF )
5747 {
5748 CegoField *pF = schema.Find(*pDF);
5749 if ( pF )
5750 {
5751 ac.add(CegoAttrComp(pF->getTableAlias(), pF->getAttrName(), EQUAL, pF->getValue()));
5752 }
5753 else
5754 {
5755 Chain msg = Chain("Unknown key attribute ") + pDF->getAttrName();
5756 throw Exception(EXLOC, msg);
5757 }
5758 pDF = keyList.Next();
5759 }
5760
5761 ListT<CegoField> tfl;
5762 CegoAttrCond::IndexMatch indexMatch = tc.setup(ac);
5763
5764 if ( indexMatch == CegoAttrCond::FULL || indexMatch == CegoAttrCond::PART )
5765 {
5766 tc.getIdxSchema(tfl);
5767 }
5768 else
5769 {
5770 CegoTableObject oe;
5771 getObject(tabSetId, refTable, CegoObject::TABLE, oe);
5772 tfl = oe.getSchema();
5773 }
5774
5775 CegoDataPointer dp;
5776
5777 bool moreRefTuple = tc.getFirst(tfl, dp);
5778
5779 bool isMatch = false;
5780 while ( moreRefTuple && ( ! isMatch ) )
5781 {
5782 CegoField *pF = tfl.First();
5783 while ( pF )
5784 {
5785 isMatch = true;
5786 CegoField *pD = schema.Find(*pF);
5787 if ( pD )
5788 {
5789 // cout << "Comparing " << pD->getValue() << " == " << pF->getValue() << endl;
5790 if ( ! ( (CegoFieldValue)pD->getValue() == (CegoFieldValue)pF->getValue()) )
5791 isMatch=false;
5792 }
5793 pF = tfl.Next();
5794 }
5795 moreRefTuple = tc.getNext(tfl, dp);
5796 }
5797 if ( ! isMatch )
5798 throw Exception(EXLOC, Chain("Foreign key reference does not exist"));
5799
5800 moreTuple = getNextTuple(pC, schema, dp);
5801 }
5802
5803 if ( _isAborted )
5804 {
5805 throw Exception(EXLOC, Chain("Foreign key creation aborted by user"));
5806 }
5807 }
5808 catch ( Exception e )
5809 {
5810 if ( pC )
5811 pC->abort();
5812 throw e;
5813 }
5814
5815 delete pC;
5816
5817 CegoKeyObject oe(tabSetId, fkey, tableName, keyList, refTable, refList );
5818
5819 createKeyObject(oe);
5820
5821 // create log entry
5822 lr.setObjectInfo(oe.getName(), oe.getType());
5823 lr.setAction(CegoLogRecord::LOGREC_CREATE);
5824
5825 char *buf;
5826 buf = (char*)malloc(oe.getEntrySize());
5827
5828 oe.encode(buf);
5829 lr.setData(buf);
5830 lr.setDataLen(oe.getEntrySize());
5831 // lr.setTID(0);
5832
5833 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle);
5834
5835 free(buf);
5836 }
5837
createCheck(int tabSetId,const Chain & checkName,const Chain & tableName,CegoPredDesc * pPredDesc)5838 void CegoTableManager::createCheck(int tabSetId, const Chain& checkName, const Chain& tableName, CegoPredDesc *pPredDesc)
5839 {
5840 if ( getTID(tabSetId) > 0 )
5841 {
5842 Chain msg = Chain("create check in a transaction not allowed");
5843 throw Exception(EXLOC, msg);
5844 }
5845
5846 CegoLogRecord lr;
5847 lr.setLSN(_pDBMng->nextLSN(tabSetId));
5848
5849 CegoObjectCursor* pC = 0;
5850
5851 try
5852 {
5853 CegoTableObject toe;
5854 getObject(tabSetId, tableName, CegoObject::TABLE, toe);
5855
5856 ListT<CegoField> schema = toe.getSchema();
5857
5858 // we need to create an additional reference to use the setFieldListArray method
5859 ListT<CegoField>* xschema[2];
5860 xschema[0] = &schema;
5861 xschema[1] = 0;
5862
5863 pC = getObjectCursor(tabSetId, tableName, tableName, CegoObject::TABLE);
5864
5865 CegoDataPointer dp;
5866
5867 bool moreTuple = getFirstTuple(pC, schema, dp);
5868
5869 if ( moreTuple )
5870 {
5871 while ( moreTuple && _isAborted == false)
5872 {
5873 pPredDesc->clearAttrCache();
5874 if ( CegoQueryHelper::evalPredicate(0, 0, xschema, 0, pPredDesc ) == false )
5875 throw Exception(EXLOC, Chain("Check constraint violated"));
5876 moreTuple = getNextTuple(pC, schema, dp);
5877 }
5878 }
5879 else
5880 {
5881 // check attribute match for empty tables
5882 CegoExpr *pExpr = pPredDesc->getExpr1();
5883 if ( pExpr )
5884 {
5885 ListT<CegoAttrDesc*> adl = pExpr->getAttrRefList();
5886 CegoAttrDesc **pAD = adl.First();
5887 while ( pAD )
5888 {
5889 if ( ! schema.Find(CegoField((*pAD)->getTableName(), (*pAD)->getAttrName())))
5890 {
5891 Chain msg = Chain("Unknown attribute " ) + (*pAD)->getAttrName();
5892 throw Exception(EXLOC, msg);
5893 }
5894 pAD = adl.Next();
5895 }
5896 }
5897 pExpr = pPredDesc->getExpr2();
5898 if ( pExpr )
5899 {
5900 ListT<CegoAttrDesc*> adl = pExpr->getAttrRefList();
5901 CegoAttrDesc **pAD = adl.First();
5902 while ( pAD )
5903 {
5904 if ( ! schema.Find(CegoField((*pAD)->getTableName(), (*pAD)->getAttrName())))
5905 {
5906 Chain msg = Chain("Unknown attribute " ) + (*pAD)->getAttrName();
5907 throw Exception(EXLOC, msg);
5908 }
5909 pAD = adl.Next();
5910 }
5911 }
5912 pExpr = pPredDesc->getExpr3();
5913 if ( pExpr )
5914 {
5915 ListT<CegoAttrDesc*> adl = pExpr->getAttrRefList();
5916 CegoAttrDesc **pAD = adl.First();
5917 while ( pAD )
5918 {
5919 if ( ! schema.Find(CegoField((*pAD)->getTableName(), (*pAD)->getAttrName())))
5920 {
5921 Chain msg = Chain("Unknown attribute " ) + (*pAD)->getAttrName();
5922 throw Exception(EXLOC, msg);
5923 }
5924 pAD = adl.Next();
5925 }
5926 }
5927 }
5928 if ( _isAborted )
5929 {
5930 throw Exception(EXLOC, Chain("Check constraint creation aborted by user"));
5931 }
5932
5933 }
5934 catch ( Exception e )
5935 {
5936 if ( pC )
5937 pC->abort();
5938
5939 throw e;
5940 }
5941
5942 delete pC;
5943
5944 CegoCheckObject oe(tabSetId, checkName, tableName, pPredDesc );
5945
5946 createCheckObject(oe);
5947
5948 // create log entry
5949 lr.setObjectInfo(oe.getName(), oe.getType());
5950 lr.setAction(CegoLogRecord::LOGREC_CREATE);
5951
5952 char *buf;
5953 buf = (char*)malloc(oe.getEntrySize());
5954
5955 oe.encode(buf);
5956 lr.setData(buf);
5957 lr.setDataLen(oe.getEntrySize());
5958 // lr.setTID(0);
5959 _pDBMng->logIt(oe.getTabSetId(), lr, _pLockHandle);
5960 free(buf);
5961 }
5962
5963
createAlias(int tabSetId,const Chain & aliasName,const Chain & tableName,const ListT<CegoAttrAlias> & aliasList)5964 void CegoTableManager::createAlias(int tabSetId, const Chain& aliasName, const Chain& tableName, const ListT<CegoAttrAlias>& aliasList)
5965 {
5966 if ( aliasName == tableName )
5967 {
5968 Chain msg = Chain("Table name and alias name cannot be equal");
5969 throw Exception(EXLOC, msg);
5970 }
5971
5972 if ( getTID(tabSetId) > 0 )
5973 {
5974 Chain msg = Chain("create check in a transaction not allowed");
5975 throw Exception(EXLOC, msg);
5976 }
5977
5978 try
5979 {
5980 CegoTableObject toe;
5981 getObject(tabSetId, tableName, CegoObject::TABLE, toe);
5982 }
5983 catch ( Exception e )
5984 {
5985 throw e;
5986 }
5987
5988
5989
5990 CegoAliasObject ao(tabSetId, aliasName, tableName, aliasList);
5991
5992 CegoLogRecord lr;
5993 lr.setLSN(_pDBMng->nextLSN(tabSetId));
5994
5995 createAliasObject(ao);
5996
5997 // create log entry
5998 lr.setObjectInfo(ao.getName(), ao.getType());
5999 lr.setAction(CegoLogRecord::LOGREC_CREATE);
6000
6001 char *buf;
6002 buf = (char*)malloc(ao.getEntrySize());
6003 ao.encode(buf);
6004 lr.setData(buf);
6005 lr.setDataLen(ao.getEntrySize());
6006 // lr.setTID(0);
6007 _pDBMng->logIt(ao.getTabSetId(), lr, _pLockHandle);
6008 free(buf);
6009 }
6010
createTrigger(int tabSetId,const Chain & triggerName,bool isBefore,bool isOnInsert,bool isOnUpdate,bool isOnDelete,const Chain & tableName,const Chain & triggerText)6011 void CegoTableManager::createTrigger(int tabSetId, const Chain& triggerName,
6012 bool isBefore, bool isOnInsert, bool isOnUpdate, bool isOnDelete,
6013 const Chain& tableName, const Chain& triggerText)
6014 {
6015 if ( getTID(tabSetId) > 0 )
6016 {
6017 Chain msg = Chain("create check in a transaction not allowed");
6018 throw Exception(EXLOC, msg);
6019 }
6020
6021 try
6022 {
6023 CegoTableObject toe;
6024 getObject(tabSetId, tableName, CegoObject::TABLE, toe);
6025 }
6026 catch ( Exception e )
6027 {
6028 throw e;
6029 }
6030
6031 CegoTriggerObject to(tabSetId, triggerName, isBefore, isOnInsert, isOnUpdate, isOnDelete, tableName, triggerText);
6032
6033 CegoLogRecord lr;
6034 lr.setLSN(_pDBMng->nextLSN(tabSetId));
6035
6036 createTriggerObject(to);
6037
6038 // create log entry
6039 lr.setObjectInfo(to.getName(), to.getType());
6040 lr.setAction(CegoLogRecord::LOGREC_CREATE);
6041
6042 char *buf;
6043 buf = (char*)malloc(to.getEntrySize());
6044 to.encode(buf);
6045 lr.setData(buf);
6046 lr.setDataLen(to.getEntrySize());
6047 // lr.setTID(0);
6048 _pDBMng->logIt(to.getTabSetId(), lr, _pLockHandle);
6049 free(buf);
6050 }
6051
getPoolInfo(CegoTableObject & oe,ListT<ListT<CegoFieldValue>> & info)6052 void CegoTableManager::getPoolInfo(CegoTableObject& oe, ListT< ListT<CegoFieldValue> > &info)
6053 {
6054 ListT<CegoField> schema;
6055 schema.Insert(CegoField(Chain("POOLINFO"), Chain("POOLINFO"), Chain("PARAMETER"),VARCHAR_TYPE, 20));
6056 schema.Insert(CegoField(Chain("POOLINFO"), Chain("POOLINFO"), Chain("VALUE"), VARCHAR_TYPE, 20));
6057 oe = CegoTableObject(0, CegoObject::SYSTEM, Chain("POOLINFO"), schema, Chain("POOLINFO"));
6058
6059 int pageSize;
6060 unsigned long long totalPages;
6061 unsigned long long usedPages;
6062 unsigned long long freePages;
6063 unsigned long long dirtyPages;
6064 unsigned long long fixedPages;
6065 unsigned long long persistentPages;
6066 unsigned long long noSyncPages;
6067 unsigned long long numDiskRead;
6068 unsigned long long numDiskWrite;
6069 double hitRate;
6070 double spreadRate;
6071 unsigned long long readDelay;
6072 unsigned long long writeDelay;
6073 unsigned long long curFixCount;
6074 unsigned long long maxFixCount;
6075 unsigned long long avgFixTry;
6076
6077 unsigned long long statStart;
6078 unsigned long long uptime;
6079
6080 _pDBMng->poolInfo(pageSize, totalPages, usedPages, freePages, dirtyPages, fixedPages, persistentPages, noSyncPages, numDiskRead, numDiskWrite, hitRate, spreadRate, readDelay, writeDelay, curFixCount, maxFixCount, avgFixTry, statStart, uptime);
6081
6082 CegoFieldValue f1a(VARCHAR_TYPE, Chain("Page Size"));
6083 CegoFieldValue f1b(VARCHAR_TYPE, Chain(pageSize));
6084 ListT<CegoFieldValue> fl1;
6085 fl1.Insert(f1a);
6086 fl1.Insert(f1b);
6087 info.Insert(fl1);
6088
6089 CegoFieldValue f2a(VARCHAR_TYPE, Chain("Total Pages"));
6090 CegoFieldValue f2b(VARCHAR_TYPE, Chain(totalPages));
6091 ListT<CegoFieldValue> fl2;
6092 fl2.Insert(f2a);
6093 fl2.Insert(f2b);
6094 info.Insert(fl2);
6095
6096 CegoFieldValue f3a(VARCHAR_TYPE, Chain("Used Pages"));
6097 CegoFieldValue f3b(VARCHAR_TYPE, Chain(usedPages));
6098 ListT<CegoFieldValue> fl3;
6099 fl3.Insert(f3a);
6100 fl3.Insert(f3b);
6101 info.Insert(fl3);
6102
6103 CegoFieldValue f4a(VARCHAR_TYPE, Chain("Free Pages"));
6104 CegoFieldValue f4b(VARCHAR_TYPE, Chain(freePages));
6105 ListT<CegoFieldValue> fl4;
6106 fl4.Insert(f4a);
6107 fl4.Insert(f4b);
6108 info.Insert(fl4);
6109
6110 CegoFieldValue f5a(VARCHAR_TYPE, Chain("Dirty Pages"));
6111 CegoFieldValue f5b(VARCHAR_TYPE, Chain(dirtyPages));
6112 ListT<CegoFieldValue> fl5;
6113 fl5.Insert(f5a);
6114 fl5.Insert(f5b);
6115 info.Insert(fl5);
6116
6117 CegoFieldValue f6a(VARCHAR_TYPE, Chain("Fixed Pages"));
6118 CegoFieldValue f6b(VARCHAR_TYPE, Chain(fixedPages));
6119 ListT<CegoFieldValue> fl6;
6120 fl6.Insert(f6a);
6121 fl6.Insert(f6b);
6122 info.Insert(fl6);
6123
6124 CegoFieldValue f7a(VARCHAR_TYPE, Chain("Persistent Pages"));
6125 CegoFieldValue f7b(VARCHAR_TYPE, Chain(persistentPages));
6126 ListT<CegoFieldValue> fl7;
6127 fl7.Insert(f7a);
6128 fl7.Insert(f7b);
6129 info.Insert(fl7);
6130
6131 CegoFieldValue f8a(VARCHAR_TYPE, Chain("No Sync Pages"));
6132 CegoFieldValue f8b(VARCHAR_TYPE, Chain(noSyncPages));
6133 ListT<CegoFieldValue> fl8;
6134 fl8.Insert(f8a);
6135 fl8.Insert(f8b);
6136 info.Insert(fl8);
6137
6138 // format spread rate
6139 Chain srFormated = Chain(spreadRate, "%3.3f");
6140
6141 CegoFieldValue f9a(VARCHAR_TYPE, Chain("Spread Rate"));
6142 CegoFieldValue f9b(VARCHAR_TYPE, srFormated);
6143 ListT<CegoFieldValue> fl9;
6144 fl9.Insert(f9a);
6145 fl9.Insert(f9b);
6146 info.Insert(fl9);
6147
6148
6149 CegoFieldValue f10a(VARCHAR_TYPE, Chain("-------------------"));
6150 CegoFieldValue f10b(VARCHAR_TYPE, Chain("-------------------"));
6151 ListT<CegoFieldValue> fl10;
6152 fl10.Insert(f10a);
6153 fl10.Insert(f10b);
6154 info.Insert(fl10);
6155
6156 Datetime dt(statStart);
6157 CegoFieldValue f11a(VARCHAR_TYPE, Chain("Stat Start"));
6158 CegoFieldValue f11b(VARCHAR_TYPE, dt.asChain(BUPMNG_STATDTFORMAT));
6159 ListT<CegoFieldValue> fl11;
6160 fl11.Insert(f11a);
6161 fl11.Insert(f11b);
6162 info.Insert(fl11);
6163
6164 // format hitrate
6165 Chain hrFormated = Chain(hitRate, "%3.2f") + Chain("%");
6166
6167 CegoFieldValue f12a(VARCHAR_TYPE, Chain("Hit Rate"));
6168 CegoFieldValue f12b(VARCHAR_TYPE, hrFormated);
6169 ListT<CegoFieldValue> fl12;
6170 fl12.Insert(f12a);
6171 fl12.Insert(f12b);
6172 info.Insert(fl12);
6173
6174 CegoFieldValue f13a(VARCHAR_TYPE, Chain("Cur Fix Count"));
6175 CegoFieldValue f13b(VARCHAR_TYPE, curFixCount);
6176 ListT<CegoFieldValue> fl13;
6177 fl13.Insert(f13a);
6178 fl13.Insert(f13b);
6179 info.Insert(fl13);
6180
6181 CegoFieldValue f14a(VARCHAR_TYPE, Chain("Max Fix Count"));
6182 CegoFieldValue f14b(VARCHAR_TYPE, maxFixCount);
6183 ListT<CegoFieldValue> fl14;
6184 fl14.Insert(f14a);
6185 fl14.Insert(f14b);
6186 info.Insert(fl14);
6187
6188 CegoFieldValue f15a(VARCHAR_TYPE, Chain("Avg Fix Try"));
6189 CegoFieldValue f15b(VARCHAR_TYPE, avgFixTry);
6190 ListT<CegoFieldValue> fl15;
6191 fl15.Insert(f15a);
6192 fl15.Insert(f15b);
6193 info.Insert(fl15);
6194
6195
6196 CegoFieldValue f16a(VARCHAR_TYPE, Chain("Disk Reads"));
6197 CegoFieldValue f16b(VARCHAR_TYPE, Chain(numDiskRead));
6198 ListT<CegoFieldValue> fl16;
6199 fl16.Insert(f16a);
6200 fl16.Insert(f16b);
6201 info.Insert(fl16);
6202
6203 CegoFieldValue f17a(VARCHAR_TYPE, Chain("Disk Writes"));
6204 CegoFieldValue f17b(VARCHAR_TYPE, Chain(numDiskWrite));
6205 ListT<CegoFieldValue> fl17;
6206 fl17.Insert(f17a);
6207 fl17.Insert(f17b);
6208 info.Insert(fl17);
6209
6210 int secDelay;
6211 int msecDelay;
6212 Chain delayStr;
6213 Chain fillStr;
6214
6215 secDelay = readDelay / 1000;
6216 msecDelay = readDelay % 1000;
6217 fillStr = Chain("000") + Chain(msecDelay);
6218 delayStr = Chain(secDelay) + Chain(".") + fillStr.subChain(fillStr.length()-3, fillStr.length()) + Chain (" msec");
6219
6220 CegoFieldValue f18a(VARCHAR_TYPE, Chain("Read Delay"));
6221 CegoFieldValue f18b(VARCHAR_TYPE, Chain(delayStr));
6222 ListT<CegoFieldValue> fl18;
6223 fl18.Insert(f18a);
6224 fl18.Insert(f18b);
6225 info.Insert(fl18);
6226
6227 secDelay = writeDelay / 1000;
6228 msecDelay = writeDelay % 1000;
6229 fillStr = Chain("000") + Chain(msecDelay);
6230 delayStr = Chain(secDelay) + Chain(".") + fillStr.subChain(fillStr.length()-3, fillStr.length()) + Chain (" msec");
6231
6232 CegoFieldValue f19a(VARCHAR_TYPE, Chain("Write Delay"));
6233 CegoFieldValue f19b(VARCHAR_TYPE, Chain(delayStr));
6234 ListT<CegoFieldValue> fl19;
6235 fl19.Insert(f19a);
6236 fl19.Insert(f19b);
6237 info.Insert(fl19);
6238
6239
6240 CegoFieldValue f20a(VARCHAR_TYPE, Chain("-------------------"));
6241 CegoFieldValue f20b(VARCHAR_TYPE, Chain("-------------------"));
6242 ListT<CegoFieldValue> fl20;
6243 fl20.Insert(f20a);
6244 fl20.Insert(f20b);
6245 info.Insert(fl20);
6246
6247 CegoFieldValue f21a(VARCHAR_TYPE, Chain("Pool Uptime"));
6248
6249 // calculate time string
6250 unsigned long long d = uptime / ( 3600 * 24 );
6251 unsigned long long h = ( uptime - ( d * 24 * 3600 )) / 3600;
6252 unsigned long long m = ( uptime - ( d * 24 * 3600 ) - ( h * 3600) ) / 60;
6253 unsigned long long s = uptime % 60;
6254
6255 Chain ss = Chain("0") + Chain(s);
6256 Chain sec = ss.subChain(ss.length()-2,ss.length());
6257
6258 Chain ms = Chain("0") + Chain(m);
6259 Chain min = ms.subChain(ms.length()-2,ms.length());
6260
6261 Chain uptimeString = Chain(d) + Chain("d ") + Chain(h) + Chain(":") + min + Chain(":") + sec;
6262 CegoFieldValue f21b(VARCHAR_TYPE, uptimeString);
6263 ListT<CegoFieldValue> fl21;
6264 fl21.Insert(f21a);
6265 fl21.Insert(f21b);
6266 info.Insert(fl21);
6267 }
6268
getSystemInfo(const Chain & tableSet,CegoTableObject & oe,ListT<ListT<CegoFieldValue>> & fa,Chain & format)6269 void CegoTableManager::getSystemInfo(const Chain& tableSet, CegoTableObject& oe, ListT< ListT<CegoFieldValue> > &fa, Chain& format)
6270 {
6271 int tabSetId = _pDBMng->getTabSetId(tableSet);
6272 int tmpFid = _pDBMng->getTmpFid(tableSet);
6273
6274 ListT<CegoField> schema;
6275 schema.Insert(CegoField(Chain("SYSINFO"), Chain("SYSINFO"), Chain("SPACE"), VARCHAR_TYPE, 10));
6276 schema.Insert(CegoField(Chain("SYSINFO"), Chain("SYSINFO"), Chain("NUMPAGES"), INT_TYPE, sizeof(int)));
6277 schema.Insert(CegoField(Chain("SYSINFO"), Chain("SYSINFO"), Chain("USEDPAGES"), INT_TYPE, sizeof(int)));
6278
6279 oe = CegoTableObject(tabSetId, CegoObject::SYSTEM, Chain("SYSINFO"), schema, Chain("SYSINFO"));
6280
6281 format = Chain("lrr");
6282
6283 ListT<CegoFieldValue> fv1;
6284
6285 fv1.Insert(CegoFieldValue(VARCHAR_TYPE, Chain("SYSTEM")));
6286 fv1.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumPages(tabSetId))));
6287 fv1.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumUsedPages(tabSetId, _pLockHandle))));
6288
6289 fa.Insert(fv1);
6290
6291 ListT<Chain> dfList;
6292 ListT<int> fidList;
6293 ListT<int> sizeList;
6294
6295 _pDBMng->getDataFileInfo(tableSet, Chain(XML_SYSFILE_VALUE), dfList, fidList, sizeList);
6296
6297 Chain *pDF = dfList.First();
6298 int *pFid = fidList.First();
6299
6300 while ( pFid && pDF)
6301 {
6302 ListT<CegoFieldValue> fv;
6303
6304 fv.Insert(CegoFieldValue(VARCHAR_TYPE, Chain("SYSTEM")));
6305 fv.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumPages(*pFid))));
6306 fv.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumUsedPages(*pFid, _pLockHandle))));
6307
6308 fa.Insert(fv);
6309
6310 pFid = fidList.Next();
6311 pDF = dfList.Next();
6312 }
6313
6314 ListT<CegoFieldValue> fv2;
6315
6316 fv2.Insert(CegoFieldValue(VARCHAR_TYPE, Chain("TEMP")));
6317 fv2.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumPages(tmpFid))));
6318 fv2.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumUsedPages(tmpFid, _pLockHandle))));
6319
6320 fa.Insert(fv2);
6321
6322 dfList.Empty();
6323 fidList.Empty();
6324 sizeList.Empty();
6325
6326 _pDBMng->getDataFileInfo(tableSet, Chain(XML_TEMPFILE_VALUE), dfList, fidList, sizeList);
6327
6328 pDF = dfList.First();
6329 pFid = fidList.First();
6330
6331 while ( pFid && pDF)
6332 {
6333 ListT<CegoFieldValue> fv;
6334
6335 fv.Insert(CegoFieldValue(VARCHAR_TYPE, Chain("TEMP")));
6336 fv.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumPages(*pFid))));
6337 fv.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumUsedPages(*pFid, _pLockHandle))));
6338
6339 fa.Insert(fv);
6340
6341 pFid = fidList.Next();
6342 pDF = dfList.Next();
6343 }
6344
6345 dfList.Empty();
6346 fidList.Empty();
6347 sizeList.Empty();
6348
6349 _pDBMng->getDataFileInfo(tableSet, Chain(XML_APPFILE_VALUE), dfList, fidList, sizeList);
6350
6351 pDF = dfList.First();
6352 pFid = fidList.First();
6353
6354 while ( pFid && pDF)
6355 {
6356 ListT<CegoFieldValue> fv;
6357
6358 fv.Insert(CegoFieldValue(VARCHAR_TYPE, Chain("DATAFILE")));
6359
6360 // fv.Insert(CegoFieldValue(VARCHAR_TYPE, *pDF));
6361
6362 fv.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumPages(*pFid))));
6363 fv.Insert(CegoFieldValue(INT_TYPE, Chain(_pDBMng->getNumUsedPages(*pFid, _pLockHandle))));
6364
6365 fa.Insert(fv);
6366
6367 pFid = fidList.Next();
6368 pDF = dfList.Next();
6369 }
6370 }
6371
dumpObject(const Chain & tableSet,const Chain & objName,CegoObject::ObjectType type,Chain & chainDump)6372 void CegoTableManager::dumpObject(const Chain& tableSet, const Chain& objName, CegoObject::ObjectType type, Chain& chainDump)
6373 {
6374 int tabSetId = _pDBMng->getTabSetId(tableSet);
6375 dumpObject(tabSetId, objName, type, chainDump);
6376 }
6377
dumpObject(int tabSetId,const Chain & objName,CegoObject::ObjectType type,Chain & chainDump)6378 void CegoTableManager::dumpObject(int tabSetId, const Chain& objName, CegoObject::ObjectType type, Chain& chainDump)
6379 {
6380
6381 chainDump = Chain("Name: <") + objName + Chain(">\n");
6382 chainDump += Chain("Type: ");
6383
6384 switch (type)
6385 {
6386 case CegoObject::TABLE:
6387 case CegoObject::AVLTREE:
6388 case CegoObject::UAVLTREE:
6389 case CegoObject::PAVLTREE:
6390 {
6391 chainDump += CegoTypeConverter::getObjectTypeString(type) + Chain("\n");
6392
6393 CegoTableObject oe;
6394 getObject(tabSetId, objName, type, oe);
6395
6396 chainDump += Chain("Schema:\n");
6397 CegoField* pF = oe.getSchema().First();
6398 while (pF)
6399 {
6400 chainDump += Chain(" TableName: <") + pF->getTableName() + Chain(">\n");
6401 chainDump += Chain(" TableAlias: <") + pF->getTableAlias() + Chain(">\n");
6402 chainDump += Chain(" AttrName: <") + pF->getAttrName() + Chain(">\n");
6403 chainDump += Chain(" Id: <") + Chain(pF->getId()) + Chain(">\n");
6404
6405 pF = oe.getSchema().Next();
6406 }
6407
6408 CegoObjectCursor* pC = getObjectCursor(tabSetId, oe.getTabName(), objName, type);
6409
6410 CegoDataPointer dp;
6411 int len;
6412 char* pc = (char*)pC->getFirst(len, dp);
6413
6414 unsigned long long rowCount=0;
6415 while ( pc && len > 0 )
6416 {
6417 rowCount++;
6418
6419 unsigned long long tid;
6420 unsigned long long tastep;
6421 CegoTupleState ts;
6422
6423 int toff = CegoQueryHelper::decodeTupleHeader(tid, tastep, ts, pc);
6424
6425 char* tp = pc + toff;
6426 int tlen = len - toff;
6427
6428
6429 chainDump += dp.toChain();
6430 chainDump += Chain(" Row=") + Chain(rowCount)
6431 + Chain(",Tid=") + Chain(tid)
6432 + Chain(",Step=") + Chain(tastep);
6433
6434 if ( ts == COMMITTED )
6435 chainDump += Chain(",State=C");
6436 else if ( ts == INSERTED )
6437 chainDump += Chain(",State=I");
6438 else if ( ts == DELETED )
6439 chainDump += Chain(",State=D");
6440 else if ( ts == OBSOLETE )
6441 chainDump += Chain(",State=O");
6442
6443 chainDump += Chain(",Data=");
6444
6445 if ( type == CegoObject::TABLE )
6446 {
6447 ListT<CegoField> fl = oe.getSchema();
6448 CegoQueryHelper::decodeFVL(fl, tp, tlen);
6449 CegoField *pF = fl.First();
6450 while ( pF )
6451 {
6452 chainDump += Chain("<") + pF->getValue().toChain() + Chain(">");
6453 pF = fl.Next();
6454 }
6455 chainDump += Chain("\n");
6456
6457 }
6458 else if ( type == CegoObject::AVLTREE || type == CegoObject::UAVLTREE || type == CegoObject::PAVLTREE )
6459 {
6460 CegoAVLIndexEntry ie;
6461 ie.setPtr(pc,len);
6462
6463 chainDump += "Entry " + dp.toChain() + ": Parent=" + ie.getParent().toChain() + " Left=" + ie.getLeftBranch().toChain() + " Right=" + ie.getRightBranch().toChain() + " Data=" + ie.getData().toChain();
6464
6465 int h = (int)ie.getHeight();
6466 chainDump += " Height=" + Chain(h);
6467
6468 if ( ie.getIdxPtr() != 0 )
6469 {
6470 int l;
6471 memcpy(&l, ie.getIdxPtr(), sizeof(int));
6472 chainDump += " Len: " + Chain(l);
6473
6474 int v;
6475 memcpy(&v, (int*)((long long)ie.getIdxPtr() + sizeof(int)), sizeof(int));
6476 chainDump += " Val: " + Chain(v);
6477
6478 // cout << " IdxPtr: " << ie.getIdxPtr();
6479 }
6480 chainDump += "\n";
6481 }
6482 else
6483 {
6484 cout << "Not implemented .." << endl;
6485 }
6486
6487 pc = (char*)pC->getNext(len, dp);
6488 }
6489
6490 delete pC;
6491
6492 break;
6493 }
6494 case CegoObject::BTREE:
6495 case CegoObject::PBTREE:
6496 case CegoObject::UBTREE:
6497 case CegoObject::PROCEDURE:
6498 case CegoObject::VIEW:
6499 case CegoObject::ALIAS:
6500 case CegoObject::TRIGGER:
6501 case CegoObject::UNDEFINED:
6502 case CegoObject::SYSTEM:
6503 case CegoObject::RBSEG:
6504 case CegoObject::FKEY:
6505 case CegoObject::CHECK:
6506 case CegoObject::JOIN:
6507 {
6508 chainDump = Chain("Not implemented");
6509 break;
6510 }
6511 }
6512 }
6513
regDataFiles(const Chain & tableSet)6514 void CegoTableManager::regDataFiles(const Chain& tableSet)
6515 {
6516 int tmpFileId = _pDBMng->getTmpFid(tableSet);
6517 int tabSetId = _pDBMng->getTabSetId(tableSet);
6518
6519 Chain dbTempFileName = _pDBMng->getTmpFileName(tableSet);
6520 Chain dbSysFileName = _pDBMng->getSysFileName(tableSet);
6521
6522 _pDBMng->log(_modId, Logger::NOTICE, Chain("Registering system datafile ") + dbSysFileName + Chain(" ..."));
6523 _pDBMng->regDataFile(tabSetId, dbSysFileName, tabSetId, _pLockHandle);
6524
6525 _pDBMng->log(_modId, Logger::NOTICE, Chain("Registering temp datafile ") + dbTempFileName + Chain(" ..."));
6526 _pDBMng->regDataFile(tabSetId, dbTempFileName, tmpFileId, _pLockHandle);
6527
6528 ListT<Chain> dfList;
6529 ListT<int> fidList;
6530 ListT<int> sizeList;
6531
6532 _pDBMng->getDataFileInfo(tableSet, Chain(XML_APPFILE_VALUE), dfList, fidList, sizeList);
6533
6534 Chain *pFileName = dfList.First();
6535 int *pFid = fidList.First();
6536 int *pSize = sizeList.First();
6537
6538 while ( pFileName && pFid && pSize )
6539 {
6540 _pDBMng->regDataFile(tabSetId, *pFileName, *pFid, _pLockHandle);
6541
6542 pFileName = dfList.Next();
6543 pFid = fidList.Next();
6544 pSize = sizeList.Next();
6545 }
6546
6547 dfList.Empty();
6548 fidList.Empty();
6549 sizeList.Empty();
6550
6551 _pDBMng->getDataFileInfo(tableSet, Chain(XML_SYSFILE_VALUE), dfList, fidList, sizeList);
6552
6553 pFileName = dfList.First();
6554 pFid = fidList.First();
6555 pSize = sizeList.First();
6556
6557 while ( pFileName && pFid && pSize )
6558 {
6559 _pDBMng->regDataFile(tabSetId, *pFileName, *pFid, _pLockHandle);
6560
6561 pFileName = dfList.Next();
6562 pFid = fidList.Next();
6563 pSize = sizeList.Next();
6564 }
6565
6566 dfList.Empty();
6567 fidList.Empty();
6568 sizeList.Empty();
6569
6570 _pDBMng->getDataFileInfo(tableSet, Chain(XML_TEMPFILE_VALUE), dfList, fidList, sizeList);
6571
6572 pFileName = dfList.First();
6573 pFid = fidList.First();
6574 pSize = sizeList.First();
6575
6576 while ( pFileName && pFid && pSize )
6577 {
6578 _pDBMng->regDataFile(tabSetId, *pFileName, *pFid, _pLockHandle);
6579
6580 pFileName = dfList.Next();
6581 pFid = fidList.Next();
6582 pSize = sizeList.Next();
6583 }
6584
6585 dfList.Empty();
6586 fidList.Empty();
6587 sizeList.Empty();
6588
6589 if ( _pDBMng->checkPointDumpEnabled(tabSetId) )
6590 {
6591 _pDBMng->restoreCheckpointDump(tabSetId, _pLockHandle);
6592 }
6593
6594 _pDBMng->log(_modId, Logger::NOTICE, Chain("Registration finished"));
6595 }
6596
6597 ///////////////////////
6598 // protected methods //
6599 ///////////////////////
6600
resetTemp(const Chain & tableSet)6601 void CegoTableManager::resetTemp(const Chain& tableSet)
6602 {
6603 int tabSetId = _pDBMng->getTabSetId(tableSet);
6604 int tmpFileId = _pDBMng->getTmpFid(tableSet);
6605
6606 _pDBMng->resetDataFile(tmpFileId);
6607
6608 PageIdType pageOffset = _pDBMng->getTempPageOffset(tabSetId);
6609
6610 for ( PageIdType i = 0 ; i < TABMNG_HASHSIZE ; i++ )
6611 {
6612 _pDBMng->claimPage(pageOffset + i, _pLockHandle);
6613 }
6614
6615 ListT<Chain> dfList;
6616 ListT<int> fidList;
6617 ListT<int> sizeList;
6618
6619 _pDBMng->getDataFileInfo(tableSet, Chain(XML_TEMPFILE_VALUE), dfList, fidList, sizeList);
6620
6621 Chain *pFileName = dfList.First();
6622 int *pFid = fidList.First();
6623 int *pSize = sizeList.First();
6624
6625 while ( pFileName && pFid && pSize )
6626 {
6627 _pDBMng->resetDataFile(*pFid);
6628 pFileName = dfList.Next();
6629 pFid = fidList.Next();
6630 pSize = sizeList.Next();
6631 }
6632 }
6633
6634
finishOpenTransaction(int tabSetId)6635 void CegoTableManager::finishOpenTransaction(int tabSetId)
6636 {
6637 // ensure that no transaction is active, in case of a crash recovery, this might be
6638 _tid[tabSetId] = 0;
6639 _tastep[tabSetId] = 0;
6640
6641 _pTM->finishOpenTransaction(tabSetId);
6642
6643 }
6644
extractIndexValue(const ListT<CegoField> & tableSchema,const ListT<CegoField> & indexSchema,char * p,int len,int & idxLen)6645 void CegoTableManager::extractIndexValue(const ListT<CegoField>& tableSchema, const ListT<CegoField>& indexSchema, char* p, int len, int& idxLen)
6646 {
6647 CegoField* pIF = indexSchema.First();
6648
6649 idxLen = 0;
6650
6651 while (pIF)
6652 {
6653 CegoField* pTF = tableSchema.First();
6654
6655 while (pTF)
6656 {
6657 if ( (Chain)pTF->getAttrName() == (Chain)pIF->getAttrName() )
6658 {
6659 int flen = pTF->getValue().getLength();
6660
6661 idxLen += flen + sizeof(int);
6662 if ( idxLen > len)
6663 {
6664 throw Exception(EXLOC, Chain("Index value too long"));
6665 }
6666
6667 memcpy(p, &flen, sizeof(int));
6668 p += sizeof(int);
6669 if ( flen > 0 )
6670 {
6671 memcpy(p, pTF->getValue().getValue(), flen);
6672 p += flen;
6673 }
6674 }
6675 pTF = tableSchema.Next();
6676 }
6677
6678 pIF = indexSchema.Next();
6679 }
6680 }
6681
abort()6682 void CegoTableManager::abort()
6683 {
6684 _isAborted = true;
6685 }
6686
proceed()6687 void CegoTableManager::proceed()
6688 {
6689 _isAborted = false;
6690 }
6691
isAborted() const6692 bool CegoTableManager::isAborted() const
6693 {
6694 return _isAborted;
6695 }
6696
poolP()6697 void CegoTableManager::poolP()
6698 {
6699 if ( _pPool )
6700 {
6701 _pPool->P(_thrIdx);
6702 }
6703 }
6704
poolV()6705 void CegoTableManager::poolV()
6706 {
6707 if ( _pPool )
6708 {
6709 _pPool->V(_thrIdx);
6710 }
6711 }
6712
addCompProcedure(int tabSetId,CegoProcedure * pProc)6713 void CegoTableManager::addCompProcedure(int tabSetId, CegoProcedure *pProc)
6714 {
6715 poolP();
6716
6717 try
6718 {
6719 CegoProcedure** pCheckProc = _procList[tabSetId].First();
6720 while ( pCheckProc )
6721 {
6722 if ( (Chain)(*pCheckProc)->getName() == (Chain)pProc->getName() )
6723 {
6724 throw Exception(EXLOC, Chain("Procedure ") + pProc->getName() + Chain(" already exists"));
6725 }
6726 pCheckProc = _procList[tabSetId].Next();
6727 }
6728 _procList[tabSetId].Insert(pProc);
6729
6730 poolV();
6731 }
6732 catch ( Exception e )
6733 {
6734 poolV();
6735 throw e;
6736 }
6737 }
6738
removeCompProcedure(int tabSetId,const Chain & procName)6739 void CegoTableManager::removeCompProcedure(int tabSetId, const Chain& procName)
6740 {
6741 poolP();
6742
6743 CegoProcedure** pProc = _procList[tabSetId].First();
6744 while ( pProc )
6745 {
6746 if ( (Chain)(*pProc)->getName() == (Chain)procName )
6747 {
6748 CegoProcedure *pDelProc = *pProc;
6749 delete pDelProc;
6750
6751 _procList[tabSetId].Remove(*pProc);
6752
6753 poolV();
6754 return;
6755 }
6756 pProc = _procList[tabSetId].Next();
6757 }
6758
6759 poolV();
6760
6761 return;
6762 }
6763
checkCompProcedure(int tabSetId,const Chain & procName)6764 bool CegoTableManager::checkCompProcedure(int tabSetId, const Chain& procName)
6765 {
6766 poolP();
6767
6768 CegoProcedure** pProc = _procList[tabSetId].First();
6769 while ( pProc )
6770 {
6771 if ( (Chain)(*pProc)->getName() == (Chain)procName )
6772 {
6773 poolV();
6774 return true;
6775 }
6776 pProc = _procList[tabSetId].Next();
6777 }
6778 poolV();
6779 return false;
6780 }
6781
getCompProcedure(int tabSetId,const Chain & procName)6782 CegoProcedure* CegoTableManager::getCompProcedure(int tabSetId, const Chain& procName)
6783 {
6784 poolP();
6785 CegoProcedure** pProc = _procList[tabSetId].First();
6786 while ( pProc )
6787 {
6788 if ( (Chain)(*pProc)->getName() == (Chain)procName )
6789 {
6790 poolV();
6791 return *pProc;
6792 }
6793 pProc = _procList[tabSetId].Next();
6794 }
6795
6796 poolV();
6797 Chain msg = Chain("Procedure ") + procName + Chain(" not compiled");
6798 throw Exception(EXLOC, msg);
6799 }
6800
addCompView(int tabSetId,CegoView * pView)6801 void CegoTableManager::addCompView(int tabSetId, CegoView *pView)
6802 {
6803 poolP();
6804 _viewList[tabSetId].Insert(pView);
6805 poolV();
6806 }
6807
removeCompView(int tabSetId,const Chain & viewName)6808 void CegoTableManager::removeCompView(int tabSetId, const Chain& viewName)
6809 {
6810 poolP();
6811 CegoView** pView = _viewList[tabSetId].First();
6812 while ( pView )
6813 {
6814 if ( (Chain)(*pView)->getViewName() == (Chain)viewName )
6815 {
6816
6817 CegoView *pDelView = *pView;
6818 delete pDelView;
6819
6820 _viewList[tabSetId].Remove(*pView);
6821
6822 poolV();
6823
6824 return;
6825 }
6826 pView = _viewList[tabSetId].Next();
6827 }
6828 poolV();
6829 return;
6830 }
6831
checkCompView(int tabSetId,const Chain & viewName)6832 bool CegoTableManager::checkCompView(int tabSetId, const Chain& viewName)
6833 {
6834 poolP();
6835 CegoView** pView = _viewList[tabSetId].First();
6836 while ( pView )
6837 {
6838 if ( (Chain)(*pView)->getViewName() == (Chain)viewName )
6839 {
6840 poolV();
6841 return true;
6842 }
6843 pView = _viewList[tabSetId].Next();
6844 }
6845 poolV();
6846 return false;
6847 }
6848
getCompView(int tabSetId,const Chain & viewName)6849 CegoView* CegoTableManager::getCompView(int tabSetId, const Chain& viewName)
6850 {
6851 poolP();
6852 CegoView** pView = _viewList[tabSetId].First();
6853 while ( pView )
6854 {
6855 if ( (Chain)(*pView)->getViewName() == (Chain)viewName )
6856 {
6857 poolV();
6858 return *pView;
6859 }
6860 pView = _viewList[tabSetId].Next();
6861 }
6862 poolV();
6863
6864 Chain msg = Chain("View ") + viewName + Chain(" not compiled");
6865 throw Exception(EXLOC, msg);
6866 }
6867
addCompTrigger(int tabSetId,CegoTrigger * pTrigger)6868 void CegoTableManager::addCompTrigger(int tabSetId, CegoTrigger *pTrigger)
6869 {
6870 poolP();
6871 _triggerList[tabSetId].Insert(pTrigger);
6872 poolV();
6873 }
6874
removeCompTrigger(int tabSetId,const Chain & triggerName)6875 void CegoTableManager::removeCompTrigger(int tabSetId, const Chain& triggerName)
6876 {
6877 poolP();
6878 CegoTrigger** pTrigger = _triggerList[tabSetId].First();
6879 while ( pTrigger )
6880 {
6881 if ( (Chain)(*pTrigger)->getName() == (Chain)triggerName )
6882 {
6883 CegoTrigger* pDelTrigger = *pTrigger;
6884 delete pDelTrigger;
6885
6886 _triggerList[tabSetId].Remove(*pTrigger);
6887
6888 poolV();
6889
6890 return;
6891 }
6892 pTrigger = _triggerList[tabSetId].Next();
6893 }
6894 poolV();
6895 return;
6896 }
6897
checkCompTrigger(int tabSetId,const Chain & triggerName)6898 bool CegoTableManager::checkCompTrigger(int tabSetId, const Chain& triggerName)
6899 {
6900 poolP();
6901 CegoTrigger** pTrigger = _triggerList[tabSetId].First();
6902 while ( pTrigger )
6903 {
6904 if ( (Chain)(*pTrigger)->getName() == (Chain)triggerName )
6905 {
6906 poolV();
6907 return true;
6908 }
6909 pTrigger = _triggerList[tabSetId].Next();
6910 }
6911 poolV();
6912 return false;
6913 }
6914
getCompTrigger(int tabSetId,const Chain & triggerName)6915 CegoTrigger* CegoTableManager::getCompTrigger(int tabSetId, const Chain& triggerName)
6916 {
6917 poolP();
6918 CegoTrigger** pTrigger = _triggerList[tabSetId].First();
6919 while ( pTrigger )
6920 {
6921 if ( (Chain)(*pTrigger)->getName() == (Chain)triggerName )
6922 {
6923 poolV();
6924 return *pTrigger;
6925 }
6926 pTrigger = _triggerList[tabSetId].Next();
6927 }
6928 poolV();
6929
6930 Chain msg = Chain("Trigger ") + triggerName + Chain(" not compiled");
6931 throw Exception(EXLOC, msg);
6932 }
6933
removeAllComp(int tabSetId)6934 void CegoTableManager::removeAllComp(int tabSetId)
6935 {
6936 poolP();
6937 CegoProcedure** pProc = _procList[tabSetId].First();
6938 while ( pProc )
6939 {
6940 CegoProcedure *pDelProc = *pProc;
6941
6942 // we first have to delete
6943 delete pDelProc;
6944
6945 // the we can remove from the list
6946 _procList[tabSetId].Remove(*pProc);
6947
6948 pProc = _procList[tabSetId].First();
6949 }
6950
6951 CegoView** pView = _viewList[tabSetId].First();
6952 while ( pView )
6953 {
6954 CegoView *pDelView = *pView;
6955
6956 // we first have to delete
6957 delete pDelView;
6958
6959 // then we can release from the list
6960 _viewList[tabSetId].Remove(*pView);
6961
6962 pView = _viewList[tabSetId].First();
6963 }
6964
6965 CegoTrigger** pTrigger = _triggerList[tabSetId].First();
6966 while ( pTrigger )
6967 {
6968 CegoTrigger *pDelTrigger = *pTrigger;
6969
6970 // we first have to delete
6971 delete pDelTrigger;
6972
6973 // then we can release from the list
6974 _triggerList[tabSetId].Remove(*pTrigger);
6975
6976 pTrigger = _triggerList[tabSetId].First();
6977 }
6978
6979 poolV();
6980 }
6981
getLHLockStat(unsigned long long lockId,Chain & lockName,int & lockCount,unsigned long long & numRdLock,unsigned long long & numWrLock,unsigned long long & sumRdDelay,unsigned long long & sumWrDelay)6982 void CegoTableManager::getLHLockStat(unsigned long long lockId, Chain& lockName, int& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay)
6983 {
6984 _pLockHandle->getLockStat(lockId, lockName, lockCount, numRdLock, numWrLock, sumRdDelay, sumWrDelay);
6985 }
6986
getLHAggLockStat(const Chain & lockName,int & numLock,int & lockCount,unsigned long long & numRdLock,unsigned long long & numWrLock,unsigned long long & sumRdDelay,unsigned long long & sumWrDelay)6987 void CegoTableManager::getLHAggLockStat(const Chain& lockName, int& numLock, int& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay)
6988 {
6989 _pLockHandle->getAggLockStat(lockName, numLock, lockCount, numRdLock, numWrLock, sumRdDelay, sumWrDelay);
6990 }
6991
getTransactionManager()6992 CegoTransactionManager* CegoTableManager::getTransactionManager()
6993 {
6994 return _pTM;
6995 }
6996
increaseBlobRef(int tabSetId,PageIdType pageId)6997 void CegoTableManager::increaseBlobRef(int tabSetId, PageIdType pageId)
6998 {
6999 CegoBufferPage bp;
7000 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7001
7002 unsigned long long blobRef;
7003
7004 memcpy (&blobRef, bp.getChunkEntry(), sizeof(unsigned long long));
7005 blobRef++;
7006 memcpy (bp.getChunkEntry(), &blobRef, sizeof(unsigned long long));
7007 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7008 }
7009
decreaseBlobRef(int tabSetId,PageIdType pageId)7010 void CegoTableManager::decreaseBlobRef(int tabSetId, PageIdType pageId)
7011 {
7012 CegoBufferPage bp;
7013 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7014
7015 unsigned long long blobRef;
7016 memcpy (&blobRef, bp.getChunkEntry(), sizeof(unsigned long long));
7017
7018 if ( blobRef <= 1 )
7019 {
7020 while ( bp.isFixed() )
7021 {
7022 pageId = bp.getNextPageId();
7023
7024 _pDBMng->bufferRelease(bp, _pLockHandle);
7025
7026 if ( pageId )
7027 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7028 }
7029 }
7030 else
7031 {
7032 blobRef--;
7033 memcpy (bp.getChunkEntry(), &blobRef, sizeof(unsigned long long));
7034 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7035 }
7036 }
7037
increaseClobRef(int tabSetId,PageIdType pageId)7038 void CegoTableManager::increaseClobRef(int tabSetId, PageIdType pageId)
7039 {
7040 CegoBufferPage bp;
7041 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7042
7043 unsigned long long clobRef;
7044
7045 memcpy (&clobRef, bp.getChunkEntry(), sizeof(unsigned long long));
7046 clobRef++;
7047 memcpy (bp.getChunkEntry(), &clobRef, sizeof(unsigned long long));
7048 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7049 }
7050
decreaseClobRef(int tabSetId,PageIdType pageId)7051 void CegoTableManager::decreaseClobRef(int tabSetId, PageIdType pageId)
7052 {
7053 CegoBufferPage bp;
7054 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7055
7056 unsigned long long clobRef;
7057 memcpy (&clobRef, bp.getChunkEntry(), sizeof(unsigned long long));
7058
7059 if ( clobRef <= 1 )
7060 {
7061 while ( bp.isFixed() )
7062 {
7063 pageId = bp.getNextPageId();
7064
7065 _pDBMng->bufferRelease(bp, _pLockHandle);
7066
7067 if ( pageId )
7068 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7069 }
7070 }
7071 else
7072 {
7073 clobRef--;
7074 memcpy (bp.getChunkEntry(), &clobRef, sizeof(unsigned long long));
7075 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7076 }
7077 }
7078
getBlobData(int tabSetId,PageIdType pageId,unsigned long long & blobSize)7079 unsigned char* CegoTableManager::getBlobData(int tabSetId, PageIdType pageId, unsigned long long& blobSize)
7080 {
7081 CegoBufferPage bp;
7082 try
7083 {
7084 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7085
7086 unsigned long long blobRef;
7087 memcpy (&blobRef, bp.getChunkEntry(), sizeof(unsigned long long));
7088
7089 memcpy (&blobSize, (char*)(bp.getChunkEntry() + sizeof(unsigned long long)), sizeof(unsigned long long));
7090
7091 // allocate buffer of size blobsize
7092
7093 unsigned char* rawBuf = (unsigned char*)malloc(blobSize);
7094 if (rawBuf == NULL)
7095 {
7096 Chain msg = Chain("Cannot allocate blob data of ") + Chain(blobSize + 1) + Chain(" bytes");
7097 throw Exception(EXLOC, msg);
7098 }
7099
7100 unsigned char* rawPtr = rawBuf;
7101
7102 unsigned long long writtenByte = 0;
7103
7104 while ( bp.isFixed() )
7105 {
7106 int chunkSize;
7107
7108 // first page with written clob size, so we have to sub the size bytes
7109 if ( writtenByte == 0 )
7110 {
7111 // take the full page chunk ?
7112 if ( bp.getChunkLen() - 2 * sizeof(unsigned long long ) < blobSize )
7113 {
7114 chunkSize = bp.getChunkLen() - 2 * sizeof(unsigned long long);
7115 }
7116 else // just take the needed chunk
7117 {
7118 chunkSize = blobSize;
7119 }
7120 }
7121 else // just take the needed
7122 {
7123 // take the full page chunk ?
7124 if ( bp.getChunkLen() < blobSize - writtenByte )
7125 {
7126 chunkSize = bp.getChunkLen();
7127 }
7128 else // just take the needed chunk
7129 {
7130 chunkSize = blobSize - writtenByte;
7131 }
7132 }
7133
7134 char* src = 0;
7135 if ( writtenByte == 0 )
7136 {
7137 src = (char*)(bp.getChunkEntry() + 2 * sizeof(unsigned long long));
7138 }
7139 else
7140 {
7141 src = (char*)(bp.getChunkEntry());
7142
7143 }
7144 memcpy(rawPtr, src, chunkSize);
7145
7146 rawPtr += chunkSize;
7147 writtenByte += chunkSize;
7148
7149 pageId = bp.getNextPageId();
7150
7151 _pDBMng->bufferUnfix(bp, false, _pLockHandle);
7152
7153 if ( pageId )
7154 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7155
7156 }
7157 return rawBuf;
7158 }
7159 catch ( Exception e )
7160 {
7161 if ( bp.isFixed() )
7162 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7163 throw e;
7164 }
7165 return 0;
7166 }
7167
getClobData(int tabSetId,PageIdType pageId,unsigned long long & clobSize)7168 char* CegoTableManager::getClobData(int tabSetId, PageIdType pageId, unsigned long long& clobSize)
7169 {
7170 CegoBufferPage bp;
7171 try
7172 {
7173 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7174
7175 unsigned long long clobRef;
7176 memcpy (&clobRef, bp.getChunkEntry(), sizeof(unsigned long long));
7177
7178 memcpy (&clobSize, (char*)(bp.getChunkEntry() + sizeof(unsigned long long)), sizeof(unsigned long long));
7179
7180 // allocate buffer of size clobsize
7181
7182 // cout << "Reading " << clobSize << " bytes from page " << pageId << endl;
7183
7184 char* rawBuf = (char*)malloc(clobSize + 1);
7185 if (rawBuf == NULL)
7186 {
7187 Chain msg = Chain("Cannot allocate clob data of ") + Chain(clobSize + 1) + Chain(" bytes");
7188 throw Exception(EXLOC, msg);
7189 }
7190
7191 char* rawPtr = rawBuf;
7192
7193 unsigned long long writtenByte = 0;
7194
7195 while ( bp.isFixed() )
7196 {
7197 int chunkSize;
7198
7199 // first page with written clob size, so we have to sub the size bytes
7200 if ( writtenByte == 0 )
7201 {
7202 // take the full page chunk ?
7203 if ( bp.getChunkLen() - 2 * sizeof(unsigned long long ) < clobSize )
7204 {
7205 chunkSize = bp.getChunkLen() - 2 * sizeof(unsigned long long);
7206 }
7207 else // just take the needed chunk
7208 {
7209 chunkSize = clobSize;
7210 }
7211 }
7212 else // just take the needed
7213 {
7214 // take the full page chunk ?
7215 if ( bp.getChunkLen() < clobSize - writtenByte )
7216 {
7217 chunkSize = bp.getChunkLen();
7218 }
7219 else // just take the needed chunk
7220 {
7221 chunkSize = clobSize - writtenByte;
7222 }
7223 }
7224
7225 char* src = 0;
7226 if ( writtenByte == 0 )
7227 {
7228 src = (char*)(bp.getChunkEntry() + 2 * sizeof(unsigned long long));
7229 }
7230 else
7231 {
7232 src = (char*)(bp.getChunkEntry());
7233
7234 }
7235 memcpy(rawPtr, src, chunkSize);
7236
7237 rawPtr += chunkSize;
7238 writtenByte += chunkSize;
7239
7240 pageId = bp.getNextPageId();
7241
7242 _pDBMng->bufferUnfix(bp, false, _pLockHandle);
7243
7244 if ( pageId )
7245 _pDBMng->bufferFix(bp, tabSetId, pageId, CegoBufferPool::SYNC, _pLockHandle);
7246
7247 }
7248 // ensure termination character
7249 rawBuf[clobSize]=0;
7250 return rawBuf;
7251 }
7252 catch ( Exception e )
7253 {
7254 if ( bp.isFixed() )
7255 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7256 throw e;
7257 }
7258 return 0;
7259 }
7260
putBlobData(int tabSetId,unsigned char * data,unsigned long long blobSize,PageIdType & pageId)7261 void CegoTableManager::putBlobData(int tabSetId, unsigned char* data, unsigned long long blobSize, PageIdType& pageId)
7262 {
7263 CegoBufferPage bp;
7264
7265 try
7266 {
7267 getNewFilePage(bp, tabSetId, CegoObject::TABLE, false, true);
7268 bp.initPage(CegoBufferPage::BLOB);
7269
7270 pageId = bp.getPageId();
7271
7272 int freeInPage = bp.getChunkLen();
7273 char* pagePtr = bp.getChunkEntry();
7274
7275 unsigned long long blobRef = 0;
7276 memcpy(pagePtr, &blobRef, sizeof(unsigned long long));
7277 pagePtr += sizeof(unsigned long long);
7278 freeInPage -= sizeof(unsigned long long);
7279
7280 memcpy(pagePtr, &blobSize, sizeof(unsigned long long));
7281 pagePtr += sizeof(unsigned long long);
7282 freeInPage -= sizeof(unsigned long long);
7283
7284 unsigned char *bufPtr = 0;
7285 unsigned long long availFromBuf = 0;
7286
7287 unsigned long long writtenByte = 0;
7288 while ( writtenByte < blobSize )
7289 {
7290 if ( availFromBuf == 0 )
7291 {
7292 availFromBuf=blobSize;
7293 bufPtr = data;
7294 }
7295 if ( freeInPage == 0 )
7296 {
7297 CegoBufferPage nextPage;
7298 getNewFilePage(nextPage, tabSetId, CegoObject::TABLE, false, true);
7299 nextPage.initPage(CegoBufferPage::BLOB);
7300
7301 bp.setNextPageId(nextPage.getPageId());
7302
7303 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7304
7305 bp = nextPage;
7306
7307 freeInPage = bp.getChunkLen();
7308 pagePtr = bp.getChunkEntry();
7309 }
7310
7311 if ( freeInPage >= availFromBuf )
7312 {
7313 memcpy(pagePtr, bufPtr, availFromBuf);
7314 writtenByte += availFromBuf;
7315 pagePtr += availFromBuf;
7316 freeInPage -= availFromBuf;
7317 availFromBuf = 0;
7318 }
7319 else if ( freeInPage < availFromBuf )
7320 {
7321 memcpy(pagePtr, bufPtr, freeInPage);
7322 writtenByte += freeInPage;
7323 bufPtr += freeInPage;
7324 availFromBuf -= freeInPage;
7325 freeInPage = 0;
7326 }
7327 }
7328 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7329 }
7330 catch ( Exception e )
7331 {
7332 if ( bp.isFixed() )
7333 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7334 throw e;
7335 }
7336 }
7337
putClobData(int tabSetId,char * data,unsigned long long clobSize,PageIdType & pageId)7338 void CegoTableManager::putClobData(int tabSetId, char* data, unsigned long long clobSize, PageIdType& pageId)
7339 {
7340 CegoBufferPage bp;
7341
7342 try
7343 {
7344 getNewFilePage(bp, tabSetId, CegoObject::TABLE, false, true);
7345 bp.initPage(CegoBufferPage::CLOB);
7346
7347 pageId = bp.getPageId();
7348
7349 int freeInPage = bp.getChunkLen();
7350 char* pagePtr = bp.getChunkEntry();
7351
7352 // cout << "Writing " << clobSize << " bytes to page " << pageId << endl;
7353
7354 unsigned long long clobRef = 0;
7355 memcpy(pagePtr, &clobRef, sizeof(unsigned long long));
7356 pagePtr += sizeof(unsigned long long);
7357 freeInPage -= sizeof(unsigned long long);
7358
7359 memcpy(pagePtr, &clobSize, sizeof(unsigned long long));
7360 pagePtr += sizeof(unsigned long long);
7361 freeInPage -= sizeof(unsigned long long);
7362
7363 char *bufPtr = 0;
7364 unsigned long long availFromBuf = 0;
7365
7366 unsigned long long writtenByte = 0;
7367 while ( writtenByte < clobSize )
7368 {
7369 if ( availFromBuf == 0 )
7370 {
7371 availFromBuf=clobSize;
7372 bufPtr = data;
7373 }
7374 if ( freeInPage == 0 )
7375 {
7376 CegoBufferPage nextPage;
7377 getNewFilePage(nextPage, tabSetId, CegoObject::TABLE, false, true);
7378 nextPage.initPage(CegoBufferPage::CLOB);
7379
7380 bp.setNextPageId(nextPage.getPageId());
7381
7382 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7383
7384 bp = nextPage;
7385
7386 freeInPage = bp.getChunkLen();
7387 pagePtr = bp.getChunkEntry();
7388 }
7389
7390 if ( freeInPage >= availFromBuf )
7391 {
7392 memcpy(pagePtr, bufPtr, availFromBuf);
7393 writtenByte += availFromBuf;
7394 pagePtr += availFromBuf;
7395 freeInPage -= availFromBuf;
7396 availFromBuf = 0;
7397 }
7398 else if ( freeInPage < availFromBuf )
7399 {
7400 memcpy(pagePtr, bufPtr, freeInPage);
7401 writtenByte += freeInPage;
7402 bufPtr += freeInPage;
7403 availFromBuf -= freeInPage;
7404 freeInPage = 0;
7405 }
7406 }
7407 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7408 }
7409 catch ( Exception e )
7410 {
7411 if ( bp.isFixed() )
7412 _pDBMng->bufferUnfix(bp, true, _pLockHandle);
7413 throw e;
7414 }
7415 }
7416
getBlobs(int tabSetId,const ListT<CegoField> & fvl,ListT<CegoBlob> & blobList)7417 void CegoTableManager::getBlobs(int tabSetId, const ListT<CegoField>& fvl, ListT<CegoBlob>& blobList)
7418 {
7419 CegoField* pF = fvl.First();
7420 while (pF)
7421 {
7422 if ( pF->getValue().getType() == BLOB_TYPE )
7423 {
7424 PageIdType pageId;
7425 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
7426
7427 unsigned long long blobSize;
7428 unsigned char* blobBuf = getBlobData(tabSetId, pageId, blobSize);
7429
7430 blobList.Insert(CegoBlob(pageId, blobBuf, blobSize));
7431 }
7432 pF = fvl.Next();
7433 }
7434 }
7435
getClobs(int tabSetId,const ListT<CegoField> & fvl,ListT<CegoClob> & clobList)7436 void CegoTableManager::getClobs(int tabSetId, const ListT<CegoField>& fvl, ListT<CegoClob>& clobList)
7437 {
7438 CegoField* pF = fvl.First();
7439 while (pF)
7440 {
7441 if ( pF->getValue().getType() == CLOB_TYPE )
7442 {
7443 PageIdType pageId;
7444 memcpy(&pageId, pF->getValue().getValue(), sizeof(PageIdType));
7445
7446 unsigned long long clobSize;
7447 char* clobBuf = getClobData(tabSetId, pageId, clobSize);
7448
7449 clobList.Insert(CegoClob(pageId, clobBuf, clobSize));
7450 }
7451 pF = fvl.Next();
7452 }
7453 }
7454
getBlobs(int tabSetId,ListT<CegoExpr * > & exprList,CegoProcBlock * pBlock,ListT<CegoBlob> & blobList)7455 void CegoTableManager::getBlobs(int tabSetId, ListT<CegoExpr*>& exprList, CegoProcBlock* pBlock, ListT<CegoBlob>& blobList )
7456 {
7457 CegoExpr** pExpr = exprList.First();
7458 while ( pExpr )
7459 {
7460 (*pExpr)->setBlock(pBlock);
7461
7462 CegoFieldValue fv;
7463
7464 if ( (*pExpr)->checkLob(fv) )
7465 {
7466 if ( fv.getType() == BLOB_TYPE )
7467 {
7468 PageIdType pageId;
7469 memcpy(&pageId, fv.getValue(), sizeof(PageIdType));
7470
7471 unsigned long long blobSize;
7472 unsigned char* blobBuf = getBlobData(tabSetId, pageId, blobSize);
7473
7474 blobList.Insert(CegoBlob(pageId, blobBuf, blobSize));
7475 }
7476 }
7477 pExpr = exprList.Next();
7478 }
7479 }
7480
getClobs(int tabSetId,ListT<CegoExpr * > & exprList,CegoProcBlock * pBlock,ListT<CegoClob> & clobList)7481 void CegoTableManager::getClobs(int tabSetId, ListT<CegoExpr*>& exprList, CegoProcBlock* pBlock, ListT<CegoClob>& clobList)
7482 {
7483 CegoExpr** pExpr = exprList.First();
7484 while ( pExpr )
7485 {
7486 (*pExpr)->setBlock(pBlock);
7487
7488 CegoFieldValue fv;
7489 if ( (*pExpr)->checkLob(fv) )
7490 {
7491 if ( fv.getType() == CLOB_TYPE)
7492 {
7493 PageIdType pageId;
7494 memcpy(&pageId, fv.getValue(), sizeof(PageIdType));
7495
7496 unsigned long long clobSize;
7497 char* clobBuf = getClobData(tabSetId, pageId, clobSize);
7498
7499 clobList.Insert(CegoClob(pageId, clobBuf, clobSize));
7500 }
7501 }
7502 pExpr = exprList.Next();
7503 }
7504 }
7505
addBUStat(int tabSetId,const Chain & butype,const Chain & msg)7506 void CegoTableManager::addBUStat(int tabSetId, const Chain& butype, const Chain& msg)
7507 {
7508 // insert entry in bustat table
7509
7510 CegoTableObject boe;
7511 getObject(tabSetId, Chain(SYSTAB_BUSTAT_ID), CegoObject::SYSTEM, boe);
7512 ListT<CegoField> fvl = boe.getSchema();
7513 CegoField *pF = fvl.First();
7514 while ( pF )
7515 {
7516 if (pF->getAttrName() == Chain(SYSTAB_TS_ATTR) )
7517 {
7518 Datetime n;
7519 unsigned long long *pDV = new (unsigned long long);
7520 *pDV = n.asLong();
7521 CegoFieldValue fv(DATETIME_TYPE, pDV, sizeof(unsigned long long), true);
7522 pF->setValue(fv);
7523 }
7524 else if ( pF->getAttrName() == Chain(SYSTAB_BUINFO_ATTR) )
7525 {
7526 pF->setValue(CegoFieldValue(VARCHAR_TYPE, butype));
7527 }
7528 else if ( pF->getAttrName() == Chain(SYSTAB_BUMSG_ATTR) )
7529 {
7530 pF->setValue(CegoFieldValue(VARCHAR_TYPE, msg));
7531 }
7532 pF = fvl.Next();
7533 }
7534
7535 CegoDataPointer bp;
7536 insertDataTable(boe, fvl, bp, true, true);
7537 }
7538
typeConversionAllowed(CegoDataType fromType,CegoDataType toType)7539 bool CegoTableManager::typeConversionAllowed(CegoDataType fromType, CegoDataType toType)
7540 {
7541 if ( fromType == toType
7542 || ( fromType == INT_TYPE && toType == LONG_TYPE )
7543 || ( fromType == INT_TYPE && toType == VARCHAR_TYPE )
7544 || ( fromType == INT_TYPE && toType == BOOL_TYPE )
7545 || ( fromType == INT_TYPE && toType == DATETIME_TYPE )
7546 || ( fromType == INT_TYPE && toType == BIGINT_TYPE )
7547 || ( fromType == INT_TYPE && toType == FLOAT_TYPE )
7548 || ( fromType == INT_TYPE && toType == DOUBLE_TYPE )
7549 || ( fromType == INT_TYPE && toType == DECIMAL_TYPE )
7550 || ( fromType == BOOL_TYPE && toType == FIXED_TYPE )
7551 || ( fromType == LONG_TYPE && toType == VARCHAR_TYPE )
7552 || ( fromType == LONG_TYPE && toType == BOOL_TYPE )
7553 || ( fromType == LONG_TYPE && toType == BIGINT_TYPE )
7554 || ( fromType == LONG_TYPE && toType == DOUBLE_TYPE )
7555 || ( fromType == LONG_TYPE && toType == DECIMAL_TYPE )
7556 || ( fromType == BOOL_TYPE && toType == FIXED_TYPE )
7557 || ( fromType == BOOL_TYPE && toType == INT_TYPE )
7558 || ( fromType == BOOL_TYPE && toType == LONG_TYPE )
7559 || ( fromType == BOOL_TYPE && toType == VARCHAR_TYPE )
7560 || ( fromType == BOOL_TYPE && toType == BIGINT_TYPE )
7561 || ( fromType == BOOL_TYPE && toType == FLOAT_TYPE )
7562 || ( fromType == BOOL_TYPE && toType == DOUBLE_TYPE )
7563 || ( fromType == BOOL_TYPE && toType == DECIMAL_TYPE )
7564 || ( fromType == BOOL_TYPE && toType == FIXED_TYPE )
7565 || ( fromType == DATETIME_TYPE && toType == INT_TYPE )
7566 || ( fromType == DATETIME_TYPE && toType == VARCHAR_TYPE )
7567 || ( fromType == DATETIME_TYPE && toType == BIGINT_TYPE )
7568 || ( fromType == DATETIME_TYPE && toType == FLOAT_TYPE )
7569 || ( fromType == DATETIME_TYPE && toType == DOUBLE_TYPE )
7570 || ( fromType == DATETIME_TYPE && toType == DECIMAL_TYPE )
7571 || ( fromType == BIGINT_TYPE && toType == VARCHAR_TYPE )
7572 || ( fromType == FLOAT_TYPE && toType == VARCHAR_TYPE )
7573 || ( fromType == DOUBLE_TYPE && toType == VARCHAR_TYPE )
7574 || ( fromType == DECIMAL_TYPE && toType == VARCHAR_TYPE )
7575 || ( fromType == FIXED_TYPE && toType == VARCHAR_TYPE )
7576 || ( fromType == SMALLINT_TYPE && toType == VARCHAR_TYPE )
7577 || ( fromType == TINYINT_TYPE && toType == VARCHAR_TYPE )
7578 || ( fromType == TINYINT_TYPE && toType == INT_TYPE )
7579 || ( fromType == TINYINT_TYPE && toType == LONG_TYPE ) )
7580 {
7581 return true;
7582 }
7583
7584 return false;
7585 }
7586