fix for trie index
[csql.git] / src / adapter / SqlOdbcStatement.cxx
blob08c84612d5593d4323ce4684c8aab8f643bff560
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 <SqlOdbcStatement.h>
21 //Important Note: MySQL Bug
22 //Bug #1382 SQLDescribeParam returns the same type information for any type
23 //as varchar of length 255. To avoid this, this class converts every data type
24 //to varchar by using appropriate conversion functions.
26 DbRetVal SqlOdbcStatement::executeDirect(char *stmtstr)
28 DbRetVal rv = OK;
29 int retValue = 0;
30 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
31 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
32 if (retValue) return ErrBadCall;
33 SQLCHAR* sstr= (SQLCHAR*)stmtstr;
34 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLExecDirectPtr) (hstmt, sstr, SQL_NTS);
35 if (retValue) return ErrBadCall;
36 logFinest(Conf::logger, "executeDirect %s", stmtstr);
37 return rv;
40 DbRetVal SqlOdbcStatement::prepare(char *stmtstr)
42 DbRetVal rv = OK;
43 if (innerStmt) rv = ErrBadCall;
44 if (rv != OK) return rv;
45 int retValue =0;
46 isPrepared = false;
47 isProcedureCallStmt = false;
48 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
49 //retValue=SQLAllocHandle (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
50 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
51 if (retValue) return ErrBadCall;
52 SQLCHAR* sstr= (SQLCHAR*)stmtstr;
53 //retValue = SQLPrepare (hstmt, sstr, SQL_NTS);
54 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLPreparePtr) (hstmt, sstr, SQL_NTS);
55 if (retValue) {
56 //setErrorState(hstmt);
57 printError(ErrSysInternal, "Unable to prepare statement");
58 return ErrSysInternal;
60 isSelStmt=checkStmtType(stmtstr);
61 isPrepared = true;
62 if(strstr(stmtstr,"call ")!=NULL || strstr(stmtstr,"CALL ")!=NULL)
64 logFinest(Conf::logger, "Procedure call statement =true");
65 isProcedureCallStmt=true;
67 short totalFields=0;
68 tdbname = conn->getTrDbName();
69 rv = resolveForBindField(hstmt);
70 if(rv!=OK) return rv;
71 UWORD icol;
72 SWORD colNameMax;
73 SWORD scale;
74 SWORD nullable;
75 BindSqlField *bindField;
76 //retValue = SQLNumParams (hstmt, &totalFields);
77 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLNumParamsPtr) (hstmt, &totalFields);
78 if (retValue) return ErrBadCall;
79 icol = 1; colNameMax = IDENTIFIER_LENGTH;
80 SWORD cType=0;
81 SQLULEN cLength=0;
82 scale=0;
83 logFinest(Conf::logger, "NumParams %d", totalFields);
84 if(totalFields != 0)
86 paramlen =(SQLINTEGER *) malloc((totalFields+1)*sizeof(SQLINTEGER));
87 for(int i=0;i<=totalFields;i++) { paramlen[i] = SQL_NTS; }
90 while (icol <= totalFields)
92 //retValue = SQLDescribeParam(hstmt, icol, &cType, &cLength,
93 //Note: MySQL Bug
94 //Bug #1382 SQLDescribeParam returns the same type information
96 bindField = new BindSqlField();
97 bindField->type = typeString;
98 bindField->length = 512;
99 bindField->value = AllDataType::alloc(bindField->type, bindField->length);
100 bindField->targetvalue = NULL;
101 int fieldsize =0;
102 switch(bindField->type)
104 case typeString:
105 fieldsize = bindField->length;
106 bindField->targetvalue = malloc(fieldsize);
107 break;
108 case typeDate:
109 fieldsize = sizeof(DATE_STRUCT);
110 bindField->targetvalue = malloc(sizeof(DATE_STRUCT));
111 break;
112 case typeTime:
113 fieldsize = sizeof(TIME_STRUCT);
114 bindField->targetvalue = malloc(sizeof(TIME_STRUCT));
115 break;
116 case typeTimeStamp:
117 fieldsize = sizeof(TIMESTAMP_STRUCT);
118 bindField->targetvalue = malloc(sizeof(TIMESTAMP_STRUCT));
119 break;
120 default:
121 bindField->targetvalue = AllDataType::alloc(bindField->type, cLength);
122 break;
125 //retValue = SQLBindParameter(hstmt, icol, SQL_PARAM_INPUT,
126 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindParameterPtr)(hstmt, icol, SQL_PARAM_INPUT,
127 AllDataType::convertToSQL_C_Type(bindField->type,tdbname),
128 AllDataType::convertToSQLType(bindField->type), fieldsize, scale, bindField->targetvalue,
129 fieldsize, &paramlen[icol]);
130 if (retValue) return ErrBadCall;
131 paramList.append(bindField);
132 icol++;
134 //TODO::deallocate memory and remove elements from list in case of any
135 //failure in any of the above ODBC functions
136 logFinest(Conf::logger, "Statement prepared %s", stmtstr);
137 return OK;
140 bool SqlOdbcStatement::isSelect()
142 //TODO
143 return isSelStmt;
146 DbRetVal SqlOdbcStatement::execute(int &rowsAffected)
148 DbRetVal rv = OK;
149 if (!isPrepared) return ErrNotPrepared;
150 int retValue=0;
151 ListIterator iter = paramList.getIterator();
152 BindSqlField *bindField = NULL;
153 int col = 0;
154 while (iter.hasElement())
156 bindField = (BindSqlField*)iter.nextElement();
157 if(paramlen[++col] == SQL_NULL_DATA){
158 ::free(bindField->targetvalue);
159 bindField->targetvalue = NULL;
160 continue;
162 switch(bindField->type)
164 case typeDate: {
165 Date *dtCSQL = (Date*) bindField->value;
166 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
167 dtTarget->year= dtCSQL->year();
168 dtTarget->month= dtCSQL->month();
169 dtTarget->day = dtCSQL->dayOfMonth();
170 break;
172 case typeTime: {
173 Time *dtCSQL = (Time*) bindField->value;
174 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
175 dtTarget->hour = dtCSQL->hours();
176 dtTarget->minute = dtCSQL->minutes();
177 dtTarget->second = dtCSQL->seconds();
178 break;
180 case typeTimeStamp: {
181 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
182 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
183 dtTarget->year= dtCSQL->year();
184 dtTarget->month= dtCSQL->month();
185 dtTarget->day = dtCSQL->dayOfMonth();
186 dtTarget->hour = dtCSQL->hours();
187 dtTarget->minute = dtCSQL->minutes();
188 dtTarget->second = dtCSQL->seconds();
189 break;
191 default: {
192 AllDataType::cachecopyVal(bindField->targetvalue, bindField->value,
193 bindField->type, bindField->length);
194 break;
198 //int retValue = SQLExecute (hstmt);
199 if(isProcedureCallStmt)
201 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLExecutePtr) (hstmt);
202 if ((retValue != SQL_SUCCESS) && (retValue != SQL_SUCCESS_WITH_INFO )) {
203 return ErrBadCall;
205 rv = resolveForBindField(hstmt);
206 if(rv!=OK) return rv;
207 logFinest(Conf::logger, "Procedure executed");
208 }else{
209 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLExecutePtr) (hstmt);
210 if ((retValue != SQL_SUCCESS) && (retValue != SQL_SUCCESS_WITH_INFO )) {
211 // setErrorState(hstmt);
212 return ErrBadCall;
214 logFinest(Conf::logger, "Statement executed");
216 //retValue=SQLRowCount(hstmt,(SQLINTEGER*)&rowsAffected);
217 retValue= (*SqlOdbcConnection::ODBCFuncPtrs.SQLRowCountPtr)(hstmt,(SQLINTEGER*)&rowsAffected);
218 if(isSelStmt) rowsAffected = 0;
219 return rv;
222 DbRetVal SqlOdbcStatement::bindParam(int pos, void* value)
224 DbRetVal rv = OK;
225 printError(ErrWarning, "Deprecated. Use setParamXXX instead\n");
226 return rv;
229 DbRetVal SqlOdbcStatement::bindField(int pos, void* value)
231 if (!isPrepared) return OK;
232 BindSqlProjectField *bindField = (BindSqlProjectField*)bindList.get(pos);
233 if (NULL == bindField)
235 printError(ErrBadArg, "Could not get the projection list. Should be called only for SELECT statement");
236 return ErrBadArg;
238 bindField->value = value;
239 return OK;
242 //void SqlOdbcStatement::setNullInfo(Table *table)
243 void SqlOdbcStatement::setNullInfo(AbsSqlStatement *stmt)
245 int fldpos=0;
246 while(fldpos < totalFld)
248 if(len[++fldpos] == SQL_NULL_DATA)
250 stmt->setNull(fldpos);
255 void* SqlOdbcStatement::fetch()
257 if (!isPrepared) return NULL;
258 //int retValue = SQLFetch (hstmt);
259 int retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr) (hstmt);
260 if (retValue) return NULL;
261 ListIterator iter = bindList.getIterator();
262 BindSqlProjectField *bindField = NULL;
263 void *ptrToFirstField = NULL;
264 int icol=0;
265 while (iter.hasElement())
267 bindField = (BindSqlProjectField*)iter.nextElement();
268 if (ptrToFirstField == NULL) ptrToFirstField=bindField->value;
269 if(len[++icol] == SQL_NULL_DATA)
271 if(bindField->value) AllDataType::memoryset(bindField->value,bindField->type);
272 continue;
274 if( isSelStmt && NULL == bindField->value )
276 if (ptrToFirstField == NULL) ptrToFirstField=bindField->targetvalue;
277 continue;
279 switch(bindField->type)
281 case typeDate: {
282 Date *dtCSQL = (Date*) bindField->value;
283 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
284 dtCSQL->set(dtTarget->year,dtTarget->month,dtTarget->day);
285 break;
287 case typeTime: {
288 Time *dtCSQL = (Time*) bindField->value;
289 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
290 dtCSQL->set(dtTarget->hour,dtTarget->minute,dtTarget->second);
291 break;
293 case typeTimeStamp: {
294 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
295 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
296 dtCSQL->setDate(dtTarget->year,dtTarget->month,dtTarget->day);
297 dtCSQL->setTime(dtTarget->hour,dtTarget->minute,
298 dtTarget->second, 0);//dtTarget->fraction);
299 break;
301 default: {
302 AllDataType::cachecopyVal(bindField->value, bindField->targetvalue,
303 bindField->type, bindField->length,tdbname);
304 break;
308 return ptrToFirstField;
311 void* SqlOdbcStatement::fetch(DbRetVal &rv)
313 SqlOdbcConnection *sqlOdbcCon = (SqlOdbcConnection *)con;
314 if (! sqlOdbcCon->isConnectionOpen()) {
315 printError(ErrNotOpen, "Connection not open");
316 rv = ErrNoConnection;
317 return NULL;
319 if (!isPrepared) return NULL;
320 //int retValue = SQLFetch (hstmt);
321 int retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr) (hstmt);
322 if (retValue) { rv = OK; return NULL; }
323 ListIterator iter = bindList.getIterator();
324 BindSqlProjectField *bindField = NULL;
325 void *ptrToFirstField = NULL;
326 int icol=0;
327 while (iter.hasElement())
329 bindField = (BindSqlProjectField*)iter.nextElement();
330 if (ptrToFirstField == NULL) ptrToFirstField=bindField->value;
331 if(len[++icol] == SQL_NULL_DATA)
333 if(bindField->value) AllDataType::memoryset(bindField->value,bindField->type);
334 continue;
336 if( isSelStmt && NULL == bindField->value )
338 if (ptrToFirstField == NULL) ptrToFirstField=bindField->targetvalue;
339 continue;
341 switch(bindField->type)
343 case typeDate: {
344 Date *dtCSQL = (Date*) bindField->value;
345 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
346 dtCSQL->set(dtTarget->year,dtTarget->month,dtTarget->day);
347 break;
349 case typeTime: {
350 Time *dtCSQL = (Time*) bindField->value;
351 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
352 dtCSQL->set(dtTarget->hour,dtTarget->minute,dtTarget->second);
353 break;
355 case typeTimeStamp: {
356 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
357 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
358 dtCSQL->setDate(dtTarget->year,dtTarget->month,dtTarget->day);
359 dtCSQL->setTime(dtTarget->hour,dtTarget->minute,
360 dtTarget->second, 0);// dtTarget->fraction);
361 break;
363 default: {
364 AllDataType::cachecopyVal(bindField->value, bindField->targetvalue, bindField->type, bindField->length, tdbname);
365 break;
369 return ptrToFirstField;
372 void* SqlOdbcStatement::fetchAndPrint(bool SQL)
374 if (!isPrepared) return NULL;
375 //int retValue = SQLFetch (hstmt);
376 int retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr) (hstmt);
377 if (retValue) return NULL;
378 ListIterator iter = bindList.getIterator();
379 BindSqlProjectField *bindField = NULL;
380 void *ptrToFirstField = NULL;
381 int icol=1;
382 while (iter.hasElement())
385 bindField = (BindSqlProjectField*)iter.nextElement();
386 if (ptrToFirstField == NULL) ptrToFirstField=bindField->targetvalue;
387 if(len[icol++] == SQL_NULL_DATA)
389 printf("NULL");
390 continue;
392 switch(bindField->type)
394 case typeDate: {
395 Date dtCSQL;
396 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
397 dtCSQL.set(dtTarget->year,dtTarget->month,dtTarget->day);
398 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
399 break;
401 case typeTime: {
402 Time dtCSQL;
403 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
404 dtCSQL.set(dtTarget->hour,dtTarget->minute,dtTarget->second);
405 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
406 break;
408 case typeTimeStamp: {
409 TimeStamp dtCSQL;
410 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
411 dtCSQL.setDate(dtTarget->year,dtTarget->month,dtTarget->day);
412 dtCSQL.setTime(dtTarget->hour,dtTarget->minute,
413 dtTarget->second, 0);//dtTarget->fraction);
414 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
415 break;
417 default: {
418 AllDataType::printVal(bindField->targetvalue,
419 bindField->type, bindField->length,tdbname);
420 break;
423 printf("\t");
425 return ptrToFirstField;
428 void* SqlOdbcStatement::next()
430 return fetch();
433 DbRetVal SqlOdbcStatement::close()
435 if (!isPrepared) return OK;
436 (*SqlOdbcConnection::ODBCFuncPtrs.SQLCloseCursorPtr)(hstmt);
437 logFinest(Conf::logger, "CloseCursor");
438 return OK;
440 bool SqlOdbcStatement::checkStmtType(char *buf)
442 char c;
443 while(1) { c=*buf; if(c !=' ') break; buf++; }
444 if (strncasecmp (buf, "SELECT", 6) == 0) { return true; }
445 return false;
447 void* SqlOdbcStatement::getFieldValuePtr( int pos )
450 ListIterator biter = bindList.getIterator();
451 BindSqlProjectField *elem = NULL;
452 int count =0;
453 while (biter.hasElement())
455 elem = (BindSqlProjectField*) biter.nextElement();
456 if (count == pos)
458 if(elem->value == NULL)
460 switch(elem->type)
462 case typeDate: {
463 Date *dtCSQL=(Date *) elem->jdbcBindValue;
464 DATE_STRUCT *dtTarget = (DATE_STRUCT*) elem->targetvalue;
465 dtCSQL->set(dtTarget->year,dtTarget->month,dtTarget->day);
466 return dtCSQL;
468 case typeTime: {
469 Time *dtCSQL = (Time *) elem->jdbcBindValue;
470 TIME_STRUCT *dtTarget = (TIME_STRUCT*) elem->targetvalue;
471 dtCSQL->set(dtTarget->hour,dtTarget->minute,dtTarget->second);
472 return dtCSQL;
474 case typeTimeStamp: {
475 TimeStamp *dtCSQL= (TimeStamp *) elem->jdbcBindValue;
476 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) elem->targetvalue;
477 dtCSQL->setDate(dtTarget->year,dtTarget->month,dtTarget->day);
478 dtCSQL->setTime(dtTarget->hour,dtTarget->minute,dtTarget->second, 0);//dtTarget->fraction);
479 return dtCSQL;
483 return elem->targetvalue;
485 count++;
487 return NULL;
490 void SqlOdbcStatement::getProjFieldType(int *data)
492 ListIterator biter = bindList.getIterator();
493 BindSqlProjectField *elem = NULL;
494 int i = 1;
495 while (biter.hasElement())
497 elem = (BindSqlProjectField*) biter.nextElement();
498 if((tdbname == postgres) && typeLongLong == elem->type)
499 data[i++] = typeString;
500 else
501 data[i++] = elem->type;
505 void* SqlOdbcStatement::getFieldValuePtr( char *name )
507 ListIterator biter = bindList.getIterator();
508 BindSqlProjectField *elem = NULL;
509 int count =0;
510 while (biter.hasElement())
512 elem = (BindSqlProjectField*) biter.nextElement();
513 if ( strcpy(elem->fName,name) == 0 )
515 return elem->targetvalue;
518 return NULL;
521 int SqlOdbcStatement::noOfProjFields()
523 if (!isPrepared) return 0;
524 return bindList.size();
527 int SqlOdbcStatement::noOfParamFields()
529 if (!isPrepared) return 0;
530 return paramList.size();
533 DbRetVal SqlOdbcStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
535 ListIterator biter = bindList.getIterator();
536 BindSqlProjectField *elem = NULL;
537 int count =0;
538 while (biter.hasElement())
540 elem = (BindSqlProjectField*) biter.nextElement();
541 if (count == projpos-1)
543 strcpy(fInfo->fldName, elem->fName);
544 fInfo->length = elem->length;
545 fInfo->type =elem->type;
546 return OK;
548 count++;
550 return ErrNotFound;
553 DbRetVal SqlOdbcStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
555 ListIterator biter = paramList.getIterator();
556 BindSqlField *elem = NULL;
557 int count =0;
558 while (biter.hasElement())
560 elem = (BindSqlField*) biter.nextElement();
561 if (count == parampos-1)
563 fInfo->length = elem->length;
564 fInfo->type =elem->type;
565 return OK;
567 count++;
569 return ErrNotFound;
572 DbRetVal SqlOdbcStatement::free()
574 if(!isPrepared) return OK;
575 ListIterator biter = bindList.getIterator();
576 BindSqlProjectField *elem = NULL;
577 while (biter.hasElement())
579 elem = (BindSqlProjectField*) biter.nextElement();
580 if(elem->targetvalue)
581 ::free(elem->targetvalue);
582 if(elem->jdbcBindValue)
583 ::free(elem->jdbcBindValue);
584 delete elem;
586 if (rowStatus) { ::free(rowStatus); rowStatus = NULL; }
587 bindList.reset();
588 ListIterator piter = paramList.getIterator();
589 BindSqlField *bindField = NULL;
590 while (piter.hasElement())
592 bindField = (BindSqlField*) piter.nextElement();
593 ::free(bindField->value);
594 ::free(bindField->targetvalue);
595 delete bindField;
597 paramList.reset();
598 if(len){ ::free(len); len = NULL;}
599 if(paramlen) {::free(paramlen); paramlen = NULL;}
600 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
601 isPrepared = false;
602 isProcedureCallStmt = false;
603 logFinest(Conf::logger, "Statement Freed");
604 return OK;
606 void SqlOdbcStatement::setShortParam(int paramPos, short value)
608 if (!isPrepared) return ;
609 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
610 AllDataType::convertToString(bindField->value, &value, typeShort, 0,tdbname);
611 return;
613 void SqlOdbcStatement::setIntParam(int paramPos, int value)
615 if (!isPrepared) return ;
616 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
617 //Note: MySQL Bug
618 //Bug #1382 SQLDescribeParam returns the same type information, varchar
619 AllDataType::convertToString(bindField->value, &value, typeInt,0,tdbname);
620 return;
623 void SqlOdbcStatement::setLongParam(int paramPos, long value)
625 if (!isPrepared) return ;
626 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
627 //Note: MySQL Bug
628 //Bug #1382 SQLDescribeParam returns the same type information, varchar
629 AllDataType::convertToString(bindField->value, &value, typeLong,0,tdbname);
630 return;
633 void SqlOdbcStatement::setLongLongParam(int paramPos, long long value)
635 if (!isPrepared) return ;
636 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
637 AllDataType::convertToString(bindField->value, &value, typeLongLong,0,tdbname);
638 return;
640 void SqlOdbcStatement::setByteIntParam(int paramPos, ByteInt value)
642 if (!isPrepared) return ;
643 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
644 AllDataType::convertToString(bindField->value, &value, typeByteInt,0,tdbname);
645 return;
647 void SqlOdbcStatement::setFloatParam(int paramPos, float value)
649 if (!isPrepared) return ;
650 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
651 AllDataType::convertToString(bindField->value, &value, typeFloat,0, tdbname);
652 return;
654 void SqlOdbcStatement::setDoubleParam(int paramPos, double value)
656 if (!isPrepared) return ;
657 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
658 AllDataType::convertToString(bindField->value, &value, typeDouble,0,tdbname);
659 return;
661 void SqlOdbcStatement::setStringParam(int paramPos, char *value)
663 if (!isPrepared) return ;
664 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
665 if (bindField->type != typeString) return;
666 char *dest = (char*)bindField->value;
667 strncpy(dest, value, bindField->length);
668 dest[ bindField->length - 1] ='\0';
669 return;
671 void SqlOdbcStatement::setDateParam(int paramPos, Date value)
673 if (!isPrepared) return ;
674 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
675 AllDataType::convertToString(bindField->value, &value, typeDate,0,tdbname);
676 return;
678 void SqlOdbcStatement::setTimeParam(int paramPos, Time value)
680 if (!isPrepared) return ;
681 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
682 AllDataType::convertToString(bindField->value, &value, typeTime,0,tdbname);
683 return;
685 void SqlOdbcStatement::setTimeStampParam(int paramPos, TimeStamp value)
687 if (!isPrepared) return ;
688 BindSqlField *bindField = (BindSqlField*) paramList.get(paramPos);
689 AllDataType::convertToString(bindField->value, &value, typeTimeStamp,0, tdbname);
690 return;
692 void SqlOdbcStatement::setBinaryParam(int paramPos, void *value, int length)
694 if (!isPrepared) return;
695 BindSqlField *bindField = (BindSqlField*) paramList.get(paramPos);
696 AllDataType::convertToString(bindField->value, value, typeBinary, bindField->length,tdbname);
697 return;
700 void SqlOdbcStatement::getPrimaryKeyFieldName(char *tablename, char *pkfieldname)
702 if (pkfieldname == NULL) return;
703 SQLCHAR outstr[1024];
704 SQLSMALLINT outstrlen;
705 int retValue =0;
706 SQLHENV henv;
707 SQLHDBC hdbc;
708 SQLHSTMT hstmt;
709 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
710 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
711 if (retValue) {
712 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
714 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetEnvAttrPtr)(henv, SQL_ATTR_ODBC_VERSION,(void *) SQL_OV_ODBC3, 0);
715 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_DBC, henv, &hdbc);
716 if (retValue) {
717 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
719 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDriverConnectPtr)(hdbc, NULL, (SQLCHAR*)conn->dsString, SQL_NTS, outstr, sizeof(outstr), &outstrlen,SQL_DRIVER_NOPROMPT);
720 if (SQL_SUCCEEDED(retValue)) {
721 printDebug(DM_Gateway, "Connected to target database using dsn = %s\n", conn->dsString);
722 } else {
723 printError(ErrSysInit, "Failed to connect to target database\n");
725 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, hdbc, &hstmt);
726 if (retValue) {
727 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
729 char columnname[IDENTIFIER_LENGTH];
730 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLPrimaryKeysPtr)(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, (SQLCHAR*) tablename, SQL_NTS);
731 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, 4, SQL_C_CHAR,columnname, 129,NULL);
732 bool isPkExists=false;
733 if((*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr)( hstmt ) == SQL_SUCCESS)
735 Util::str_tolower(columnname);
736 strcpy(pkfieldname, columnname);
737 isPkExists = true;
739 tdbname = conn->getTrDbName();
740 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
741 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
742 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
743 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
744 return;
747 bool SqlOdbcStatement::isFldNull(int pos)
749 if( len[pos] == SQL_NULL_DATA )
750 return true;
751 else
752 return false;
754 bool SqlOdbcStatement::isFldNull(char *name)
756 ListIterator iter = bindList.getIterator();
757 BindSqlProjectField *bindField = NULL;
758 int pos=1;
759 while (iter.hasElement())
761 bindField = (BindSqlProjectField*)iter.nextElement();
762 if(strcmp(name,bindField->fName)==0)
764 break;
766 pos++;
768 if( len[pos] == SQL_NULL_DATA )
769 return true;
770 else
771 return false;
774 void SqlOdbcStatement::setNull(int pos)
776 paramlen[pos] = SQL_NULL_DATA ;
779 bool SqlOdbcStatement::isTableExists( char *name)
782 SQLCHAR outstr[1024];
783 SQLSMALLINT outstrlen;
784 int retValue =0;
785 SQLHENV henv;
786 SQLHDBC hdbc;
787 SQLHSTMT hstmt;
788 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
789 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
790 if (retValue) {
791 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
794 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetEnvAttrPtr)(henv, SQL_ATTR_ODBC_VERSION,(void *) SQL_OV_ODBC3, 0);
795 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_DBC, henv, &hdbc);
796 if (retValue) {
797 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
799 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDriverConnectPtr)(hdbc, NULL, (SQLCHAR*)conn->dsString, SQL_NTS, outstr, sizeof(outstr), &outstrlen,SQL_DRIVER_NOPROMPT);
800 if (SQL_SUCCEEDED(retValue)) {
801 printDebug(DM_Gateway, "Connected to target database using dsn = %s\n", conn->dsString);
802 } else {
803 printError(ErrSysInit, "Failed to connect to target database\n");
806 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, hdbc, &hstmt);
807 if (retValue) {
808 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
810 char tablename[IDENTIFIER_LENGTH];
811 //retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLTablesPtr)(hstmt, (SQLCHAR*)"test", SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"TABLE", SQL_NTS );
812 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLTablesPtr)(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS );
813 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt,3,SQL_C_CHAR,tablename,sizeof(tablename),NULL);
814 while(SQL_SUCCEEDED(retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr)(hstmt)))
816 if(strcmp(tablename,name)==0){
817 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
818 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
819 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
820 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
821 return true;
825 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
826 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
827 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
828 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
829 return false;
831 void SqlOdbcStatement::setErrorState(SQLHSTMT hStmt)
833 SQLINTEGER i = 0;
834 SQLINTEGER native;
835 SQLCHAR state[ 7 ];
836 SQLCHAR text[256];
837 SQLSMALLINT len;
838 SQLRETURN ret;
839 ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLGetDiagRecPtr)(SQL_HANDLE_STMT, hStmt, ++i,
840 state, &native, text, sizeof(text), &len );
842 if (SQL_SUCCEEDED(ret)){
843 printf("%s:%ld:%ld:%s\n", state, i, native, text);
844 strcpy(errState,(char*)state);
848 DbRetVal SqlOdbcStatement::resolveForBindField(SQLHSTMT hstmt)
850 short totalFields=0;
851 int retValue = 0;
852 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLNumResultColsPtr) (hstmt, &totalFields);
853 if (retValue){ return ErrBadCall; }
854 BindSqlProjectField *bindProjField = NULL;
855 UWORD icol;
856 UCHAR colName[IDENTIFIER_LENGTH];
857 SWORD colNameMax;
858 SWORD nameLength;
859 SWORD colType;
860 SQLULEN colLength;
861 SWORD scale;
862 SWORD nullable;
863 icol = 1; colNameMax = IDENTIFIER_LENGTH;
864 if(totalFields != 0)
866 if(isProcedureCallStmt) isSelStmt = true;
867 len = (SQLINTEGER *)malloc((totalFields+1)*sizeof(SQLINTEGER));
868 for(int i=0;i<=totalFields;i++) { len[i] = SQL_NTS ;}
870 while (icol <= totalFields)
872 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDescribeColPtr)(hstmt, icol, colName, colNameMax,
873 &nameLength, &colType, &colLength,
874 &scale, &nullable);
875 if (retValue) return ErrBadCall;
876 bindProjField = new BindSqlProjectField();
877 strcpy(bindProjField->fName, (char*)colName);
878 bindProjField->type = AllDataType::convertFromSQLType(colType,colLength,scale,tdbname);
879 bindProjField->length = AllDataType::size(bindProjField->type, colLength+1);
880 bindProjField->value = NULL;
881 bindProjField->targetvalue = NULL;
882 int fieldsize =0;
883 if(tdbname==postgres && -5 == colType) {
884 bindProjField->targetvalue = AllDataType::alloc(typeString, 128);
885 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, icol,
886 AllDataType::convertToSQLType(typeString),
887 bindProjField->targetvalue, 128, &len[icol]);
888 }else{
889 switch(bindProjField->type)
891 case typeString:
892 case typeVarchar:
893 fieldsize = colLength+1;
894 bindProjField->targetvalue = malloc(fieldsize);
895 break;
896 case typeDate:
897 fieldsize = sizeof(DATE_STRUCT);
898 bindProjField->targetvalue = malloc(sizeof(DATE_STRUCT));
899 bindProjField->jdbcBindValue = AllDataType::alloc(typeDate);
900 break;
901 case typeTime:
902 fieldsize = sizeof(TIME_STRUCT);
903 bindProjField->targetvalue = malloc(sizeof(TIME_STRUCT));
904 bindProjField->jdbcBindValue = AllDataType::alloc(typeTime);
905 break;
906 case typeTimeStamp:
907 fieldsize = sizeof(TIMESTAMP_STRUCT);
908 bindProjField->targetvalue = malloc(sizeof(TIMESTAMP_STRUCT));
909 bindProjField->jdbcBindValue = AllDataType::alloc(typeTimeStamp);
910 break;
911 default:
912 bindProjField->targetvalue = AllDataType::alloc(bindProjField->type, bindProjField->length);
914 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, icol,
915 AllDataType::convertToSQL_C_Type(bindProjField->type,tdbname),
916 bindProjField->targetvalue, fieldsize, &len[icol]);
918 if (retValue) return ErrBadCall;
919 bindList.append(bindProjField);
920 icol++;
922 totalFld = totalFields;
923 return OK;
926 DbRetVal SqlOdbcStatement::resolveForResultSetBindField(SQLHSTMT hstmt)
928 short totalFields=0;
929 int retValue = 0;
930 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLNumResultColsPtr) (hstmt, &totalFields);
931 if (retValue){ return ErrBadCall; }
932 BindSqlProjectField *bindProjField = NULL;
933 UWORD icol;
934 UCHAR colName[IDENTIFIER_LENGTH];
935 SWORD colNameMax;
936 SWORD nameLength;
937 SWORD colType;
938 SQLULEN colLength;
939 SWORD scale;
940 SWORD nullable;
941 icol = 1; colNameMax = IDENTIFIER_LENGTH;
942 if(totalFields != 0)
944 if(isProcedureCallStmt) isSelStmt = true;
945 len = (SQLINTEGER *)malloc((totalFields+1)*sizeof(SQLINTEGER));
946 for(int i=0;i<=totalFields;i++) { len[i] = SQL_NTS ;}
948 while (icol <= totalFields)
950 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDescribeColPtr)(hstmt, icol, colName, colNameMax, &nameLength, &colType, &colLength, &scale, &nullable);
951 if (retValue) return ErrBadCall;
952 bindProjField = new BindSqlProjectField();
953 strcpy(bindProjField->fName, (char*)colName);
955 bindProjField->type = AllDataType::convertFromSQLType(colType,colLength,scale,tdbname);
956 bindProjField->length = AllDataType::size(bindProjField->type, colLength+1);
957 bindProjField->value = NULL;
958 bindProjField->targetvalue = NULL;
959 bindList.append(bindProjField);
960 icol++;
962 totalFld = totalFields;
963 return OK;
966 DbRetVal SqlOdbcStatement::prepareForResultSet(char *stmtstr)
968 DbRetVal rv = OK;
969 if (innerStmt) { rv = ErrBadCall; return rv; }
970 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
971 SQLRETURN ret;
972 isPrepared = false;
973 //retValue=SQLAllocHandle (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
974 ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
975 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
976 return ErrBadCall;
978 SQLCHAR* sstr= (SQLCHAR*)stmtstr;
979 ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLPreparePtr) (hstmt, sstr, SQL_NTS);
980 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
981 return ErrBadCall;
983 isSelStmt=checkStmtType(stmtstr);
984 isPrepared = true;
985 if(strstr(stmtstr,"call ")!=NULL || strstr(stmtstr,"CALL ")!=NULL)
987 isProcedureCallStmt=true;
988 logFinest(Conf::logger, "Procedure call statement =true");
990 short totalFields=0;
991 tdbname = conn->getTrDbName();
992 rv = resolveForResultSetBindField(hstmt);
993 if(rv!=OK) return rv;
994 UWORD icol;
995 SWORD colNameMax;
996 SWORD scale;
997 SWORD nullable;
998 BindSqlField *bindField;
999 //retValue = SQLNumParams (hstmt, &totalFields);
1000 ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLNumParamsPtr) (hstmt, &totalFields);
1001 if (ret) return ErrBadCall;
1002 icol = 1; colNameMax = IDENTIFIER_LENGTH;
1003 SWORD cType=0;
1004 SQLULEN cLength=0;
1005 scale=0;
1006 if(totalFields != 0)
1008 paramlen =(SQLINTEGER *) malloc((totalFields+1)*sizeof(SQLINTEGER));
1009 for(int i=0;i<=totalFields;i++) { paramlen[i] = SQL_NTS; }
1011 logFinest(Conf::logger, "NumParams %d", totalFields);
1012 while (icol <= totalFields)
1014 bindField = new BindSqlField();
1015 bindField->type = typeString;
1016 bindField->length = 512;
1017 bindField->value = AllDataType::alloc(bindField->type,
1018 bindField->length);
1019 bindField->targetvalue = AllDataType::alloc(bindField->type, cLength);
1020 int fieldsize = 0;
1021 ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindParameterPtr)(hstmt, icol, SQL_PARAM_INPUT, AllDataType::convertToSQL_C_Type(bindField->type,tdbname), AllDataType::convertToSQLType(bindField->type), fieldsize, scale, bindField->targetvalue, fieldsize, &paramlen[icol]);
1022 if (ret) return ErrBadCall;
1023 paramList.append(bindField);
1024 icol++;
1026 //TODO::deallocate memory and remove elements from list in case of any
1027 //failure in any of the above ODBC functions
1028 logFinest(Conf::logger, "Statement prepared %s", stmtstr);
1029 return OK;
1032 void SqlOdbcStatement::setResultSetInfo(int nrecs)
1034 rowStatus = (SQLUSMALLINT *) malloc(nrecs * sizeof(SQLUSMALLINT));
1035 memset(rowStatus, 0, nrecs * sizeof(SQLUSMALLINT) );
1036 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetStmtAttrPtr)(hstmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0);
1037 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetStmtAttrPtr)(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (void *) nrecs, 0);
1038 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetStmtAttrPtr)(hstmt, SQL_ATTR_ROW_STATUS_PTR, rowStatus, 0 );
1039 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetStmtAttrPtr)(hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &nRecords, 0 );
1042 DbRetVal SqlOdbcStatement::rsBindField(int pos, void *val)
1044 if (!isPrepared) return OK;
1045 BindSqlProjectField *bindField = (BindSqlProjectField*)bindList.get(pos);
1046 if (NULL == bindField)
1048 printError(ErrBadArg, "Could not get the projection list. Should be called only for SELECT statement");
1049 return ErrBadArg;
1051 //get the sqlctype from bind list and send it to dsn
1053 // Following is a work around done corresponding to AllDataType::convertToSQL_C_Type for typeLongLong type
1054 SQLSMALLINT type = AllDataType::convertToSQL_C_Type(bindField->type, tdbname);
1055 if (type == SQL_C_CHAR || type == SQL_C_BINARY) {
1056 // length was increased by one for null character during prepare.
1057 (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, pos, type, val, bindField->length-1, NULL);
1059 else {
1060 (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, pos, type, val, 0, NULL);
1064 DbRetVal SqlOdbcStatement::executeForResultSet()
1066 SQLRETURN ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLExecutePtr) (hstmt);
1067 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
1068 //setErrorState(hstmt);
1069 return ErrBadCall;
1071 return OK;
1074 DbRetVal SqlOdbcStatement::fetchScroll(void *nrows)
1076 DbRetVal rv = OK;
1077 SQLRETURN ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchScrollPtr)(hstmt, SQL_FETCH_NEXT, 0);
1078 if (ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO) {
1079 *(int *) nrows = 0;
1080 if (ret != SQL_NO_DATA) {
1081 //setErrorState(hstmt);
1082 return ErrBadCall;
1084 else return OK;
1086 *(int *) nrows = nRecords;
1087 return OK;