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
);
609 isCachedStmt
= false;
612 if(stmt
) delete stmt
;
615 isMgmtStatement
= false;
617 isCachedStmt
= false;
618 if (sqlStmtString
) { ::free(sqlStmtString
); sqlStmtString
=NULL
; }
622 void SqlStatement::setNull(int pos
)
626 void SqlStatement::setShortParam(int paramPos
, short value
)
628 stmt
->setShortParam(paramPos
, value
);
630 void SqlStatement::setIntParam(int paramPos
, int value
)
632 stmt
->setIntParam(paramPos
, value
);
634 void SqlStatement::setLongParam(int paramPos
, long value
)
636 stmt
->setLongParam(paramPos
, value
);
638 void SqlStatement::setLongLongParam(int paramPos
, long long value
)
640 stmt
->setLongLongParam(paramPos
, value
);
642 void SqlStatement::setByteIntParam(int paramPos
, ByteInt value
)
644 stmt
->setByteIntParam(paramPos
, value
);
646 void SqlStatement::setFloatParam(int paramPos
, float value
)
648 stmt
->setFloatParam(paramPos
, value
);
650 void SqlStatement::setDoubleParam(int paramPos
, double value
)
652 stmt
->setDoubleParam(paramPos
, value
);
654 void SqlStatement::setStringParam(int paramPos
, char *value
)
656 stmt
->setStringParam(paramPos
, value
);
658 void SqlStatement::setDateParam(int paramPos
, Date value
)
660 stmt
->setDateParam(paramPos
, value
);
662 void SqlStatement::setTimeParam(int paramPos
, Time value
)
664 stmt
->setTimeParam(paramPos
, value
);
666 void SqlStatement::setTimeStampParam(int paramPos
, TimeStamp value
)
668 stmt
->setTimeStampParam(paramPos
, value
);
670 void SqlStatement::setBinaryParam(int paramPos
, void *value
, int length
)
672 stmt
->setBinaryParam(paramPos
, value
, length
);
674 int SqlStatement::getFldPos(char *name
)
676 return stmt
->getFldPos(name
);
678 long long SqlStatement::getLastInsertedVal(DbRetVal
&rv
)
680 return stmt
->getLastInsertedVal(rv
);
682 List
SqlStatement::getAllTableNames(DbRetVal
&ret
)
684 DatabaseManager
*dbMgr
= NULL
;
686 dbMgr
=sqlCon
->getConnObject().getDatabaseManager();
688 if(dbMgr
!= NULL
) tbNmList
= dbMgr
->getAllTableNames(&rv
);
693 List
SqlStatement::getAllUserNames(DbRetVal
&ret
)
695 UserManager
*urMgr
= NULL
;
697 urMgr
=sqlCon
->getConnObject().getUserManager();
700 urNmList
= urMgr
->getAllUserNames(&rv
);
704 List
SqlStatement::getFieldNameList(const char *tblName
, DbRetVal
&rv
)
708 fldNameList
= stmt
->getFieldNameList(tblName
, rv
);
711 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
712 Table
*table
= dbMgr
->openTable(tblName
);
715 printError(ErrLockTimeOut
, "Unable to open table %s", tblName
);
718 fldNameList
= table
->getFieldNameList();
719 dbMgr
->closeTable(table
);
722 DbRetVal
SqlStatement::getFieldInfo(const char *tblName
, const char *fldName
, FieldInfo
*&info
)
726 rv
= stmt
->getFieldInfo(tblName
, fldName
, info
);
729 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
730 Table
*table
= dbMgr
->openTable(tblName
);
732 printError(ErrLockTimeOut
, "Unable to open table %s", tblName
);
733 return ErrLockTimeOut
;
735 rv
= table
->getFieldInfo(fldName
, info
);
736 dbMgr
->closeTable(table
);
739 void SqlStatement::setLoading(bool flag
)
741 if (pData
.getStmtType() == InsertStatement
||
742 pData
.getStmtType() == UpdateStatement
||
743 pData
.getStmtType() == DeleteStatement
)
745 DmlStatement
*dmlStmt
= (DmlStatement
*) stmt
;
746 dmlStmt
->setLoading(flag
);
751 int SqlStatement::getNoOfPagesForTable(char *tblName
)
753 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
754 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
755 return dbMgrImpl
->getNoOfPagesForTable(tblName
);
758 DbRetVal
SqlStatement::loadRecords(char *tblName
, void *buf
)
760 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
761 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
762 return dbMgrImpl
->loadRecords(tblName
, (char *) buf
);
765 DbRetVal
SqlStatement::pasteRecords(char *tblName
, void *buffer
)
767 DatabaseManager
*dbMgr
= sqlCon
->getConnObject().getDatabaseManager();
768 DatabaseManagerImpl
*dbMgrImpl
= (DatabaseManagerImpl
*)dbMgr
;
769 return dbMgrImpl
->pasteRecords(tblName
, buffer
);
771 void SqlStatement::flushCacheStmt()
773 return sqlCon
->flushCacheStmt();
776 void SqlStatement::resetStmtString() {
779 //-------------------------------------------------------------------
781 static void sigTermHandler(int sig
)
783 ListIterator iter
= SqlConnection::connList
.getIterator();
784 SqlConnection
*conn
= NULL
;
785 while (iter
.hasElement())
787 conn
= (SqlConnection
*) iter
.nextElement();
788 conn
->flushCacheStmt();
789 if (conn
->isConnectionOpen()) conn
->disconnect();
794 DbRetVal
SqlConnection::connect (char *user
, char * pass
)
796 DbRetVal ret
= conn
.open(user
, pass
);
797 if (ret
!= OK
) return ret
;
798 if (ret
== OK
) isConnOpen
= true;
799 if (!isInit
) initialize();
800 connList
.append(this);
802 #if (defined MMDB && EMBED)
803 os::signal(SIGINT
, sigTermHandler
);
804 os::signal(SIGTERM
, sigTermHandler
);
805 if (Conf::config
.useDurability() && !firstThread
) {
806 rv
= recoverCsqlDB();
808 printError(ErrSysInternal
, "Recovery Failed");
813 rollback(); //for drop table execute in redo log
818 void SqlConnection::flushCacheStmt()
820 ListIterator iter
= cachedStmts
.getIterator();
821 while (iter
.hasElement()) {
822 CachedStmtNode
* node
= (CachedStmtNode
*) iter
.nextElement();
823 //do not delete when the statement is currently in use.
824 //otherwise it leads to illegal memory access when application
825 //calls any method on this statement
826 if (node
->inUse
) continue;
827 //if (node->inUse) node->inUse = 0;
828 free(node
->sqlString
);
829 node
->sqlStmt
->setCachedStmt(false);
830 node
->sqlStmt
->free();
831 delete node
->sqlStmt
;
838 void SqlConnection::setStmtNotInUse(char *stmtstr
)
840 ListIterator iter
= cachedStmts
.getIterator();
841 int inputStmtLen
= strlen(stmtstr
);
842 CachedStmtNode
*node
= NULL
;
843 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
845 if (node
->stmtLength
== inputStmtLen
)
847 if (0 == strcmp(node
->sqlString
, stmtstr
))
856 SqlStatement
* SqlConnection::findInCache(char *stmtstr
)
858 ListIterator iter
= cachedStmts
.getIterator();
859 int inputStmtLen
= strlen(stmtstr
);
860 CachedStmtNode
*node
= NULL
;
861 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
863 if (node
->stmtLength
== inputStmtLen
)
865 if (0 == strcmp(node
->sqlString
, stmtstr
))
867 logFiner(Conf::logger
, "Statement Retrieved From Cache %x\n",
871 return node
->sqlStmt
;
878 void SqlConnection::addToCache(SqlStatement
*sqlStmt
, char* stmtString
)
880 SqlStatement
*stmt
= new SqlStatement();
882 CachedStmtNode
*node
= new CachedStmtNode();
883 node
->sqlStmt
= stmt
;
884 node
->stmtLength
= strlen(stmtString
);
885 node
->sqlString
= (char*)malloc(node
->stmtLength
+1);
887 strcpy(node
->sqlString
, stmtString
);
888 if (cachedStmts
.size() >= Conf::config
.getStmtCacheSize())
892 node
->sqlStmt
->resetStmtString();
893 cachedStmts
.append(node
);
894 logFiner(Conf::logger
, "Statement added To Cache %x\n", node
->sqlStmt
);
895 logFinest(Conf::logger
, "Statement added To Cache %s\n", node
->sqlString
);
899 void SqlConnection::removeLeastUsed()
901 ListIterator iter
= cachedStmts
.getIterator();
902 CachedStmtNode
*node
= NULL
, *toRemove
=NULL
;
904 bool firstCall
= true;
905 while((node
= (CachedStmtNode
*) iter
.nextElement()) != NULL
)
909 lowHits
= node
->hits
;
910 toRemove
= node
; //if cache size is 1
913 if (lowHits
>= node
->hits
) toRemove
= node
;
915 cachedStmts
.remove(toRemove
);
916 //TODO::check whether there is memory leak for list elements
917 logFiner(Conf::logger
, "Statement removed from Cache %x\n", toRemove
->sqlStmt
);
918 logFinest(Conf::logger
, "Statement removed from Cache %s\n", toRemove
->sqlString
);
919 delete toRemove
; toRemove
= NULL
;
923 SqlConnection::~SqlConnection()
926 if (isConnOpen
) disconnect();
930 static void sigUsr1Handler(int sig
)
932 ListIterator iter
= SqlConnection::connList
.getIterator();
933 SqlConnection
*conn
= NULL
;
934 while (iter
.hasElement())
936 conn
= (SqlConnection
*) iter
.nextElement();
937 conn
->flushCacheStmt();
939 os::signal(SIGCSQL1
, sigUsr1Handler
);
943 static void exithandler(void)
945 ListIterator iter
= SqlConnection::connList
.getIterator();
946 SqlConnection
*conn
= NULL
;
947 while (iter
.hasElement())
949 conn
= (SqlConnection
*) iter
.nextElement();
950 conn
->flushCacheStmt();
954 void SqlConnection::displayStmtCache()
956 ListIterator iter
= cachedStmts
.getIterator();
957 CachedStmtNode
*node
= NULL
;
958 printf("STATEMENT CACHE START \n");
959 while ((node
= (CachedStmtNode
*)iter
.nextElement()) != NULL
)
963 printf("STATEMENT CACHE END\n");
966 void SqlConnection::initialize()
968 os::signal(SIGCSQL1
, sigUsr1Handler
);
969 #if (defined MMDB && defined EMBED)
970 os::atexit(exithandler
);
975 #if (defined MMDB && defined EMBED)
977 DbRetVal
SqlConnection::recoverCsqlDB()
980 char dbRedoFileName
[MAX_FILE_LEN
];
981 char dbChkptSchema
[MAX_FILE_LEN
];
982 char dbChkptMap
[MAX_FILE_LEN
];
983 char dbChkptData
[MAX_FILE_LEN
];
984 char dbBackupFile
[MAX_FILE_LEN
];
985 char cmd
[IDENTIFIER_LENGTH
];
986 //check for check point file if present recover
987 sprintf(dbChkptSchema
, "%s/db.chkpt.schema1", Conf::config
.getDbFile());
988 if (FILE *file
= fopen(dbChkptSchema
, "r")) {
990 sprintf(cmd
, "cp -f %s %s/db.chkpt.schema", dbChkptSchema
,
991 Conf::config
.getDbFile());
992 int ret
= system(cmd
);
993 if (ret
!= 0) return ErrOS
;
995 sprintf(dbChkptMap
, "%s/db.chkpt.map1", Conf::config
.getDbFile());
996 if (FILE *file
= fopen(dbChkptMap
, "r")) {
998 sprintf(cmd
, "cp -f %s %s/db.chkpt.map", dbChkptMap
,
999 Conf::config
.getDbFile());
1000 int ret
= system(cmd
);
1001 if (ret
!= 0) return ErrOS
;
1003 int chkptID
= Database::getCheckpointID();
1004 sprintf(dbChkptData
, "%s/db.chkpt.data%d", Conf::config
.getDbFile(),
1006 sprintf(dbBackupFile
, "%s/db.chkpt.data1", Conf::config
.getDbFile());
1008 if (!Conf::config
.useMmap() && (fl
= fopen(dbBackupFile
, "r"))) {
1010 sprintf(cmd
, "cp %s/db.chkpt.data1 %s", Conf::config
.getDbFile(),
1012 int ret
= system(cmd
);
1013 if (ret
!= 0) return ErrOS
;
1015 if (FILE *file
= fopen(dbChkptData
, "r")) {
1017 rv
= recoverSystemAndUserDB();
1018 if (rv
!= OK
) return rv
;
1021 //check for redo log file if present apply redo logs
1022 sprintf(dbRedoFileName
, "%s/csql.db.cur", Conf::config
.getDbFile());
1023 if (FILE *file
= fopen(dbRedoFileName
, "r"))
1026 rv
= (DbRetVal
) applyRedoLogs(dbRedoFileName
);
1027 if (rv
!= OK
) return rv
;
1028 DatabaseManager
*dbMgr
= getConnObject().getDatabaseManager();
1029 rv
= dbMgr
->checkPoint();
1032 printError(ErrSysInternal
, "checkpoint failed after redo log apply");
1039 DbRetVal
SqlConnection::recoverSystemAndUserDB()
1043 sprintf(schFile
, "%s/db.chkpt.schema", Conf::config
.getDbFile());
1044 if (FILE *file
= fopen(schFile
, "r")) {
1045 rv
= applySchemaFile(file
);
1046 if (rv
!= OK
) { fclose(file
); return rv
; }
1048 DatabaseManager
*dbMgr
= getConnObject().getDatabaseManager();
1049 rv
= dbMgr
->recover();
1053 DbRetVal
SqlConnection::applySchemaFile(FILE *fp
)
1058 SqlStatement
*stmt
= new SqlStatement();
1059 while ((eof
= getQueryFromSchemaFile(fp
,buf
)) != EOF
) {
1060 stmt
->setConnection(this);
1061 rv
= stmt
->prepare(buf
);
1062 if (rv
!= OK
) { delete stmt
; return rv
; }
1064 stmt
->execute(rows
);
1065 if (rv
!= OK
) { stmt
->free(); delete stmt
; return rv
; }
1071 char SqlConnection::getQueryFromSchemaFile(FILE *fp
, char *buf
)
1073 char c
, *bufBegin
=buf
;
1075 while( (c
=(char ) fgetc(fp
)) != EOF
&& c
!= ';')
1077 *buf
++ = c
; charCnt
++;
1078 if( charCnt
== SQL_STMT_LEN
) {
1079 printf("SQL Statement length is greater than %d. "
1080 "Ignoring the statement.\n", SQL_STMT_LEN
);
1091 int SqlConnection::applyRedoLogs(char *redoFile
)
1095 int fd
= open(redoFile
, O_RDONLY
);
1096 if (-1 == fd
) { return OK
; }
1097 if (fstat(fd
, &st
) == -1) {
1098 printError(ErrSysInternal
, "Unable to retrieve undo log file size");
1102 if (st
.st_size
==0) {
1103 printError(ErrNote
, "No Redo logs found during recovery");
1104 SqlStatement::readAndPopulateStmts(this, stmtBuckets
);
1108 void *startAddr
= mmap(NULL
, st
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
1109 if (MAP_FAILED
== startAddr
) {
1110 printf("Unable to read undo log file:mmap failed.\n");
1114 rv
= SqlStatement::readAndPopulateStmts(this, stmtBuckets
);
1117 printf("Unable to read stmt log file\n");
1121 char *iter
= (char*)startAddr
;
1126 int len
, ret
, retVal
=0;
1128 char stmtString
[SQL_STMT_LEN
];
1130 if (iter
- (char*)startAddr
>= st
.st_size
) break;
1131 logType
= *(int*)iter
;
1132 if (logType
== -1) { //prepare
1133 iter
= iter
+ sizeof(int);
1134 txnID
= *(int*) iter
; iter
+= sizeof(int);
1135 loglen
= *(int*) iter
; iter
+= sizeof(int);
1136 stmtID
= *(int*)iter
;
1137 iter
= iter
+ sizeof(int);
1139 iter
= iter
+ sizeof(int);
1140 strncpy(stmtString
, iter
, len
);
1142 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlDirect
);
1143 SqlStatement
*sqlStmt
= (SqlStatement
*)stmt
;
1144 stmt
->setConnection(this);
1145 rv
= stmt
->prepare(stmtString
);
1147 printError(ErrSysInternal
, "unable to prepare stmt:%s", stmtString
);
1151 sqlStmt
->setLoading(true);
1152 SqlStatement::addToHashTable(stmtID
, stmt
, stmtBuckets
, stmtString
);
1154 else if(logType
== -2) { //commit
1156 iter
= iter
+ sizeof(int);
1157 txnID
= *(int*) iter
; iter
+= sizeof(int);
1158 loglen
= *(int*) iter
; iter
+= sizeof(int);
1159 char *curPtr
= iter
;
1161 if (iter
- (char*)startAddr
>= st
.st_size
) {
1166 stmtID
= *(int*)iter
;
1167 iter
= iter
+ sizeof(int);
1168 eType
= *(int*)iter
;
1169 AbsSqlStatement
*stmt
=
1170 SqlStatement::getStmtFromHashTable(stmtID
,stmtBuckets
);
1172 printError(ErrSysInternal
,
1173 "Unable to find in stmt hashtable");
1177 if (0 == eType
) { //execute type
1178 iter
= iter
+ sizeof(int);
1179 rv
= stmt
->execute(ret
);
1181 printError(ErrSysInternal
, "unable to execute");
1185 if (*(int*)iter
<0) break;
1186 } else if ( 1 == eType
) { //set type
1187 iter
=iter
+sizeof(int);
1188 int pos
= *(int*) iter
;
1189 iter
=iter
+sizeof(int);
1190 int isNull
= *(int *)iter
;
1191 iter
= iter
+ sizeof(int);
1193 DataType type
= (DataType
)(*(int*)iter
);
1194 iter
=iter
+sizeof(int);
1195 int len
= *(int*) iter
;
1196 iter
=iter
+sizeof(int);
1199 SqlStatement::setParamValues(stmt
, pos
,
1201 } else stmt
->setNull(pos
);
1202 if (*(int*)iter
<0) break;
1207 else if(logType
== -3) { //free
1208 iter
= iter
+ sizeof(int);
1209 txnID
= *(int*) iter
; iter
+= sizeof(int);
1210 loglen
= *(int*) iter
; iter
+= sizeof(int);
1211 stmtID
= *(int*)iter
;
1212 iter
= iter
+ sizeof(int);
1213 AbsSqlStatement
*stmt
= SqlStatement::getStmtFromHashTable(stmtID
,
1217 SqlStatement::removeFromHashTable(stmtID
,stmtBuckets
);
1218 } else { printError(ErrSysInternal
, "statement not found for %d\n",stmtID
);}
1220 else if(logType
== -4) { //prepare and execute
1221 iter
= iter
+ sizeof(int);
1222 txnID
= *(int*) iter
; iter
+= sizeof(int);
1223 loglen
= *(int*) iter
; iter
+= sizeof(int);
1224 stmtID
= *(int*)iter
;
1225 iter
= iter
+ sizeof(int);
1227 iter
= iter
+ sizeof(int);
1228 strncpy(stmtString
, iter
, len
);
1229 stmtString
[len
+1] ='\0';
1231 AbsSqlStatement
*stmt
= SqlFactory::createStatement(CSqlDirect
);
1232 if ( NULL
== stmt
) {
1233 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
1237 stmt
->setConnection(this);
1238 rv
= stmt
->prepare(stmtString
);
1240 printError(ErrSysInternal
, "unable to prepare:%s", stmtString
);
1244 rv
= stmt
->execute(ret
);
1246 if (strlen(stmtString
) > 6 &&
1247 ( (strncasecmp(stmtString
,"CREATE", 6) == 0) ||
1248 (strncasecmp(stmtString
,"DROP", 4) == 0) ||
1249 (strncasecmp(stmtString
,"RENAME", 6) == 0) ||
1250 (strncasecmp(stmtString
,"ALTER", 5) == 0) )) {
1253 printError(ErrSysInternal
, "unable to execute %s", stmtString
);
1259 printError(ErrSysInternal
, "Redo log file corrupted: logType:%d", logType
);
1264 munmap((char*)startAddr
, st
.st_size
);
1266 SqlStatement::filterAndWriteStmtLogs(stmtBuckets
);
1267 SqlStatement::freeAllStmtHandles(stmtBuckets
);