flush cache statements during create index and drop table/index
[csql.git] / src / sql / SqlStatement.cxx
blob34f566d2f56c4e3ded42d706b9897603cb6ca58f
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;
27 bool SqlConnection::isInit = false;
28 List SqlConnection::connList;
31 int yyparse ();
33 SqlStatement::~SqlStatement()
35 if (isPrepd) { free(); isPrepd = false; }
38 List SqlStatement::getTableNameList()
40 return pData.getTableNameList();
42 SqlStatement::SqlStatement()
44 innerStmt = NULL;
45 sqlCon = NULL;
46 stmt = NULL;
47 isPrepd = false;
48 isCachedStmt=false;
49 isMgmtStatement = false;
51 void SqlStatement::setConnection(AbsSqlConnection *conn)
53 sqlCon = (SqlConnection*)conn;
54 con = conn;
57 void SqlStatement::setSqlConnection(SqlConnection *conn)
59 sqlCon = conn;
62 DbRetVal SqlStatement::executeDirect(char *str)
64 DbRetVal rv = OK;
65 int rows = 0;
66 rv = prepare(str);
67 if (rv != OK) return rv;
68 rv = execute(rows);
69 if (rv != OK) return rv;
70 return rv;
73 DbRetVal SqlStatement::prepare(char *stmtstr)
75 DbRetVal rv = OK;
76 if (! sqlCon->isConnectionOpen()) {
77 printError(ErrNotOpen, "Connection not open");
78 return ErrNotOpen;
80 SqlStatement *cachedStmt = sqlCon->findInCache(stmtstr);
81 if (cachedStmt)
83 *this = *cachedStmt;
84 this->stmt->setParsedData(&this->pData);
85 logFine(Conf::logger,"GOT STMT FROM CACHE: %s %x", stmtstr, cachedStmt);
86 return OK;
88 // take mutex here
89 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
90 Database *sysdb = ((DatabaseManagerImpl *)dbMgr)->sysDb();
91 int tries = Conf::config.getMutexRetries();
92 struct timeval timeout;
93 timeout.tv_sec = Conf::config.getMutexSecs();
94 timeout.tv_usec = Conf::config.getMutexUSecs();
96 while (true) {
97 rv = sysdb->getPrepareStmtMutex();
98 if (rv == OK) break;
99 tries--;
100 if (tries == 0) {
101 printError(rv,
102 "Unable to get prepare statement mutex after %d tries", Conf::config.getMutexRetries());
103 return rv;
105 os::select(0, 0, 0, 0, &timeout);
108 if (isPrepared()) free();
109 lexInput = stmtstr;
110 parsedData = &pData;
112 yy_buffer_state *yy_buffer= yy_scan_string(stmtstr);
113 int rc = yyparse();
114 if (yy_buffer) yy_delete_buffer(yy_buffer);
115 if (rc != 0)
117 free();
118 parsedData = NULL;
119 sysdb->releasePrepareStmtMutex();
120 return ErrSyntaxError;
122 if( parsedData->getStmtType() == MgmtStatement)
124 isPrepd = true;
125 parsedData = NULL;
126 isMgmtStatement = true;
127 sysdb->releasePrepareStmtMutex();
128 logFine(Conf::logger,"PREPARE: %s %x", stmtstr, stmt);
129 return OK;
131 stmt = StatementFactory::getStatement(parsedData);
132 stmt->setDbMgr(dbMgr);
133 if( parsedData->getStmtType() == UserStatement)
135 UserManager* userMgr = sqlCon->getConnObject().getUserManager();
136 UserTblStatement *ustmt = (UserTblStatement *)stmt;
137 ustmt->setUserManager(userMgr,sqlCon->getConnObject().getUserName());
139 rv = stmt->resolve();
140 if (rv != OK)
142 free();
143 parsedData = NULL;
144 sysdb->releasePrepareStmtMutex();
145 return rv;
147 isPrepd = true;
148 if (Conf::config.getStmtCacheSize()) {
149 if (stmt->noOfParamFields() > 0) {
150 isCachedStmt = true;
151 sqlCon->addToCache(this, stmtstr);
153 else if (Conf::config.useCacheNoParam())
155 if (parsedData->getCacheWorthy())
157 isCachedStmt = true;
158 sqlCon->addToCache(this, stmtstr);
162 parsedData = NULL;
163 sysdb->releasePrepareStmtMutex();
164 return OK;
167 char* SqlStatement::getTableName()
169 return pData.getTableName();
172 bool SqlStatement::isSelect()
174 if ((pData.getStmtType() == SelectStatement) || (pData.getStmtType() == MetaStatement)) return true;
175 return false;
178 bool SqlStatement::isPrepared() { return isPrepd; }
180 DbRetVal SqlStatement::execute(int &rowsAffected)
182 DbRetVal rv = OK;
183 if (! sqlCon->isConnectionOpen()) {
184 printError(ErrNotOpen, "Connection not open");
185 return ErrNotOpen;
187 if (! isPrepared()) {
188 printError(ErrNotPrepared, "Statement Not Prepared");
189 return ErrNotPrepared;
191 if( isMgmtStatement )
193 flushCacheStmt();
194 logFiner(Conf::logger,"EXECUTE: %x", stmt);
195 return OK;
197 rv = stmt->execute(rowsAffected);
198 if (rv == ErrAlready && pData.getStmtType() == SelectStatement )
199 { //if previous scan is not closed, close it
200 SelStatement *selStmt = (SelStatement*) stmt;
201 selStmt->close();
202 rv = stmt->execute(rowsAffected);
204 logFiner(Conf::logger,"EXECUTE: %x", stmt);
205 return rv;
208 void* SqlStatement::fetch()
210 if (! sqlCon->isConnectionOpen()) {
211 printError(ErrNotOpen, "Connection not open");
212 return NULL;
214 if (! isPrepared()) {
215 printError(ErrNotPrepared, "Statement Not Prepared");
216 return NULL;
218 if (pData.getStmtType() == SelectStatement ) {
219 SelStatement *selStmt = (SelStatement*) stmt;
220 return selStmt->fetch();
222 else if(pData.getStmtType() == MetaStatement){
223 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
224 return metaStmt->fetch();
226 else { return NULL;}
229 void* SqlStatement::fetch(DbRetVal &rv)
231 if (! sqlCon->isConnectionOpen()) {
232 printError(ErrNotOpen, "Connection not open");
233 return NULL;
235 if (! isPrepared()) {
236 printError(ErrNotPrepared, "Statement Not Prepared");
237 return NULL;
239 if (pData.getStmtType() == SelectStatement ) {
240 SelStatement *selStmt = (SelStatement*) stmt;
241 return selStmt->fetch(rv);
243 else if(pData.getStmtType() == MetaStatement){
244 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
245 return metaStmt->fetch(rv);
247 else { return NULL;}
250 void* SqlStatement::fetchAndPrint(bool SQL)
252 if (! sqlCon->isConnectionOpen()) {
253 printError(ErrNotOpen, "Connection not open");
254 return NULL;
256 if (! isPrepared()) {
257 printError(ErrNotPrepared, "Statement Not Prepared");
258 return NULL;
260 if (pData.getStmtType() != SelectStatement) return NULL;
261 SelStatement *selStmt = (SelStatement*) stmt;
262 return selStmt->fetchAndPrint(SQL);
265 DbRetVal SqlStatement::bindParam(int pos, void* value)
267 DbRetVal rv = OK;
268 rv = stmt->setParam(pos, value);
269 return rv;
272 DbRetVal SqlStatement::bindField(int pos, void* value)
274 DbRetVal rv = OK;
275 if (pData.getStmtType() == SelectStatement ) {
276 SelStatement *selStmt = (SelStatement*) stmt;
277 return selStmt->setBindField(pos, value);
279 else if(pData.getStmtType() == MetaStatement){
280 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
281 return metaStmt->setBindField(pos, value);
283 else { return ErrBadCall;}
285 void* SqlStatement::next()
287 if (pData.getStmtType() == SelectStatement ) {
288 SelStatement *selStmt = (SelStatement*) stmt;
289 return( (void*) selStmt->next() );
291 else if(pData.getStmtType() == MetaStatement){
292 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
293 return( (void*) metaStmt->next() );
295 else { return 0;}
298 bool SqlStatement::isFldNull(int pos)
300 if (pData.getStmtType() != SelectStatement) return 0;
301 SelStatement *selStmt = (SelStatement*) stmt;
302 return (selStmt->isFldNull(pos));
304 bool SqlStatement::isFldNull(char *name)
306 if (pData.getStmtType() != SelectStatement) return 0;
307 SelStatement *selStmt = (SelStatement*) stmt;
308 return (selStmt->isFldNull(name));
310 DbRetVal SqlStatement::close()
312 if (pData.getStmtType() == SelectStatement ) {
313 SelStatement *selStmt = (SelStatement*) stmt;
314 logFinest(Conf::logger,"CLOSE: %x", stmt);
315 return selStmt->close();
317 else if(pData.getStmtType() == MetaStatement){
318 MetadataStatement *selStmt = (MetadataStatement*) stmt;
319 logFinest(Conf::logger,"CLOSE: %x", stmt);
320 return selStmt->close();
322 else { return OK;}
325 void* SqlStatement::getParamValuePtr( int pos )
327 //if (pData.getStmtType() != SelectStatement) return 0;
328 DmlStatement *dmlStmt = (DmlStatement*) stmt;
329 return( (void*) dmlStmt->getParamValuePtr( pos ) );
332 char* SqlStatement::getFieldName( int pos )
334 if (pData.getStmtType() == SelectStatement ) {
335 SelStatement *selStmt = (SelStatement*) stmt;
336 return( (char*) selStmt->getFieldName( pos ) );
338 else if(pData.getStmtType() == MetaStatement){
339 MetadataStatement *selStmt = (MetadataStatement*) stmt;
340 return( (char*) selStmt->getFieldName( pos ) );
342 else { return 0;}
345 DataType SqlStatement::getFieldType( int pos )
347 if (pData.getStmtType() == SelectStatement ) {
348 SelStatement *selStmt = (SelStatement*) stmt;
349 return( (DataType) selStmt->getFieldType( pos ) );
351 else if(pData.getStmtType() == MetaStatement){
352 MetadataStatement *selStmt = (MetadataStatement*) stmt;
353 return( (DataType) selStmt->getFieldType( pos ) );
355 else { return typeUnknown;}
357 int SqlStatement::getFieldLength( int pos )
359 if (pData.getStmtType() == SelectStatement ) {
360 SelStatement *selStmt = (SelStatement*) stmt;
361 return( (int) selStmt->getFieldLength( pos ) );
363 else if(pData.getStmtType() == MetaStatement){
364 MetadataStatement *selStmt = (MetadataStatement*) stmt;
365 return( (int) selStmt->getFieldLength( pos ) );
367 else { return 0;}
370 void* SqlStatement::getFieldValuePtr( int pos )
372 if (pData.getStmtType() == SelectStatement ) {
373 SelStatement *selStmt = (SelStatement*) stmt;
374 return( (void*) selStmt->getFieldValuePtr( pos ) );
376 else if(pData.getStmtType() == MetaStatement){
377 MetadataStatement *selStmt = (MetadataStatement*) stmt;
378 return( (void*) selStmt->getFieldValuePtr( pos ) );
380 else { return 0;}
382 void* SqlStatement::getFieldValuePtr( char *name )
384 if (pData.getStmtType() == SelectStatement ) {
385 SelStatement *selStmt = (SelStatement*) stmt;
386 return( (void*) selStmt->getFieldValuePtr( name ) );
388 else if(pData.getStmtType() == MetaStatement){
389 MetadataStatement *selStmt = (MetadataStatement*) stmt;
390 return( (void*) selStmt->getFieldValuePtr( name ) );
392 else { return NULL;}
395 int SqlStatement::noOfProjFields()
397 if (pData.getStmtType() == SelectStatement ) {
398 SelStatement *selStmt = (SelStatement*) stmt;
399 return selStmt->noOfProjFields();
401 else if(pData.getStmtType() == MetaStatement){
402 MetadataStatement *selStmt = (MetadataStatement*) stmt;
403 return selStmt->noOfProjFields();
405 else { return 0;}
408 void SqlStatement::getProjFieldType(int *data)
410 if (pData.getStmtType() == SelectStatement ) {
411 SelStatement *selStmt = (SelStatement*) stmt;
412 return( selStmt->getProjFieldType(data) );
414 else if(pData.getStmtType() == MetaStatement){
415 MetadataStatement *selStmt = (MetadataStatement*) stmt;
416 return( selStmt->getProjFieldType(data) );
422 int SqlStatement::noOfParamFields()
424 return stmt->noOfParamFields();
427 DbRetVal SqlStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
429 DbRetVal rv = OK;
430 if (pData.getStmtType() == SelectStatement ) {
431 SelStatement *selStmt = (SelStatement*) stmt;
432 rv = selStmt->getProjFldInfo(projpos, fInfo);
434 else if(pData.getStmtType() == MetaStatement){
435 MetadataStatement *selStmt = (MetadataStatement*) stmt;
436 rv = selStmt->getProjFldInfo(projpos, fInfo);
437 } else { return ErrBadCall;}
438 return rv;
441 DbRetVal SqlStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
443 DbRetVal rv = OK;
444 if (pData.getStmtType() ==SelectStatement ||
445 pData.getStmtType() ==InsertStatement ||
446 pData.getStmtType() ==UpdateStatement ||
447 pData.getStmtType() ==DeleteStatement)
450 DmlStatement *dmlStmt = (DmlStatement*) stmt;
451 rv = dmlStmt->getParamFldInfo(parampos, fInfo);
453 return rv;
456 DbRetVal SqlStatement::free()
458 logFinest(Conf::logger,"FREE: %x", stmt);
459 if (isCachedStmt) {
460 stmt=NULL;
461 pData.init();
462 isPrepd = false;
463 return OK;
465 if(stmt) delete stmt;
466 stmt = NULL;
467 pData.reset();
468 isMgmtStatement = false;
469 isPrepd = false;
470 return OK;
473 void SqlStatement::setNull(int pos)
475 stmt->setNull(pos);
477 void SqlStatement::setShortParam(int paramPos, short value)
479 stmt->setShortParam(paramPos, value);
481 void SqlStatement::setIntParam(int paramPos, int value)
483 stmt->setIntParam(paramPos, value);
485 void SqlStatement::setLongParam(int paramPos, long value)
487 stmt->setLongParam(paramPos, value);
489 void SqlStatement::setLongLongParam(int paramPos, long long value)
491 stmt->setLongLongParam(paramPos, value);
493 void SqlStatement::setByteIntParam(int paramPos, ByteInt value)
495 stmt->setByteIntParam(paramPos, value);
497 void SqlStatement::setFloatParam(int paramPos, float value)
499 stmt->setFloatParam(paramPos, value);
501 void SqlStatement::setDoubleParam(int paramPos, double value)
503 stmt->setDoubleParam(paramPos, value);
505 void SqlStatement::setStringParam(int paramPos, char *value)
507 stmt->setStringParam(paramPos, value);
509 void SqlStatement::setDateParam(int paramPos, Date value)
511 stmt->setDateParam(paramPos, value);
513 void SqlStatement::setTimeParam(int paramPos, Time value)
515 stmt->setTimeParam(paramPos, value);
517 void SqlStatement::setTimeStampParam(int paramPos, TimeStamp value)
519 stmt->setTimeStampParam(paramPos, value);
521 void SqlStatement::setBinaryParam(int paramPos, void *value, int length)
523 stmt->setBinaryParam(paramPos, value, length);
525 int SqlStatement::getFldPos(char *name)
527 return stmt->getFldPos(name);
529 List SqlStatement::getAllTableNames(DbRetVal &ret)
531 DatabaseManager *dbMgr = NULL;
532 List tbNmList;
533 dbMgr=sqlCon->getConnObject().getDatabaseManager();
534 int rv = ret;
535 if(dbMgr != NULL)
536 tbNmList = dbMgr->getAllTableNames(&rv);
537 ret = (DbRetVal) rv;
538 return tbNmList;
541 List SqlStatement::getAllUserNames(DbRetVal &ret)
543 UserManager *urMgr = NULL;
544 List urNmList;
545 urMgr=sqlCon->getConnObject().getUserManager();
546 int rv = ret;
547 if(urMgr != NULL)
548 urNmList = urMgr->getAllUserNames(&rv);
549 ret = (DbRetVal) rv;
550 return urNmList;
552 List SqlStatement::getFieldNameList(const char *tblName)
554 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
555 Table *table = dbMgr->openTable(tblName);
556 List fldNameList = table->getFieldNameList();
557 dbMgr->closeTable(table);
558 return fldNameList;
560 DbRetVal SqlStatement::getFieldInfo(const char *tblName, const char *fldName, FieldInfo *&info)
562 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
563 Table *table = dbMgr->openTable(tblName);
564 DbRetVal rv = table->getFieldInfo(fldName, info);
565 dbMgr->closeTable(table);
566 return OK;
568 void SqlStatement::setLoading(bool flag)
570 if (pData.getStmtType() == InsertStatement||
571 pData.getStmtType() == UpdateStatement||
572 pData.getStmtType() == DeleteStatement)
574 DmlStatement *dmlStmt = (DmlStatement*) stmt;
575 dmlStmt->setLoading(flag);
577 return;
580 int SqlStatement::getNoOfPagesForTable(char *tblName)
582 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
583 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
584 return dbMgrImpl->getNoOfPagesForTable(tblName);
587 DbRetVal SqlStatement::loadRecords(char *tblName, void *buf)
589 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
590 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
591 return dbMgrImpl->loadRecords(tblName, (char *) buf);
594 DbRetVal SqlStatement::pasteRecords(char *tblName, void *buffer)
596 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
597 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
598 return dbMgrImpl->pasteRecords(tblName, buffer);
600 void SqlStatement::flushCacheStmt()
602 return sqlCon->flushCacheStmt();
604 //-------------------------------------------------------------------
605 void SqlConnection::flushCacheStmt()
607 ListIterator iter = cachedStmts.getIterator();
608 while (iter.hasElement()) {
609 CachedStmtNode* node = (CachedStmtNode*) iter.nextElement();
610 free(node->sqlString);
611 node->sqlStmt->setCachedStmt(false);
612 node->sqlStmt->free();
613 delete node->sqlStmt;
614 delete node;
616 cachedStmts.reset();
617 return;
620 SqlStatement* SqlConnection::findInCache(char *stmtstr)
622 ListIterator iter = cachedStmts.getIterator();
623 int inputStmtLen = strlen(stmtstr);
624 CachedStmtNode *node = NULL;
625 while ((node = (CachedStmtNode*)iter.nextElement()) != NULL)
627 if (node->stmtLength == inputStmtLen)
629 if (0 == strcmp(node->sqlString, stmtstr))
631 logFiner(Conf::logger, "Statement Retrieved From Cache %x\n",
632 node->sqlStmt);
633 node->hits++;
634 return node->sqlStmt;
638 return NULL;
640 void SqlConnection::addToCache(SqlStatement *sqlStmt, char* stmtString)
642 SqlStatement *stmt = new SqlStatement();
643 *stmt= *sqlStmt;
644 CachedStmtNode *node = new CachedStmtNode();
645 node->sqlStmt = stmt;
646 node->stmtLength = strlen(stmtString);
647 node->sqlString = (char*)malloc(node->stmtLength+1);
648 strcpy(node->sqlString, stmtString);
649 if (cachedStmts.size() >= Conf::config.getStmtCacheSize())
651 removeLeastUsed();
653 cachedStmts.append(node);
654 logFiner(Conf::logger, "Statement added To Cache %x\n", node->sqlStmt);
655 logFinest(Conf::logger, "Statement added To Cache %s\n", node->sqlString);
656 return ;
658 void SqlConnection::removeLeastUsed()
660 ListIterator iter = cachedStmts.getIterator();
661 CachedStmtNode *node = NULL, *toRemove =NULL;
662 int lowHits = 0;
663 bool firstCall = true;
664 while((node = (CachedStmtNode*) iter.nextElement()) != NULL)
666 if (firstCall) {
667 firstCall = false;
668 lowHits = node->hits;
669 toRemove = node; //if cache size is 1
670 continue;
672 if (lowHits >= node->hits) toRemove = node;
674 cachedStmts.remove(toRemove);
675 logFiner(Conf::logger, "Statement removed from Cache %x\n", toRemove->sqlStmt);
676 logFinest(Conf::logger, "Statement removed from Cache %s\n", toRemove->sqlString);
677 return;
679 SqlConnection::~SqlConnection()
681 innerConn = NULL;
682 flushCacheStmt();
683 if (isConnOpen) disconnect();
685 static void sigUsr1Handler(int sig)
687 ListIterator iter= SqlConnection::connList.getIterator();
688 SqlConnection *conn = NULL;
689 while (iter.hasElement())
691 conn = (SqlConnection*) iter.nextElement();
692 conn->flushCacheStmt();
694 return;
696 void SqlConnection::initialize()
698 os::signal(SIGCSQL1, sigUsr1Handler);
699 isInit = true;