jdbc resultset and odbc parameter fixes for non cache table on Date, Time ,TimeStamp...
[csql.git] / src / adapter / SqlOdbcStatement.cxx
blob22bbef65e3f69e548ec5a050b547ba6fcf50ff9b
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=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 return rv;
39 DbRetVal SqlOdbcStatement::prepare(char *stmtstr)
41 DbRetVal rv = OK;
42 if (innerStmt) rv = ErrBadCall;
43 if (rv != OK) return rv;
44 int retValue =0;
45 isPrepared = false;
46 isProcedureCallStmt = false;
47 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
48 //retValue=SQLAllocHandle (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
49 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
50 if (retValue) return ErrBadCall;
51 SQLCHAR* sstr= (SQLCHAR*)stmtstr;
52 //retValue = SQLPrepare (hstmt, sstr, SQL_NTS);
53 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLPreparePtr) (hstmt, sstr, SQL_NTS);
54 if (retValue) {
55 // setErrorState(hstmt);
56 return ErrBadCall;
58 isSelStmt=chechStmtType(stmtstr);
59 isPrepared = true;
60 if(strstr(stmtstr,"call ")!=NULL || strstr(stmtstr,"CALL ")!=NULL)
62 isProcedureCallStmt=true;
64 short totalFields=0;
65 tdbname = conn->getTrDbName();
66 rv = resolveForBindField(hstmt);
67 if(rv!=OK) return rv;
68 UWORD icol;
69 SWORD colNameMax;
70 SWORD scale;
71 SWORD nullable;
72 BindSqlField *bindField;
73 //retValue = SQLNumParams (hstmt, &totalFields);
74 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLNumParamsPtr) (hstmt, &totalFields);
75 if (retValue) return ErrBadCall;
76 icol = 1; colNameMax = IDENTIFIER_LENGTH;
77 SWORD cType=0;
78 SQLULEN cLength=0;
79 scale=0;
80 if(totalFields != 0)
82 paramlen =(SQLINTEGER *) malloc((totalFields+1)*sizeof(SQLINTEGER));
83 for(int i=0;i<=totalFields;i++) { paramlen[i] = SQL_NTS; }
86 while (icol <= totalFields)
88 //retValue = SQLDescribeParam(hstmt, icol, &cType, &cLength,
89 //Note: MySQL Bug
90 //Bug #1382 SQLDescribeParam returns the same type information
92 bindField = new BindSqlField();
93 bindField->type = typeString;
94 bindField->length = 512;
95 bindField->value = AllDataType::alloc(bindField->type, bindField->length);
96 bindField->targetvalue = NULL;
97 int fieldsize =0;
98 switch(bindField->type)
100 case typeString:
101 fieldsize = bindField->length;
102 bindField->targetvalue = malloc(fieldsize);
103 break;
104 case typeDate:
105 fieldsize = sizeof(DATE_STRUCT);
106 bindField->targetvalue = malloc(sizeof(DATE_STRUCT));
107 break;
108 case typeTime:
109 fieldsize = sizeof(TIME_STRUCT);
110 bindField->targetvalue = malloc(sizeof(TIME_STRUCT));
111 break;
112 case typeTimeStamp:
113 fieldsize = sizeof(TIMESTAMP_STRUCT);
114 bindField->targetvalue = malloc(sizeof(TIMESTAMP_STRUCT));
115 break;
116 default:
117 bindField->targetvalue = AllDataType::alloc(bindField->type, cLength);
118 break;
121 //retValue = SQLBindParameter(hstmt, icol, SQL_PARAM_INPUT,
122 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindParameterPtr)(hstmt, icol, SQL_PARAM_INPUT,
123 AllDataType::convertToSQL_C_Type(bindField->type,tdbname),
124 AllDataType::convertToSQLType(bindField->type), fieldsize, scale, bindField->targetvalue,
125 fieldsize, &paramlen[icol]);
126 if (retValue) return ErrBadCall;
127 paramList.append(bindField);
128 icol++;
130 //TODO::deallocate memory and remove elements from list in case of any
131 //failure in any of the above ODBC functions
132 return OK;
135 bool SqlOdbcStatement::isSelect()
137 //TODO
138 return isSelStmt;
141 DbRetVal SqlOdbcStatement::execute(int &rowsAffected)
143 DbRetVal rv = OK;
144 if (!isPrepared) return ErrNotPrepared;
145 int retValue=0;
146 ListIterator iter = paramList.getIterator();
147 BindSqlField *bindField = NULL;
148 int col = 0;
149 while (iter.hasElement())
151 bindField = (BindSqlField*)iter.nextElement();
152 if(paramlen[++col] == SQL_NULL_DATA){
153 ::free(bindField->targetvalue);
154 bindField->targetvalue = NULL;
155 continue;
157 switch(bindField->type)
159 case typeDate: {
160 Date *dtCSQL = (Date*) bindField->value;
161 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
162 dtTarget->year= dtCSQL->year();
163 dtTarget->month= dtCSQL->month();
164 dtTarget->day = dtCSQL->dayOfMonth();
165 break;
167 case typeTime: {
168 Time *dtCSQL = (Time*) bindField->value;
169 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
170 dtTarget->hour = dtCSQL->hours();
171 dtTarget->minute = dtCSQL->minutes();
172 dtTarget->second = dtCSQL->seconds();
173 break;
175 case typeTimeStamp: {
176 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
177 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
178 dtTarget->year= dtCSQL->year();
179 dtTarget->month= dtCSQL->month();
180 dtTarget->day = dtCSQL->dayOfMonth();
181 dtTarget->hour = dtCSQL->hours();
182 dtTarget->minute = dtCSQL->minutes();
183 dtTarget->second = dtCSQL->seconds();
184 break;
186 default: {
187 AllDataType::cachecopyVal(bindField->targetvalue, bindField->value,
188 bindField->type, bindField->length);
189 break;
193 //int retValue = SQLExecute (hstmt);
194 if(isProcedureCallStmt)
196 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLExecutePtr) (hstmt);
197 if ((retValue != SQL_SUCCESS) && (retValue != SQL_SUCCESS_WITH_INFO )) {
198 return ErrBadCall;
200 rv = resolveForBindField(hstmt);
201 if(rv!=OK) return rv;
202 }else{
203 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLExecutePtr) (hstmt);
204 if ((retValue != SQL_SUCCESS) && (retValue != SQL_SUCCESS_WITH_INFO )) {
205 // setErrorState(hstmt);
206 return ErrBadCall;
209 //retValue=SQLRowCount(hstmt,(SQLINTEGER*)&rowsAffected);
210 retValue= (*SqlOdbcConnection::ODBCFuncPtrs.SQLRowCountPtr)(hstmt,(SQLINTEGER*)&rowsAffected);
211 if(isSelStmt) rowsAffected = 0;
212 return rv;
215 DbRetVal SqlOdbcStatement::bindParam(int pos, void* value)
217 DbRetVal rv = OK;
218 printError(ErrWarning, "Deprecated. Use setParamXXX instead\n");
219 return rv;
222 DbRetVal SqlOdbcStatement::bindField(int pos, void* value)
224 if (!isPrepared) return OK;
225 BindSqlProjectField *bindField = (BindSqlProjectField*)bindList.get(pos);
226 if (NULL == bindField)
228 printError(ErrBadArg, "Could not get the projection list. Should be called only for SELECT statement");
229 return ErrBadArg;
231 bindField->value = value;
232 return OK;
235 //void SqlOdbcStatement::setNullInfo(Table *table)
236 void SqlOdbcStatement::setNullInfo(AbsSqlStatement *stmt)
238 int fldpos=0;
239 while(fldpos < totalFld)
241 if(len[++fldpos] == SQL_NULL_DATA)
243 stmt->setNull(fldpos);
248 void* SqlOdbcStatement::fetch()
250 if (!isPrepared) return NULL;
251 //int retValue = SQLFetch (hstmt);
252 int retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr) (hstmt);
253 if (retValue) return NULL;
254 ListIterator iter = bindList.getIterator();
255 BindSqlProjectField *bindField = NULL;
256 void *ptrToFirstField = NULL;
257 int icol=0;
258 while (iter.hasElement())
260 bindField = (BindSqlProjectField*)iter.nextElement();
261 if (ptrToFirstField == NULL) ptrToFirstField=bindField->value;
262 if(len[++icol] == SQL_NULL_DATA)
264 if(bindField->value) AllDataType::memoryset(bindField->value,bindField->type);
265 continue;
267 if( isSelStmt && NULL == bindField->value )
269 if (ptrToFirstField == NULL) ptrToFirstField=bindField->targetvalue;
270 continue;
272 switch(bindField->type)
274 case typeDate: {
275 Date *dtCSQL = (Date*) bindField->value;
276 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
277 dtCSQL->set(dtTarget->year,dtTarget->month,dtTarget->day);
278 break;
280 case typeTime: {
281 Time *dtCSQL = (Time*) bindField->value;
282 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
283 dtCSQL->set(dtTarget->hour,dtTarget->minute,dtTarget->second);
284 break;
286 case typeTimeStamp: {
287 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
288 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
289 dtCSQL->setDate(dtTarget->year,dtTarget->month,dtTarget->day);
290 dtCSQL->setTime(dtTarget->hour,dtTarget->minute,
291 dtTarget->second, 0);//dtTarget->fraction);
292 break;
294 default: {
295 AllDataType::cachecopyVal(bindField->value, bindField->targetvalue,
296 bindField->type, bindField->length,tdbname);
297 break;
301 return ptrToFirstField;
304 void* SqlOdbcStatement::fetch(DbRetVal &rv)
306 if (!isPrepared) return NULL;
307 //int retValue = SQLFetch (hstmt);
308 int retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr) (hstmt);
309 if (retValue) { rv = OK; return NULL; }
310 ListIterator iter = bindList.getIterator();
311 BindSqlProjectField *bindField = NULL;
312 void *ptrToFirstField = NULL;
313 int icol=0;
314 while (iter.hasElement())
316 bindField = (BindSqlProjectField*)iter.nextElement();
317 if (ptrToFirstField == NULL) ptrToFirstField=bindField->value;
318 if(len[++icol] == SQL_NULL_DATA)
320 if(bindField->value) AllDataType::memoryset(bindField->value,bindField->type);
321 continue;
323 if( isSelStmt && NULL == bindField->value )
325 if (ptrToFirstField == NULL) ptrToFirstField=bindField->targetvalue;
326 continue;
328 switch(bindField->type)
330 case typeDate: {
331 Date *dtCSQL = (Date*) bindField->value;
332 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
333 dtCSQL->set(dtTarget->year,dtTarget->month,dtTarget->day);
334 break;
336 case typeTime: {
337 Time *dtCSQL = (Time*) bindField->value;
338 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
339 dtCSQL->set(dtTarget->hour,dtTarget->minute,dtTarget->second);
340 break;
342 case typeTimeStamp: {
343 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
344 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
345 dtCSQL->setDate(dtTarget->year,dtTarget->month,dtTarget->day);
346 dtCSQL->setTime(dtTarget->hour,dtTarget->minute,
347 dtTarget->second, 0);// dtTarget->fraction);
348 break;
350 default: {
351 AllDataType::cachecopyVal(bindField->value, bindField->targetvalue, bindField->type, bindField->length, tdbname);
352 break;
356 return ptrToFirstField;
359 void* SqlOdbcStatement::fetchAndPrint(bool SQL)
361 if (!isPrepared) return NULL;
362 //int retValue = SQLFetch (hstmt);
363 int retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr) (hstmt);
364 if (retValue) return NULL;
365 ListIterator iter = bindList.getIterator();
366 BindSqlProjectField *bindField = NULL;
367 void *ptrToFirstField = NULL;
368 int icol=1;
369 while (iter.hasElement())
372 bindField = (BindSqlProjectField*)iter.nextElement();
373 if (ptrToFirstField == NULL) ptrToFirstField=bindField->targetvalue;
374 if(len[icol++] == SQL_NULL_DATA)
376 printf("NULL");
377 continue;
379 switch(bindField->type)
381 case typeDate: {
382 Date dtCSQL;
383 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
384 dtCSQL.set(dtTarget->year,dtTarget->month,dtTarget->day);
385 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
386 break;
388 case typeTime: {
389 Time dtCSQL;
390 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
391 dtCSQL.set(dtTarget->hour,dtTarget->minute,dtTarget->second);
392 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
393 break;
395 case typeTimeStamp: {
396 TimeStamp dtCSQL;
397 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
398 dtCSQL.setDate(dtTarget->year,dtTarget->month,dtTarget->day);
399 dtCSQL.setTime(dtTarget->hour,dtTarget->minute,
400 dtTarget->second, 0);//dtTarget->fraction);
401 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
402 break;
404 default: {
405 AllDataType::printVal(bindField->targetvalue,
406 bindField->type, bindField->length,tdbname);
407 break;
410 printf("\t");
412 return ptrToFirstField;
415 void* SqlOdbcStatement::next()
417 return fetch();
420 DbRetVal SqlOdbcStatement::close()
422 if (!isPrepared) return OK;
423 (*SqlOdbcConnection::ODBCFuncPtrs.SQLCloseCursorPtr)(hstmt);
424 return OK;
426 bool SqlOdbcStatement::chechStmtType(char *buf)
428 char c;
429 while(1)
431 c=*buf;
432 if(c !=' ') break;
433 buf++;
435 if (strncasecmp (buf, "SELECT", 6) == 0) { return true;}
436 return false;
438 void* SqlOdbcStatement::getFieldValuePtr( int pos )
441 ListIterator biter = bindList.getIterator();
442 BindSqlProjectField *elem = NULL;
443 int count =0;
444 while (biter.hasElement())
446 elem = (BindSqlProjectField*) biter.nextElement();
447 if (count == pos)
449 if(elem->value == NULL)
451 switch(elem->type)
453 case typeDate: {
454 Date *dtCSQL=(Date *) elem->jdbcBindValue;
455 DATE_STRUCT *dtTarget = (DATE_STRUCT*) elem->targetvalue;
456 dtCSQL->set(dtTarget->year,dtTarget->month,dtTarget->day);
457 return dtCSQL;
459 case typeTime: {
460 Time *dtCSQL = (Time *) elem->jdbcBindValue;
461 TIME_STRUCT *dtTarget = (TIME_STRUCT*) elem->targetvalue;
462 dtCSQL->set(dtTarget->hour,dtTarget->minute,dtTarget->second);
463 return dtCSQL;
465 case typeTimeStamp: {
466 TimeStamp *dtCSQL= (TimeStamp *) elem->jdbcBindValue;
467 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) elem->targetvalue;
468 dtCSQL->setDate(dtTarget->year,dtTarget->month,dtTarget->day);
469 dtCSQL->setTime(dtTarget->hour,dtTarget->minute,dtTarget->second, 0);//dtTarget->fraction);
470 return dtCSQL;
474 return elem->targetvalue;
476 count++;
478 return NULL;
481 void SqlOdbcStatement::getProjFieldType(int *data)
483 ListIterator biter = bindList.getIterator();
484 BindSqlProjectField *elem = NULL;
485 int i = 1;
486 while (biter.hasElement())
488 elem = (BindSqlProjectField*) biter.nextElement();
489 if((tdbname == postgres) && typeLongLong == elem->type)
490 data[i++] = typeString;
491 else
492 data[i++] = elem->type;
496 void* SqlOdbcStatement::getFieldValuePtr( char *name )
498 ListIterator biter = bindList.getIterator();
499 BindSqlProjectField *elem = NULL;
500 int count =0;
501 while (biter.hasElement())
503 elem = (BindSqlProjectField*) biter.nextElement();
504 if ( strcpy(elem->fName,name) == 0 )
506 return elem->targetvalue;
509 return NULL;
512 int SqlOdbcStatement::noOfProjFields()
514 if (!isPrepared) return 0;
515 return bindList.size();
518 int SqlOdbcStatement::noOfParamFields()
520 if (!isPrepared) return 0;
521 return paramList.size();
524 DbRetVal SqlOdbcStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
526 ListIterator biter = bindList.getIterator();
527 BindSqlProjectField *elem = NULL;
528 int count =0;
529 while (biter.hasElement())
531 elem = (BindSqlProjectField*) biter.nextElement();
532 if (count == projpos-1)
534 strcpy(fInfo->fldName, elem->fName);
535 fInfo->length = elem->length;
536 fInfo->type =elem->type;
537 return OK;
539 count++;
541 return ErrNotFound;
544 DbRetVal SqlOdbcStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
546 ListIterator biter = paramList.getIterator();
547 BindSqlField *elem = NULL;
548 int count =0;
549 while (biter.hasElement())
551 elem = (BindSqlField*) biter.nextElement();
552 if (count == parampos-1)
554 fInfo->length = elem->length;
555 fInfo->type =elem->type;
556 return OK;
558 count++;
560 return ErrNotFound;
563 DbRetVal SqlOdbcStatement::free()
565 if(!isPrepared) return OK;
566 ListIterator biter = bindList.getIterator();
567 BindSqlProjectField *elem = NULL;
568 while (biter.hasElement())
570 elem = (BindSqlProjectField*) biter.nextElement();
571 if(elem->targetvalue)
572 ::free(elem->targetvalue);
573 if(elem->jdbcBindValue)
574 ::free(elem->jdbcBindValue);
575 delete elem;
577 bindList.reset();
578 ListIterator piter = paramList.getIterator();
579 BindSqlField *bindField = NULL;
580 while (piter.hasElement())
582 bindField = (BindSqlField*) piter.nextElement();
583 ::free(bindField->value);
584 ::free(bindField->targetvalue);
585 delete bindField;
587 paramList.reset();
588 if(len){ ::free(len); len = NULL;}
589 if(paramlen) {::free(paramlen); paramlen = NULL;}
590 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
591 isPrepared = false;
592 isProcedureCallStmt = false;
593 return OK;
595 void SqlOdbcStatement::setShortParam(int paramPos, short value)
597 if (!isPrepared) return ;
598 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
599 AllDataType::convertToString(bindField->value, &value, typeShort, 0,tdbname);
600 return;
602 void SqlOdbcStatement::setIntParam(int paramPos, int value)
604 if (!isPrepared) return ;
605 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
606 //Note: MySQL Bug
607 //Bug #1382 SQLDescribeParam returns the same type information, varchar
608 AllDataType::convertToString(bindField->value, &value, typeInt,0,tdbname);
609 return;
612 void SqlOdbcStatement::setLongParam(int paramPos, long value)
614 if (!isPrepared) return ;
615 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
616 //Note: MySQL Bug
617 //Bug #1382 SQLDescribeParam returns the same type information, varchar
618 AllDataType::convertToString(bindField->value, &value, typeLong,0,tdbname);
619 return;
622 void SqlOdbcStatement::setLongLongParam(int paramPos, long long value)
624 if (!isPrepared) return ;
625 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
626 AllDataType::convertToString(bindField->value, &value, typeLongLong,0,tdbname);
627 return;
629 void SqlOdbcStatement::setByteIntParam(int paramPos, ByteInt value)
631 if (!isPrepared) return ;
632 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
633 AllDataType::convertToString(bindField->value, &value, typeByteInt,0,tdbname);
634 return;
636 void SqlOdbcStatement::setFloatParam(int paramPos, float value)
638 if (!isPrepared) return ;
639 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
640 AllDataType::convertToString(bindField->value, &value, typeFloat,0, tdbname);
641 return;
643 void SqlOdbcStatement::setDoubleParam(int paramPos, double value)
645 if (!isPrepared) return ;
646 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
647 AllDataType::convertToString(bindField->value, &value, typeDouble,0,tdbname);
648 return;
650 void SqlOdbcStatement::setStringParam(int paramPos, char *value)
652 if (!isPrepared) return ;
653 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
654 if (bindField->type != typeString) return;
655 char *dest = (char*)bindField->value;
656 strncpy(dest, value, bindField->length);
657 dest[ bindField->length - 1] ='\0';
658 return;
660 void SqlOdbcStatement::setDateParam(int paramPos, Date value)
662 if (!isPrepared) return ;
663 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
664 AllDataType::convertToString(bindField->value, &value, typeDate,0,tdbname);
665 return;
667 void SqlOdbcStatement::setTimeParam(int paramPos, Time value)
669 if (!isPrepared) return ;
670 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
671 AllDataType::convertToString(bindField->value, &value, typeTime,0,tdbname);
672 return;
674 void SqlOdbcStatement::setTimeStampParam(int paramPos, TimeStamp value)
676 if (!isPrepared) return ;
677 BindSqlField *bindField = (BindSqlField*) paramList.get(paramPos);
678 AllDataType::convertToString(bindField->value, &value, typeTimeStamp,0, tdbname);
679 return;
681 void SqlOdbcStatement::setBinaryParam(int paramPos, void *value, int length)
683 if (!isPrepared) return;
684 BindSqlField *bindField = (BindSqlField*) paramList.get(paramPos);
685 AllDataType::convertToString(bindField->value, value, typeBinary, bindField->length,tdbname);
686 return;
689 void SqlOdbcStatement::getPrimaryKeyFieldName(char *tablename, char *pkfieldname)
691 if (pkfieldname == NULL) return;
692 SQLCHAR outstr[1024];
693 SQLSMALLINT outstrlen;
694 int retValue =0;
695 SQLHENV henv;
696 SQLHDBC hdbc;
697 SQLHSTMT hstmt;
698 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
699 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
700 if (retValue) {
701 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
703 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetEnvAttrPtr)(henv, SQL_ATTR_ODBC_VERSION,(void *) SQL_OV_ODBC3, 0);
704 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_DBC, henv, &hdbc);
705 if (retValue) {
706 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
708 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDriverConnectPtr)(hdbc, NULL, (SQLCHAR*)conn->dsn, SQL_NTS, outstr, sizeof(outstr), &outstrlen,SQL_DRIVER_NOPROMPT);
709 if (SQL_SUCCEEDED(retValue)) {
710 printDebug(DM_Gateway, "Connected to target database using dsn = %s\n", conn->dsn);
711 } else {
712 printError(ErrSysInit, "Failed to connect to target database\n");
714 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, hdbc, &hstmt);
715 if (retValue) {
716 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
718 char columnname[IDENTIFIER_LENGTH];
719 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLPrimaryKeysPtr)(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, (SQLCHAR*) tablename, SQL_NTS);
720 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, 4, SQL_C_CHAR,columnname, 129,NULL);
721 bool isPkExists=false;
722 if((*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr)( hstmt ) == SQL_SUCCESS)
724 Util::str_tolower(columnname);
725 strcpy(pkfieldname, columnname);
726 isPkExists = true;
728 tdbname = conn->getTrDbName();
729 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
730 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
731 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
732 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
733 return;
736 bool SqlOdbcStatement::isFldNull(int pos)
738 if( len[pos] == SQL_NULL_DATA )
739 return true;
740 else
741 return false;
743 bool SqlOdbcStatement::isFldNull(char *name)
745 ListIterator iter = bindList.getIterator();
746 BindSqlProjectField *bindField = NULL;
747 int pos=1;
748 while (iter.hasElement())
750 bindField = (BindSqlProjectField*)iter.nextElement();
751 if(strcmp(name,bindField->fName)==0)
753 break;
755 pos++;
757 if( len[pos] == SQL_NULL_DATA )
758 return true;
759 else
760 return false;
763 void SqlOdbcStatement::setNull(int pos)
765 paramlen[pos] = SQL_NULL_DATA ;
768 bool SqlOdbcStatement::isTableExists( char *name)
771 SQLCHAR outstr[1024];
772 SQLSMALLINT outstrlen;
773 int retValue =0;
774 SQLHENV henv;
775 SQLHDBC hdbc;
776 SQLHSTMT hstmt;
777 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
778 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
779 if (retValue) {
780 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
783 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetEnvAttrPtr)(henv, SQL_ATTR_ODBC_VERSION,(void *) SQL_OV_ODBC3, 0);
784 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_DBC, henv, &hdbc);
785 if (retValue) {
786 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
788 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDriverConnectPtr)(hdbc, NULL, (SQLCHAR*)conn->dsn, SQL_NTS, outstr, sizeof(outstr), &outstrlen,SQL_DRIVER_NOPROMPT);
789 if (SQL_SUCCEEDED(retValue)) {
790 printDebug(DM_Gateway, "Connected to target database using dsn = %s\n", conn->dsn);
791 } else {
792 printError(ErrSysInit, "Failed to connect to target database\n");
795 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, hdbc, &hstmt);
796 if (retValue) {
797 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
799 char tablename[IDENTIFIER_LENGTH];
800 //retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLTablesPtr)(hstmt, (SQLCHAR*)"test", SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"TABLE", SQL_NTS );
801 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLTablesPtr)(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS );
802 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt,3,SQL_C_CHAR,tablename,sizeof(tablename),NULL);
803 while(SQL_SUCCEEDED(retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr)(hstmt)))
805 if(strcmp(tablename,name)==0){
806 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
807 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
808 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
809 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
810 return true;
814 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
815 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
816 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
817 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
818 return false;
820 void SqlOdbcStatement::setErrorState(SQLHSTMT hStmt)
822 SQLINTEGER i = 0;
823 SQLINTEGER native;
824 SQLCHAR state[ 7 ];
825 SQLCHAR text[256];
826 SQLSMALLINT len;
827 SQLRETURN ret;
828 ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLGetDiagRecPtr)(SQL_HANDLE_STMT, hStmt, ++i,
829 state, &native, text, sizeof(text), &len );
831 if (SQL_SUCCEEDED(ret)){
832 printf("%s:%ld:%ld:%s\n", state, i, native, text);
833 strcpy(errState,(char*)state);
837 DbRetVal SqlOdbcStatement::resolveForBindField(SQLHSTMT hstmt)
839 short totalFields=0;
840 int retValue = 0;
841 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLNumResultColsPtr) (hstmt, &totalFields);
842 if (retValue){ return ErrBadCall; }
843 BindSqlProjectField *bindProjField = NULL;
844 UWORD icol;
845 UCHAR colName[IDENTIFIER_LENGTH];
846 SWORD colNameMax;
847 SWORD nameLength;
848 SWORD colType;
849 SQLULEN colLength;
850 SWORD scale;
851 SWORD nullable;
852 icol = 1; colNameMax = IDENTIFIER_LENGTH;
853 if(totalFields != 0)
855 if(isProcedureCallStmt) isSelStmt = true;
856 len = (SQLINTEGER *)malloc((totalFields+1)*sizeof(SQLINTEGER));
857 for(int i=0;i<=totalFields;i++) { len[i] = SQL_NTS ;}
859 while (icol <= totalFields)
861 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDescribeColPtr)(hstmt, icol, colName, colNameMax,
862 &nameLength, &colType, &colLength,
863 &scale, &nullable);
864 if (retValue) return ErrBadCall;
865 bindProjField = new BindSqlProjectField();
866 strcpy(bindProjField->fName, (char*)colName);
867 bindProjField->type = AllDataType::convertFromSQLType(colType,colLength,scale,tdbname);
868 bindProjField->length = AllDataType::size(bindProjField->type, colLength+1);
869 bindProjField->value = NULL;
870 bindProjField->targetvalue = NULL;
871 int fieldsize =0;
872 if(tdbname==postgres && -5 == colType) {
873 bindProjField->targetvalue = AllDataType::alloc(typeString, 128);
874 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, icol,
875 AllDataType::convertToSQLType(typeString),
876 bindProjField->targetvalue, 128, &len[icol]);
877 }else{
878 switch(bindProjField->type)
880 case typeString:
881 fieldsize = colLength+1;
882 bindProjField->targetvalue = malloc(fieldsize);
883 break;
884 case typeDate:
885 fieldsize = sizeof(DATE_STRUCT);
886 bindProjField->targetvalue = malloc(sizeof(DATE_STRUCT));
887 bindProjField->jdbcBindValue = AllDataType::alloc(typeDate);
888 break;
889 case typeTime:
890 fieldsize = sizeof(TIME_STRUCT);
891 bindProjField->targetvalue = malloc(sizeof(TIME_STRUCT));
892 bindProjField->jdbcBindValue = AllDataType::alloc(typeTime);
893 break;
894 case typeTimeStamp:
895 fieldsize = sizeof(TIMESTAMP_STRUCT);
896 bindProjField->targetvalue = malloc(sizeof(TIMESTAMP_STRUCT));
897 bindProjField->jdbcBindValue = AllDataType::alloc(typeTimeStamp);
898 break;
899 default:
900 bindProjField->targetvalue = AllDataType::alloc(bindProjField->type, bindProjField->length);
902 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, icol,
903 AllDataType::convertToSQL_C_Type(bindProjField->type,tdbname),
904 bindProjField->targetvalue, fieldsize, &len[icol]);
906 if (retValue) return ErrBadCall;
907 bindList.append(bindProjField);
908 icol++;
910 totalFld = totalFields;
911 return OK;