Varchar free when compact table was called.
[csql.git] / src / sql / SqlStatement.cxx
blob4773f54dca14b5a01555389a6f6dffbb2a5bf74b
1 /***************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include <os.h>
21 #include <Statement.h>
22 #include <SqlStatement.h>
23 #include <dmllex.h>
25 char *lexInput;
26 extern ParsedData *parsedData;
28 int yyparse ();
29 bool SqlConnection::isInit = false;
30 #if (defined MMDB && defined EMBED)
31 bool SqlConnection::firstThread = false;
32 GlobalUniqueID SqlConnection::UID;
33 #endif
34 List SqlConnection::connList;
37 SqlStatement::~SqlStatement()
39 if (isPrepd) { free(); isPrepd = false; }
42 List SqlStatement::getTableNameList()
44 return pData.getTableNameList();
46 SqlStatement::SqlStatement()
48 innerStmt = NULL;
49 sqlCon = NULL;
50 stmt = NULL;
51 isPrepd = false;
52 isCachedStmt=false;
53 isMgmtStatement = false;
55 void SqlStatement::setConnection(AbsSqlConnection *conn)
57 sqlCon = (SqlConnection*)conn;
58 con = conn;
61 void SqlStatement::setSqlConnection(SqlConnection *conn)
63 sqlCon = conn;
66 DbRetVal SqlStatement::executeDirect(char *str)
68 DbRetVal rv = OK;
69 int rows = 0;
70 rv = prepare(str);
71 if (rv != OK) return rv;
72 rv = execute(rows);
73 if (rv != OK) return rv;
74 return rv;
77 DbRetVal SqlStatement::prepare(char *stmtstr)
79 DbRetVal rv = OK;
80 if (! sqlCon->isConnectionOpen()) {
81 printError(ErrNotOpen, "Connection not open");
82 return ErrNotOpen;
84 SqlStatement *cachedStmt = sqlCon->findInCache(stmtstr);
85 if (cachedStmt)
87 *this = *cachedStmt;
88 this->stmt->setParsedData(&this->pData);
89 logFine(Conf::logger,"GOT STMT FROM CACHE: %s %x", stmtstr, cachedStmt);
90 return OK;
92 // take mutex here
93 int ret = ProcessManager::prepareMutex.tryLock(10, 1000);
94 if (ret != 0)
96 printError(ErrLockTimeOut, "Unable to get prepare mutex");
97 return ErrLockTimeOut;
100 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
101 if (isPrepared()) free();
102 lexInput = stmtstr;
103 parsedData = &pData;
105 yy_buffer_state *yy_buffer= yy_scan_string(stmtstr);
106 int rc = yyparse();
107 if (yy_buffer) yy_delete_buffer(yy_buffer);
108 if (rc != 0)
110 free();
111 parsedData = NULL;
112 ProcessManager::prepareMutex.releaseLock(-1, false);
113 return ErrSyntaxError;
115 if( parsedData->getStmtType() == MgmtStatement)
117 isPrepd = true;
118 parsedData = NULL;
119 isMgmtStatement = true;
120 ProcessManager::prepareMutex.releaseLock(-1, false);
121 logFine(Conf::logger,"PREPARE: %s %x", stmtstr, stmt);
122 return OK;
124 stmt = StatementFactory::getStatement(parsedData);
125 stmt->setDbMgr(dbMgr);
126 if( parsedData->getStmtType() == UserStatement)
128 UserManager* userMgr = sqlCon->getConnObject().getUserManager();
129 UserTblStatement *ustmt = (UserTblStatement *)stmt;
130 ustmt->setUserManager(userMgr,sqlCon->getConnObject().getUserName());
132 rv = stmt->resolve();
133 if (rv != OK)
135 free();
136 parsedData = NULL;
137 ProcessManager::prepareMutex.releaseLock(-1, false);
138 return rv;
140 isPrepd = true;
141 if (Conf::config.getStmtCacheSize()) {
142 if (stmt->noOfParamFields() > 0) {
143 isCachedStmt = true;
144 sqlCon->addToCache(this, stmtstr);
145 }else if (Conf::config.useCacheNoParam())
147 if (parsedData->getCacheWorthy())
149 isCachedStmt = true;
150 sqlCon->addToCache(this, stmtstr);
154 parsedData = NULL;
155 ProcessManager::prepareMutex.releaseLock(-1, false);
156 return OK;
159 char* SqlStatement::getTableName()
161 return pData.getTableName();
164 bool SqlStatement::isSelect()
166 if ((pData.getStmtType() == SelectStatement) || (pData.getStmtType() == MetaStatement)) return true;
167 return false;
170 bool SqlStatement::isPrepared() { return isPrepd; }
172 DbRetVal SqlStatement::execute(int &rowsAffected)
174 DbRetVal rv = OK;
175 if (! sqlCon->isConnectionOpen()) {
176 printError(ErrNotOpen, "Connection not open");
177 return ErrNotOpen;
179 if (! isPrepared()) {
180 printError(ErrNotPrepared, "Statement Not Prepared");
181 return ErrNotPrepared;
183 if( isMgmtStatement )
185 flushCacheStmt();
186 logFiner(Conf::logger,"EXECUTE: %x", stmt);
187 return OK;
189 rv = stmt->execute(rowsAffected);
190 if (rv == ErrAlready && pData.getStmtType() == SelectStatement )
191 { //if previous scan is not closed, close it
192 SelStatement *selStmt = (SelStatement*) stmt;
193 selStmt->close();
194 rv = stmt->execute(rowsAffected);
196 logFiner(Conf::logger,"EXECUTE: %x", stmt);
197 return rv;
200 void* SqlStatement::fetch()
202 if (! sqlCon->isConnectionOpen()) {
203 printError(ErrNotOpen, "Connection not open");
204 return NULL;
206 if (! isPrepared()) {
207 printError(ErrNotPrepared, "Statement Not Prepared");
208 return NULL;
210 if (pData.getStmtType() == SelectStatement ) {
211 SelStatement *selStmt = (SelStatement*) stmt;
212 return selStmt->fetch();
214 else if(pData.getStmtType() == MetaStatement){
215 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
216 return metaStmt->fetch();
218 else { return NULL;}
221 void* SqlStatement::fetch(DbRetVal &rv)
223 if (! sqlCon->isConnectionOpen()) {
224 printError(ErrNotOpen, "Connection not open");
225 rv = ErrNoConnection;
226 return NULL;
228 if (! isPrepared()) {
229 printError(ErrNotPrepared, "Statement Not Prepared");
230 return NULL;
232 if (pData.getStmtType() == SelectStatement ) {
233 SelStatement *selStmt = (SelStatement*) stmt;
234 return selStmt->fetch(rv);
236 else if(pData.getStmtType() == MetaStatement){
237 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
238 return metaStmt->fetch(rv);
240 else { return NULL;}
243 void* SqlStatement::fetchAndPrint(bool SQL)
245 if (! sqlCon->isConnectionOpen()) {
246 printError(ErrNotOpen, "Connection not open");
247 return NULL;
249 if (! isPrepared()) {
250 printError(ErrNotPrepared, "Statement Not Prepared");
251 return NULL;
253 if (pData.getStmtType() != SelectStatement) return NULL;
254 SelStatement *selStmt = (SelStatement*) stmt;
255 return selStmt->fetchAndPrint(SQL);
258 DbRetVal SqlStatement::bindParam(int pos, void* value)
260 DbRetVal rv = OK;
261 rv = stmt->setParam(pos, value);
262 return rv;
265 DbRetVal SqlStatement::bindField(int pos, void* value)
267 DbRetVal rv = OK;
268 if (pData.getStmtType() == SelectStatement ) {
269 SelStatement *selStmt = (SelStatement*) stmt;
270 return selStmt->setBindField(pos, value);
272 else if(pData.getStmtType() == MetaStatement){
273 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
274 return metaStmt->setBindField(pos, value);
276 else { return ErrBadCall;}
278 void* SqlStatement::next()
280 if (pData.getStmtType() == SelectStatement ) {
281 SelStatement *selStmt = (SelStatement*) stmt;
282 return( (void*) selStmt->next() );
284 else if(pData.getStmtType() == MetaStatement){
285 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
286 return( (void*) metaStmt->next() );
288 else { return 0;}
291 bool SqlStatement::isFldNull(int pos)
293 if (pData.getStmtType() != SelectStatement) return 0;
294 SelStatement *selStmt = (SelStatement*) stmt;
295 return (selStmt->isFldNull(pos));
297 bool SqlStatement::isFldNull(char *name)
299 if (pData.getStmtType() != SelectStatement) return 0;
300 SelStatement *selStmt = (SelStatement*) stmt;
301 return (selStmt->isFldNull(name));
303 DbRetVal SqlStatement::close()
305 if (pData.getStmtType() == SelectStatement ) {
306 SelStatement *selStmt = (SelStatement*) stmt;
307 logFinest(Conf::logger,"CLOSE: %x", stmt);
308 return selStmt->close();
310 else if(pData.getStmtType() == MetaStatement){
311 MetadataStatement *selStmt = (MetadataStatement*) stmt;
312 logFinest(Conf::logger,"CLOSE: %x", stmt);
313 return selStmt->close();
315 else { return OK;}
318 void* SqlStatement::getParamValuePtr( int pos )
320 //if (pData.getStmtType() != SelectStatement) return 0;
321 DmlStatement *dmlStmt = (DmlStatement*) stmt;
322 return( (void*) dmlStmt->getParamValuePtr( pos ) );
325 char* SqlStatement::getFieldName( int pos )
327 if (pData.getStmtType() == SelectStatement ) {
328 SelStatement *selStmt = (SelStatement*) stmt;
329 return( (char*) selStmt->getFieldName( pos ) );
331 else if(pData.getStmtType() == MetaStatement){
332 MetadataStatement *selStmt = (MetadataStatement*) stmt;
333 return( (char*) selStmt->getFieldName( pos ) );
335 else { return 0;}
338 DataType SqlStatement::getFieldType( int pos )
340 if (pData.getStmtType() == SelectStatement ) {
341 SelStatement *selStmt = (SelStatement*) stmt;
342 return( (DataType) selStmt->getFieldType( pos ) );
344 else if(pData.getStmtType() == MetaStatement){
345 MetadataStatement *selStmt = (MetadataStatement*) stmt;
346 return( (DataType) selStmt->getFieldType( pos ) );
348 else { return typeUnknown;}
350 int SqlStatement::getFieldLength( int pos )
352 if (pData.getStmtType() == SelectStatement ) {
353 SelStatement *selStmt = (SelStatement*) stmt;
354 return( (int) selStmt->getFieldLength( pos ) );
356 else if(pData.getStmtType() == MetaStatement){
357 MetadataStatement *selStmt = (MetadataStatement*) stmt;
358 return( (int) selStmt->getFieldLength( pos ) );
360 else { return 0;}
363 void* SqlStatement::getFieldValuePtr( int pos )
365 if (pData.getStmtType() == SelectStatement ) {
366 SelStatement *selStmt = (SelStatement*) stmt;
367 return( (void*) selStmt->getFieldValuePtr( pos ) );
369 else if(pData.getStmtType() == MetaStatement){
370 MetadataStatement *selStmt = (MetadataStatement*) stmt;
371 return( (void*) selStmt->getFieldValuePtr( pos ) );
373 else { return 0;}
375 void* SqlStatement::getFieldValuePtr( char *name )
377 if (pData.getStmtType() == SelectStatement ) {
378 SelStatement *selStmt = (SelStatement*) stmt;
379 return( (void*) selStmt->getFieldValuePtr( name ) );
381 else if(pData.getStmtType() == MetaStatement){
382 MetadataStatement *selStmt = (MetadataStatement*) stmt;
383 return( (void*) selStmt->getFieldValuePtr( name ) );
385 else { return NULL;}
388 int SqlStatement::noOfProjFields()
390 if (pData.getStmtType() == SelectStatement ) {
391 SelStatement *selStmt = (SelStatement*) stmt;
392 return selStmt->noOfProjFields();
394 else if(pData.getStmtType() == MetaStatement){
395 MetadataStatement *selStmt = (MetadataStatement*) stmt;
396 return selStmt->noOfProjFields();
398 else { return 0;}
401 void SqlStatement::getProjFieldType(int *data)
403 if (pData.getStmtType() == SelectStatement ) {
404 SelStatement *selStmt = (SelStatement*) stmt;
405 return( selStmt->getProjFieldType(data) );
407 else if(pData.getStmtType() == MetaStatement){
408 MetadataStatement *selStmt = (MetadataStatement*) stmt;
409 return( selStmt->getProjFieldType(data) );
415 int SqlStatement::noOfParamFields()
417 return stmt->noOfParamFields();
420 DbRetVal SqlStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
422 DbRetVal rv = OK;
423 if (pData.getStmtType() == SelectStatement ) {
424 SelStatement *selStmt = (SelStatement*) stmt;
425 rv = selStmt->getProjFldInfo(projpos, fInfo);
427 else if(pData.getStmtType() == MetaStatement){
428 MetadataStatement *selStmt = (MetadataStatement*) stmt;
429 rv = selStmt->getProjFldInfo(projpos, fInfo);
430 } else { return ErrBadCall;}
431 return rv;
434 DbRetVal SqlStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
436 DbRetVal rv = OK;
437 if (pData.getStmtType() ==SelectStatement ||
438 pData.getStmtType() ==InsertStatement ||
439 pData.getStmtType() ==UpdateStatement ||
440 pData.getStmtType() ==DeleteStatement)
443 DmlStatement *dmlStmt = (DmlStatement*) stmt;
444 rv = dmlStmt->getParamFldInfo(parampos, fInfo);
446 return rv;
449 DbRetVal SqlStatement::free()
451 logFinest(Conf::logger,"FREE: %x", stmt);
452 if (isCachedStmt) {
453 stmt=NULL;
454 pData.init();
455 isPrepd = false;
456 return OK;
458 if(stmt) delete stmt;
459 stmt = NULL;
460 pData.reset();
461 isMgmtStatement = false;
462 isPrepd = false;
463 return OK;
466 void SqlStatement::setNull(int pos)
468 stmt->setNull(pos);
470 void SqlStatement::setShortParam(int paramPos, short value)
472 stmt->setShortParam(paramPos, value);
474 void SqlStatement::setIntParam(int paramPos, int value)
476 stmt->setIntParam(paramPos, value);
478 void SqlStatement::setLongParam(int paramPos, long value)
480 stmt->setLongParam(paramPos, value);
482 void SqlStatement::setLongLongParam(int paramPos, long long value)
484 stmt->setLongLongParam(paramPos, value);
486 void SqlStatement::setByteIntParam(int paramPos, ByteInt value)
488 stmt->setByteIntParam(paramPos, value);
490 void SqlStatement::setFloatParam(int paramPos, float value)
492 stmt->setFloatParam(paramPos, value);
494 void SqlStatement::setDoubleParam(int paramPos, double value)
496 stmt->setDoubleParam(paramPos, value);
498 void SqlStatement::setStringParam(int paramPos, char *value)
500 stmt->setStringParam(paramPos, value);
502 void SqlStatement::setDateParam(int paramPos, Date value)
504 stmt->setDateParam(paramPos, value);
506 void SqlStatement::setTimeParam(int paramPos, Time value)
508 stmt->setTimeParam(paramPos, value);
510 void SqlStatement::setTimeStampParam(int paramPos, TimeStamp value)
512 stmt->setTimeStampParam(paramPos, value);
514 void SqlStatement::setBinaryParam(int paramPos, void *value, int length)
516 stmt->setBinaryParam(paramPos, value, length);
518 int SqlStatement::getFldPos(char *name)
520 return stmt->getFldPos(name);
522 long long SqlStatement::getLastInsertedVal(DbRetVal &rv)
524 return stmt->getLastInsertedVal(rv);
526 List SqlStatement::getAllTableNames(DbRetVal &ret)
528 DatabaseManager *dbMgr = NULL;
529 List tbNmList;
530 dbMgr=sqlCon->getConnObject().getDatabaseManager();
531 int rv = ret;
532 if(dbMgr != NULL)
533 tbNmList = dbMgr->getAllTableNames(&rv);
534 ret = (DbRetVal) rv;
535 return tbNmList;
538 List SqlStatement::getAllUserNames(DbRetVal &ret)
540 UserManager *urMgr = NULL;
541 List urNmList;
542 urMgr=sqlCon->getConnObject().getUserManager();
543 int rv = ret;
544 if(urMgr != NULL)
545 urNmList = urMgr->getAllUserNames(&rv);
546 ret = (DbRetVal) rv;
547 return urNmList;
549 List SqlStatement::getFieldNameList(const char *tblName)
551 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
552 Table *table = dbMgr->openTable(tblName);
553 if (NULL == table) {
554 List dummyList;
555 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
556 return dummyList;
558 List fldNameList = table->getFieldNameList();
559 dbMgr->closeTable(table);
560 return fldNameList;
562 DbRetVal SqlStatement::getFieldInfo(const char *tblName, const char *fldName, FieldInfo *&info)
564 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
565 Table *table = dbMgr->openTable(tblName);
566 if (NULL == table) {
567 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
568 return ErrLockTimeOut;
570 DbRetVal rv = table->getFieldInfo(fldName, info);
571 dbMgr->closeTable(table);
572 return OK;
574 void SqlStatement::setLoading(bool flag)
576 if (pData.getStmtType() == InsertStatement||
577 pData.getStmtType() == UpdateStatement||
578 pData.getStmtType() == DeleteStatement)
580 DmlStatement *dmlStmt = (DmlStatement*) stmt;
581 dmlStmt->setLoading(flag);
583 return;
586 int SqlStatement::getNoOfPagesForTable(char *tblName)
588 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
589 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
590 return dbMgrImpl->getNoOfPagesForTable(tblName);
593 DbRetVal SqlStatement::loadRecords(char *tblName, void *buf)
595 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
596 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
597 return dbMgrImpl->loadRecords(tblName, (char *) buf);
600 DbRetVal SqlStatement::pasteRecords(char *tblName, void *buffer)
602 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
603 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
604 return dbMgrImpl->pasteRecords(tblName, buffer);
606 void SqlStatement::flushCacheStmt()
608 return sqlCon->flushCacheStmt();
610 //-------------------------------------------------------------------
612 static void sigTermHandler(int sig)
614 ListIterator iter= SqlConnection::connList.getIterator();
615 SqlConnection *conn = NULL;
616 while (iter.hasElement())
618 conn = (SqlConnection*) iter.nextElement();
619 conn->flushCacheStmt();
620 if (conn->isConnectionOpen()) conn->disconnect();
622 exit(0);
625 DbRetVal SqlConnection::connect (char *user, char * pass)
627 DbRetVal ret = conn.open(user, pass);
628 if (ret != OK) return ret;
629 if (ret == OK) isConnOpen = true;
630 if (!isInit) initialize();
631 connList.append(this);
632 DbRetVal rv = OK;
633 #if (defined MMDB && EMBED)
634 os::signal(SIGINT, sigTermHandler);
635 os::signal(SIGTERM, sigTermHandler);
636 if (Conf::config.useDurability() && !firstThread) {
637 rv = recoverCsqlDB();
638 if (rv != OK) {
639 printError(ErrSysInternal, "Recovery Failed");
640 return rv;
642 firstThread = true;
644 rollback(); //for drop table execute in redo log
645 #endif
646 return ret;
649 void SqlConnection::flushCacheStmt()
651 ListIterator iter = cachedStmts.getIterator();
652 while (iter.hasElement()) {
653 CachedStmtNode* node = (CachedStmtNode*) iter.nextElement();
654 free(node->sqlString);
655 node->sqlStmt->setCachedStmt(false);
656 node->sqlStmt->free();
657 delete node->sqlStmt;
658 delete node;
660 cachedStmts.reset();
661 return;
664 SqlStatement* SqlConnection::findInCache(char *stmtstr)
666 ListIterator iter = cachedStmts.getIterator();
667 int inputStmtLen = strlen(stmtstr);
668 CachedStmtNode *node = NULL;
669 while ((node = (CachedStmtNode*)iter.nextElement()) != NULL)
671 if (node->stmtLength == inputStmtLen)
673 if (0 == strcmp(node->sqlString, stmtstr))
675 logFiner(Conf::logger, "Statement Retrieved From Cache %x\n",
676 node->sqlStmt);
677 node->hits++;
678 return node->sqlStmt;
682 return NULL;
684 void SqlConnection::addToCache(SqlStatement *sqlStmt, char* stmtString)
686 SqlStatement *stmt = new SqlStatement();
687 *stmt= *sqlStmt;
688 CachedStmtNode *node = new CachedStmtNode();
689 node->sqlStmt = stmt;
690 node->stmtLength = strlen(stmtString);
691 node->sqlString = (char*)malloc(node->stmtLength+1);
692 strcpy(node->sqlString, stmtString);
693 if (cachedStmts.size() >= Conf::config.getStmtCacheSize())
695 removeLeastUsed();
697 cachedStmts.append(node);
698 logFiner(Conf::logger, "Statement added To Cache %x\n", node->sqlStmt);
699 logFinest(Conf::logger, "Statement added To Cache %s\n", node->sqlString);
700 return ;
702 void SqlConnection::removeLeastUsed()
704 ListIterator iter = cachedStmts.getIterator();
705 CachedStmtNode *node = NULL, *toRemove =NULL;
706 int lowHits = 0;
707 bool firstCall = true;
708 while((node = (CachedStmtNode*) iter.nextElement()) != NULL)
710 if (firstCall) {
711 firstCall = false;
712 lowHits = node->hits;
713 toRemove = node; //if cache size is 1
714 continue;
716 if (lowHits >= node->hits) toRemove = node;
718 cachedStmts.remove(toRemove);
719 logFiner(Conf::logger, "Statement removed from Cache %x\n", toRemove->sqlStmt);
720 logFinest(Conf::logger, "Statement removed from Cache %s\n", toRemove->sqlString);
721 return;
723 SqlConnection::~SqlConnection()
725 innerConn = NULL;
726 flushCacheStmt();
727 if (isConnOpen) disconnect();
729 static void sigUsr1Handler(int sig)
731 ListIterator iter= SqlConnection::connList.getIterator();
732 SqlConnection *conn = NULL;
733 while (iter.hasElement())
735 conn = (SqlConnection*) iter.nextElement();
736 conn->flushCacheStmt();
738 os::signal(SIGCSQL1, sigUsr1Handler);
739 return;
742 static void exithandler(void)
744 ListIterator iter= SqlConnection::connList.getIterator();
745 SqlConnection *conn = NULL;
746 while (iter.hasElement())
748 conn = (SqlConnection*) iter.nextElement();
749 conn->flushCacheStmt();
750 conn->disconnect();
754 void SqlConnection::initialize()
756 os::signal(SIGCSQL1, sigUsr1Handler);
757 #if (defined MMDB && defined EMBED)
758 os::atexit(exithandler);
759 #endif
760 isInit = true;
763 #if (defined MMDB && defined EMBED)
764 DbRetVal SqlConnection::recoverCsqlDB()
766 DbRetVal rv = OK;
767 char dbRedoFileName[MAX_FILE_LEN];
768 char dbChkptSchema[MAX_FILE_LEN];
769 char dbChkptMap[MAX_FILE_LEN];
770 char dbChkptData[MAX_FILE_LEN];
771 char dbBackupFile[MAX_FILE_LEN];
772 char cmd[IDENTIFIER_LENGTH];
773 //check for check point file if present recover
774 sprintf(dbChkptSchema, "%s/db.chkpt.schema1", Conf::config.getDbFile());
775 if (FILE *file = fopen(dbChkptSchema, "r")) {
776 fclose(file);
777 sprintf(cmd, "cp -f %s %s/db.chkpt.schema", dbChkptSchema,
778 Conf::config.getDbFile());
779 int ret = system(cmd);
780 if (ret != 0) return ErrOS;
782 sprintf(dbChkptMap, "%s/db.chkpt.map1", Conf::config.getDbFile());
783 if (FILE *file = fopen(dbChkptMap, "r")) {
784 fclose(file);
785 sprintf(cmd, "cp -f %s %s/db.chkpt.map", dbChkptMap,
786 Conf::config.getDbFile());
787 int ret = system(cmd);
788 if (ret != 0) return ErrOS;
790 int chkptID= Database::getCheckpointID();
791 sprintf(dbChkptData, "%s/db.chkpt.data%d", Conf::config.getDbFile(),
792 chkptID);
793 sprintf(dbBackupFile, "%s/db.chkpt.data1", Conf::config.getDbFile());
794 FILE *fl = NULL;
795 if (!Conf::config.useMmap() && (fl = fopen(dbBackupFile, "r"))) {
796 fclose(fl);
797 sprintf(cmd, "cp %s/db.chkpt.data1 %s", Conf::config.getDbFile(),
798 dbChkptData);
799 int ret = system(cmd);
800 if (ret != 0) return ErrOS;
802 if (FILE *file = fopen(dbChkptData, "r")) {
803 fclose(file);
804 rv = recoverSystemAndUserDB();
807 //check for redo log file if present apply redo logs
808 sprintf(dbRedoFileName, "%s/csql.db.cur", Conf::config.getDbFile());
809 if (FILE *file = fopen(dbRedoFileName, "r"))
811 fclose(file);
812 applyRedoLogs(dbRedoFileName);
813 DatabaseManager *dbMgr = getConnObject().getDatabaseManager();
814 rv = dbMgr->checkPoint();
815 if (rv != OK)
817 printError(ErrSysInternal, "checkpoint failed after redo log apply");
818 return ErrOS;
821 return OK;
824 DbRetVal SqlConnection::recoverSystemAndUserDB()
826 DbRetVal rv = OK;
827 char schFile[1024];
828 sprintf(schFile, "%s/db.chkpt.schema", Conf::config.getDbFile());
829 if (FILE *file = fopen(schFile, "r")) {
830 applySchemaFile(file);
832 DatabaseManager *dbMgr = getConnObject().getDatabaseManager();
833 dbMgr->recover();
834 return OK;
837 DbRetVal SqlConnection::applySchemaFile(FILE *fp)
839 char buf[8192];
840 char eof;
841 SqlStatement *stmt = new SqlStatement();
842 while ((eof = getQueryFromSchemaFile(fp,buf)) != EOF) {
843 stmt->setConnection(this);
844 stmt->prepare(buf);
845 int rows = 0;
846 stmt->execute(rows);
848 delete stmt;
849 return OK;
852 char SqlConnection::getQueryFromSchemaFile(FILE *fp, char *buf)
854 char c, *bufBegin=buf;
855 int charCnt=0;
856 while( (c=(char ) fgetc(fp)) != EOF && c != ';')
858 *buf++ = c; charCnt++;
859 if( charCnt == SQL_STMT_LEN ) {
860 printf("SQL Statement length is greater than %d. "
861 "Ignoring the statement.\n", SQL_STMT_LEN );
862 *bufBegin++ =';';
863 *bufBegin ='\0';
864 return 0;
867 *buf++ = ';';
868 *buf = '\0';
869 return c;
872 void SqlConnection::addToHashTable(int stmtID, AbsSqlStatement* sHdl)
874 int bucketNo = stmtID % STMT_BUCKET_SIZE;
875 StmtBucket *buck = (StmtBucket *) stmtBuckets;
876 StmtBucket *stmtBucket = &buck[bucketNo];
877 StmtNode *node = new StmtNode();
878 node->stmtId = stmtID;
879 node->stmt = sHdl;
880 stmtBucket->bucketList.append(node);
881 return;
884 void SqlConnection::removeFromHashTable(int stmtID)
886 int bucketNo = stmtID % STMT_BUCKET_SIZE;
887 StmtBucket *buck = (StmtBucket *) stmtBuckets;
888 StmtBucket *stmtBucket = &buck[bucketNo];
889 StmtNode *node = NULL;
890 ListIterator it = stmtBucket->bucketList.getIterator();
891 while(it.hasElement()) {
892 node = (StmtNode *) it.nextElement();
893 if(stmtID == node->stmtId) break;
895 it.reset();
896 stmtBucket->bucketList.remove(node);
897 return;
900 AbsSqlStatement *SqlConnection::getStmtFromHashTable(int stmtId)
902 int bucketNo = stmtId % STMT_BUCKET_SIZE;
903 StmtBucket *buck = (StmtBucket *) stmtBuckets;
904 StmtBucket *stmtBucket = &buck[bucketNo];
905 StmtNode *node = NULL;
906 ListIterator it = stmtBucket->bucketList.getIterator();
907 while(it.hasElement()) {
908 node = (StmtNode *) it.nextElement();
909 if(stmtId == node->stmtId) {
910 return node->stmt;
913 return NULL;
916 void setParam(AbsSqlStatement *stmt, int pos, DataType type , int length, void *value)
918 switch(type)
920 case typeInt:
921 stmt->setIntParam(pos, *(int*)value);
922 break;
923 case typeLong:
924 stmt->setLongParam(pos, *(long*) value);
925 break;
926 case typeLongLong:
927 stmt->setLongLongParam(pos, *(long long*)value);
928 break;
929 case typeShort:
930 stmt->setShortParam(pos, *(short*)value);
931 break;
932 case typeByteInt:
933 stmt->setByteIntParam(pos, *(ByteInt*)value);
934 break;
935 case typeDouble:
936 stmt->setDoubleParam(pos, *(double*)value);
937 break;
938 case typeFloat:
939 stmt->setFloatParam(pos, *(float*)value);
940 break;
941 case typeDate:
942 stmt->setDateParam(pos, *(Date*)value);
943 break;
944 case typeTime:
945 stmt->setTimeParam(pos, *(Time*)value);
946 break;
947 case typeTimeStamp:
948 stmt->setTimeStampParam(pos, *(TimeStamp*)value);
949 break;
950 case typeString:
951 case typeVarchar:
952 stmt->setStringParam(pos, (char*)value);
953 break;
954 case typeBinary:
955 stmt->setBinaryParam(pos, value, length);
956 break;
957 default:
958 printf("unknown type\n");
959 break;
961 return;
964 int SqlConnection::applyRedoLogs(char *redoFile)
966 struct stat st;
967 DbRetVal rv = OK;
968 int fd = open(redoFile, O_RDONLY);
969 if (-1 == fd) { return OK; }
970 if (fstat(fd, &st) == -1) {
971 printError(ErrSysInternal, "Unable to retrieve undo log file size");
972 close(fd);
973 return 1;
975 if (st.st_size ==0) {
976 close(fd);
977 return OK;
979 void *startAddr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
980 if (MAP_FAILED == startAddr) {
981 printf("Unable to read undo log file:mmap failed.\n");
982 return 2;
984 stmtBuckets = malloc (STMT_BUCKET_SIZE * sizeof(StmtBucket));
985 memset(stmtBuckets, 0, STMT_BUCKET_SIZE * sizeof(StmtBucket));
987 char *iter = (char*)startAddr;
988 void *value = NULL;
989 int logType, eType;
990 int stmtID;
991 int txnID;
992 int len, ret, retVal =0;
993 int loglen;
994 char stmtString[SQL_STMT_LEN];
995 //printf("size of file %d\n", st.st_size);
996 while(true) {
997 //printf("OFFSET HERE %d\n", iter - (char*)startAddr);
998 if (iter - (char*)startAddr >= st.st_size) break;
999 logType = *(int*)iter;
1000 if (logType == -1) { //prepare
1001 iter = iter + sizeof(int);
1002 txnID = *(int*) iter; iter += sizeof(int);
1003 loglen = *(int*) iter; iter += sizeof(int);
1004 stmtID = *(int*)iter;
1005 iter = iter + sizeof(int);
1006 len = *(int*)iter;
1007 iter = iter + sizeof(int);
1008 strncpy(stmtString, iter, len);
1009 iter = iter + len;
1010 //printf("PREPARE:%d %d %s\n", stmtID, len, stmtString);
1011 AbsSqlStatement *st = SqlFactory::createStatement(CSqlDirect);
1012 SqlStatement *stmt = (SqlStatement *)st;
1013 stmt->setConnection(this);
1014 rv = stmt->prepare(stmtString);
1015 if (rv != OK) {
1016 printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString);
1017 retVal=1;
1018 break;
1020 stmt->prepare(stmtString);
1021 SqlStatement *sqlStmt = (SqlStatement*)stmt;
1022 sqlStmt->setLoading(true);
1023 addToHashTable(stmtID, stmt);
1025 else if(logType == -2) { //commit
1026 beginTrans();
1027 iter = iter + sizeof(int);
1028 txnID = *(int*) iter; iter += sizeof(int);
1029 loglen = *(int*) iter; iter += sizeof(int);
1030 char *curPtr = iter;
1031 while(true) {
1032 //printf("Iter length %d\n", iter - curPtr);
1033 if (iter - (char*)startAddr >= st.st_size) {
1034 //file end reached
1035 //printf("Redo log file end\n");
1036 retVal=0;
1037 break;
1039 stmtID = *(int*)iter;
1040 //printf("stmtid %d\n", stmtID);
1041 iter = iter + sizeof(int);
1042 eType = *(int*)iter;
1043 //printf("eType is %d\n", eType);
1044 AbsSqlStatement *stmt = getStmtFromHashTable(stmtID);
1045 if (0 == eType) { //execute type
1046 iter = iter + sizeof(int);
1047 //printf("EXEC: %d\n", stmtID);
1048 if (stmt) {
1049 rv = stmt->execute(ret);
1050 if (rv != OK) {
1051 printError(ErrSysInternal, "unable to execute");
1052 retVal=2;
1053 break;
1055 } else {
1056 printError(ErrSysInternal, "statement not found for %d\n",stmtID);
1058 if (*(int*)iter <0) break;
1059 } else if ( 1 == eType) { //set type
1060 iter=iter+sizeof(int);
1061 int pos = *(int*) iter;
1062 iter=iter+sizeof(int);
1063 DataType type = (DataType)(*(int*)iter);
1064 iter=iter+sizeof(int);
1065 int len = *(int*) iter;
1066 iter=iter+sizeof(int);
1067 value = iter;
1068 //AllDataType::printVal(value, type, len);
1069 iter=iter+len;
1070 //printf("SET: %d %d %d %d\n", stmtID, pos, type, len);
1071 setParam(stmt, pos, type, len, value);
1072 if (*(int*)iter <0) break;
1075 commit();
1077 else if(logType == -3) { //free
1078 iter = iter + sizeof(int);
1079 txnID = *(int*) iter; iter += sizeof(int);
1080 loglen = *(int*) iter; iter += sizeof(int);
1081 stmtID = *(int*)iter;
1082 iter = iter + sizeof(int);
1083 AbsSqlStatement *stmt = getStmtFromHashTable(stmtID);
1084 if (stmt) {
1085 stmt->free();
1086 removeFromHashTable(stmtID);
1087 } else { printError(ErrSysInternal, "statement not found for %d\n",stmtID);}
1089 else if(logType == -4) { //prepare and execute
1090 iter = iter + sizeof(int);
1091 txnID = *(int*) iter; iter += sizeof(int);
1092 loglen = *(int*) iter; iter += sizeof(int);
1093 stmtID = *(int*)iter;
1094 iter = iter + sizeof(int);
1095 len = *(int*)iter;
1096 iter = iter + sizeof(int);
1097 strncpy(stmtString, iter, len);
1098 stmtString[len+1] ='\0';
1099 iter = iter + len;
1100 //printf("CREATE:%d %d %s\n", stmtID, len, stmtString);
1101 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
1102 if ( NULL == stmt) {
1103 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
1104 retVal=3;
1105 break;
1107 stmt->setConnection(this);
1108 rv = stmt->prepare(stmtString);
1109 if (rv != OK) {
1110 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
1111 retVal=4;
1112 break;
1114 rv = stmt->execute(ret);
1115 if (rv != OK) {
1116 if (strlen(stmtString) > 6 &&
1117 ( (strncasecmp(stmtString,"CREATE", 6) == 0) ||
1118 (strncasecmp(stmtString,"DROP", 4) == 0)) ) {
1119 // conn->disconnect();
1120 // return OK;
1121 continue;
1123 printError(ErrSysInternal, "unable to execute %s", stmtString);
1124 retVal=5;
1125 break;
1127 stmt->free();
1128 }else{
1129 printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType);
1130 retVal=6;
1131 break;
1134 munmap((char*)startAddr, st.st_size);
1135 close(fd);
1136 //freeAllStmtHandles();
1137 return retVal;
1139 #endif