1 /***************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.com *
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. *
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. *
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
)
30 SqlOdbcConnection
*conn
= (SqlOdbcConnection
*)con
;
31 retValue
=SQLAllocHandle (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
);
40 DbRetVal
SqlOdbcStatement::prepare(char *stmtstr
)
43 if (innerStmt
) rv
= ErrBadCall
;
44 if (rv
!= OK
) return rv
;
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
);
56 //setErrorState(hstmt);
57 printError(ErrSysInternal
, "Unable to prepare statement");
58 return ErrSysInternal
;
60 isSelStmt
=checkStmtType(stmtstr
);
62 if(strstr(stmtstr
,"call ")!=NULL
|| strstr(stmtstr
,"CALL ")!=NULL
)
64 logFinest(Conf::logger
, "Procedure call statement =true");
65 isProcedureCallStmt
=true;
68 tdbname
= conn
->getTrDbName();
69 rv
= resolveForBindField(hstmt
);
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
;
83 logFinest(Conf::logger
, "NumParams %d", totalFields
);
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,
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
;
102 switch(bindField
->type
)
105 fieldsize
= bindField
->length
;
106 bindField
->targetvalue
= malloc(fieldsize
);
109 fieldsize
= sizeof(DATE_STRUCT
);
110 bindField
->targetvalue
= malloc(sizeof(DATE_STRUCT
));
113 fieldsize
= sizeof(TIME_STRUCT
);
114 bindField
->targetvalue
= malloc(sizeof(TIME_STRUCT
));
117 fieldsize
= sizeof(TIMESTAMP_STRUCT
);
118 bindField
->targetvalue
= malloc(sizeof(TIMESTAMP_STRUCT
));
121 bindField
->targetvalue
= AllDataType::alloc(bindField
->type
, cLength
);
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
, ¶mlen
[icol
]);
130 if (retValue
) return ErrBadCall
;
131 paramList
.append(bindField
);
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
);
140 bool SqlOdbcStatement::isSelect()
146 DbRetVal
SqlOdbcStatement::execute(int &rowsAffected
)
149 if (!isPrepared
) return ErrNotPrepared
;
151 ListIterator iter
= paramList
.getIterator();
152 BindSqlField
*bindField
= NULL
;
154 while (iter
.hasElement())
156 bindField
= (BindSqlField
*)iter
.nextElement();
157 if(paramlen
[++col
] == SQL_NULL_DATA
){
158 ::free(bindField
->targetvalue
);
159 bindField
->targetvalue
= NULL
;
162 switch(bindField
->type
)
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();
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();
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();
192 AllDataType::cachecopyVal(bindField
->targetvalue
, bindField
->value
,
193 bindField
->type
, bindField
->length
);
198 //int retValue = SQLExecute (hstmt);
199 if(isProcedureCallStmt
)
201 retValue
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLExecutePtr
) (hstmt
);
202 if ((retValue
!= SQL_SUCCESS
) && (retValue
!= SQL_SUCCESS_WITH_INFO
)) {
205 rv
= resolveForBindField(hstmt
);
206 if(rv
!=OK
) return rv
;
207 logFinest(Conf::logger
, "Procedure executed");
209 retValue
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLExecutePtr
) (hstmt
);
210 if ((retValue
!= SQL_SUCCESS
) && (retValue
!= SQL_SUCCESS_WITH_INFO
)) {
211 // setErrorState(hstmt);
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;
222 DbRetVal
SqlOdbcStatement::bindParam(int pos
, void* value
)
225 printError(ErrWarning
, "Deprecated. Use setParamXXX instead\n");
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");
238 bindField
->value
= value
;
242 //void SqlOdbcStatement::setNullInfo(Table *table)
243 void SqlOdbcStatement::setNullInfo(AbsSqlStatement
*stmt
)
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
;
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
);
274 if( isSelStmt
&& NULL
== bindField
->value
)
276 if (ptrToFirstField
== NULL
) ptrToFirstField
=bindField
->targetvalue
;
279 switch(bindField
->type
)
282 Date
*dtCSQL
= (Date
*) bindField
->value
;
283 DATE_STRUCT
*dtTarget
= (DATE_STRUCT
*) bindField
->targetvalue
;
284 dtCSQL
->set(dtTarget
->year
,dtTarget
->month
,dtTarget
->day
);
288 Time
*dtCSQL
= (Time
*) bindField
->value
;
289 TIME_STRUCT
*dtTarget
= (TIME_STRUCT
*) bindField
->targetvalue
;
290 dtCSQL
->set(dtTarget
->hour
,dtTarget
->minute
,dtTarget
->second
);
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);
302 AllDataType::cachecopyVal(bindField
->value
, bindField
->targetvalue
,
303 bindField
->type
, bindField
->length
,tdbname
);
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
;
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
;
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
);
336 if( isSelStmt
&& NULL
== bindField
->value
)
338 if (ptrToFirstField
== NULL
) ptrToFirstField
=bindField
->targetvalue
;
341 switch(bindField
->type
)
344 Date
*dtCSQL
= (Date
*) bindField
->value
;
345 DATE_STRUCT
*dtTarget
= (DATE_STRUCT
*) bindField
->targetvalue
;
346 dtCSQL
->set(dtTarget
->year
,dtTarget
->month
,dtTarget
->day
);
350 Time
*dtCSQL
= (Time
*) bindField
->value
;
351 TIME_STRUCT
*dtTarget
= (TIME_STRUCT
*) bindField
->targetvalue
;
352 dtCSQL
->set(dtTarget
->hour
,dtTarget
->minute
,dtTarget
->second
);
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);
364 AllDataType::cachecopyVal(bindField
->value
, bindField
->targetvalue
, bindField
->type
, bindField
->length
, tdbname
);
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
;
382 while (iter
.hasElement())
385 bindField
= (BindSqlProjectField
*)iter
.nextElement();
386 if (ptrToFirstField
== NULL
) ptrToFirstField
=bindField
->targetvalue
;
387 if(len
[icol
++] == SQL_NULL_DATA
)
392 switch(bindField
->type
)
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
);
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
);
408 case typeTimeStamp
: {
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
);
418 AllDataType::printVal(bindField
->targetvalue
,
419 bindField
->type
, bindField
->length
,tdbname
);
425 return ptrToFirstField
;
428 void* SqlOdbcStatement::next()
433 DbRetVal
SqlOdbcStatement::close()
435 if (!isPrepared
) return OK
;
436 (*SqlOdbcConnection::ODBCFuncPtrs
.SQLCloseCursorPtr
)(hstmt
);
437 logFinest(Conf::logger
, "CloseCursor");
440 bool SqlOdbcStatement::checkStmtType(char *buf
)
443 while(1) { c
=*buf
; if(c
!=' ') break; buf
++; }
444 if (strncasecmp (buf
, "SELECT", 6) == 0) { return true; }
447 void* SqlOdbcStatement::getFieldValuePtr( int pos
)
450 ListIterator biter
= bindList
.getIterator();
451 BindSqlProjectField
*elem
= NULL
;
453 while (biter
.hasElement())
455 elem
= (BindSqlProjectField
*) biter
.nextElement();
458 if(elem
->value
== NULL
)
463 Date
*dtCSQL
=(Date
*) elem
->jdbcBindValue
;
464 DATE_STRUCT
*dtTarget
= (DATE_STRUCT
*) elem
->targetvalue
;
465 dtCSQL
->set(dtTarget
->year
,dtTarget
->month
,dtTarget
->day
);
469 Time
*dtCSQL
= (Time
*) elem
->jdbcBindValue
;
470 TIME_STRUCT
*dtTarget
= (TIME_STRUCT
*) elem
->targetvalue
;
471 dtCSQL
->set(dtTarget
->hour
,dtTarget
->minute
,dtTarget
->second
);
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);
483 return elem
->targetvalue
;
490 void SqlOdbcStatement::getProjFieldType(int *data
)
492 ListIterator biter
= bindList
.getIterator();
493 BindSqlProjectField
*elem
= NULL
;
495 while (biter
.hasElement())
497 elem
= (BindSqlProjectField
*) biter
.nextElement();
498 if((tdbname
== postgres
) && typeLongLong
== elem
->type
)
499 data
[i
++] = typeString
;
501 data
[i
++] = elem
->type
;
505 void* SqlOdbcStatement::getFieldValuePtr( char *name
)
507 ListIterator biter
= bindList
.getIterator();
508 BindSqlProjectField
*elem
= NULL
;
510 while (biter
.hasElement())
512 elem
= (BindSqlProjectField
*) biter
.nextElement();
513 if ( strcpy(elem
->fName
,name
) == 0 )
515 return elem
->targetvalue
;
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
;
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
;
553 DbRetVal
SqlOdbcStatement::getParamFldInfo (int parampos
, FieldInfo
*&fInfo
)
555 ListIterator biter
= paramList
.getIterator();
556 BindSqlField
*elem
= NULL
;
558 while (biter
.hasElement())
560 elem
= (BindSqlField
*) biter
.nextElement();
561 if (count
== parampos
-1)
563 fInfo
->length
= elem
->length
;
564 fInfo
->type
=elem
->type
;
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
);
586 if (rowStatus
) { ::free(rowStatus
); rowStatus
= NULL
; }
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
);
598 if(len
){ ::free(len
); len
= NULL
;}
599 if(paramlen
) {::free(paramlen
); paramlen
= NULL
;}
600 (*SqlOdbcConnection::ODBCFuncPtrs
.SQLFreeHandlePtr
)(SQL_HANDLE_STMT
, hstmt
);
602 isProcedureCallStmt
= false;
603 logFinest(Conf::logger
, "Statement Freed");
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
);
613 void SqlOdbcStatement::setIntParam(int paramPos
, int value
)
615 if (!isPrepared
) return ;
616 BindSqlField
*bindField
= (BindSqlField
*)paramList
.get(paramPos
);
618 //Bug #1382 SQLDescribeParam returns the same type information, varchar
619 AllDataType::convertToString(bindField
->value
, &value
, typeInt
,0,tdbname
);
623 void SqlOdbcStatement::setLongParam(int paramPos
, long value
)
625 if (!isPrepared
) return ;
626 BindSqlField
*bindField
= (BindSqlField
*)paramList
.get(paramPos
);
628 //Bug #1382 SQLDescribeParam returns the same type information, varchar
629 AllDataType::convertToString(bindField
->value
, &value
, typeLong
,0,tdbname
);
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
);
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
);
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
);
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
);
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';
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
);
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
);
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
);
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
);
700 void SqlOdbcStatement::getPrimaryKeyFieldName(char *tablename
, char *pkfieldname
)
702 if (pkfieldname
== NULL
) return;
703 SQLCHAR outstr
[1024];
704 SQLSMALLINT outstrlen
;
709 SqlOdbcConnection
*conn
= (SqlOdbcConnection
*)con
;
710 retValue
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLAllocHandlePtr
) (SQL_HANDLE_ENV
, SQL_NULL_HANDLE
, &henv
);
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
);
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
);
723 printError(ErrSysInit
, "Failed to connect to target database\n");
725 retValue
=(*SqlOdbcConnection::ODBCFuncPtrs
.SQLAllocHandlePtr
) (SQL_HANDLE_STMT
, hdbc
, &hstmt
);
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
);
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
);
747 bool SqlOdbcStatement::isFldNull(int pos
)
749 if( len
[pos
] == SQL_NULL_DATA
)
754 bool SqlOdbcStatement::isFldNull(char *name
)
756 ListIterator iter
= bindList
.getIterator();
757 BindSqlProjectField
*bindField
= NULL
;
759 while (iter
.hasElement())
761 bindField
= (BindSqlProjectField
*)iter
.nextElement();
762 if(strcmp(name
,bindField
->fName
)==0)
768 if( len
[pos
] == SQL_NULL_DATA
)
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
;
788 SqlOdbcConnection
*conn
= (SqlOdbcConnection
*)con
;
789 retValue
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLAllocHandlePtr
) (SQL_HANDLE_ENV
, SQL_NULL_HANDLE
, &henv
);
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
);
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
);
803 printError(ErrSysInit
, "Failed to connect to target database\n");
806 retValue
=(*SqlOdbcConnection::ODBCFuncPtrs
.SQLAllocHandlePtr
) (SQL_HANDLE_STMT
, hdbc
, &hstmt
);
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
);
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
);
831 void SqlOdbcStatement::setErrorState(SQLHSTMT hStmt
)
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
)
852 retValue
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLNumResultColsPtr
) (hstmt
, &totalFields
);
853 if (retValue
){ return ErrBadCall
; }
854 BindSqlProjectField
*bindProjField
= NULL
;
856 UCHAR colName
[IDENTIFIER_LENGTH
];
863 icol
= 1; colNameMax
= IDENTIFIER_LENGTH
;
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
,
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
;
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
]);
889 switch(bindProjField
->type
)
893 fieldsize
= colLength
+1;
894 bindProjField
->targetvalue
= malloc(fieldsize
);
897 fieldsize
= sizeof(DATE_STRUCT
);
898 bindProjField
->targetvalue
= malloc(sizeof(DATE_STRUCT
));
899 bindProjField
->jdbcBindValue
= AllDataType::alloc(typeDate
);
902 fieldsize
= sizeof(TIME_STRUCT
);
903 bindProjField
->targetvalue
= malloc(sizeof(TIME_STRUCT
));
904 bindProjField
->jdbcBindValue
= AllDataType::alloc(typeTime
);
907 fieldsize
= sizeof(TIMESTAMP_STRUCT
);
908 bindProjField
->targetvalue
= malloc(sizeof(TIMESTAMP_STRUCT
));
909 bindProjField
->jdbcBindValue
= AllDataType::alloc(typeTimeStamp
);
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
);
922 totalFld
= totalFields
;
926 DbRetVal
SqlOdbcStatement::resolveForResultSetBindField(SQLHSTMT hstmt
)
930 retValue
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLNumResultColsPtr
) (hstmt
, &totalFields
);
931 if (retValue
){ return ErrBadCall
; }
932 BindSqlProjectField
*bindProjField
= NULL
;
934 UCHAR colName
[IDENTIFIER_LENGTH
];
941 icol
= 1; colNameMax
= IDENTIFIER_LENGTH
;
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
);
962 totalFld
= totalFields
;
966 DbRetVal
SqlOdbcStatement::prepareForResultSet(char *stmtstr
)
969 if (innerStmt
) { rv
= ErrBadCall
; return rv
; }
970 SqlOdbcConnection
*conn
= (SqlOdbcConnection
*)con
;
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
) {
978 SQLCHAR
* sstr
= (SQLCHAR
*)stmtstr
;
979 ret
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLPreparePtr
) (hstmt
, sstr
, SQL_NTS
);
980 if (ret
!= SQL_SUCCESS
&& ret
!= SQL_SUCCESS_WITH_INFO
) {
983 isSelStmt
=checkStmtType(stmtstr
);
985 if(strstr(stmtstr
,"call ")!=NULL
|| strstr(stmtstr
,"CALL ")!=NULL
)
987 isProcedureCallStmt
=true;
988 logFinest(Conf::logger
, "Procedure call statement =true");
991 tdbname
= conn
->getTrDbName();
992 rv
= resolveForResultSetBindField(hstmt
);
993 if(rv
!=OK
) return rv
;
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
;
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
,
1019 bindField
->targetvalue
= AllDataType::alloc(bindField
->type
, cLength
);
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
, ¶mlen
[icol
]);
1022 if (ret
) return ErrBadCall
;
1023 paramList
.append(bindField
);
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
);
1032 void SqlOdbcStatement::setResultSetInfo(int nrecs
)
1034 rowStatus
= (SQLUSMALLINT
*) malloc(nrecs
* sizeof(SQLUSMALLINT
));
1035 memset(rowStatus
, 0, nrecs
* sizeof(SQLUSMALLINT
) );
1036 SQLSetStmtAttr(hstmt
, SQL_ATTR_ROW_BIND_TYPE
, SQL_BIND_BY_COLUMN
, 0);
1037 SQLSetStmtAttr(hstmt
, SQL_ATTR_ROW_ARRAY_SIZE
, (void *) nrecs
, 0);
1038 SQLSetStmtAttr(hstmt
, SQL_ATTR_ROW_STATUS_PTR
, rowStatus
, 0 );
1039 SQLSetStmtAttr(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");
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 SQLBindCol(hstmt
, pos
, type
, val
, bindField
->length
-1, NULL
);
1060 SQLBindCol(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);
1074 DbRetVal
SqlOdbcStatement::fetchScroll(void *nrows
)
1077 SQLRETURN ret
= (*SqlOdbcConnection::ODBCFuncPtrs
.SQLFetchScrollPtr
)(hstmt
, SQL_FETCH_NEXT
, 0);
1078 if (ret
!= SQL_SUCCESS
&& ret
!= SQL_SUCCESS_WITH_INFO
) {
1080 if (ret
!= SQL_NO_DATA
) {
1081 //setErrorState(hstmt);
1086 *(int *) nrows
= nRecords
;