64 bit build fix
[csql.git] / src / sql / SqlStatement.cxx
blobf135ca5908de0ae9657bffee0d99fc28b8d82ad9
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;
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)
44 switch(type)
46 case typeInt:
47 sqlStmt->setIntParam(parampos, *(int*)value);
48 break;
49 case typeLong:
50 sqlStmt->setLongParam(parampos, *(long*)value);
51 break;
52 case typeLongLong:
53 sqlStmt->setLongLongParam(parampos, *(long long*)value);
54 break;
55 case typeShort:
56 sqlStmt->setShortParam(parampos, *(short*)value);
57 break;
58 case typeByteInt:
59 sqlStmt->setByteIntParam(parampos, *(char*)value);
60 break;
61 case typeDouble:
62 sqlStmt->setDoubleParam(parampos, *(double*)value);
63 break;
64 case typeFloat:
65 sqlStmt->setFloatParam(parampos, *(float*)value);
66 break;
67 case typeDate:
68 sqlStmt->setDateParam(parampos, *(Date*)value);
69 break;
70 case typeTime:
71 sqlStmt->setTimeParam(parampos, *(Time*)value);
72 break;
73 case typeTimeStamp:
74 sqlStmt->setTimeStampParam(parampos, *(TimeStamp*)value);
75 break;
76 case typeVarchar:
77 case typeString:
79 sqlStmt->setStringParam(parampos, (char*)value);
80 break;
82 case typeBinary:
83 sqlStmt->setBinaryParam(parampos, (char *) value, length);
84 break;
85 default:
86 printf("unknown type\n");
87 break;
89 return;
92 void *SqlStatement::fillBindBuffer(TDBInfo tdbName, DataType type, void *&valBuf, int length, int nRecords)
94 BindBuffer *bBuf = NULL;
95 switch(type)
97 case typeDate:
98 bBuf = new BindBuffer();
99 bBuf->csql = valBuf;
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;
105 break;
106 case typeTime:
107 bBuf = new BindBuffer();
108 bBuf->csql = valBuf;
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;
114 break;
115 case typeTimeStamp:
116 bBuf = new BindBuffer();
117 bBuf->csql = valBuf;
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;
123 break;
124 case typeLongLong:
126 if( tdbName == postgres)
128 bBuf = new BindBuffer();
129 bBuf->type = typeLongLong;
130 bBuf->length = 40;
131 bBuf->csql = valBuf;
132 int size = nRecords*AllDataType::size(typeString,bBuf->length);
133 bBuf->targetdb = malloc(size);
134 memset(bBuf->targetdb, 0, size);
135 valBuf = bBuf->targetdb;
136 break;
137 }else
139 bBuf = new BindBuffer();
140 bBuf->type = type;
141 bBuf->csql = valBuf;
142 bBuf->length = length;
143 break;
146 case typeVarchar:
147 case typeString:
149 bBuf = new BindBuffer();
150 bBuf->type = typeString;
151 bBuf->csql = valBuf;
152 bBuf->length = length;
153 break;
155 default:
156 bBuf = new BindBuffer();
157 bBuf->type = type;
158 bBuf->csql = valBuf;
159 bBuf->length = length;
160 break;
162 bBuf->nullData = (SQLLEN *) malloc(nRecords * sizeof(SQLLEN));
163 for (int i = 0; i < nRecords; i++) bBuf->nullData[i] = SQL_NTS;
164 return bBuf;
168 List SqlStatement::getTableNameList()
170 return pData.getTableNameList();
172 SqlStatement::SqlStatement()
174 innerStmt = NULL;
175 sqlCon = NULL;
176 stmt = NULL;
177 isPrepd = false;
178 isCachedStmt=false;
179 isMgmtStatement = false;
180 sqlStmtString = NULL;
181 dontCache = false;
183 void SqlStatement::setConnection(AbsSqlConnection *conn)
185 sqlCon = (SqlConnection*)conn;
186 con = conn;
189 void SqlStatement::setSqlConnection(SqlConnection *conn)
191 sqlCon = conn;
194 DbRetVal SqlStatement::executeDirect(char *str)
196 DbRetVal rv = OK;
197 int rows = 0;
198 rv = prepare(str);
199 if (rv != OK) return rv;
200 rv = execute(rows);
201 if (rv != OK) return rv;
202 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)
227 DbRetVal rv = OK;
228 if (! sqlCon->isConnectionOpen()) {
229 printError(ErrNotOpen, "Connection not open");
230 return ErrNotOpen;
232 SqlStatement *cachedStmt = sqlCon->findInCache(stmtstr);
233 if (cachedStmt)
235 *this = *cachedStmt;
236 this->stmt->setParsedData(&this->pData);
237 isCachedStmt=true;
238 logFine(Conf::logger,"GOT STMT FROM CACHE: %s %x", stmtstr, cachedStmt);
239 return OK;
241 // take mutex here
242 int ret = ProcessManager::prepareMutex.tryLock(10, 1000);
243 if (ret != 0)
245 printError(ErrLockTimeOut, "Unable to get prepare mutex");
246 return ErrLockTimeOut;
249 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
250 if (isPrepared()) free();
251 lexInput = stmtstr;
252 parsedData = &pData;
254 yy_buffer_state *yy_buffer= yy_scan_string(stmtstr);
255 int rc = yyparse();
256 if (yy_buffer) yy_delete_buffer(yy_buffer);
257 if (rc != 0)
259 free();
260 parsedData = NULL;
261 ProcessManager::prepareMutex.releaseLock(-1, false);
262 return ErrSyntaxError;
264 if( parsedData->getStmtType() == MgmtStatement)
266 isPrepd = true;
267 parsedData = NULL;
268 isMgmtStatement = true;
269 ProcessManager::prepareMutex.releaseLock(-1, false);
270 logFine(Conf::logger,"PREPARE: %s %x", stmtstr, stmt);
271 return OK;
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();
282 if (rv != OK)
284 free();
285 parsedData = NULL;
286 ProcessManager::prepareMutex.releaseLock(-1, false);
287 return rv;
289 isPrepd = true;
290 if (!isCachedStmt && Conf::config.getStmtCacheSize() && !getDontCache()) {
291 if (stmt->noOfParamFields() > 0) {
292 isCachedStmt = true;
293 sqlCon->addToCache(this, stmtstr);
294 } else if (Conf::config.useCacheNoParam()) {
295 if (parsedData->getCacheWorthy()) {
296 isCachedStmt = true;
297 sqlCon->addToCache(this, stmtstr);
300 } else { printf("stmtstring '%s' not cached\n", stmtstr); }
301 parsedData = NULL;
302 ProcessManager::prepareMutex.releaseLock(-1, false);
303 return OK;
306 char* SqlStatement::getTableName()
308 return pData.getTableName();
311 bool SqlStatement::isSelect()
313 if ((pData.getStmtType() == SelectStatement) || (pData.getStmtType() == MetaStatement)) return true;
314 return false;
317 bool SqlStatement::isPrepared() { return isPrepd; }
319 DbRetVal SqlStatement::execute(int &rowsAffected)
321 DbRetVal rv = OK;
322 if (! sqlCon->isConnectionOpen()) {
323 printError(ErrNotOpen, "Connection not open");
324 return ErrNotOpen;
326 if (! isPrepared()) {
327 printError(ErrNotPrepared, "Statement Not Prepared");
328 return ErrNotPrepared;
330 if( isMgmtStatement )
332 flushCacheStmt();
333 logFiner(Conf::logger,"EXECUTE: %x", stmt);
334 return OK;
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;
340 selStmt->close();
341 rv = stmt->execute(rowsAffected);
343 logFiner(Conf::logger,"EXECUTE: %x", stmt);
344 return rv;
347 void* SqlStatement::fetch()
349 if (! sqlCon->isConnectionOpen()) {
350 printError(ErrNotOpen, "Connection not open");
351 return NULL;
353 if (! isPrepared()) {
354 printError(ErrNotPrepared, "Statement Not Prepared");
355 return NULL;
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();
365 else { return NULL;}
368 void* SqlStatement::fetch(DbRetVal &rv)
370 if (! sqlCon->isConnectionOpen()) {
371 printError(ErrNotOpen, "Connection not open");
372 rv = ErrNoConnection;
373 return NULL;
375 if (! isPrepared()) {
376 printError(ErrNotPrepared, "Statement Not Prepared");
377 return NULL;
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);
387 else { return NULL;}
390 void* SqlStatement::fetchAndPrint(bool SQL)
392 if (! sqlCon->isConnectionOpen()) {
393 printError(ErrNotOpen, "Connection not open");
394 return NULL;
396 if (! isPrepared()) {
397 printError(ErrNotPrepared, "Statement Not Prepared");
398 return NULL;
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)
407 DbRetVal rv = OK;
408 rv = stmt->setParam(pos, value);
409 return rv;
412 DbRetVal SqlStatement::bindField(int pos, void* value)
414 DbRetVal rv = OK;
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() );
435 else { return 0;}
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();
462 else { return OK;}
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 ) );
482 else { return 0;}
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 ) );
507 else { return 0;}
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 ) );
520 else { return 0;}
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 ) );
532 else { return NULL;}
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();
545 else { return 0;}
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)
570 DbRetVal rv = OK;
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;}
579 return rv;
582 DbRetVal SqlStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
584 DbRetVal rv = OK;
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);
594 return rv;
597 DbRetVal SqlStatement::free()
599 logFinest(Conf::logger,"FREE: %x", stmt);
600 if (isCachedStmt) {
601 stmt=NULL;
602 pData.init();
603 isPrepd = false;
604 if (sqlStmtString) {
605 sqlCon->setStmtNotInUse(sqlStmtString);
606 ::free(sqlStmtString);
607 sqlStmtString=NULL;
609 isCachedStmt = false;
610 return OK;
612 if(stmt) delete stmt;
613 stmt = NULL;
614 pData.reset();
615 isMgmtStatement = false;
616 isPrepd = false;
617 isCachedStmt = false;
618 if (sqlStmtString) { ::free(sqlStmtString); sqlStmtString=NULL; }
619 return OK;
622 void SqlStatement::setNull(int pos)
624 stmt->setNull(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;
685 List tbNmList;
686 dbMgr=sqlCon->getConnObject().getDatabaseManager();
687 int rv = ret;
688 if(dbMgr != NULL) tbNmList = dbMgr->getAllTableNames(&rv);
689 ret = (DbRetVal) rv;
690 return tbNmList;
693 List SqlStatement::getAllUserNames(DbRetVal &ret)
695 UserManager *urMgr = NULL;
696 List urNmList;
697 urMgr=sqlCon->getConnObject().getUserManager();
698 int rv = ret;
699 if(urMgr != NULL)
700 urNmList = urMgr->getAllUserNames(&rv);
701 ret = (DbRetVal) rv;
702 return urNmList;
704 List SqlStatement::getFieldNameList(const char *tblName, DbRetVal &rv)
706 List fldNameList;
707 if (isPrepared()) {
708 fldNameList = stmt->getFieldNameList(tblName, rv);
709 return fldNameList;
711 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
712 Table *table = dbMgr->openTable(tblName);
713 if (NULL == table) {
714 List dummyList;
715 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
716 return dummyList;
718 fldNameList = table->getFieldNameList();
719 dbMgr->closeTable(table);
720 return fldNameList;
722 DbRetVal SqlStatement::getFieldInfo(const char *tblName, const char *fldName, FieldInfo *&info)
724 DbRetVal rv = OK;
725 if (isPrepared()) {
726 rv = stmt->getFieldInfo(tblName, fldName, info);
727 return rv;
729 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
730 Table *table = dbMgr->openTable(tblName);
731 if (NULL == table) {
732 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
733 return ErrLockTimeOut;
735 rv = table->getFieldInfo(fldName, info);
736 dbMgr->closeTable(table);
737 return rv;
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);
748 return;
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() {
777 sqlStmtString=NULL;
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();
791 exit(0);
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);
801 DbRetVal rv = OK;
802 #if (defined MMDB && EMBED)
803 os::signal(SIGINT, sigTermHandler);
804 os::signal(SIGTERM, sigTermHandler);
805 if (Conf::config.useDurability() && !firstThread) {
806 rv = recoverCsqlDB();
807 if (rv != OK) {
808 printError(ErrSysInternal, "Recovery Failed");
809 return rv;
811 firstThread = true;
813 rollback(); //for drop table execute in redo log
814 #endif
815 return ret;
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;
832 delete node;
834 cachedStmts.reset();
835 return;
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))
849 node->inUse =0;
850 return;
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",
868 node->sqlStmt);
869 node->hits++;
870 node->inUse = 1;
871 return node->sqlStmt;
875 return NULL;
878 void SqlConnection::addToCache(SqlStatement *sqlStmt, char* stmtString)
880 SqlStatement *stmt = new SqlStatement();
881 *stmt= *sqlStmt;
882 CachedStmtNode *node = new CachedStmtNode();
883 node->sqlStmt = stmt;
884 node->stmtLength = strlen(stmtString);
885 node->sqlString = (char*)malloc(node->stmtLength+1);
886 node->inUse=1;
887 strcpy(node->sqlString, stmtString);
888 if (cachedStmts.size() >= Conf::config.getStmtCacheSize())
890 removeLeastUsed();
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);
896 return ;
899 void SqlConnection::removeLeastUsed()
901 ListIterator iter = cachedStmts.getIterator();
902 CachedStmtNode *node = NULL, *toRemove =NULL;
903 int lowHits = 0;
904 bool firstCall = true;
905 while((node = (CachedStmtNode*) iter.nextElement()) != NULL)
907 if (firstCall) {
908 firstCall = false;
909 lowHits = node->hits;
910 toRemove = node; //if cache size is 1
911 continue;
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;
920 return;
923 SqlConnection::~SqlConnection()
925 flushCacheStmt();
926 if (isConnOpen) disconnect();
927 innerConn = NULL;
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);
940 return;
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();
951 conn->disconnect();
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)
961 node->display();
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);
971 #endif
972 isInit = true;
975 #if (defined MMDB && defined EMBED)
977 DbRetVal SqlConnection::recoverCsqlDB()
979 DbRetVal rv = OK;
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")) {
989 fclose(file);
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")) {
997 fclose(file);
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(),
1005 chkptID);
1006 sprintf(dbBackupFile, "%s/db.chkpt.data1", Conf::config.getDbFile());
1007 FILE *fl = NULL;
1008 if (!Conf::config.useMmap() && (fl = fopen(dbBackupFile, "r"))) {
1009 fclose(fl);
1010 sprintf(cmd, "cp %s/db.chkpt.data1 %s", Conf::config.getDbFile(),
1011 dbChkptData);
1012 int ret = system(cmd);
1013 if (ret != 0) return ErrOS;
1015 if (FILE *file = fopen(dbChkptData, "r")) {
1016 fclose(file);
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"))
1025 fclose(file);
1026 rv = (DbRetVal) applyRedoLogs(dbRedoFileName);
1027 if (rv != OK) return rv;
1028 DatabaseManager *dbMgr = getConnObject().getDatabaseManager();
1029 rv = dbMgr->checkPoint();
1030 if (rv != OK)
1032 printError(ErrSysInternal, "checkpoint failed after redo log apply");
1033 return ErrOS;
1036 return OK;
1039 DbRetVal SqlConnection::recoverSystemAndUserDB()
1041 DbRetVal rv = OK;
1042 char schFile[1024];
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();
1050 return rv;
1053 DbRetVal SqlConnection::applySchemaFile(FILE *fp)
1055 char buf[8192];
1056 char eof;
1057 DbRetVal rv = OK;
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; }
1063 int rows = 0;
1064 stmt->execute(rows);
1065 if (rv != OK) { stmt->free(); delete stmt; return rv; }
1067 delete stmt;
1068 return OK;
1071 char SqlConnection::getQueryFromSchemaFile(FILE *fp, char *buf)
1073 char c, *bufBegin=buf;
1074 int charCnt=0;
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 );
1081 *bufBegin++ =';';
1082 *bufBegin ='\0';
1083 return 0;
1086 *buf++ = ';';
1087 *buf = '\0';
1088 return c;
1091 int SqlConnection::applyRedoLogs(char *redoFile)
1093 struct stat st;
1094 DbRetVal rv = OK;
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");
1099 close(fd);
1100 return 1;
1102 if (st.st_size ==0) {
1103 printError(ErrNote, "No Redo logs found during recovery");
1104 SqlStatement::readAndPopulateStmts(this, stmtBuckets);
1105 close(fd);
1106 return OK;
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");
1111 return 2;
1114 rv = SqlStatement::readAndPopulateStmts(this, stmtBuckets);
1115 if (OK != rv)
1117 printf("Unable to read stmt log file\n");
1118 return 2;
1121 char *iter = (char*)startAddr;
1122 void *value = NULL;
1123 int logType, eType;
1124 int stmtID;
1125 int txnID;
1126 int len, ret, retVal =0;
1127 int loglen;
1128 char stmtString[SQL_STMT_LEN];
1129 while(true) {
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);
1138 len = *(int*)iter;
1139 iter = iter + sizeof(int);
1140 strncpy(stmtString, iter, len);
1141 iter = iter + len;
1142 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
1143 SqlStatement *sqlStmt = (SqlStatement *)stmt;
1144 stmt->setConnection(this);
1145 rv = stmt->prepare(stmtString);
1146 if (rv != OK) {
1147 printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString);
1148 retVal=1;
1149 break;
1151 sqlStmt->setLoading(true);
1152 SqlStatement::addToHashTable(stmtID, stmt, stmtBuckets, stmtString);
1154 else if(logType == -2) { //commit
1155 beginTrans();
1156 iter = iter + sizeof(int);
1157 txnID = *(int*) iter; iter += sizeof(int);
1158 loglen = *(int*) iter; iter += sizeof(int);
1159 char *curPtr = iter;
1160 while(true) {
1161 if (iter - (char*)startAddr >= st.st_size) {
1162 //file end reached
1163 retVal=0;
1164 break;
1166 stmtID = *(int*)iter;
1167 iter = iter + sizeof(int);
1168 eType = *(int*)iter;
1169 AbsSqlStatement *stmt =
1170 SqlStatement::getStmtFromHashTable(stmtID,stmtBuckets);
1171 if (NULL == stmt) {
1172 printError(ErrSysInternal,
1173 "Unable to find in stmt hashtable");
1174 retVal=2;
1175 break;
1177 if (0 == eType) { //execute type
1178 iter = iter + sizeof(int);
1179 rv = stmt->execute(ret);
1180 if (rv != OK) {
1181 printError(ErrSysInternal, "unable to execute");
1182 retVal=2;
1183 break;
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);
1192 if (isNull == 0) {
1193 DataType type = (DataType)(*(int*)iter);
1194 iter=iter+sizeof(int);
1195 int len = *(int*) iter;
1196 iter=iter+sizeof(int);
1197 value = iter;
1198 iter=iter+len;
1199 SqlStatement::setParamValues(stmt, pos,
1200 type, len, value);
1201 } else stmt->setNull(pos);
1202 if (*(int*)iter <0) break;
1205 commit();
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,
1214 stmtBuckets);
1215 if (stmt) {
1216 stmt->free();
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);
1226 len = *(int*)iter;
1227 iter = iter + sizeof(int);
1228 strncpy(stmtString, iter, len);
1229 stmtString[len+1] ='\0';
1230 iter = iter + len;
1231 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
1232 if ( NULL == stmt) {
1233 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
1234 retVal=3;
1235 break;
1237 stmt->setConnection(this);
1238 rv = stmt->prepare(stmtString);
1239 if (rv != OK) {
1240 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
1241 retVal=4;
1242 break;
1244 rv = stmt->execute(ret);
1245 if (rv != OK) {
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) )) {
1251 continue;
1253 printError(ErrSysInternal, "unable to execute %s", stmtString);
1254 retVal=5;
1255 break;
1257 stmt->free();
1258 }else{
1259 printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType);
1260 retVal=6;
1261 break;
1264 munmap((char*)startAddr, st.st_size);
1265 close(fd);
1266 SqlStatement::filterAndWriteStmtLogs(stmtBuckets);
1267 SqlStatement::freeAllStmtHandles(stmtBuckets);
1268 return retVal;
1270 #endif