1 /***************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.com *
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. *
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. *
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 ***************************************************************************/
21 #include <Statement.h>
22 #include <SqlStatement.h>
26 extern ParsedData
*parsedData
;
29 bool SqlConnection::isInit
= false;
30 #if (defined MMDB && defined EMBED)
31 bool SqlConnection::firstThread
= false;
32 GlobalUniqueID
SqlConnection::UID
;
34 List
SqlConnection::connList
;
36 SqlStatement::~SqlStatement()
38 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
;}
39 if (isPrepd
) { free(); isPrepd
= false; }
42 List
SqlStatement::getTableNameList()
44 return pData
.getTableNameList();
46 SqlStatement::SqlStatement()
53 isMgmtStatement
= false;
56 void SqlStatement::setConnection(AbsSqlConnection
*conn
)
58 sqlCon
= (SqlConnection
*)conn
;
62 void SqlStatement::setSqlConnection(SqlConnection
*conn
)
67 DbRetVal
SqlStatement::executeDirect(char *str
)
72 if (rv
!= OK
) return rv
;
74 if (rv
!= OK
) return rv
;
77 void SqlStatement::setStmtString(char *ststr
)
79 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
; }
80 sqlStmtString
= (char*) malloc(strlen(ststr
)+1);
81 strcpy(sqlStmtString
, ststr
);
84 DbRetVal
SqlStatement::prepare()
86 return prepareInt(sqlStmtString
);
89 DbRetVal
SqlStatement::prepare(char *stmtstr
)
91 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
;}
92 sqlStmtString
= (char*) malloc(strlen(stmtstr
)+1);
93 strcpy(sqlStmtString
, stmtstr
);
94 return prepareInt(stmtstr
);
97 DbRetVal
SqlStatement::prepareInt(char *stmtstr
)
100 if (! sqlCon
->isConnectionOpen()) {
101 printError(ErrNotOpen
, "Connection not open");
104 SqlStatement
*cachedStmt
= sqlCon
->findInCache(stmtstr
);
108 this->stmt
->setParsedData(&this->pData
);
110 logFine(Conf::logger
,"GOT STMT FROM CACHE: %s %x", stmtstr
, cachedStmt
);
114 int ret
= ProcessManager::prepareMutex
.tryLock(10, 1000);
117 printError(ErrLockTimeOut
, "Unable to get prepare mutex");
118 return ErrLockTimeOut
;
121 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
122 if (isPrepared()) free();
126 yy_buffer_state
*yy_buffer
= yy_scan_string(stmtstr
);
128 if (yy_buffer
) yy_delete_buffer(yy_buffer
);
133 ProcessManager::prepareMutex
.releaseLock(-1, false);
134 return ErrSyntaxError
;
136 if( parsedData
->getStmtType() == MgmtStatement
)
140 isMgmtStatement
= true;
141 ProcessManager::prepareMutex
.releaseLock(-1, false);
142 logFine(Conf::logger
,"PREPARE: %s %x", stmtstr
, stmt
);
145 stmt
= StatementFactory::getStatement(parsedData
);
146 stmt
->setDbMgr(dbMgr
);
147 if( parsedData
->getStmtType() == UserStatement
)
149 UserManager
* userMgr
= sqlCon
->getConnObject().getUserManager();
150 UserTblStatement
*ustmt
= (UserTblStatement
*)stmt
;
151 ustmt
->setUserManager(userMgr
,sqlCon
->getConnObject().getUserName());
153 rv
= stmt
->resolve();
158 ProcessManager::prepareMutex
.releaseLock(-1, false);
162 if (!isCachedStmt
&& Conf::config
.getStmtCacheSize()) {
163 if (stmt
->noOfParamFields() > 0) {
165 sqlCon
->addToCache(this, stmtstr
);
166 }else if (Conf::config
.useCacheNoParam())
168 if (parsedData
->getCacheWorthy())
171 sqlCon
->addToCache(this, stmtstr
);
176 ProcessManager::prepareMutex
.releaseLock(-1, false);
180 char* SqlStatement::getTableName()
182 return pData
.getTableName();
185 bool SqlStatement::isSelect()
187 if ((pData
.getStmtType() == SelectStatement
) || (pData
.getStmtType() == MetaStatement
)) return true;
191 bool SqlStatement::isPrepared() { return isPrepd
; }
193 DbRetVal
SqlStatement::execute(int &rowsAffected
)
196 if (! sqlCon
->isConnectionOpen()) {
197 printError(ErrNotOpen
, "Connection not open");
200 if (! isPrepared()) {
201 printError(ErrNotPrepared
, "Statement Not Prepared");
202 return ErrNotPrepared
;
204 if( isMgmtStatement
)
207 logFiner(Conf::logger
,"EXECUTE: %x", stmt
);
210 rv
= stmt
->execute(rowsAffected
);
211 if (rv
== ErrAlready
&& pData
.getStmtType() == SelectStatement
)
212 { //if previous scan is not closed, close it
213 SelStatement
*selStmt
= (SelStatement
*) stmt
;
215 rv
= stmt
->execute(rowsAffected
);
217 logFiner(Conf::logger
,"EXECUTE: %x", stmt
);
221 void* SqlStatement::fetch()
223 if (! sqlCon
->isConnectionOpen()) {
224 printError(ErrNotOpen
, "Connection not open");
227 if (! isPrepared()) {
228 printError(ErrNotPrepared
, "Statement Not Prepared");
231 if (pData
.getStmtType() == SelectStatement
) {
232 SelStatement
*selStmt
= (SelStatement
*) stmt
;
233 return selStmt
->fetch();
235 else if(pData
.getStmtType() == MetaStatement
){
236 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
237 return metaStmt
->fetch();
242 void* SqlStatement::fetch(DbRetVal
&rv
)
244 if (! sqlCon
->isConnectionOpen()) {
245 printError(ErrNotOpen
, "Connection not open");
246 rv
= ErrNoConnection
;
249 if (! isPrepared()) {
250 printError(ErrNotPrepared
, "Statement Not Prepared");
253 if (pData
.getStmtType() == SelectStatement
) {
254 SelStatement
*selStmt
= (SelStatement
*) stmt
;
255 return selStmt
->fetch(rv
);
257 else if(pData
.getStmtType() == MetaStatement
){
258 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
259 return metaStmt
->fetch(rv
);
264 void* SqlStatement::fetchAndPrint(bool SQL
)
266 if (! sqlCon
->isConnectionOpen()) {
267 printError(ErrNotOpen
, "Connection not open");
270 if (! isPrepared()) {
271 printError(ErrNotPrepared
, "Statement Not Prepared");
274 if (pData
.getStmtType() != SelectStatement
) return NULL
;
275 SelStatement
*selStmt
= (SelStatement
*) stmt
;
276 return selStmt
->fetchAndPrint(SQL
);
279 DbRetVal
SqlStatement::bindParam(int pos
, void* value
)
282 rv
= stmt
->setParam(pos
, value
);
286 DbRetVal
SqlStatement::bindField(int pos
, void* value
)
289 if (pData
.getStmtType() == SelectStatement
) {
290 SelStatement
*selStmt
= (SelStatement
*) stmt
;
291 return selStmt
->setBindField(pos
, value
);
293 else if(pData
.getStmtType() == MetaStatement
){
294 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
295 return metaStmt
->setBindField(pos
, value
);
297 else { return ErrBadCall
;}
299 void* SqlStatement::next()
301 if (pData
.getStmtType() == SelectStatement
) {
302 SelStatement
*selStmt
= (SelStatement
*) stmt
;
303 return( (void*) selStmt
->next() );
305 else if(pData
.getStmtType() == MetaStatement
){
306 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
307 return( (void*) metaStmt
->next() );
312 bool SqlStatement::isFldNull(int pos
)
314 if (pData
.getStmtType() != SelectStatement
) return 0;
315 SelStatement
*selStmt
= (SelStatement
*) stmt
;
316 return (selStmt
->isFldNull(pos
));
318 bool SqlStatement::isFldNull(char *name
)
320 if (pData
.getStmtType() != SelectStatement
) return 0;
321 SelStatement
*selStmt
= (SelStatement
*) stmt
;
322 return (selStmt
->isFldNull(name
));
324 DbRetVal
SqlStatement::close()
326 if (pData
.getStmtType() == SelectStatement
) {
327 SelStatement
*selStmt
= (SelStatement
*) stmt
;
328 logFinest(Conf::logger
,"CLOSE: %x", stmt
);
329 return selStmt
->close();
331 else if(pData
.getStmtType() == MetaStatement
){
332 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
333 logFinest(Conf::logger
,"CLOSE: %x", stmt
);
334 return selStmt
->close();
339 void* SqlStatement::getParamValuePtr( int pos
)
341 //if (pData.getStmtType() != SelectStatement) return 0;
342 DmlStatement
*dmlStmt
= (DmlStatement
*) stmt
;
343 return( (void*) dmlStmt
->getParamValuePtr( pos
) );
346 char* SqlStatement::getFieldName( int pos
)
348 if (pData
.getStmtType() == SelectStatement
) {
349 SelStatement
*selStmt
= (SelStatement
*) stmt
;
350 return( (char*) selStmt
->getFieldName( pos
) );
352 else if(pData
.getStmtType() == MetaStatement
){
353 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
354 return( (char*) selStmt
->getFieldName( pos
) );
359 DataType
SqlStatement::getFieldType( int pos
)
361 if (pData
.getStmtType() == SelectStatement
) {
362 SelStatement
*selStmt
= (SelStatement
*) stmt
;
363 return( (DataType
) selStmt
->getFieldType( pos
) );
365 else if(pData
.getStmtType() == MetaStatement
){
366 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
367 return( (DataType
) selStmt
->getFieldType( pos
) );
369 else { return typeUnknown
;}
371 int SqlStatement::getFieldLength( int pos
)
373 if (pData
.getStmtType() == SelectStatement
) {
374 SelStatement
*selStmt
= (SelStatement
*) stmt
;
375 return( (int) selStmt
->getFieldLength( pos
) );
377 else if(pData
.getStmtType() == MetaStatement
){
378 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
379 return( (int) selStmt
->getFieldLength( pos
) );
384 void* SqlStatement::getFieldValuePtr( int pos
)
386 if (pData
.getStmtType() == SelectStatement
) {
387 SelStatement
*selStmt
= (SelStatement
*) stmt
;
388 return( (void*) selStmt
->getFieldValuePtr( pos
) );
390 else if(pData
.getStmtType() == MetaStatement
){
391 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
392 return( (void*) selStmt
->getFieldValuePtr( pos
) );
396 void* SqlStatement::getFieldValuePtr( char *name
)
398 if (pData
.getStmtType() == SelectStatement
) {
399 SelStatement
*selStmt
= (SelStatement
*) stmt
;
400 return( (void*) selStmt
->getFieldValuePtr( name
) );
402 else if(pData
.getStmtType() == MetaStatement
){
403 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
404 return( (void*) selStmt
->getFieldValuePtr( name
) );
409 int SqlStatement::noOfProjFields()
411 if (pData
.getStmtType() == SelectStatement
) {
412 SelStatement
*selStmt
= (SelStatement
*) stmt
;
413 return selStmt
->noOfProjFields();
415 else if(pData
.getStmtType() == MetaStatement
){
416 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
417 return selStmt
->noOfProjFields();
422 void SqlStatement::getProjFieldType(int *data
)
424 if (pData
.getStmtType() == SelectStatement
) {
425 SelStatement
*selStmt
= (SelStatement
*) stmt
;
426 return( selStmt
->getProjFieldType(data
) );
428 else if(pData
.getStmtType() == MetaStatement
){
429 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
430 return( selStmt
->getProjFieldType(data
) );
436 int SqlStatement::noOfParamFields()
438 return stmt
->noOfParamFields();
441 DbRetVal
SqlStatement::getProjFldInfo (int projpos
, FieldInfo
*&fInfo
)
444 if (pData
.getStmtType() == SelectStatement
) {
445 SelStatement
*selStmt
= (SelStatement
*) stmt
;
446 rv
= selStmt
->getProjFldInfo(projpos
, fInfo
);
448 else if(pData
.getStmtType() == MetaStatement
){
449 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
450 rv
= selStmt
->getProjFldInfo(projpos
, fInfo
);
451 } else { return ErrBadCall
;}
455 DbRetVal
SqlStatement::getParamFldInfo (int parampos
, FieldInfo
*&fInfo
)
458 if (pData
.getStmtType() ==SelectStatement
||
459 pData
.getStmtType() ==InsertStatement
||
460 pData
.getStmtType() ==UpdateStatement
||
461 pData
.getStmtType() ==DeleteStatement
)
464 DmlStatement
*dmlStmt
= (DmlStatement
*) stmt
;
465 rv
= dmlStmt
->getParamFldInfo(parampos
, fInfo
);
470 DbRetVal
SqlStatement::free()
472 logFinest(Conf::logger
,"FREE: %x", stmt
);
477 if (sqlStmtString
) sqlCon
->setStmtNotInUse(sqlStmtString
);
478 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
; }
479 isCachedStmt
= false;
482 if(stmt
) delete stmt
;
485 isMgmtStatement
= false;
487 isCachedStmt
= false;
488 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
; }
492 void SqlStatement::setNull(int pos
)
496 void SqlStatement::setShortParam(int paramPos
, short value
)
498 stmt
->setShortParam(paramPos
, value
);
500 void SqlStatement::setIntParam(int paramPos
, int value
)
502 stmt
->setIntParam(paramPos
, value
);
504 void SqlStatement::setLongParam(int paramPos
, long value
)
506 stmt
->setLongParam(paramPos
, value
);
508 void SqlStatement::setLongLongParam(int paramPos
, long long value
)
510 stmt
->setLongLongParam(paramPos
, value
);
512 void SqlStatement::setByteIntParam(int paramPos
, ByteInt value
)
514 stmt
->setByteIntParam(paramPos
, value
);
516 void SqlStatement::setFloatParam(int paramPos
, float value
)
518 stmt
->setFloatParam(paramPos
, value
);
520 void SqlStatement::setDoubleParam(int paramPos
, double value
)
522 stmt
->setDoubleParam(paramPos
, value
);
524 void SqlStatement::setStringParam(int paramPos
, char *value
)
526 stmt
->setStringParam(paramPos
, value
);
528 void SqlStatement::setDateParam(int paramPos
, Date value
)
530 stmt
->setDateParam(paramPos
, value
);
532 void SqlStatement::setTimeParam(int paramPos
, Time value
)
534 stmt
->setTimeParam(paramPos
, value
);
536 void SqlStatement::setTimeStampParam(int paramPos
, TimeStamp value
)
538 stmt
->setTimeStampParam(paramPos
, value
);
540 void SqlStatement::setBinaryParam(int paramPos
, void *value
, int length
)
542 stmt
->setBinaryParam(paramPos
, value
, length
);
544 int SqlStatement::getFldPos(char *name
)
546 return stmt
->getFldPos(name
);
548 long long SqlStatement::getLastInsertedVal(DbRetVal
&rv
)
550 return stmt
->getLastInsertedVal(rv
);
552 List
SqlStatement::getAllTableNames(DbRetVal
&ret
)
554 DatabaseManager
*dbMgr
= NULL
;
556 dbMgr
=sqlCon
->getConnObject().getDatabaseManager();
559 tbNmList
= dbMgr
->getAllTableNames(&rv
);
564 List
SqlStatement::getAllUserNames(DbRetVal
&ret
)
566 UserManager
*urMgr
= NULL
;
568 urMgr
=sqlCon
->getConnObject().getUserManager();
571 urNmList
= urMgr
->getAllUserNames(&rv
);
575 List
SqlStatement::getFieldNameList(const char *tblName
)
577 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
578 Table
*table
= dbMgr
->openTable(tblName
);
581 printError(ErrLockTimeOut
, "Unable to open table %s", tblName
);
584 List fldNameList
= table
->getFieldNameList();
585 dbMgr
->closeTable(table
);
588 DbRetVal
SqlStatement::getFieldInfo(const char *tblName
, const char *fldName
, FieldInfo
*&info
)
590 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
591 Table
*table
= dbMgr
->openTable(tblName
);
593 printError(ErrLockTimeOut
, "Unable to open table %s", tblName
);
594 return ErrLockTimeOut
;
596 DbRetVal rv
= table
->getFieldInfo(fldName
, info
);
597 dbMgr
->closeTable(table
);
600 void SqlStatement::setLoading(bool flag
)
602 if (pData
.getStmtType() == InsertStatement
||
603 pData
.getStmtType() == UpdateStatement
||
604 pData
.getStmtType() == DeleteStatement
)
606 DmlStatement
*dmlStmt
= (DmlStatement
*) stmt
;
607 dmlStmt
->setLoading(flag
);
612 int SqlStatement::getNoOfPagesForTable(char *tblName
)
614 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
615 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
616 return dbMgrImpl
->getNoOfPagesForTable(tblName
);
619 DbRetVal
SqlStatement::loadRecords(char *tblName
, void *buf
)
621 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
622 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
623 return dbMgrImpl
->loadRecords(tblName
, (char *) buf
);
626 DbRetVal
SqlStatement::pasteRecords(char *tblName
, void *buffer
)
628 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
629 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
630 return dbMgrImpl
->pasteRecords(tblName
, buffer
);
632 void SqlStatement::flushCacheStmt()
634 return sqlCon
->flushCacheStmt();
636 void SqlStatement::resetStmtString() {
639 //-------------------------------------------------------------------
641 static void sigTermHandler(int sig
)
643 ListIterator iter
= SqlConnection::connList
.getIterator();
644 SqlConnection
*conn
= NULL
;
645 while (iter
.hasElement())
647 conn
= (SqlConnection
*) iter
.nextElement();
648 conn
->flushCacheStmt();
649 if (conn
->isConnectionOpen()) conn
->disconnect();
654 DbRetVal
SqlConnection::connect (char *user
, char * pass
)
656 DbRetVal ret
= conn
.open(user
, pass
);
657 if (ret
!= OK
) return ret
;
658 if (ret
== OK
) isConnOpen
= true;
659 if (!isInit
) initialize();
660 connList
.append(this);
662 #if (defined MMDB && EMBED)
663 os::signal(SIGINT
, sigTermHandler
);
664 os::signal(SIGTERM
, sigTermHandler
);
665 if (Conf::config
.useDurability() && !firstThread
) {
666 rv
= recoverCsqlDB();
668 printError(ErrSysInternal
, "Recovery Failed");
673 rollback(); //for drop table execute in redo log
678 void SqlConnection::flushCacheStmt()
680 ListIterator iter
= cachedStmts
.getIterator();
681 while (iter
.hasElement()) {
682 CachedStmtNode
* node
= (CachedStmtNode
*) iter
.nextElement();
683 //do not delete when the statement is currently in use.
684 //otherwise it leads to illegal memory access when application
685 //calls any method on this statement
686 if (node
->inUse
) continue;
687 free(node
->sqlString
);
688 node
->sqlStmt
->setCachedStmt(false);
689 node
->sqlStmt
->free();
690 delete node
->sqlStmt
;
697 void SqlConnection::setStmtNotInUse(char *stmtstr
)
699 ListIterator iter
= cachedStmts
.getIterator();
700 int inputStmtLen
= strlen(stmtstr
);
701 CachedStmtNode
*node
= NULL
;
702 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
704 if (node
->stmtLength
== inputStmtLen
)
706 if (0 == strcmp(node
->sqlString
, stmtstr
))
714 SqlStatement
* SqlConnection::findInCache(char *stmtstr
)
716 ListIterator iter
= cachedStmts
.getIterator();
717 int inputStmtLen
= strlen(stmtstr
);
718 CachedStmtNode
*node
= NULL
;
719 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
721 if (node
->stmtLength
== inputStmtLen
)
723 if (0 == strcmp(node
->sqlString
, stmtstr
))
725 logFiner(Conf::logger
, "Statement Retrieved From Cache %x\n",
729 return node
->sqlStmt
;
735 void SqlConnection::addToCache(SqlStatement
*sqlStmt
, char* stmtString
)
737 SqlStatement
*stmt
= new SqlStatement();
739 CachedStmtNode
*node
= new CachedStmtNode();
740 node
->sqlStmt
= stmt
;
741 node
->stmtLength
= strlen(stmtString
);
742 node
->sqlString
= (char*)malloc(node
->stmtLength
+1);
744 strcpy(node
->sqlString
, stmtString
);
745 if (cachedStmts
.size() >= Conf::config
.getStmtCacheSize())
749 node
->sqlStmt
->resetStmtString();
750 cachedStmts
.append(node
);
751 logFiner(Conf::logger
, "Statement added To Cache %x\n", node
->sqlStmt
);
752 logFinest(Conf::logger
, "Statement added To Cache %s\n", node
->sqlString
);
755 void SqlConnection::removeLeastUsed()
757 ListIterator iter
= cachedStmts
.getIterator();
758 CachedStmtNode
*node
= NULL
, *toRemove
=NULL
;
760 bool firstCall
= true;
761 while((node
= (CachedStmtNode
*) iter
.nextElement()) != NULL
)
765 lowHits
= node
->hits
;
766 toRemove
= node
; //if cache size is 1
769 if (lowHits
>= node
->hits
) toRemove
= node
;
771 cachedStmts
.remove(toRemove
);
772 //TODO::check whether there is memory leak for list elements
773 logFiner(Conf::logger
, "Statement removed from Cache %x\n", toRemove
->sqlStmt
);
774 logFinest(Conf::logger
, "Statement removed from Cache %s\n", toRemove
->sqlString
);
777 SqlConnection::~SqlConnection()
780 if (isConnOpen
) disconnect();
784 static void sigUsr1Handler(int sig
)
786 ListIterator iter
= SqlConnection::connList
.getIterator();
787 SqlConnection
*conn
= NULL
;
788 while (iter
.hasElement())
790 conn
= (SqlConnection
*) iter
.nextElement();
791 conn
->flushCacheStmt();
793 os::signal(SIGCSQL1
, sigUsr1Handler
);
797 static void exithandler(void)
799 ListIterator iter
= SqlConnection::connList
.getIterator();
800 SqlConnection
*conn
= NULL
;
801 while (iter
.hasElement())
803 conn
= (SqlConnection
*) iter
.nextElement();
804 conn
->flushCacheStmt();
808 void SqlConnection::displayStmtCache()
810 ListIterator iter
= cachedStmts
.getIterator();
811 CachedStmtNode
*node
= NULL
;
812 printf("STATEMENT CACHE START \n");
813 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
817 printf("STATEMENT CACHE END\n");
820 void SqlConnection::initialize()
822 os::signal(SIGCSQL1
, sigUsr1Handler
);
823 #if (defined MMDB && defined EMBED)
824 os::atexit(exithandler
);
829 #if (defined MMDB && defined EMBED)
830 DbRetVal
SqlConnection::recoverCsqlDB()
833 char dbRedoFileName
[MAX_FILE_LEN
];
834 char dbChkptSchema
[MAX_FILE_LEN
];
835 char dbChkptMap
[MAX_FILE_LEN
];
836 char dbChkptData
[MAX_FILE_LEN
];
837 char dbBackupFile
[MAX_FILE_LEN
];
838 char cmd
[IDENTIFIER_LENGTH
];
839 //check for check point file if present recover
840 sprintf(dbChkptSchema
, "%s/db.chkpt.schema1", Conf::config
.getDbFile());
841 if (FILE *file
= fopen(dbChkptSchema
, "r")) {
843 sprintf(cmd
, "cp -f %s %s/db.chkpt.schema", dbChkptSchema
,
844 Conf::config
.getDbFile());
845 int ret
= system(cmd
);
846 if (ret
!= 0) return ErrOS
;
848 sprintf(dbChkptMap
, "%s/db.chkpt.map1", Conf::config
.getDbFile());
849 if (FILE *file
= fopen(dbChkptMap
, "r")) {
851 sprintf(cmd
, "cp -f %s %s/db.chkpt.map", dbChkptMap
,
852 Conf::config
.getDbFile());
853 int ret
= system(cmd
);
854 if (ret
!= 0) return ErrOS
;
856 int chkptID
= Database::getCheckpointID();
857 sprintf(dbChkptData
, "%s/db.chkpt.data%d", Conf::config
.getDbFile(),
859 sprintf(dbBackupFile
, "%s/db.chkpt.data1", Conf::config
.getDbFile());
861 if (!Conf::config
.useMmap() && (fl
= fopen(dbBackupFile
, "r"))) {
863 sprintf(cmd
, "cp %s/db.chkpt.data1 %s", Conf::config
.getDbFile(),
865 int ret
= system(cmd
);
866 if (ret
!= 0) return ErrOS
;
868 if (FILE *file
= fopen(dbChkptData
, "r")) {
870 rv
= recoverSystemAndUserDB();
873 //check for redo log file if present apply redo logs
874 sprintf(dbRedoFileName
, "%s/csql.db.cur", Conf::config
.getDbFile());
875 if (FILE *file
= fopen(dbRedoFileName
, "r"))
878 applyRedoLogs(dbRedoFileName
);
879 DatabaseManager
*dbMgr
= getConnObject().getDatabaseManager();
880 rv
= dbMgr
->checkPoint();
883 printError(ErrSysInternal
, "checkpoint failed after redo log apply");
890 DbRetVal
SqlConnection::recoverSystemAndUserDB()
894 sprintf(schFile
, "%s/db.chkpt.schema", Conf::config
.getDbFile());
895 if (FILE *file
= fopen(schFile
, "r")) {
896 applySchemaFile(file
);
898 DatabaseManager
*dbMgr
= getConnObject().getDatabaseManager();
903 DbRetVal
SqlConnection::applySchemaFile(FILE *fp
)
907 SqlStatement
*stmt
= new SqlStatement();
908 while ((eof
= getQueryFromSchemaFile(fp
,buf
)) != EOF
) {
909 stmt
->setConnection(this);
918 char SqlConnection::getQueryFromSchemaFile(FILE *fp
, char *buf
)
920 char c
, *bufBegin
=buf
;
922 while( (c
=(char ) fgetc(fp
)) != EOF
&& c
!= ';')
924 *buf
++ = c
; charCnt
++;
925 if( charCnt
== SQL_STMT_LEN
) {
926 printf("SQL Statement length is greater than %d. "
927 "Ignoring the statement.\n", SQL_STMT_LEN
);
938 void SqlConnection::addToHashTable(int stmtID
, AbsSqlStatement
* sHdl
)
940 int bucketNo
= stmtID
% STMT_BUCKET_SIZE
;
941 StmtBucket
*buck
= (StmtBucket
*) stmtBuckets
;
942 StmtBucket
*stmtBucket
= &buck
[bucketNo
];
943 StmtNode
*node
= new StmtNode();
944 node
->stmtId
= stmtID
;
946 stmtBucket
->bucketList
.append(node
);
950 void SqlConnection::removeFromHashTable(int stmtID
)
952 int bucketNo
= stmtID
% STMT_BUCKET_SIZE
;
953 StmtBucket
*buck
= (StmtBucket
*) stmtBuckets
;
954 StmtBucket
*stmtBucket
= &buck
[bucketNo
];
955 StmtNode
*node
= NULL
;
956 ListIterator it
= stmtBucket
->bucketList
.getIterator();
957 while(it
.hasElement()) {
958 node
= (StmtNode
*) it
.nextElement();
959 if(stmtID
== node
->stmtId
) break;
962 stmtBucket
->bucketList
.remove(node
);
966 AbsSqlStatement
*SqlConnection::getStmtFromHashTable(int stmtId
)
968 int bucketNo
= stmtId
% STMT_BUCKET_SIZE
;
969 StmtBucket
*buck
= (StmtBucket
*) stmtBuckets
;
970 StmtBucket
*stmtBucket
= &buck
[bucketNo
];
971 StmtNode
*node
= NULL
;
972 ListIterator it
= stmtBucket
->bucketList
.getIterator();
973 while(it
.hasElement()) {
974 node
= (StmtNode
*) it
.nextElement();
975 if(stmtId
== node
->stmtId
) {
982 void setParam(AbsSqlStatement
*stmt
, int pos
, DataType type
, int length
, void *value
)
987 stmt
->setIntParam(pos
, *(int*)value
);
990 stmt
->setLongParam(pos
, *(long*) value
);
993 stmt
->setLongLongParam(pos
, *(long long*)value
);
996 stmt
->setShortParam(pos
, *(short*)value
);
999 stmt
->setByteIntParam(pos
, *(ByteInt
*)value
);
1002 stmt
->setDoubleParam(pos
, *(double*)value
);
1005 stmt
->setFloatParam(pos
, *(float*)value
);
1008 stmt
->setDateParam(pos
, *(Date
*)value
);
1011 stmt
->setTimeParam(pos
, *(Time
*)value
);
1014 stmt
->setTimeStampParam(pos
, *(TimeStamp
*)value
);
1018 stmt
->setStringParam(pos
, (char*)value
);
1021 stmt
->setBinaryParam(pos
, value
, length
);
1024 printf("unknown type\n");
1030 int SqlConnection::applyRedoLogs(char *redoFile
)
1034 int fd
= open(redoFile
, O_RDONLY
);
1035 if (-1 == fd
) { return OK
; }
1036 if (fstat(fd
, &st
) == -1) {
1037 printError(ErrSysInternal
, "Unable to retrieve undo log file size");
1041 if (st
.st_size
==0) {
1045 void *startAddr
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
1046 if (MAP_FAILED
== startAddr
) {
1047 printf("Unable to read undo log file:mmap failed.\n");
1050 stmtBuckets
= malloc (STMT_BUCKET_SIZE
* sizeof(StmtBucket
));
1051 memset(stmtBuckets
, 0, STMT_BUCKET_SIZE
* sizeof(StmtBucket
));
1053 char *iter
= (char*)startAddr
;
1058 int len
, ret
, retVal
=0;
1060 char stmtString
[SQL_STMT_LEN
];
1061 //printf("size of file %d\n", st.st_size);
1063 //printf("OFFSET HERE %d\n", iter - (char*)startAddr);
1064 if (iter
- (char*)startAddr
>= st
.st_size
) break;
1065 logType
= *(int*)iter
;
1066 if (logType
== -1) { //prepare
1067 iter
= iter
+ sizeof(int);
1068 txnID
= *(int*) iter
; iter
+= sizeof(int);
1069 loglen
= *(int*) iter
; iter
+= sizeof(int);
1070 stmtID
= *(int*)iter
;
1071 iter
= iter
+ sizeof(int);
1073 iter
= iter
+ sizeof(int);
1074 strncpy(stmtString
, iter
, len
);
1076 //printf("PREPARE:%d %d %s\n", stmtID, len, stmtString);
1077 AbsSqlStatement
*st
= SqlFactory::createStatement(CSqlDirect
);
1078 SqlStatement
*stmt
= (SqlStatement
*)st
;
1079 stmt
->setConnection(this);
1080 rv
= stmt
->prepare(stmtString
);
1082 printError(ErrSysInternal
, "unable to prepare stmt:%s", stmtString
);
1086 stmt
->prepare(stmtString
);
1087 SqlStatement
*sqlStmt
= (SqlStatement
*)stmt
;
1088 sqlStmt
->setLoading(true);
1089 addToHashTable(stmtID
, stmt
);
1091 else if(logType
== -2) { //commit
1093 iter
= iter
+ sizeof(int);
1094 txnID
= *(int*) iter
; iter
+= sizeof(int);
1095 loglen
= *(int*) iter
; iter
+= sizeof(int);
1096 char *curPtr
= iter
;
1098 //printf("Iter length %d\n", iter - curPtr);
1099 if (iter
- (char*)startAddr
>= st
.st_size
) {
1101 //printf("Redo log file end\n");
1105 stmtID
= *(int*)iter
;
1106 //printf("stmtid %d\n", stmtID);
1107 iter
= iter
+ sizeof(int);
1108 eType
= *(int*)iter
;
1109 //printf("eType is %d\n", eType);
1110 AbsSqlStatement
*stmt
= getStmtFromHashTable(stmtID
);
1111 if (0 == eType
) { //execute type
1112 iter
= iter
+ sizeof(int);
1113 //printf("EXEC: %d\n", stmtID);
1115 rv
= stmt
->execute(ret
);
1117 printError(ErrSysInternal
, "unable to execute");
1122 printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);
1124 if (*(int*)iter
<0) break;
1125 } else if ( 1 == eType
) { //set type
1126 iter
=iter
+sizeof(int);
1127 int pos
= *(int*) iter
;
1128 iter
=iter
+sizeof(int);
1129 DataType type
= (DataType
)(*(int*)iter
);
1130 iter
=iter
+sizeof(int);
1131 int len
= *(int*) iter
;
1132 iter
=iter
+sizeof(int);
1134 //AllDataType::printVal(value, type, len);
1136 //printf("SET: %d %d %d %d\n", stmtID, pos, type, len);
1137 setParam(stmt
, pos
, type
, len
, value
);
1138 if (*(int*)iter
<0) break;
1143 else if(logType
== -3) { //free
1144 iter
= iter
+ sizeof(int);
1145 txnID
= *(int*) iter
; iter
+= sizeof(int);
1146 loglen
= *(int*) iter
; iter
+= sizeof(int);
1147 stmtID
= *(int*)iter
;
1148 iter
= iter
+ sizeof(int);
1149 AbsSqlStatement
*stmt
= getStmtFromHashTable(stmtID
);
1152 removeFromHashTable(stmtID
);
1153 } else { printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);}
1155 else if(logType
== -4) { //prepare and execute
1156 iter
= iter
+ sizeof(int);
1157 txnID
= *(int*) iter
; iter
+= sizeof(int);
1158 loglen
= *(int*) iter
; iter
+= sizeof(int);
1159 stmtID
= *(int*)iter
;
1160 iter
= iter
+ sizeof(int);
1162 iter
= iter
+ sizeof(int);
1163 strncpy(stmtString
, iter
, len
);
1164 stmtString
[len
+1] ='\0';
1166 //printf("CREATE:%d %d %s\n", stmtID, len, stmtString);
1167 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlDirect
);
1168 if ( NULL
== stmt
) {
1169 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
1173 stmt
->setConnection(this);
1174 rv
= stmt
->prepare(stmtString
);
1176 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
1180 rv
= stmt
->execute(ret
);
1182 if (strlen(stmtString
) > 6 &&
1183 ( (strncasecmp(stmtString
,"CREATE", 6) == 0) ||
1184 (strncasecmp(stmtString
,"DROP", 4) == 0)) ) {
1185 // conn->disconnect();
1189 printError(ErrSysInternal
, "unable to execute %s", stmtString
);
1195 printError(ErrSysInternal
, "Redo log file corrupted: logType:%d", logType
);
1200 munmap((char*)startAddr
, st
.st_size
);
1202 //freeAllStmtHandles();