changing global prepare mutex to process level mutex
[csql.git] / src / sql / SqlStatement.cxx
blob725cd483450f6e51cf7cda1649f4c3daac57d43b
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 List SqlConnection::connList;
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 int ret = ProcessManager::prepareMutex.tryLock(10, 1000);
90 if (ret != 0)
92 printError(ErrLockTimeOut, "Unable to get prepare mutex");
93 return ErrLockTimeOut;
96 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
97 if (isPrepared()) free();
98 lexInput = stmtstr;
99 parsedData = &pData;
101 yy_buffer_state *yy_buffer= yy_scan_string(stmtstr);
102 int rc = yyparse();
103 if (yy_buffer) yy_delete_buffer(yy_buffer);
104 if (rc != 0)
106 free();
107 parsedData = NULL;
108 ProcessManager::prepareMutex.releaseLock(-1, false);
109 return ErrSyntaxError;
111 if( parsedData->getStmtType() == MgmtStatement)
113 isPrepd = true;
114 parsedData = NULL;
115 isMgmtStatement = true;
116 ProcessManager::prepareMutex.releaseLock(-1, false);
117 logFine(Conf::logger,"PREPARE: %s %x", stmtstr, stmt);
118 return OK;
120 stmt = StatementFactory::getStatement(parsedData);
121 stmt->setDbMgr(dbMgr);
122 if( parsedData->getStmtType() == UserStatement)
124 UserManager* userMgr = sqlCon->getConnObject().getUserManager();
125 UserTblStatement *ustmt = (UserTblStatement *)stmt;
126 ustmt->setUserManager(userMgr,sqlCon->getConnObject().getUserName());
128 rv = stmt->resolve();
129 if (rv != OK)
131 free();
132 parsedData = NULL;
133 ProcessManager::prepareMutex.releaseLock(-1, false);
134 return rv;
136 isPrepd = true;
137 if (Conf::config.getStmtCacheSize()) {
138 if (stmt->noOfParamFields() > 0) {
139 isCachedStmt = true;
140 sqlCon->addToCache(this, stmtstr);
141 }else if (Conf::config.useCacheNoParam())
143 if (parsedData->getCacheWorthy())
145 isCachedStmt = true;
146 sqlCon->addToCache(this, stmtstr);
150 parsedData = NULL;
151 ProcessManager::prepareMutex.releaseLock(-1, false);
152 return OK;
155 char* SqlStatement::getTableName()
157 return pData.getTableName();
160 bool SqlStatement::isSelect()
162 if ((pData.getStmtType() == SelectStatement) || (pData.getStmtType() == MetaStatement)) return true;
163 return false;
166 bool SqlStatement::isPrepared() { return isPrepd; }
168 DbRetVal SqlStatement::execute(int &rowsAffected)
170 DbRetVal rv = OK;
171 if (! sqlCon->isConnectionOpen()) {
172 printError(ErrNotOpen, "Connection not open");
173 return ErrNotOpen;
175 if (! isPrepared()) {
176 printError(ErrNotPrepared, "Statement Not Prepared");
177 return ErrNotPrepared;
179 if( isMgmtStatement )
181 flushCacheStmt();
182 logFiner(Conf::logger,"EXECUTE: %x", stmt);
183 return OK;
185 rv = stmt->execute(rowsAffected);
186 if (rv == ErrAlready && pData.getStmtType() == SelectStatement )
187 { //if previous scan is not closed, close it
188 SelStatement *selStmt = (SelStatement*) stmt;
189 selStmt->close();
190 rv = stmt->execute(rowsAffected);
192 logFiner(Conf::logger,"EXECUTE: %x", stmt);
193 return rv;
196 void* SqlStatement::fetch()
198 if (! sqlCon->isConnectionOpen()) {
199 printError(ErrNotOpen, "Connection not open");
200 return NULL;
202 if (! isPrepared()) {
203 printError(ErrNotPrepared, "Statement Not Prepared");
204 return NULL;
206 if (pData.getStmtType() == SelectStatement ) {
207 SelStatement *selStmt = (SelStatement*) stmt;
208 return selStmt->fetch();
210 else if(pData.getStmtType() == MetaStatement){
211 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
212 return metaStmt->fetch();
214 else { return NULL;}
217 void* SqlStatement::fetch(DbRetVal &rv)
219 if (! sqlCon->isConnectionOpen()) {
220 printError(ErrNotOpen, "Connection not open");
221 return NULL;
223 if (! isPrepared()) {
224 printError(ErrNotPrepared, "Statement Not Prepared");
225 return NULL;
227 if (pData.getStmtType() == SelectStatement ) {
228 SelStatement *selStmt = (SelStatement*) stmt;
229 return selStmt->fetch(rv);
231 else if(pData.getStmtType() == MetaStatement){
232 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
233 return metaStmt->fetch(rv);
235 else { return NULL;}
238 void* SqlStatement::fetchAndPrint(bool SQL)
240 if (! sqlCon->isConnectionOpen()) {
241 printError(ErrNotOpen, "Connection not open");
242 return NULL;
244 if (! isPrepared()) {
245 printError(ErrNotPrepared, "Statement Not Prepared");
246 return NULL;
248 if (pData.getStmtType() != SelectStatement) return NULL;
249 SelStatement *selStmt = (SelStatement*) stmt;
250 return selStmt->fetchAndPrint(SQL);
253 DbRetVal SqlStatement::bindParam(int pos, void* value)
255 DbRetVal rv = OK;
256 rv = stmt->setParam(pos, value);
257 return rv;
260 DbRetVal SqlStatement::bindField(int pos, void* value)
262 DbRetVal rv = OK;
263 if (pData.getStmtType() == SelectStatement ) {
264 SelStatement *selStmt = (SelStatement*) stmt;
265 return selStmt->setBindField(pos, value);
267 else if(pData.getStmtType() == MetaStatement){
268 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
269 return metaStmt->setBindField(pos, value);
271 else { return ErrBadCall;}
273 void* SqlStatement::next()
275 if (pData.getStmtType() == SelectStatement ) {
276 SelStatement *selStmt = (SelStatement*) stmt;
277 return( (void*) selStmt->next() );
279 else if(pData.getStmtType() == MetaStatement){
280 MetadataStatement *metaStmt = (MetadataStatement*) stmt;
281 return( (void*) metaStmt->next() );
283 else { return 0;}
286 bool SqlStatement::isFldNull(int pos)
288 if (pData.getStmtType() != SelectStatement) return 0;
289 SelStatement *selStmt = (SelStatement*) stmt;
290 return (selStmt->isFldNull(pos));
292 bool SqlStatement::isFldNull(char *name)
294 if (pData.getStmtType() != SelectStatement) return 0;
295 SelStatement *selStmt = (SelStatement*) stmt;
296 return (selStmt->isFldNull(name));
298 DbRetVal SqlStatement::close()
300 if (pData.getStmtType() == SelectStatement ) {
301 SelStatement *selStmt = (SelStatement*) stmt;
302 logFinest(Conf::logger,"CLOSE: %x", stmt);
303 return selStmt->close();
305 else if(pData.getStmtType() == MetaStatement){
306 MetadataStatement *selStmt = (MetadataStatement*) stmt;
307 logFinest(Conf::logger,"CLOSE: %x", stmt);
308 return selStmt->close();
310 else { return OK;}
313 void* SqlStatement::getParamValuePtr( int pos )
315 //if (pData.getStmtType() != SelectStatement) return 0;
316 DmlStatement *dmlStmt = (DmlStatement*) stmt;
317 return( (void*) dmlStmt->getParamValuePtr( pos ) );
320 char* SqlStatement::getFieldName( int pos )
322 if (pData.getStmtType() == SelectStatement ) {
323 SelStatement *selStmt = (SelStatement*) stmt;
324 return( (char*) selStmt->getFieldName( pos ) );
326 else if(pData.getStmtType() == MetaStatement){
327 MetadataStatement *selStmt = (MetadataStatement*) stmt;
328 return( (char*) selStmt->getFieldName( pos ) );
330 else { return 0;}
333 DataType SqlStatement::getFieldType( int pos )
335 if (pData.getStmtType() == SelectStatement ) {
336 SelStatement *selStmt = (SelStatement*) stmt;
337 return( (DataType) selStmt->getFieldType( pos ) );
339 else if(pData.getStmtType() == MetaStatement){
340 MetadataStatement *selStmt = (MetadataStatement*) stmt;
341 return( (DataType) selStmt->getFieldType( pos ) );
343 else { return typeUnknown;}
345 int SqlStatement::getFieldLength( int pos )
347 if (pData.getStmtType() == SelectStatement ) {
348 SelStatement *selStmt = (SelStatement*) stmt;
349 return( (int) selStmt->getFieldLength( pos ) );
351 else if(pData.getStmtType() == MetaStatement){
352 MetadataStatement *selStmt = (MetadataStatement*) stmt;
353 return( (int) selStmt->getFieldLength( pos ) );
355 else { return 0;}
358 void* SqlStatement::getFieldValuePtr( int pos )
360 if (pData.getStmtType() == SelectStatement ) {
361 SelStatement *selStmt = (SelStatement*) stmt;
362 return( (void*) selStmt->getFieldValuePtr( pos ) );
364 else if(pData.getStmtType() == MetaStatement){
365 MetadataStatement *selStmt = (MetadataStatement*) stmt;
366 return( (void*) selStmt->getFieldValuePtr( pos ) );
368 else { return 0;}
370 void* SqlStatement::getFieldValuePtr( char *name )
372 if (pData.getStmtType() == SelectStatement ) {
373 SelStatement *selStmt = (SelStatement*) stmt;
374 return( (void*) selStmt->getFieldValuePtr( name ) );
376 else if(pData.getStmtType() == MetaStatement){
377 MetadataStatement *selStmt = (MetadataStatement*) stmt;
378 return( (void*) selStmt->getFieldValuePtr( name ) );
380 else { return NULL;}
383 int SqlStatement::noOfProjFields()
385 if (pData.getStmtType() == SelectStatement ) {
386 SelStatement *selStmt = (SelStatement*) stmt;
387 return selStmt->noOfProjFields();
389 else if(pData.getStmtType() == MetaStatement){
390 MetadataStatement *selStmt = (MetadataStatement*) stmt;
391 return selStmt->noOfProjFields();
393 else { return 0;}
396 void SqlStatement::getProjFieldType(int *data)
398 if (pData.getStmtType() == SelectStatement ) {
399 SelStatement *selStmt = (SelStatement*) stmt;
400 return( selStmt->getProjFieldType(data) );
402 else if(pData.getStmtType() == MetaStatement){
403 MetadataStatement *selStmt = (MetadataStatement*) stmt;
404 return( selStmt->getProjFieldType(data) );
410 int SqlStatement::noOfParamFields()
412 return stmt->noOfParamFields();
415 DbRetVal SqlStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
417 DbRetVal rv = OK;
418 if (pData.getStmtType() == SelectStatement ) {
419 SelStatement *selStmt = (SelStatement*) stmt;
420 rv = selStmt->getProjFldInfo(projpos, fInfo);
422 else if(pData.getStmtType() == MetaStatement){
423 MetadataStatement *selStmt = (MetadataStatement*) stmt;
424 rv = selStmt->getProjFldInfo(projpos, fInfo);
425 } else { return ErrBadCall;}
426 return rv;
429 DbRetVal SqlStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
431 DbRetVal rv = OK;
432 if (pData.getStmtType() ==SelectStatement ||
433 pData.getStmtType() ==InsertStatement ||
434 pData.getStmtType() ==UpdateStatement ||
435 pData.getStmtType() ==DeleteStatement)
438 DmlStatement *dmlStmt = (DmlStatement*) stmt;
439 rv = dmlStmt->getParamFldInfo(parampos, fInfo);
441 return rv;
444 DbRetVal SqlStatement::free()
446 logFinest(Conf::logger,"FREE: %x", stmt);
447 if (isCachedStmt) {
448 stmt=NULL;
449 pData.init();
450 isPrepd = false;
451 return OK;
453 if(stmt) delete stmt;
454 stmt = NULL;
455 pData.reset();
456 isMgmtStatement = false;
457 isPrepd = false;
458 return OK;
461 void SqlStatement::setNull(int pos)
463 stmt->setNull(pos);
465 void SqlStatement::setShortParam(int paramPos, short value)
467 stmt->setShortParam(paramPos, value);
469 void SqlStatement::setIntParam(int paramPos, int value)
471 stmt->setIntParam(paramPos, value);
473 void SqlStatement::setLongParam(int paramPos, long value)
475 stmt->setLongParam(paramPos, value);
477 void SqlStatement::setLongLongParam(int paramPos, long long value)
479 stmt->setLongLongParam(paramPos, value);
481 void SqlStatement::setByteIntParam(int paramPos, ByteInt value)
483 stmt->setByteIntParam(paramPos, value);
485 void SqlStatement::setFloatParam(int paramPos, float value)
487 stmt->setFloatParam(paramPos, value);
489 void SqlStatement::setDoubleParam(int paramPos, double value)
491 stmt->setDoubleParam(paramPos, value);
493 void SqlStatement::setStringParam(int paramPos, char *value)
495 stmt->setStringParam(paramPos, value);
497 void SqlStatement::setDateParam(int paramPos, Date value)
499 stmt->setDateParam(paramPos, value);
501 void SqlStatement::setTimeParam(int paramPos, Time value)
503 stmt->setTimeParam(paramPos, value);
505 void SqlStatement::setTimeStampParam(int paramPos, TimeStamp value)
507 stmt->setTimeStampParam(paramPos, value);
509 void SqlStatement::setBinaryParam(int paramPos, void *value, int length)
511 stmt->setBinaryParam(paramPos, value, length);
513 int SqlStatement::getFldPos(char *name)
515 return stmt->getFldPos(name);
517 List SqlStatement::getAllTableNames(DbRetVal &ret)
519 DatabaseManager *dbMgr = NULL;
520 List tbNmList;
521 dbMgr=sqlCon->getConnObject().getDatabaseManager();
522 int rv = ret;
523 if(dbMgr != NULL)
524 tbNmList = dbMgr->getAllTableNames(&rv);
525 ret = (DbRetVal) rv;
526 return tbNmList;
529 List SqlStatement::getAllUserNames(DbRetVal &ret)
531 UserManager *urMgr = NULL;
532 List urNmList;
533 urMgr=sqlCon->getConnObject().getUserManager();
534 int rv = ret;
535 if(urMgr != NULL)
536 urNmList = urMgr->getAllUserNames(&rv);
537 ret = (DbRetVal) rv;
538 return urNmList;
540 List SqlStatement::getFieldNameList(const char *tblName)
542 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
543 Table *table = dbMgr->openTable(tblName);
544 if (NULL == table) {
545 List dummyList;
546 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
547 return dummyList;
549 List fldNameList = table->getFieldNameList();
550 dbMgr->closeTable(table);
551 return fldNameList;
553 DbRetVal SqlStatement::getFieldInfo(const char *tblName, const char *fldName, FieldInfo *&info)
555 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
556 Table *table = dbMgr->openTable(tblName);
557 if (NULL == table) {
558 printError(ErrLockTimeOut, "Unable to open table %s", tblName);
559 return ErrLockTimeOut;
561 DbRetVal rv = table->getFieldInfo(fldName, info);
562 dbMgr->closeTable(table);
563 return OK;
565 void SqlStatement::setLoading(bool flag)
567 if (pData.getStmtType() == InsertStatement||
568 pData.getStmtType() == UpdateStatement||
569 pData.getStmtType() == DeleteStatement)
571 DmlStatement *dmlStmt = (DmlStatement*) stmt;
572 dmlStmt->setLoading(flag);
574 return;
577 int SqlStatement::getNoOfPagesForTable(char *tblName)
579 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
580 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
581 return dbMgrImpl->getNoOfPagesForTable(tblName);
584 DbRetVal SqlStatement::loadRecords(char *tblName, void *buf)
586 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
587 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
588 return dbMgrImpl->loadRecords(tblName, (char *) buf);
591 DbRetVal SqlStatement::pasteRecords(char *tblName, void *buffer)
593 DatabaseManager *dbMgr = sqlCon->getConnObject().getDatabaseManager();
594 DatabaseManagerImpl *dbMgrImpl = (DatabaseManagerImpl *)dbMgr;
595 return dbMgrImpl->pasteRecords(tblName, buffer);
597 void SqlStatement::flushCacheStmt()
599 return sqlCon->flushCacheStmt();
601 //-------------------------------------------------------------------
602 void SqlConnection::flushCacheStmt()
604 ListIterator iter = cachedStmts.getIterator();
605 while (iter.hasElement()) {
606 CachedStmtNode* node = (CachedStmtNode*) iter.nextElement();
607 free(node->sqlString);
608 node->sqlStmt->setCachedStmt(false);
609 node->sqlStmt->free();
610 delete node->sqlStmt;
611 delete node;
613 cachedStmts.reset();
614 return;
617 SqlStatement* SqlConnection::findInCache(char *stmtstr)
619 ListIterator iter = cachedStmts.getIterator();
620 int inputStmtLen = strlen(stmtstr);
621 CachedStmtNode *node = NULL;
622 while ((node = (CachedStmtNode*)iter.nextElement()) != NULL)
624 if (node->stmtLength == inputStmtLen)
626 if (0 == strcmp(node->sqlString, stmtstr))
628 logFiner(Conf::logger, "Statement Retrieved From Cache %x\n",
629 node->sqlStmt);
630 node->hits++;
631 return node->sqlStmt;
635 return NULL;
637 void SqlConnection::addToCache(SqlStatement *sqlStmt, char* stmtString)
639 SqlStatement *stmt = new SqlStatement();
640 *stmt= *sqlStmt;
641 CachedStmtNode *node = new CachedStmtNode();
642 node->sqlStmt = stmt;
643 node->stmtLength = strlen(stmtString);
644 node->sqlString = (char*)malloc(node->stmtLength+1);
645 strcpy(node->sqlString, stmtString);
646 if (cachedStmts.size() >= Conf::config.getStmtCacheSize())
648 removeLeastUsed();
650 cachedStmts.append(node);
651 logFiner(Conf::logger, "Statement added To Cache %x\n", node->sqlStmt);
652 logFinest(Conf::logger, "Statement added To Cache %s\n", node->sqlString);
653 return ;
655 void SqlConnection::removeLeastUsed()
657 ListIterator iter = cachedStmts.getIterator();
658 CachedStmtNode *node = NULL, *toRemove =NULL;
659 int lowHits = 0;
660 bool firstCall = true;
661 while((node = (CachedStmtNode*) iter.nextElement()) != NULL)
663 if (firstCall) {
664 firstCall = false;
665 lowHits = node->hits;
666 toRemove = node; //if cache size is 1
667 continue;
669 if (lowHits >= node->hits) toRemove = node;
671 cachedStmts.remove(toRemove);
672 logFiner(Conf::logger, "Statement removed from Cache %x\n", toRemove->sqlStmt);
673 logFinest(Conf::logger, "Statement removed from Cache %s\n", toRemove->sqlString);
674 return;
676 SqlConnection::~SqlConnection()
678 innerConn = NULL;
679 flushCacheStmt();
680 if (isConnOpen) disconnect();
682 static void sigUsr1Handler(int sig)
684 ListIterator iter= SqlConnection::connList.getIterator();
685 SqlConnection *conn = NULL;
686 while (iter.hasElement())
688 conn = (SqlConnection*) iter.nextElement();
689 conn->flushCacheStmt();
691 os::signal(SIGCSQL1, sigUsr1Handler);
692 return;
694 void SqlConnection::initialize()
696 os::signal(SIGCSQL1, sigUsr1Handler);
697 isInit = true;