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 void SqlStatement::setParamValues(AbsSqlStatement
*sqlStmt
, int parampos
, DataType type
, int length
, void *value
)
47 sqlStmt
->setIntParam(parampos
, *(int*)value
);
50 sqlStmt
->setLongParam(parampos
, *(long*)value
);
53 sqlStmt
->setLongLongParam(parampos
, *(long long*)value
);
56 sqlStmt
->setShortParam(parampos
, *(short*)value
);
59 sqlStmt
->setByteIntParam(parampos
, *(char*)value
);
62 sqlStmt
->setDoubleParam(parampos
, *(double*)value
);
65 sqlStmt
->setFloatParam(parampos
, *(float*)value
);
68 sqlStmt
->setDateParam(parampos
, *(Date
*)value
);
71 sqlStmt
->setTimeParam(parampos
, *(Time
*)value
);
74 sqlStmt
->setTimeStampParam(parampos
, *(TimeStamp
*)value
);
79 sqlStmt
->setStringParam(parampos
, (char*)value
);
83 sqlStmt
->setBinaryParam(parampos
, (char *) value
, length
);
86 printf("unknown type\n");
92 void *SqlStatement::fillBindBuffer(TDBInfo tdbName
, DataType type
, void *&valBuf
, int length
, int nRecords
)
94 BindBuffer
*bBuf
= NULL
;
98 bBuf
= new BindBuffer();
100 bBuf
->type
= typeDate
;
101 bBuf
->length
= sizeof(DATE_STRUCT
);
102 bBuf
->targetdb
= malloc(nRecords
* bBuf
->length
);
103 memset(bBuf
->targetdb
, 0, nRecords
* bBuf
->length
);
104 valBuf
= bBuf
->targetdb
;
107 bBuf
= new BindBuffer();
109 bBuf
->type
= typeTime
;
110 bBuf
->length
= sizeof(TIME_STRUCT
);
111 bBuf
->targetdb
= malloc(nRecords
* bBuf
->length
);
112 memset(bBuf
->targetdb
, 0, nRecords
* bBuf
->length
);
113 valBuf
= bBuf
->targetdb
;
116 bBuf
= new BindBuffer();
118 bBuf
->type
= typeTimeStamp
;
119 bBuf
->length
= sizeof(TIMESTAMP_STRUCT
);
120 bBuf
->targetdb
= malloc(nRecords
* bBuf
->length
);
121 memset(bBuf
->targetdb
, 0, nRecords
* bBuf
->length
);
122 valBuf
= bBuf
->targetdb
;
126 if( tdbName
== postgres
)
128 bBuf
= new BindBuffer();
129 bBuf
->type
= typeLongLong
;
132 int size
= nRecords
*AllDataType::size(typeString
,bBuf
->length
);
133 bBuf
->targetdb
= malloc(size
);
134 memset(bBuf
->targetdb
, 0, size
);
135 valBuf
= bBuf
->targetdb
;
139 bBuf
= new BindBuffer();
142 bBuf
->length
= length
;
149 bBuf
= new BindBuffer();
150 bBuf
->type
= typeString
;
152 bBuf
->length
= length
;
156 bBuf
= new BindBuffer();
159 bBuf
->length
= length
;
162 bBuf
->nullData
= (SQLLEN
*) malloc(nRecords
* sizeof(SQLLEN
));
163 for (int i
= 0; i
< nRecords
; i
++) bBuf
->nullData
[i
] = SQL_NTS
;
168 List
SqlStatement::getTableNameList()
170 return pData
.getTableNameList();
172 SqlStatement::SqlStatement()
179 isMgmtStatement
= false;
180 sqlStmtString
= NULL
;
183 void SqlStatement::setConnection(AbsSqlConnection
*conn
)
185 sqlCon
= (SqlConnection
*)conn
;
189 void SqlStatement::setSqlConnection(SqlConnection
*conn
)
194 DbRetVal
SqlStatement::executeDirect(char *str
)
199 if (rv
!= OK
) return rv
;
201 if (rv
!= OK
) return rv
;
205 void SqlStatement::setStmtString(char *ststr
)
207 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
; }
208 sqlStmtString
= (char*) malloc(strlen(ststr
)+1);
209 strcpy(sqlStmtString
, ststr
);
212 DbRetVal
SqlStatement::prepare()
214 return prepareInt(sqlStmtString
);
217 DbRetVal
SqlStatement::prepare(char *stmtstr
)
219 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
;}
220 sqlStmtString
= (char*) malloc(strlen(stmtstr
)+1);
221 strcpy(sqlStmtString
, stmtstr
);
222 return prepareInt(stmtstr
);
225 DbRetVal
SqlStatement::prepareInt(char *stmtstr
)
228 if (! sqlCon
->isConnectionOpen()) {
229 printError(ErrNotOpen
, "Connection not open");
232 SqlStatement
*cachedStmt
= sqlCon
->findInCache(stmtstr
);
236 this->stmt
->setParsedData(&this->pData
);
238 logFine(Conf::logger
,"GOT STMT FROM CACHE: %s %x", stmtstr
, cachedStmt
);
242 int ret
= ProcessManager::prepareMutex
.tryLock(10, 1000);
245 printError(ErrLockTimeOut
, "Unable to get prepare mutex");
246 return ErrLockTimeOut
;
249 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
250 if (isPrepared()) free();
254 yy_buffer_state
*yy_buffer
= yy_scan_string(stmtstr
);
256 if (yy_buffer
) yy_delete_buffer(yy_buffer
);
261 ProcessManager::prepareMutex
.releaseLock(-1, false);
262 return ErrSyntaxError
;
264 if( parsedData
->getStmtType() == MgmtStatement
)
268 isMgmtStatement
= true;
269 ProcessManager::prepareMutex
.releaseLock(-1, false);
270 logFine(Conf::logger
,"PREPARE: %s %x", stmtstr
, stmt
);
273 stmt
= StatementFactory::getStatement(parsedData
);
274 stmt
->setDbMgr(dbMgr
);
275 if( parsedData
->getStmtType() == UserStatement
)
277 UserManager
* userMgr
= sqlCon
->getConnObject().getUserManager();
278 UserTblStatement
*ustmt
= (UserTblStatement
*)stmt
;
279 ustmt
->setUserManager(userMgr
,sqlCon
->getConnObject().getUserName());
281 rv
= stmt
->resolve();
286 ProcessManager::prepareMutex
.releaseLock(-1, false);
290 if (!isCachedStmt
&& Conf::config
.getStmtCacheSize() && !getDontCache()) {
291 if (stmt
->noOfParamFields() > 0) {
293 sqlCon
->addToCache(this, stmtstr
);
294 } else if (Conf::config
.useCacheNoParam()) {
295 if (parsedData
->getCacheWorthy()) {
297 sqlCon
->addToCache(this, stmtstr
);
300 } else { printf("stmtstring '%s' not cached\n", stmtstr
); }
302 ProcessManager::prepareMutex
.releaseLock(-1, false);
306 char* SqlStatement::getTableName()
308 return pData
.getTableName();
311 bool SqlStatement::isSelect()
313 if ((pData
.getStmtType() == SelectStatement
) || (pData
.getStmtType() == MetaStatement
)) return true;
317 bool SqlStatement::isPrepared() { return isPrepd
; }
319 DbRetVal
SqlStatement::execute(int &rowsAffected
)
322 if (! sqlCon
->isConnectionOpen()) {
323 printError(ErrNotOpen
, "Connection not open");
326 if (! isPrepared()) {
327 printError(ErrNotPrepared
, "Statement Not Prepared");
328 return ErrNotPrepared
;
330 if( isMgmtStatement
)
333 logFiner(Conf::logger
,"EXECUTE: %x", stmt
);
336 rv
= stmt
->execute(rowsAffected
);
337 if (rv
== ErrAlready
&& pData
.getStmtType() == SelectStatement
)
338 { //if previous scan is not closed, close it
339 SelStatement
*selStmt
= (SelStatement
*) stmt
;
341 rv
= stmt
->execute(rowsAffected
);
343 logFiner(Conf::logger
,"EXECUTE: %x", stmt
);
347 void* SqlStatement::fetch()
349 if (! sqlCon
->isConnectionOpen()) {
350 printError(ErrNotOpen
, "Connection not open");
353 if (! isPrepared()) {
354 printError(ErrNotPrepared
, "Statement Not Prepared");
357 if (pData
.getStmtType() == SelectStatement
) {
358 SelStatement
*selStmt
= (SelStatement
*) stmt
;
359 return selStmt
->fetch();
361 else if(pData
.getStmtType() == MetaStatement
){
362 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
363 return metaStmt
->fetch();
368 void* SqlStatement::fetch(DbRetVal
&rv
)
370 if (! sqlCon
->isConnectionOpen()) {
371 printError(ErrNotOpen
, "Connection not open");
372 rv
= ErrNoConnection
;
375 if (! isPrepared()) {
376 printError(ErrNotPrepared
, "Statement Not Prepared");
379 if (pData
.getStmtType() == SelectStatement
) {
380 SelStatement
*selStmt
= (SelStatement
*) stmt
;
381 return selStmt
->fetch(rv
);
383 else if(pData
.getStmtType() == MetaStatement
){
384 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
385 return metaStmt
->fetch(rv
);
390 void* SqlStatement::fetchAndPrint(bool SQL
)
392 if (! sqlCon
->isConnectionOpen()) {
393 printError(ErrNotOpen
, "Connection not open");
396 if (! isPrepared()) {
397 printError(ErrNotPrepared
, "Statement Not Prepared");
400 if (pData
.getStmtType() != SelectStatement
) return NULL
;
401 SelStatement
*selStmt
= (SelStatement
*) stmt
;
402 return selStmt
->fetchAndPrint(SQL
);
405 DbRetVal
SqlStatement::bindParam(int pos
, void* value
)
408 rv
= stmt
->setParam(pos
, value
);
412 DbRetVal
SqlStatement::bindField(int pos
, void* value
)
415 if (pData
.getStmtType() == SelectStatement
) {
416 SelStatement
*selStmt
= (SelStatement
*) stmt
;
417 return selStmt
->setBindField(pos
, value
);
419 else if(pData
.getStmtType() == MetaStatement
){
420 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
421 return metaStmt
->setBindField(pos
, value
);
423 else { return ErrBadCall
;}
425 void* SqlStatement::next()
427 if (pData
.getStmtType() == SelectStatement
) {
428 SelStatement
*selStmt
= (SelStatement
*) stmt
;
429 return( (void*) selStmt
->next() );
431 else if(pData
.getStmtType() == MetaStatement
){
432 MetadataStatement
*metaStmt
= (MetadataStatement
*) stmt
;
433 return( (void*) metaStmt
->next() );
438 bool SqlStatement::isFldNull(int pos
)
440 if (pData
.getStmtType() != SelectStatement
) return 0;
441 SelStatement
*selStmt
= (SelStatement
*) stmt
;
442 return (selStmt
->isFldNull(pos
));
444 bool SqlStatement::isFldNull(char *name
)
446 if (pData
.getStmtType() != SelectStatement
) return 0;
447 SelStatement
*selStmt
= (SelStatement
*) stmt
;
448 return (selStmt
->isFldNull(name
));
450 DbRetVal
SqlStatement::close()
452 if (pData
.getStmtType() == SelectStatement
) {
453 SelStatement
*selStmt
= (SelStatement
*) stmt
;
454 logFinest(Conf::logger
,"CLOSE: %x", stmt
);
455 return selStmt
->close();
457 else if(pData
.getStmtType() == MetaStatement
){
458 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
459 logFinest(Conf::logger
,"CLOSE: %x", stmt
);
460 return selStmt
->close();
465 void* SqlStatement::getParamValuePtr( int pos
)
467 //if (pData.getStmtType() != SelectStatement) return 0;
468 DmlStatement
*dmlStmt
= (DmlStatement
*) stmt
;
469 return( (void*) dmlStmt
->getParamValuePtr( pos
) );
472 char* SqlStatement::getFieldName( int pos
)
474 if (pData
.getStmtType() == SelectStatement
) {
475 SelStatement
*selStmt
= (SelStatement
*) stmt
;
476 return( (char*) selStmt
->getFieldName( pos
) );
478 else if(pData
.getStmtType() == MetaStatement
){
479 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
480 return( (char*) selStmt
->getFieldName( pos
) );
485 DataType
SqlStatement::getFieldType( int pos
)
487 if (pData
.getStmtType() == SelectStatement
) {
488 SelStatement
*selStmt
= (SelStatement
*) stmt
;
489 return( (DataType
) selStmt
->getFieldType( pos
) );
491 else if(pData
.getStmtType() == MetaStatement
){
492 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
493 return( (DataType
) selStmt
->getFieldType( pos
) );
495 else { return typeUnknown
;}
497 int SqlStatement::getFieldLength( int pos
)
499 if (pData
.getStmtType() == SelectStatement
) {
500 SelStatement
*selStmt
= (SelStatement
*) stmt
;
501 return( (int) selStmt
->getFieldLength( pos
) );
503 else if(pData
.getStmtType() == MetaStatement
){
504 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
505 return( (int) selStmt
->getFieldLength( pos
) );
510 void* SqlStatement::getFieldValuePtr( int pos
)
512 if (pData
.getStmtType() == SelectStatement
) {
513 SelStatement
*selStmt
= (SelStatement
*) stmt
;
514 return( (void*) selStmt
->getFieldValuePtr( pos
) );
516 else if(pData
.getStmtType() == MetaStatement
){
517 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
518 return( (void*) selStmt
->getFieldValuePtr( pos
) );
522 void* SqlStatement::getFieldValuePtr( char *name
)
524 if (pData
.getStmtType() == SelectStatement
) {
525 SelStatement
*selStmt
= (SelStatement
*) stmt
;
526 return( (void*) selStmt
->getFieldValuePtr( name
) );
528 else if(pData
.getStmtType() == MetaStatement
){
529 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
530 return( (void*) selStmt
->getFieldValuePtr( name
) );
535 int SqlStatement::noOfProjFields()
537 if (pData
.getStmtType() == SelectStatement
) {
538 SelStatement
*selStmt
= (SelStatement
*) stmt
;
539 return selStmt
->noOfProjFields();
541 else if(pData
.getStmtType() == MetaStatement
){
542 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
543 return selStmt
->noOfProjFields();
548 void SqlStatement::getProjFieldType(int *data
)
550 if (pData
.getStmtType() == SelectStatement
) {
551 SelStatement
*selStmt
= (SelStatement
*) stmt
;
552 return( selStmt
->getProjFieldType(data
) );
554 else if(pData
.getStmtType() == MetaStatement
){
555 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
556 return( selStmt
->getProjFieldType(data
) );
562 int SqlStatement::noOfParamFields()
564 if (NULL
== stmt
) return 0;
565 else return stmt
->noOfParamFields();
568 DbRetVal
SqlStatement::getProjFldInfo (int projpos
, FieldInfo
*&fInfo
)
571 if (pData
.getStmtType() == SelectStatement
) {
572 SelStatement
*selStmt
= (SelStatement
*) stmt
;
573 rv
= selStmt
->getProjFldInfo(projpos
, fInfo
);
575 else if(pData
.getStmtType() == MetaStatement
){
576 MetadataStatement
*selStmt
= (MetadataStatement
*) stmt
;
577 rv
= selStmt
->getProjFldInfo(projpos
, fInfo
);
578 } else { return ErrBadCall
;}
582 DbRetVal
SqlStatement::getParamFldInfo (int parampos
, FieldInfo
*&fInfo
)
585 if (pData
.getStmtType() ==SelectStatement
||
586 pData
.getStmtType() ==InsertStatement
||
587 pData
.getStmtType() ==UpdateStatement
||
588 pData
.getStmtType() ==DeleteStatement
)
591 DmlStatement
*dmlStmt
= (DmlStatement
*) stmt
;
592 rv
= dmlStmt
->getParamFldInfo(parampos
, fInfo
);
597 DbRetVal
SqlStatement::free()
599 logFinest(Conf::logger
,"FREE: %x", stmt
);
605 sqlCon
->setStmtNotInUse(sqlStmtString
);
606 ::free(sqlStmtString
); sqlStmtString
=NULL
;
608 isCachedStmt
= false;
611 if(stmt
) delete stmt
;
614 isMgmtStatement
= false;
616 isCachedStmt
= false;
617 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
; }
621 void SqlStatement::setNull(int pos
)
625 void SqlStatement::setShortParam(int paramPos
, short value
)
627 stmt
->setShortParam(paramPos
, value
);
629 void SqlStatement::setIntParam(int paramPos
, int value
)
631 stmt
->setIntParam(paramPos
, value
);
633 void SqlStatement::setLongParam(int paramPos
, long value
)
635 stmt
->setLongParam(paramPos
, value
);
637 void SqlStatement::setLongLongParam(int paramPos
, long long value
)
639 stmt
->setLongLongParam(paramPos
, value
);
641 void SqlStatement::setByteIntParam(int paramPos
, ByteInt value
)
643 stmt
->setByteIntParam(paramPos
, value
);
645 void SqlStatement::setFloatParam(int paramPos
, float value
)
647 stmt
->setFloatParam(paramPos
, value
);
649 void SqlStatement::setDoubleParam(int paramPos
, double value
)
651 stmt
->setDoubleParam(paramPos
, value
);
653 void SqlStatement::setStringParam(int paramPos
, char *value
)
655 stmt
->setStringParam(paramPos
, value
);
657 void SqlStatement::setDateParam(int paramPos
, Date value
)
659 stmt
->setDateParam(paramPos
, value
);
661 void SqlStatement::setTimeParam(int paramPos
, Time value
)
663 stmt
->setTimeParam(paramPos
, value
);
665 void SqlStatement::setTimeStampParam(int paramPos
, TimeStamp value
)
667 stmt
->setTimeStampParam(paramPos
, value
);
669 void SqlStatement::setBinaryParam(int paramPos
, void *value
, int length
)
671 stmt
->setBinaryParam(paramPos
, value
, length
);
673 int SqlStatement::getFldPos(char *name
)
675 return stmt
->getFldPos(name
);
677 long long SqlStatement::getLastInsertedVal(DbRetVal
&rv
)
679 return stmt
->getLastInsertedVal(rv
);
681 List
SqlStatement::getAllTableNames(DbRetVal
&ret
)
683 DatabaseManager
*dbMgr
= NULL
;
685 dbMgr
=sqlCon
->getConnObject().getDatabaseManager();
687 if(dbMgr
!= NULL
) tbNmList
= dbMgr
->getAllTableNames(&rv
);
692 List
SqlStatement::getAllUserNames(DbRetVal
&ret
)
694 UserManager
*urMgr
= NULL
;
696 urMgr
=sqlCon
->getConnObject().getUserManager();
699 urNmList
= urMgr
->getAllUserNames(&rv
);
703 List
SqlStatement::getFieldNameList(const char *tblName
, DbRetVal
&rv
)
707 fldNameList
= stmt
->getFieldNameList(tblName
, rv
);
710 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
711 Table
*table
= dbMgr
->openTable(tblName
);
714 printError(ErrLockTimeOut
, "Unable to open table %s", tblName
);
717 fldNameList
= table
->getFieldNameList();
718 dbMgr
->closeTable(table
);
721 DbRetVal
SqlStatement::getFieldInfo(const char *tblName
, const char *fldName
, FieldInfo
*&info
)
725 rv
= stmt
->getFieldInfo(tblName
, fldName
, info
);
728 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
729 Table
*table
= dbMgr
->openTable(tblName
);
731 printError(ErrLockTimeOut
, "Unable to open table %s", tblName
);
732 return ErrLockTimeOut
;
734 rv
= table
->getFieldInfo(fldName
, info
);
735 dbMgr
->closeTable(table
);
738 void SqlStatement::setLoading(bool flag
)
740 if (pData
.getStmtType() == InsertStatement
||
741 pData
.getStmtType() == UpdateStatement
||
742 pData
.getStmtType() == DeleteStatement
)
744 DmlStatement
*dmlStmt
= (DmlStatement
*) stmt
;
745 dmlStmt
->setLoading(flag
);
750 int SqlStatement::getNoOfPagesForTable(char *tblName
)
752 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
753 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
754 return dbMgrImpl
->getNoOfPagesForTable(tblName
);
757 DbRetVal
SqlStatement::loadRecords(char *tblName
, void *buf
)
759 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
760 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
761 return dbMgrImpl
->loadRecords(tblName
, (char *) buf
);
764 DbRetVal
SqlStatement::pasteRecords(char *tblName
, void *buffer
)
766 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
767 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
768 return dbMgrImpl
->pasteRecords(tblName
, buffer
);
770 void SqlStatement::flushCacheStmt()
772 return sqlCon
->flushCacheStmt();
775 void SqlStatement::resetStmtString() {
778 //-------------------------------------------------------------------
780 static void sigTermHandler(int sig
)
782 ListIterator iter
= SqlConnection::connList
.getIterator();
783 SqlConnection
*conn
= NULL
;
784 while (iter
.hasElement())
786 conn
= (SqlConnection
*) iter
.nextElement();
787 conn
->flushCacheStmt();
788 if (conn
->isConnectionOpen()) conn
->disconnect();
793 DbRetVal
SqlConnection::connect (char *user
, char * pass
)
795 DbRetVal ret
= conn
.open(user
, pass
);
796 if (ret
!= OK
) return ret
;
797 if (ret
== OK
) isConnOpen
= true;
798 if (!isInit
) initialize();
799 connList
.append(this);
801 #if (defined MMDB && EMBED)
802 os::signal(SIGINT
, sigTermHandler
);
803 os::signal(SIGTERM
, sigTermHandler
);
804 if (Conf::config
.useDurability() && !firstThread
) {
805 rv
= recoverCsqlDB();
807 printError(ErrSysInternal
, "Recovery Failed");
812 rollback(); //for drop table execute in redo log
817 void SqlConnection::flushCacheStmt()
819 ListIterator iter
= cachedStmts
.getIterator();
820 while (iter
.hasElement()) {
821 CachedStmtNode
* node
= (CachedStmtNode
*) iter
.nextElement();
822 //do not delete when the statement is currently in use.
823 //otherwise it leads to illegal memory access when application
824 //calls any method on this statement
825 if (node
->inUse
) continue;
826 //if (node->inUse) node->inUse = 0;
827 free(node
->sqlString
);
828 node
->sqlStmt
->setCachedStmt(false);
829 node
->sqlStmt
->free();
830 delete node
->sqlStmt
;
837 void SqlConnection::setStmtNotInUse(char *stmtstr
)
839 ListIterator iter
= cachedStmts
.getIterator();
840 int inputStmtLen
= strlen(stmtstr
);
841 CachedStmtNode
*node
= NULL
;
842 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
844 if (node
->stmtLength
== inputStmtLen
)
846 if (0 == strcmp(node
->sqlString
, stmtstr
))
855 SqlStatement
* SqlConnection::findInCache(char *stmtstr
)
857 ListIterator iter
= cachedStmts
.getIterator();
858 int inputStmtLen
= strlen(stmtstr
);
859 CachedStmtNode
*node
= NULL
;
860 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
862 if (node
->stmtLength
== inputStmtLen
)
864 if (0 == strcmp(node
->sqlString
, stmtstr
))
866 logFiner(Conf::logger
, "Statement Retrieved From Cache %x\n",
870 return node
->sqlStmt
;
877 void SqlConnection::addToCache(SqlStatement
*sqlStmt
, char* stmtString
)
879 SqlStatement
*stmt
= new SqlStatement();
881 CachedStmtNode
*node
= new CachedStmtNode();
882 node
->sqlStmt
= stmt
;
883 node
->stmtLength
= strlen(stmtString
);
884 node
->sqlString
= (char*)malloc(node
->stmtLength
+1);
886 strcpy(node
->sqlString
, stmtString
);
887 if (cachedStmts
.size() >= Conf::config
.getStmtCacheSize())
891 node
->sqlStmt
->resetStmtString();
892 cachedStmts
.append(node
);
893 logFiner(Conf::logger
, "Statement added To Cache %x\n", node
->sqlStmt
);
894 logFinest(Conf::logger
, "Statement added To Cache %s\n", node
->sqlString
);
898 void SqlConnection::removeLeastUsed()
900 ListIterator iter
= cachedStmts
.getIterator();
901 CachedStmtNode
*node
= NULL
, *toRemove
=NULL
;
903 bool firstCall
= true;
904 while((node
= (CachedStmtNode
*) iter
.nextElement()) != NULL
)
908 lowHits
= node
->hits
;
909 toRemove
= node
; //if cache size is 1
912 if (lowHits
>= node
->hits
) toRemove
= node
;
914 cachedStmts
.remove(toRemove
);
915 //TODO::check whether there is memory leak for list elements
916 logFiner(Conf::logger
, "Statement removed from Cache %x\n", toRemove
->sqlStmt
);
917 logFinest(Conf::logger
, "Statement removed from Cache %s\n", toRemove
->sqlString
);
918 delete toRemove
; toRemove
= NULL
;
922 SqlConnection::~SqlConnection()
925 if (isConnOpen
) disconnect();
929 static void sigUsr1Handler(int sig
)
931 ListIterator iter
= SqlConnection::connList
.getIterator();
932 SqlConnection
*conn
= NULL
;
933 while (iter
.hasElement())
935 conn
= (SqlConnection
*) iter
.nextElement();
936 conn
->flushCacheStmt();
938 os::signal(SIGCSQL1
, sigUsr1Handler
);
942 static void exithandler(void)
944 ListIterator iter
= SqlConnection::connList
.getIterator();
945 SqlConnection
*conn
= NULL
;
946 while (iter
.hasElement())
948 conn
= (SqlConnection
*) iter
.nextElement();
949 conn
->flushCacheStmt();
953 void SqlConnection::displayStmtCache()
955 ListIterator iter
= cachedStmts
.getIterator();
956 CachedStmtNode
*node
= NULL
;
957 printf("STATEMENT CACHE START \n");
958 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
962 printf("STATEMENT CACHE END\n");
965 void SqlConnection::initialize()
967 os::signal(SIGCSQL1
, sigUsr1Handler
);
968 #if (defined MMDB && defined EMBED)
969 os::atexit(exithandler
);
974 #if (defined MMDB && defined EMBED)
976 DbRetVal
SqlConnection::recoverCsqlDB()
979 char dbRedoFileName
[MAX_FILE_LEN
];
980 char dbChkptSchema
[MAX_FILE_LEN
];
981 char dbChkptMap
[MAX_FILE_LEN
];
982 char dbChkptData
[MAX_FILE_LEN
];
983 char dbBackupFile
[MAX_FILE_LEN
];
984 char cmd
[IDENTIFIER_LENGTH
];
985 //check for check point file if present recover
986 sprintf(dbChkptSchema
, "%s/db.chkpt.schema1", Conf::config
.getDbFile());
987 if (FILE *file
= fopen(dbChkptSchema
, "r")) {
989 sprintf(cmd
, "cp -f %s %s/db.chkpt.schema", dbChkptSchema
,
990 Conf::config
.getDbFile());
991 int ret
= system(cmd
);
992 if (ret
!= 0) return ErrOS
;
994 sprintf(dbChkptMap
, "%s/db.chkpt.map1", Conf::config
.getDbFile());
995 if (FILE *file
= fopen(dbChkptMap
, "r")) {
997 sprintf(cmd
, "cp -f %s %s/db.chkpt.map", dbChkptMap
,
998 Conf::config
.getDbFile());
999 int ret
= system(cmd
);
1000 if (ret
!= 0) return ErrOS
;
1002 int chkptID
= Database::getCheckpointID();
1003 sprintf(dbChkptData
, "%s/db.chkpt.data%d", Conf::config
.getDbFile(),
1005 sprintf(dbBackupFile
, "%s/db.chkpt.data1", Conf::config
.getDbFile());
1007 if (!Conf::config
.useMmap() && (fl
= fopen(dbBackupFile
, "r"))) {
1009 sprintf(cmd
, "cp %s/db.chkpt.data1 %s", Conf::config
.getDbFile(),
1011 int ret
= system(cmd
);
1012 if (ret
!= 0) return ErrOS
;
1014 if (FILE *file
= fopen(dbChkptData
, "r")) {
1016 rv
= recoverSystemAndUserDB();
1017 if (rv
!= OK
) return rv
;
1020 //check for redo log file if present apply redo logs
1021 sprintf(dbRedoFileName
, "%s/csql.db.cur", Conf::config
.getDbFile());
1022 if (FILE *file
= fopen(dbRedoFileName
, "r"))
1025 rv
= (DbRetVal
) applyRedoLogs(dbRedoFileName
);
1026 if (rv
!= OK
) return rv
;
1027 DatabaseManager
*dbMgr
= getConnObject().getDatabaseManager();
1028 rv
= dbMgr
->checkPoint();
1031 printError(ErrSysInternal
, "checkpoint failed after redo log apply");
1038 DbRetVal
SqlConnection::recoverSystemAndUserDB()
1042 sprintf(schFile
, "%s/db.chkpt.schema", Conf::config
.getDbFile());
1043 if (FILE *file
= fopen(schFile
, "r")) {
1044 rv
= applySchemaFile(file
);
1045 if (rv
!= OK
) { fclose(file
); return rv
; }
1047 DatabaseManager
*dbMgr
= getConnObject().getDatabaseManager();
1048 rv
= dbMgr
->recover();
1052 DbRetVal
SqlConnection::applySchemaFile(FILE *fp
)
1057 SqlStatement
*stmt
= new SqlStatement();
1058 while ((eof
= getQueryFromSchemaFile(fp
,buf
)) != EOF
) {
1059 stmt
->setConnection(this);
1060 rv
= stmt
->prepare(buf
);
1061 if (rv
!= OK
) { delete stmt
; return rv
; }
1063 stmt
->execute(rows
);
1064 if (rv
!= OK
) { stmt
->free(); delete stmt
; return rv
; }
1070 char SqlConnection::getQueryFromSchemaFile(FILE *fp
, char *buf
)
1072 char c
, *bufBegin
=buf
;
1074 while( (c
=(char ) fgetc(fp
)) != EOF
&& c
!= ';')
1076 *buf
++ = c
; charCnt
++;
1077 if( charCnt
== SQL_STMT_LEN
) {
1078 printf("SQL Statement length is greater than %d. "
1079 "Ignoring the statement.\n", SQL_STMT_LEN
);
1090 int SqlConnection::applyRedoLogs(char *redoFile
)
1094 int fd
= open(redoFile
, O_RDONLY
);
1095 if (-1 == fd
) { return OK
; }
1096 if (fstat(fd
, &st
) == -1) {
1097 printError(ErrSysInternal
, "Unable to retrieve undo log file size");
1101 if (st
.st_size
==0) {
1102 printError(ErrNote
, "No Redo logs found during recovery");
1103 SqlStatement::readAndPopulateStmts(this, stmtBuckets
);
1107 void *startAddr
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
1108 if (MAP_FAILED
== startAddr
) {
1109 printf("Unable to read undo log file:mmap failed.\n");
1113 rv
= SqlStatement::readAndPopulateStmts(this, stmtBuckets
);
1116 printf("Unable to read stmt log file\n");
1120 char *iter
= (char*)startAddr
;
1125 int len
, ret
, retVal
=0;
1127 char stmtString
[SQL_STMT_LEN
];
1129 if (iter
- (char*)startAddr
>= st
.st_size
) break;
1130 logType
= *(int*)iter
;
1131 if (logType
== -1) { //prepare
1132 iter
= iter
+ sizeof(int);
1133 txnID
= *(int*) iter
; iter
+= sizeof(int);
1134 loglen
= *(int*) iter
; iter
+= sizeof(int);
1135 stmtID
= *(int*)iter
;
1136 iter
= iter
+ sizeof(int);
1138 iter
= iter
+ sizeof(int);
1139 strncpy(stmtString
, iter
, len
);
1141 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlDirect
);
1142 SqlStatement
*sqlStmt
= (SqlStatement
*)stmt
;
1143 stmt
->setConnection(this);
1144 rv
= stmt
->prepare(stmtString
);
1146 printError(ErrSysInternal
, "unable to prepare stmt:%s", stmtString
);
1150 sqlStmt
->setLoading(true);
1151 SqlStatement::addToHashTable(stmtID
, stmt
, stmtBuckets
, stmtString
);
1153 else if(logType
== -2) { //commit
1155 iter
= iter
+ sizeof(int);
1156 txnID
= *(int*) iter
; iter
+= sizeof(int);
1157 loglen
= *(int*) iter
; iter
+= sizeof(int);
1158 char *curPtr
= iter
;
1160 if (iter
- (char*)startAddr
>= st
.st_size
) {
1165 stmtID
= *(int*)iter
;
1166 iter
= iter
+ sizeof(int);
1167 eType
= *(int*)iter
;
1168 AbsSqlStatement
*stmt
=
1169 SqlStatement::getStmtFromHashTable(stmtID
,stmtBuckets
);
1171 printError(ErrSysInternal
,
1172 "Unable to find in stmt hashtable");
1176 if (0 == eType
) { //execute type
1177 iter
= iter
+ sizeof(int);
1178 rv
= stmt
->execute(ret
);
1180 printError(ErrSysInternal
, "unable to execute");
1184 if (*(int*)iter
<0) break;
1185 } else if ( 1 == eType
) { //set type
1186 iter
=iter
+sizeof(int);
1187 int pos
= *(int*) iter
;
1188 iter
=iter
+sizeof(int);
1189 int isNull
= *(int *)iter
;
1190 iter
= iter
+ sizeof(int);
1192 DataType type
= (DataType
)(*(int*)iter
);
1193 iter
=iter
+sizeof(int);
1194 int len
= *(int*) iter
;
1195 iter
=iter
+sizeof(int);
1198 SqlStatement::setParamValues(stmt
, pos
,
1200 } else stmt
->setNull(pos
);
1201 if (*(int*)iter
<0) break;
1206 else if(logType
== -3) { //free
1207 iter
= iter
+ sizeof(int);
1208 txnID
= *(int*) iter
; iter
+= sizeof(int);
1209 loglen
= *(int*) iter
; iter
+= sizeof(int);
1210 stmtID
= *(int*)iter
;
1211 iter
= iter
+ sizeof(int);
1212 AbsSqlStatement
*stmt
= SqlStatement::getStmtFromHashTable(stmtID
,
1216 SqlStatement::removeFromHashTable(stmtID
,stmtBuckets
);
1217 } else { printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);}
1219 else if(logType
== -4) { //prepare and execute
1220 iter
= iter
+ sizeof(int);
1221 txnID
= *(int*) iter
; iter
+= sizeof(int);
1222 loglen
= *(int*) iter
; iter
+= sizeof(int);
1223 stmtID
= *(int*)iter
;
1224 iter
= iter
+ sizeof(int);
1226 iter
= iter
+ sizeof(int);
1227 strncpy(stmtString
, iter
, len
);
1228 stmtString
[len
+1] ='\0';
1230 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlDirect
);
1231 if ( NULL
== stmt
) {
1232 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
1236 stmt
->setConnection(this);
1237 rv
= stmt
->prepare(stmtString
);
1239 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
1243 rv
= stmt
->execute(ret
);
1245 if (strlen(stmtString
) > 6 &&
1246 ( (strncasecmp(stmtString
,"CREATE", 6) == 0) ||
1247 (strncasecmp(stmtString
,"DROP", 4) == 0) ||
1248 (strncasecmp(stmtString
,"RENAME", 6) == 0) ||
1249 (strncasecmp(stmtString
,"ALTER", 5) == 0) )) {
1252 printError(ErrSysInternal
, "unable to execute %s", stmtString
);
1258 printError(ErrSysInternal
, "Redo log file corrupted: logType:%d", logType
);
1263 munmap((char*)startAddr
, st
.st_size
);
1265 SqlStatement::filterAndWriteStmtLogs(stmtBuckets
);
1266 SqlStatement::freeAllStmtHandles(stmtBuckets
);