----------------------------------------------------------------------
[csql.git] / src / sql / SqlStatement.cxx
blob7d3d41c1f955f76b33d29c3bb9d7544ff65beb64
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;
167 void SqlStatement::addToHashTable(int stmtID, AbsSqlStatement* sHdl,
168 void *stmtBuckets, char *stmtstr)
170 int bucketNo = stmtID % STMT_BUCKET_SIZE;
171 StmtBucket *buck = (StmtBucket *) stmtBuckets;
172 StmtBucket *stmtBucket = &buck[bucketNo];
173 StmtNode *node = new StmtNode();
174 node->stmtId = stmtID;
175 node->stmt = sHdl;
176 strcpy(node->stmtstr, stmtstr);
177 stmtBucket->bucketList.append(node);
178 return;
181 void SqlStatement::removeFromHashTable(int stmtID, void *stmtBuckets)
183 int bucketNo = stmtID % STMT_BUCKET_SIZE;
184 StmtBucket *buck = (StmtBucket *) stmtBuckets;
185 StmtBucket *stmtBucket = &buck[bucketNo];
186 StmtNode *node = NULL, *delNode = NULL;
187 ListIterator it = stmtBucket->bucketList.getIterator();
188 while(it.hasElement()) {
189 node = (StmtNode *) it.nextElement();
190 if(stmtID == node->stmtId) { delNode = node; break; }
192 it.reset();
193 if (delNode != NULL) {
194 stmtBucket->bucketList.remove(delNode);
195 delete delNode;
197 return;
200 AbsSqlStatement *SqlStatement::getStmtFromHashTable(int stmtId,
201 void *stmtBuckets)
203 int bucketNo = stmtId % STMT_BUCKET_SIZE;
204 StmtBucket *buck = (StmtBucket *) stmtBuckets;
205 StmtBucket *stmtBucket = &buck[bucketNo];
206 if (stmtBucket == NULL) return NULL;
207 StmtNode *node = NULL;
208 ListIterator it = stmtBucket->bucketList.getIterator();
209 while(it.hasElement()) {
210 node = (StmtNode *) it.nextElement();
211 if(stmtId == node->stmtId) {
212 SqlStatement *sqlStmt = (SqlStatement*)node->stmt;
213 if (!sqlStmt->isPrepared()) sqlStmt->prepare(node->stmtstr);
214 return node->stmt;
217 return NULL;
220 bool SqlStatement::isStmtInHashTable(int stmtId, void *stmtBuckets)
222 int bucketNo = stmtId % STMT_BUCKET_SIZE;
223 StmtBucket *buck = (StmtBucket *) stmtBuckets;
224 StmtBucket *stmtBucket = &buck[bucketNo];
225 if (stmtBucket == NULL) return false;
226 StmtNode *node = NULL;
227 ListIterator it = stmtBucket->bucketList.getIterator();
228 while(it.hasElement()) {
229 node = (StmtNode *) it.nextElement();
230 if(stmtId == node->stmtId) {
231 SqlStatement *sqlStmt = (SqlStatement*)node->stmt;
232 if (sqlStmt->isPrepared()) return true;
233 else break;
236 return false;
239 void SqlStatement::freeAllStmtHandles(void *stmtBuckets)
241 if (NULL == stmtBuckets) return;
242 StmtBucket *buck = (StmtBucket *) stmtBuckets;
243 StmtNode *node = NULL;
244 for (int i=0; i <STMT_BUCKET_SIZE; i++)
246 StmtBucket *stmtBucket = &buck[i];
247 if (stmtBucket == NULL) continue;
248 ListIterator it = stmtBucket->bucketList.getIterator();
249 while(it.hasElement()) {
250 node = (StmtNode *) it.nextElement();
251 node->stmt->free();
252 delete node->stmt;
255 ::free(stmtBuckets);
258 List SqlStatement::getTableNameList()
260 return pData.getTableNameList();
262 SqlStatement::SqlStatement()
264 innerStmt = NULL;
265 sqlCon = NULL;
266 stmt = NULL;
267 isPrepd = false;
268 isCachedStmt=false;
269 isMgmtStatement = false;
270 sqlStmtString = NULL;
271 dontCache = false;
273 void SqlStatement::setConnection(AbsSqlConnection *conn)
275 sqlCon = (SqlConnection*)conn;
276 con = conn;
279 void SqlStatement::setSqlConnection(SqlConnection *conn)
281 sqlCon = conn;
284 DbRetVal SqlStatement::executeDirect(char *str)
286 DbRetVal rv = OK;
287 int rows = 0;
288 rv = prepare(str);
289 if (rv != OK) return rv;
290 rv = execute(rows);
291 if (rv != OK) return rv;
292 return rv;
295 void SqlStatement::setStmtString(char *ststr)
297 if (sqlStmtString) { ::free(sqlStmtString); sqlStmtString=NULL; }
298 sqlStmtString = (char*) malloc(strlen(ststr)+1);
299 strcpy(sqlStmtString, ststr);
302 DbRetVal SqlStatement::prepare()
304 return prepareInt(sqlStmtString);
307 DbRetVal SqlStatement::prepare(char *stmtstr)
309 if (sqlStmtString) { ::free(sqlStmtString); sqlStmtString=NULL;}
310 sqlStmtString = (char*) malloc(strlen(stmtstr)+1);
311 strcpy(sqlStmtString, stmtstr);
312 return prepareInt(stmtstr);
315 DbRetVal SqlStatement::prepareInt(char *stmtstr)
317 DbRetVal rv = OK;
318 if (! sqlCon->isConnectionOpen()) {
319 printError(ErrNotOpen, "Connection not open");
320 return ErrNotOpen;
322 SqlStatement *cachedStmt = sqlCon->findInCache(stmtstr);
323 if (cachedStmt)
325 *this = *cachedStmt;
326 this->stmt->setParsedData(&this->pData);
327 isCachedStmt=true;
328 logFine(Conf::logger,"GOT STMT FROM CACHE: %s %x", stmtstr, cachedStmt);
329 return OK;
331 // take mutex here
332 int ret = ProcessManager::prepareMutex.tryLock(10, 1000);
333 if (ret != 0)
335 printError(ErrLockTimeOut, "Unable to get prepare mutex");
336 return ErrLockTimeOut;
339 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
340 if (isPrepared()) free();
341 lexInput = stmtstr;
342 parsedData = &pData;
344 yy_buffer_state *yy_buffer= yy_scan_string(stmtstr);
345 int rc = yyparse();
346 if (yy_buffer) yy_delete_buffer(yy_buffer);
347 if (rc != 0)
349 free();
350 parsedData = NULL;
351 ProcessManager::prepareMutex.releaseLock(-1, false);
352 return ErrSyntaxError;
354 if( parsedData->getStmtType() == MgmtStatement)
356 isPrepd = true;
357 parsedData = NULL;
358 isMgmtStatement = true;
359 ProcessManager::prepareMutex.releaseLock(-1, false);
360 logFine(Conf::logger,"PREPARE: %s %x", stmtstr, stmt);
361 return OK;
363 stmt = StatementFactory::getStatement(parsedData);
364 stmt->setDbMgr(dbMgr);
365 if( parsedData->getStmtType() == UserStatement)
367 UserManager* userMgr = sqlCon->getConnObject().getUserManager();
368 UserTblStatement *ustmt = (UserTblStatement *)stmt;
369 ustmt->setUserManager(userMgr,sqlCon->getConnObject().getUserName());
371 rv = stmt->resolve();
372 if (rv != OK)
374 free();
375 parsedData = NULL;
376 ProcessManager::prepareMutex.releaseLock(-1, false);
377 return rv;
379 isPrepd = true;
380 if (!isCachedStmt && Conf::config.getStmtCacheSize() && !getDontCache()) {
381 if (stmt->noOfParamFields() > 0) {
382 isCachedStmt = true;
383 sqlCon->addToCache(this, stmtstr);
384 } else if (Conf::config.useCacheNoParam()) {
385 if (parsedData->getCacheWorthy()) {
386 isCachedStmt = true;
387 sqlCon->addToCache(this, stmtstr);
390 } else { printf("stmtstring '%s' not cached\n", stmtstr); }
391 parsedData = NULL;
392 ProcessManager::prepareMutex.releaseLock(-1, false);
393 return OK;
396 char* SqlStatement::getTableName()
398 return pData.getTableName();
401 bool SqlStatement::isSelect()
403 if ((pData.getStmtType() == SelectStatement) || (pData.getStmtType() == MetaStatement)) return true;
404 return false;
407 bool SqlStatement::isPrepared() { return isPrepd; }
409 DbRetVal SqlStatement::execute(int &rowsAffected)
411 DbRetVal rv = OK;
412 if (! sqlCon->isConnectionOpen()) {
413 printError(ErrNotOpen, "Connection not open");
414 return ErrNotOpen;
416 if (! isPrepared()) {
417 printError(ErrNotPrepared, "Statement Not Prepared");
418 return ErrNotPrepared;
420 if( isMgmtStatement )
422 flushCacheStmt();
423 logFiner(Conf::logger,"EXECUTE: %x", stmt);
424 return OK;
426 rv = stmt->execute(rowsAffected);
427 if (rv == ErrAlready && pData.getStmtType() == SelectStatement )
428 { //if previous scan is not closed, close it
429 SelStatement *selStmt = (SelStatement*) stmt;
430 selStmt->close();
431 rv = stmt->execute(rowsAffected);
433 logFiner(Conf::logger,"EXECUTE: %x", stmt);
434 return rv;
437 void* SqlStatement::fetch()
439 if (! sqlCon->isConnectionOpen()) {
440 printError(ErrNotOpen, "Connection not open");
441 return NULL;
443 if (! isPrepared()) {
444 printError(ErrNotPrepared, "Statement Not Prepared");
445 return NULL;
447 if (pData.getStmtType() == SelectStatement ) {
448 SelStatement *selStmt = (SelStatement*) stmt;
449 return selStmt->fetch();
451 else if(pData.getStmtType() == MetaStatement){
452 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
453 return metaStmt->fetch();
455 else { return NULL;}
458 void* SqlStatement::fetch(DbRetVal &rv)
460 if (! sqlCon->isConnectionOpen()) {
461 printError(ErrNotOpen, "Connection not open");
462 rv = ErrNoConnection;
463 return NULL;
465 if (! isPrepared()) {
466 printError(ErrNotPrepared, "Statement Not Prepared");
467 return NULL;
469 if (pData.getStmtType() == SelectStatement ) {
470 SelStatement *selStmt = (SelStatement*) stmt;
471 return selStmt->fetch(rv);
473 else if(pData.getStmtType() == MetaStatement){
474 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
475 return metaStmt->fetch(rv);
477 else { return NULL;}
480 void* SqlStatement::fetchAndPrint(bool SQL)
482 if (! sqlCon->isConnectionOpen()) {
483 printError(ErrNotOpen, "Connection not open");
484 return NULL;
486 if (! isPrepared()) {
487 printError(ErrNotPrepared, "Statement Not Prepared");
488 return NULL;
490 if (pData.getStmtType() != SelectStatement) return NULL;
491 SelStatement *selStmt = (SelStatement*) stmt;
492 return selStmt->fetchAndPrint(SQL);
495 DbRetVal SqlStatement::bindParam(int pos, void* value)
497 DbRetVal rv = OK;
498 rv = stmt->setParam(pos, value);
499 return rv;
502 DbRetVal SqlStatement::bindField(int pos, void* value)
504 DbRetVal rv = OK;
505 if (pData.getStmtType() == SelectStatement ) {
506 SelStatement *selStmt = (SelStatement*) stmt;
507 return selStmt->setBindField(pos, value);
509 else if(pData.getStmtType() == MetaStatement){
510 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
511 return metaStmt->setBindField(pos, value);
513 else { return ErrBadCall;}
515 void* SqlStatement::next()
517 if (pData.getStmtType() == SelectStatement ) {
518 SelStatement *selStmt = (SelStatement*) stmt;
519 return( (void*) selStmt->next() );
521 else if(pData.getStmtType() == MetaStatement){
522 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
523 return( (void*) metaStmt->next() );
525 else { return 0;}
528 bool SqlStatement::isFldNull(int pos)
530 if (pData.getStmtType() != SelectStatement) return 0;
531 SelStatement *selStmt = (SelStatement*) stmt;
532 return (selStmt->isFldNull(pos));
534 bool SqlStatement::isFldNull(char *name)
536 if (pData.getStmtType() != SelectStatement) return 0;
537 SelStatement *selStmt = (SelStatement*) stmt;
538 return (selStmt->isFldNull(name));
540 DbRetVal SqlStatement::close()
542 if (pData.getStmtType() == SelectStatement ) {
543 SelStatement *selStmt = (SelStatement*) stmt;
544 logFinest(Conf::logger,"CLOSE: %x", stmt);
545 return selStmt->close();
547 else if(pData.getStmtType() == MetaStatement){
548 MetadataStatement *selStmt = (MetadataStatement*) stmt;
549 logFinest(Conf::logger,"CLOSE: %x", stmt);
550 return selStmt->close();
552 else { return OK;}
555 void* SqlStatement::getParamValuePtr( int pos )
557 //if (pData.getStmtType() != SelectStatement) return 0;
558 DmlStatement *dmlStmt = (DmlStatement*) stmt;
559 return( (void*) dmlStmt->getParamValuePtr( pos ) );
562 char* SqlStatement::getFieldName( int pos )
564 if (pData.getStmtType() == SelectStatement ) {
565 SelStatement *selStmt = (SelStatement*) stmt;
566 return( (char*) selStmt->getFieldName( pos ) );
568 else if(pData.getStmtType() == MetaStatement){
569 MetadataStatement *selStmt = (MetadataStatement*) stmt;
570 return( (char*) selStmt->getFieldName( pos ) );
572 else { return 0;}
575 DataType SqlStatement::getFieldType( int pos )
577 if (pData.getStmtType() == SelectStatement ) {
578 SelStatement *selStmt = (SelStatement*) stmt;
579 return( (DataType) selStmt->getFieldType( pos ) );
581 else if(pData.getStmtType() == MetaStatement){
582 MetadataStatement *selStmt = (MetadataStatement*) stmt;
583 return( (DataType) selStmt->getFieldType( pos ) );
585 else { return typeUnknown;}
587 int SqlStatement::getFieldLength( int pos )
589 if (pData.getStmtType() == SelectStatement ) {
590 SelStatement *selStmt = (SelStatement*) stmt;
591 return( (int) selStmt->getFieldLength( pos ) );
593 else if(pData.getStmtType() == MetaStatement){
594 MetadataStatement *selStmt = (MetadataStatement*) stmt;
595 return( (int) selStmt->getFieldLength( pos ) );
597 else { return 0;}
600 void* SqlStatement::getFieldValuePtr( int pos )
602 if (pData.getStmtType() == SelectStatement ) {
603 SelStatement *selStmt = (SelStatement*) stmt;
604 return( (void*) selStmt->getFieldValuePtr( pos ) );
606 else if(pData.getStmtType() == MetaStatement){
607 MetadataStatement *selStmt = (MetadataStatement*) stmt;
608 return( (void*) selStmt->getFieldValuePtr( pos ) );
610 else { return 0;}
612 void* SqlStatement::getFieldValuePtr( char *name )
614 if (pData.getStmtType() == SelectStatement ) {
615 SelStatement *selStmt = (SelStatement*) stmt;
616 return( (void*) selStmt->getFieldValuePtr( name ) );
618 else if(pData.getStmtType() == MetaStatement){
619 MetadataStatement *selStmt = (MetadataStatement*) stmt;
620 return( (void*) selStmt->getFieldValuePtr( name ) );
622 else { return NULL;}
625 int SqlStatement::noOfProjFields()
627 if (pData.getStmtType() == SelectStatement ) {
628 SelStatement *selStmt = (SelStatement*) stmt;
629 return selStmt->noOfProjFields();
631 else if(pData.getStmtType() == MetaStatement){
632 MetadataStatement *selStmt = (MetadataStatement*) stmt;
633 return selStmt->noOfProjFields();
635 else { return 0;}
638 void SqlStatement::getProjFieldType(int *data)
640 if (pData.getStmtType() == SelectStatement ) {
641 SelStatement *selStmt = (SelStatement*) stmt;
642 return( selStmt->getProjFieldType(data) );
644 else if(pData.getStmtType() == MetaStatement){
645 MetadataStatement *selStmt = (MetadataStatement*) stmt;
646 return( selStmt->getProjFieldType(data) );
652 int SqlStatement::noOfParamFields()
654 if (NULL == stmt) return 0;
655 else return stmt->noOfParamFields();
658 DbRetVal SqlStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
660 DbRetVal rv = OK;
661 if (pData.getStmtType() == SelectStatement ) {
662 SelStatement *selStmt = (SelStatement*) stmt;
663 rv = selStmt->getProjFldInfo(projpos, fInfo);
665 else if(pData.getStmtType() == MetaStatement){
666 MetadataStatement *selStmt = (MetadataStatement*) stmt;
667 rv = selStmt->getProjFldInfo(projpos, fInfo);
668 } else { return ErrBadCall;}
669 return rv;
672 DbRetVal SqlStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
674 DbRetVal rv = OK;
675 if (pData.getStmtType() ==SelectStatement ||
676 pData.getStmtType() ==InsertStatement ||
677 pData.getStmtType() ==UpdateStatement ||
678 pData.getStmtType() ==DeleteStatement)
681 DmlStatement *dmlStmt = (DmlStatement*) stmt;
682 rv = dmlStmt->getParamFldInfo(parampos, fInfo);
684 return rv;
687 DbRetVal SqlStatement::free()
689 logFinest(Conf::logger,"FREE: %x", stmt);
690 if (isCachedStmt) {
691 stmt=NULL;
692 pData.init();
693 isPrepd = false;
694 if (sqlStmtString) {
695 sqlCon->setStmtNotInUse(sqlStmtString);
696 ::free(sqlStmtString); sqlStmtString=NULL;
698 isCachedStmt = false;
699 return OK;
701 if(stmt) delete stmt;
702 stmt = NULL;
703 pData.reset();
704 isMgmtStatement = false;
705 isPrepd = false;
706 isCachedStmt = false;
707 if (sqlStmtString) { ::free(sqlStmtString); sqlStmtString=NULL; }
708 return OK;
711 void SqlStatement::setNull(int pos)
713 stmt->setNull(pos);
715 void SqlStatement::setShortParam(int paramPos, short value)
717 stmt->setShortParam(paramPos, value);
719 void SqlStatement::setIntParam(int paramPos, int value)
721 stmt->setIntParam(paramPos, value);
723 void SqlStatement::setLongParam(int paramPos, long value)
725 stmt->setLongParam(paramPos, value);
727 void SqlStatement::setLongLongParam(int paramPos, long long value)
729 stmt->setLongLongParam(paramPos, value);
731 void SqlStatement::setByteIntParam(int paramPos, ByteInt value)
733 stmt->setByteIntParam(paramPos, value);
735 void SqlStatement::setFloatParam(int paramPos, float value)
737 stmt->setFloatParam(paramPos, value);
739 void SqlStatement::setDoubleParam(int paramPos, double value)
741 stmt->setDoubleParam(paramPos, value);
743 void SqlStatement::setStringParam(int paramPos, char *value)
745 stmt->setStringParam(paramPos, value);
747 void SqlStatement::setDateParam(int paramPos, Date value)
749 stmt->setDateParam(paramPos, value);
751 void SqlStatement::setTimeParam(int paramPos, Time value)
753 stmt->setTimeParam(paramPos, value);
755 void SqlStatement::setTimeStampParam(int paramPos, TimeStamp value)
757 stmt->setTimeStampParam(paramPos, value);
759 void SqlStatement::setBinaryParam(int paramPos, void *value, int length)
761 stmt->setBinaryParam(paramPos, value, length);
763 int SqlStatement::getFldPos(char *name)
765 return stmt->getFldPos(name);
767 long long SqlStatement::getLastInsertedVal(DbRetVal &rv)
769 return stmt->getLastInsertedVal(rv);
771 List SqlStatement::getAllTableNames(DbRetVal &ret)
773 DatabaseManager *dbMgr = NULL;
774 List tbNmList;
775 dbMgr=sqlCon->getConnObject().getDatabaseManager();
776 int rv = ret;
777 if(dbMgr != NULL) tbNmList = dbMgr->getAllTableNames(&rv);
778 ret = (DbRetVal) rv;
779 return tbNmList;
782 List SqlStatement::getAllUserNames(DbRetVal &ret)
784 UserManager *urMgr = NULL;
785 List urNmList;
786 urMgr=sqlCon->getConnObject().getUserManager();
787 int rv = ret;
788 if(urMgr != NULL)
789 urNmList = urMgr->getAllUserNames(&rv);
790 ret = (DbRetVal) rv;
791 return urNmList;
793 List SqlStatement::getFieldNameList(const char *tblName, DbRetVal &rv)
795 List fldNameList;
796 if (isPrepared()) {
797 fldNameList = stmt->getFieldNameList(tblName, rv);
798 return fldNameList;
800 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
801 Table *table = dbMgr->openTable(tblName);
802 if (NULL == table) {
803 List dummyList;
804 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
805 return dummyList;
807 fldNameList = table->getFieldNameList();
808 dbMgr->closeTable(table);
809 return fldNameList;
811 DbRetVal SqlStatement::getFieldInfo(const char *tblName, const char *fldName, FieldInfo *&info)
813 DbRetVal rv = OK;
814 if (isPrepared()) {
815 rv = stmt->getFieldInfo(tblName, fldName, info);
816 return rv;
818 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
819 Table *table = dbMgr->openTable(tblName);
820 if (NULL == table) {
821 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
822 return ErrLockTimeOut;
824 rv = table->getFieldInfo(fldName, info);
825 dbMgr->closeTable(table);
826 return rv;
828 void SqlStatement::setLoading(bool flag)
830 if (pData.getStmtType() == InsertStatement||
831 pData.getStmtType() == UpdateStatement||
832 pData.getStmtType() == DeleteStatement)
834 DmlStatement *dmlStmt = (DmlStatement*) stmt;
835 dmlStmt->setLoading(flag);
837 return;
840 int SqlStatement::getNoOfPagesForTable(char *tblName)
842 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
843 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
844 return dbMgrImpl->getNoOfPagesForTable(tblName);
847 DbRetVal SqlStatement::loadRecords(char *tblName, void *buf)
849 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
850 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
851 return dbMgrImpl->loadRecords(tblName, (char *) buf);
854 DbRetVal SqlStatement::pasteRecords(char *tblName, void *buffer)
856 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
857 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
858 return dbMgrImpl->pasteRecords(tblName, buffer);
860 void SqlStatement::flushCacheStmt()
862 return sqlCon->flushCacheStmt();
865 void SqlStatement::resetStmtString() {
866 sqlStmtString=NULL;
868 //-------------------------------------------------------------------
870 static void sigTermHandler(int sig)
872 ListIterator iter= SqlConnection::connList.getIterator();
873 SqlConnection *conn = NULL;
874 while (iter.hasElement())
876 conn = (SqlConnection*) iter.nextElement();
877 conn->flushCacheStmt();
878 if (conn->isConnectionOpen()) conn->disconnect();
880 exit(0);
883 DbRetVal SqlConnection::connect (char *user, char * pass)
885 DbRetVal ret = conn.open(user, pass);
886 if (ret != OK) return ret;
887 if (ret == OK) isConnOpen = true;
888 if (!isInit) initialize();
889 connList.append(this);
890 DbRetVal rv = OK;
891 #if (defined MMDB && EMBED)
892 os::signal(SIGINT, sigTermHandler);
893 os::signal(SIGTERM, sigTermHandler);
894 if (Conf::config.useDurability() && !firstThread) {
895 rv = recoverCsqlDB();
896 if (rv != OK) {
897 printError(ErrSysInternal, "Recovery Failed");
898 return rv;
900 firstThread = true;
902 rollback(); //for drop table execute in redo log
903 #endif
904 return ret;
907 void SqlConnection::flushCacheStmt()
909 ListIterator iter = cachedStmts.getIterator();
910 while (iter.hasElement()) {
911 CachedStmtNode* node = (CachedStmtNode*) iter.nextElement();
912 //do not delete when the statement is currently in use.
913 //otherwise it leads to illegal memory access when application
914 //calls any method on this statement
915 //if (node->inUse) continue;
916 if (node->inUse) node->inUse = 0;
917 free(node->sqlString);
918 node->sqlStmt->setCachedStmt(false);
919 node->sqlStmt->free();
920 delete node->sqlStmt;
921 delete node;
923 cachedStmts.reset();
924 return;
927 void SqlConnection::setStmtNotInUse(char *stmtstr)
929 ListIterator iter = cachedStmts.getIterator();
930 int inputStmtLen = strlen(stmtstr);
931 CachedStmtNode *node = NULL;
932 while ((node = (CachedStmtNode*)iter.nextElement()) != NULL)
934 if (node->stmtLength == inputStmtLen)
936 if (0 == strcmp(node->sqlString, stmtstr))
938 node->inUse =0;
939 return;
945 SqlStatement* SqlConnection::findInCache(char *stmtstr)
947 ListIterator iter = cachedStmts.getIterator();
948 int inputStmtLen = strlen(stmtstr);
949 CachedStmtNode *node = NULL;
950 while ((node = (CachedStmtNode*)iter.nextElement()) != NULL)
952 if (node->stmtLength == inputStmtLen)
954 if (0 == strcmp(node->sqlString, stmtstr))
956 logFiner(Conf::logger, "Statement Retrieved From Cache %x\n",
957 node->sqlStmt);
958 node->hits++;
959 node->inUse = 1;
960 return node->sqlStmt;
964 return NULL;
967 void SqlConnection::addToCache(SqlStatement *sqlStmt, char* stmtString)
969 SqlStatement *stmt = new SqlStatement();
970 *stmt= *sqlStmt;
971 CachedStmtNode *node = new CachedStmtNode();
972 node->sqlStmt = stmt;
973 node->stmtLength = strlen(stmtString);
974 node->sqlString = (char*)malloc(node->stmtLength+1);
975 node->inUse=1;
976 strcpy(node->sqlString, stmtString);
977 if (cachedStmts.size() >= Conf::config.getStmtCacheSize())
979 removeLeastUsed();
981 node->sqlStmt->resetStmtString();
982 cachedStmts.append(node);
983 logFiner(Conf::logger, "Statement added To Cache %x\n", node->sqlStmt);
984 logFinest(Conf::logger, "Statement added To Cache %s\n", node->sqlString);
985 return ;
988 void SqlConnection::removeLeastUsed()
990 ListIterator iter = cachedStmts.getIterator();
991 CachedStmtNode *node = NULL, *toRemove =NULL;
992 int lowHits = 0;
993 bool firstCall = true;
994 while((node = (CachedStmtNode*) iter.nextElement()) != NULL)
996 if (firstCall) {
997 firstCall = false;
998 lowHits = node->hits;
999 toRemove = node; //if cache size is 1
1000 continue;
1002 if (lowHits >= node->hits) toRemove = node;
1004 cachedStmts.remove(toRemove);
1005 //TODO::check whether there is memory leak for list elements
1006 logFiner(Conf::logger, "Statement removed from Cache %x\n", toRemove->sqlStmt);
1007 logFinest(Conf::logger, "Statement removed from Cache %s\n", toRemove->sqlString);
1008 delete toRemove; toRemove = NULL;
1009 return;
1012 SqlConnection::~SqlConnection()
1014 flushCacheStmt();
1015 if (isConnOpen) disconnect();
1016 innerConn = NULL;
1019 static void sigUsr1Handler(int sig)
1021 ListIterator iter= SqlConnection::connList.getIterator();
1022 SqlConnection *conn = NULL;
1023 while (iter.hasElement())
1025 conn = (SqlConnection*) iter.nextElement();
1026 conn->flushCacheStmt();
1028 os::signal(SIGCSQL1, sigUsr1Handler);
1029 return;
1032 static void exithandler(void)
1034 ListIterator iter= SqlConnection::connList.getIterator();
1035 SqlConnection *conn = NULL;
1036 while (iter.hasElement())
1038 conn = (SqlConnection*) iter.nextElement();
1039 conn->flushCacheStmt();
1040 conn->disconnect();
1043 void SqlConnection::displayStmtCache()
1045 ListIterator iter = cachedStmts.getIterator();
1046 CachedStmtNode *node = NULL;
1047 printf("STATEMENT CACHE START \n");
1048 while ((node = (CachedStmtNode*)iter.nextElement()) != NULL)
1050 node->display();
1052 printf("STATEMENT CACHE END\n");
1055 void SqlConnection::initialize()
1057 os::signal(SIGCSQL1, sigUsr1Handler);
1058 #if (defined MMDB && defined EMBED)
1059 os::atexit(exithandler);
1060 #endif
1061 isInit = true;
1064 DbRetVal SqlStatement::filterAndWriteStmtLogs(void *stmtBuckets)
1066 struct stat st;
1067 char fName[MAX_FILE_LEN];
1068 sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile());
1069 file_desc fdRead = os::openFile(fName, fileOpenReadOnly,0);
1070 if ((file_desc)-1 == fdRead) { return OK; }
1071 if (::stat(fName, &st) == -1) {
1072 printError(ErrSysInternal, "Unable to retrieve stmt log file size");
1073 os::closeFile(fdRead);
1074 return ErrSysInternal;
1076 if (st.st_size ==0) {
1077 os::closeFile(fdRead);
1078 return OK;
1080 void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fdRead, 0);
1081 if ((void*)MAP_FAILED == startAddr) {
1082 printError(ErrSysInternal, "Unable to mmap stmt log file\n");
1083 return ErrSysInternal;
1085 sprintf(fName, "%s/csql.db.stmt1", Conf::config.getDbFile());
1086 int fd = os::openFileForAppend(fName, O_CREAT|O_TRUNC);
1087 char *iter = (char*)startAddr;
1088 char *logStart = NULL, *logEnd = NULL;
1089 int logType;
1090 int stmtID;
1091 int len =0, ret =0;
1092 DbRetVal rv = OK;
1093 while(true) {
1094 if (iter - (char*)startAddr >= st.st_size) break;
1095 logType = *(int*)iter;
1096 logStart = iter;
1097 if (logType == -1) { //prepare
1098 iter = iter + sizeof(int);
1099 len = *(int*) iter;
1100 iter = iter + 2 * sizeof(int);
1101 stmtID = *(int*)iter;
1102 iter = logStart+ len;
1103 ret =0;
1104 if (isStmtInHashTable(stmtID,stmtBuckets))
1105 ret = os::write(fd, logStart, len);
1106 if (-1 == ret) {
1107 printError(ErrSysInternal, "Unable to write statement logs");
1110 else if(logType == -3) { //free
1111 iter = logStart + 4 *sizeof(int);
1112 }else{
1113 printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType);
1114 rv = ErrSysInternal;
1115 break;
1118 os::close(fd);
1119 os::munmap((char*)startAddr, st.st_size);
1120 os::closeFile(fdRead);
1121 char cmd[MAX_FILE_LEN *2];
1122 sprintf(cmd, "mv %s/csql.db.stmt1 %s/csql.db.stmt",
1123 Conf::config.getDbFile(), Conf::config.getDbFile());
1124 ret = ::system(cmd);
1125 return rv;
1128 DbRetVal SqlStatement::readAndPopulateStmts(AbsSqlConnection *conn, void *&stmtBuckets, bool list, bool interactive)
1130 struct stat st;
1131 char fName[MAX_FILE_LEN];
1132 sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile());
1133 printf("Statement Redo log filename is :%s\n", fName);
1134 file_desc fd = os::openFile(fName, fileOpenReadOnly, 0);
1135 if ((file_desc)-1 == fd) { return OK; }
1136 if (::stat(fName, &st) == -1) {
1137 printError(ErrSysInternal, "Unable to retrieve stmt log file size");
1138 os::closeFile(fd);
1139 return ErrSysInternal;
1141 if (NULL != stmtBuckets)
1143 printError(ErrSysInternal, "stmtBuckets already populated");
1144 os::closeFile(fd);
1145 return ErrSysInternal;
1147 stmtBuckets = malloc (STMT_BUCKET_SIZE * sizeof(StmtBucket));
1148 memset(stmtBuckets, 0, STMT_BUCKET_SIZE * sizeof(StmtBucket));
1149 if (st.st_size ==0) {
1150 printError(ErrNote, "No Statement logs found during recovery");
1151 ::free(stmtBuckets);
1152 stmtBuckets = NULL;
1153 os::closeFile(fd);
1154 return OK;
1156 void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fd, 0);
1157 if ((void*)MAP_FAILED == startAddr) {
1158 printError(ErrSysInternal, "Unable to mmap stmt log file\n");
1159 ::free(stmtBuckets);
1160 stmtBuckets = NULL;
1161 os::closeFile(fd);
1162 return ErrSysInternal;
1164 DbRetVal rv = iterateStmtLogs(conn, startAddr, st.st_size, stmtBuckets, list, interactive);
1165 os::munmap((char*)startAddr, st.st_size);
1166 os::closeFile(fd);
1167 return rv;
1170 DbRetVal SqlStatement::iterateStmtLogs(AbsSqlConnection *conn, void *startAddr, int size, void *stmtBuckets, bool list, bool interactive)
1172 char *iter = (char*)startAddr;
1173 void *value = NULL;
1174 int logType, eType;
1175 int stmtID;
1176 int txnID;
1177 int len, ret, retVal =0;
1178 int loglen;
1179 char stmtString[SQL_STMT_LEN];
1180 DbRetVal rv = OK;
1181 while(true) {
1182 if (iter - (char*)startAddr >= size) break;
1183 logType = *(int*)iter;
1184 if (logType == -1) { //prepare
1185 iter = iter + sizeof(int);
1186 txnID = *(int*) iter; iter += sizeof(int);
1187 loglen = *(int*) iter; iter += sizeof(int);
1188 stmtID = *(int*)iter;
1189 iter = iter + sizeof(int);
1190 len = *(int*)iter;
1191 iter = iter + sizeof(int);
1192 strncpy(stmtString, iter, len);
1193 iter = iter + len;
1194 if (list) {
1195 printf("PREPARE: SID:%d %s\n", stmtID, stmtString);
1196 continue;
1198 if (interactive) printf("STMTLOG PREPARE SID:%d %s\n", stmtID, stmtString);
1199 AbsSqlStatement *csqlStmt = SqlFactory::createStatement(CSqlDirect);
1200 csqlStmt->setConnection(conn);
1201 SqlStatement *sqlStmt = (SqlStatement*)csqlStmt;
1202 sqlStmt->setStmtString(stmtString);
1203 addToHashTable(stmtID, csqlStmt, stmtBuckets, stmtString);
1205 else if(logType == -3) { //free
1206 iter = iter + sizeof(int);
1207 txnID = *(int*) iter; iter += sizeof(int);
1208 loglen = *(int*) iter; iter += sizeof(int);
1209 stmtID = *(int*)iter;
1210 iter = iter + sizeof(int);
1211 if (list) {
1212 printf("FREE: SID:%d TID:%d \n", stmtID, txnID);
1213 continue;
1215 }else{
1216 printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType);
1217 rv = ErrSysInternal;
1218 break;
1221 return rv;
1224 #if (defined MMDB && defined EMBED)
1226 DbRetVal SqlConnection::recoverCsqlDB()
1228 DbRetVal rv = OK;
1229 char dbRedoFileName[MAX_FILE_LEN];
1230 char dbChkptSchema[MAX_FILE_LEN];
1231 char dbChkptMap[MAX_FILE_LEN];
1232 char dbChkptData[MAX_FILE_LEN];
1233 char dbBackupFile[MAX_FILE_LEN];
1234 char cmd[IDENTIFIER_LENGTH];
1235 //check for check point file if present recover
1236 sprintf(dbChkptSchema, "%s/db.chkpt.schema1", Conf::config.getDbFile());
1237 if (FILE *file = fopen(dbChkptSchema, "r")) {
1238 fclose(file);
1239 sprintf(cmd, "cp -f %s %s/db.chkpt.schema", dbChkptSchema,
1240 Conf::config.getDbFile());
1241 int ret = system(cmd);
1242 if (ret != 0) return ErrOS;
1244 sprintf(dbChkptMap, "%s/db.chkpt.map1", Conf::config.getDbFile());
1245 if (FILE *file = fopen(dbChkptMap, "r")) {
1246 fclose(file);
1247 sprintf(cmd, "cp -f %s %s/db.chkpt.map", dbChkptMap,
1248 Conf::config.getDbFile());
1249 int ret = system(cmd);
1250 if (ret != 0) return ErrOS;
1252 int chkptID= Database::getCheckpointID();
1253 sprintf(dbChkptData, "%s/db.chkpt.data%d", Conf::config.getDbFile(),
1254 chkptID);
1255 sprintf(dbBackupFile, "%s/db.chkpt.data1", Conf::config.getDbFile());
1256 FILE *fl = NULL;
1257 if (!Conf::config.useMmap() && (fl = fopen(dbBackupFile, "r"))) {
1258 fclose(fl);
1259 sprintf(cmd, "cp %s/db.chkpt.data1 %s", Conf::config.getDbFile(),
1260 dbChkptData);
1261 int ret = system(cmd);
1262 if (ret != 0) return ErrOS;
1264 if (FILE *file = fopen(dbChkptData, "r")) {
1265 fclose(file);
1266 rv = recoverSystemAndUserDB();
1267 if (rv != OK) return rv;
1270 //check for redo log file if present apply redo logs
1271 sprintf(dbRedoFileName, "%s/csql.db.cur", Conf::config.getDbFile());
1272 if (FILE *file = fopen(dbRedoFileName, "r"))
1274 fclose(file);
1275 rv = (DbRetVal) applyRedoLogs(dbRedoFileName);
1276 if (rv != OK) return rv;
1277 DatabaseManager *dbMgr = getConnObject().getDatabaseManager();
1278 rv = dbMgr->checkPoint();
1279 if (rv != OK)
1281 printError(ErrSysInternal, "checkpoint failed after redo log apply");
1282 return ErrOS;
1285 return OK;
1288 DbRetVal SqlConnection::recoverSystemAndUserDB()
1290 DbRetVal rv = OK;
1291 char schFile[1024];
1292 sprintf(schFile, "%s/db.chkpt.schema", Conf::config.getDbFile());
1293 if (FILE *file = fopen(schFile, "r")) {
1294 rv = applySchemaFile(file);
1295 if (rv != OK) { fclose(file); return rv; }
1297 DatabaseManager *dbMgr = getConnObject().getDatabaseManager();
1298 rv = dbMgr->recover();
1299 return rv;
1302 DbRetVal SqlConnection::applySchemaFile(FILE *fp)
1304 char buf[8192];
1305 char eof;
1306 DbRetVal rv = OK;
1307 SqlStatement *stmt = new SqlStatement();
1308 while ((eof = getQueryFromSchemaFile(fp,buf)) != EOF) {
1309 stmt->setConnection(this);
1310 rv = stmt->prepare(buf);
1311 if (rv != OK) { delete stmt; return rv; }
1312 int rows = 0;
1313 stmt->execute(rows);
1314 if (rv != OK) { stmt->free(); delete stmt; return rv; }
1316 delete stmt;
1317 return OK;
1320 char SqlConnection::getQueryFromSchemaFile(FILE *fp, char *buf)
1322 char c, *bufBegin=buf;
1323 int charCnt=0;
1324 while( (c=(char ) fgetc(fp)) != EOF && c != ';')
1326 *buf++ = c; charCnt++;
1327 if( charCnt == SQL_STMT_LEN ) {
1328 printf("SQL Statement length is greater than %d. "
1329 "Ignoring the statement.\n", SQL_STMT_LEN );
1330 *bufBegin++ =';';
1331 *bufBegin ='\0';
1332 return 0;
1335 *buf++ = ';';
1336 *buf = '\0';
1337 return c;
1340 int SqlConnection::applyRedoLogs(char *redoFile)
1342 struct stat st;
1343 DbRetVal rv = OK;
1344 int fd = open(redoFile, O_RDONLY);
1345 if (-1 == fd) { return OK; }
1346 if (fstat(fd, &st) == -1) {
1347 printError(ErrSysInternal, "Unable to retrieve undo log file size");
1348 close(fd);
1349 return 1;
1351 if (st.st_size ==0) {
1352 printError(ErrNote, "No Redo logs found during recovery");
1353 SqlStatement::readAndPopulateStmts(this, stmtBuckets);
1354 close(fd);
1355 return OK;
1357 void *startAddr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1358 if (MAP_FAILED == startAddr) {
1359 printf("Unable to read undo log file:mmap failed.\n");
1360 return 2;
1363 rv = SqlStatement::readAndPopulateStmts(this, stmtBuckets);
1364 if (OK != rv)
1366 printf("Unable to read stmt log file\n");
1367 return 2;
1370 char *iter = (char*)startAddr;
1371 void *value = NULL;
1372 int logType, eType;
1373 int stmtID;
1374 int txnID;
1375 int len, ret, retVal =0;
1376 int loglen;
1377 char stmtString[SQL_STMT_LEN];
1378 while(true) {
1379 if (iter - (char*)startAddr >= st.st_size) break;
1380 logType = *(int*)iter;
1381 if (logType == -1) { //prepare
1382 iter = iter + sizeof(int);
1383 txnID = *(int*) iter; iter += sizeof(int);
1384 loglen = *(int*) iter; iter += sizeof(int);
1385 stmtID = *(int*)iter;
1386 iter = iter + sizeof(int);
1387 len = *(int*)iter;
1388 iter = iter + sizeof(int);
1389 strncpy(stmtString, iter, len);
1390 iter = iter + len;
1391 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
1392 SqlStatement *sqlStmt = (SqlStatement *)stmt;
1393 stmt->setConnection(this);
1394 rv = stmt->prepare(stmtString);
1395 if (rv != OK) {
1396 printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString);
1397 retVal=1;
1398 break;
1400 sqlStmt->setLoading(true);
1401 SqlStatement::addToHashTable(stmtID, stmt, stmtBuckets, stmtString);
1403 else if(logType == -2) { //commit
1404 beginTrans();
1405 iter = iter + sizeof(int);
1406 txnID = *(int*) iter; iter += sizeof(int);
1407 loglen = *(int*) iter; iter += sizeof(int);
1408 char *curPtr = iter;
1409 while(true) {
1410 if (iter - (char*)startAddr >= st.st_size) {
1411 //file end reached
1412 retVal=0;
1413 break;
1415 stmtID = *(int*)iter;
1416 iter = iter + sizeof(int);
1417 eType = *(int*)iter;
1418 AbsSqlStatement *stmt =
1419 SqlStatement::getStmtFromHashTable(stmtID,stmtBuckets);
1420 if (NULL == stmt) {
1421 printError(ErrSysInternal,
1422 "Unable to find in stmt hashtable");
1423 retVal=2;
1424 break;
1426 if (0 == eType) { //execute type
1427 iter = iter + sizeof(int);
1428 rv = stmt->execute(ret);
1429 if (rv != OK) {
1430 printError(ErrSysInternal, "unable to execute");
1431 retVal=2;
1432 break;
1434 if (*(int*)iter <0) break;
1435 } else if ( 1 == eType) { //set type
1436 iter=iter+sizeof(int);
1437 int pos = *(int*) iter;
1438 iter=iter+sizeof(int);
1439 int isNull = *(int *)iter;
1440 iter = iter + sizeof(int);
1441 if (isNull == 0) {
1442 DataType type = (DataType)(*(int*)iter);
1443 iter=iter+sizeof(int);
1444 int len = *(int*) iter;
1445 iter=iter+sizeof(int);
1446 value = iter;
1447 iter=iter+len;
1448 SqlStatement::setParamValues(stmt, pos,
1449 type, len, value);
1450 } else stmt->setNull(pos);
1451 if (*(int*)iter <0) break;
1454 commit();
1456 else if(logType == -3) { //free
1457 iter = iter + sizeof(int);
1458 txnID = *(int*) iter; iter += sizeof(int);
1459 loglen = *(int*) iter; iter += sizeof(int);
1460 stmtID = *(int*)iter;
1461 iter = iter + sizeof(int);
1462 AbsSqlStatement *stmt = SqlStatement::getStmtFromHashTable(stmtID,
1463 stmtBuckets);
1464 if (stmt) {
1465 stmt->free();
1466 SqlStatement::removeFromHashTable(stmtID,stmtBuckets);
1467 } else { printError(ErrSysInternal, "statement not found for %d\n",stmtID);}
1469 else if(logType == -4) { //prepare and execute
1470 iter = iter + sizeof(int);
1471 txnID = *(int*) iter; iter += sizeof(int);
1472 loglen = *(int*) iter; iter += sizeof(int);
1473 stmtID = *(int*)iter;
1474 iter = iter + sizeof(int);
1475 len = *(int*)iter;
1476 iter = iter + sizeof(int);
1477 strncpy(stmtString, iter, len);
1478 stmtString[len+1] ='\0';
1479 iter = iter + len;
1480 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
1481 if ( NULL == stmt) {
1482 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
1483 retVal=3;
1484 break;
1486 stmt->setConnection(this);
1487 rv = stmt->prepare(stmtString);
1488 if (rv != OK) {
1489 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
1490 retVal=4;
1491 break;
1493 rv = stmt->execute(ret);
1494 if (rv != OK) {
1495 if (strlen(stmtString) > 6 &&
1496 ( (strncasecmp(stmtString,"CREATE", 6) == 0) ||
1497 (strncasecmp(stmtString,"DROP", 4) == 0) ||
1498 (strncasecmp(stmtString,"RENAME", 6) == 0) ||
1499 (strncasecmp(stmtString,"ALTER", 5) == 0) )) {
1500 continue;
1502 printError(ErrSysInternal, "unable to execute %s", stmtString);
1503 retVal=5;
1504 break;
1506 stmt->free();
1507 }else{
1508 printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType);
1509 retVal=6;
1510 break;
1513 munmap((char*)startAddr, st.st_size);
1514 close(fd);
1515 SqlStatement::filterAndWriteStmtLogs(stmtBuckets);
1516 SqlStatement::freeAllStmtHandles(stmtBuckets);
1517 return retVal;
1519 #endif