adding more debug messages to odbc
[csql.git] / src / adapter / SqlOdbcStatement.cxx
blob70b11b6985b55b01a8079542e637c093b879f8dc
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 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 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 return elem->targetvalue;
451 count++;
453 return NULL;
456 void SqlOdbcStatement::getProjFieldType(int *data)
458 ListIterator biter = bindList.getIterator();
459 BindSqlProjectField *elem = NULL;
460 int i = 1;
461 while (biter.hasElement())
463 elem = (BindSqlProjectField*) biter.nextElement();
464 if((tdbname == postgres) && typeLongLong == elem->type)
465 data[i++] = typeString;
466 else
467 data[i++] = elem->type;
471 void* SqlOdbcStatement::getFieldValuePtr( char *name )
473 ListIterator biter = bindList.getIterator();
474 BindSqlProjectField *elem = NULL;
475 int count =0;
476 while (biter.hasElement())
478 elem = (BindSqlProjectField*) biter.nextElement();
479 if ( strcpy(elem->fName,name) == 0 )
481 return elem->targetvalue;
484 return NULL;
487 int SqlOdbcStatement::noOfProjFields()
489 if (!isPrepared) return 0;
490 return bindList.size();
493 int SqlOdbcStatement::noOfParamFields()
495 if (!isPrepared) return 0;
496 return paramList.size();
499 DbRetVal SqlOdbcStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
501 ListIterator biter = bindList.getIterator();
502 BindSqlProjectField *elem = NULL;
503 int count =0;
504 while (biter.hasElement())
506 elem = (BindSqlProjectField*) biter.nextElement();
507 if (count == projpos-1)
509 strcpy(fInfo->fldName, elem->fName);
510 fInfo->length = elem->length;
511 fInfo->type =elem->type;
512 return OK;
514 count++;
516 return ErrNotFound;
519 DbRetVal SqlOdbcStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
521 ListIterator biter = paramList.getIterator();
522 BindSqlField *elem = NULL;
523 int count =0;
524 while (biter.hasElement())
526 elem = (BindSqlField*) biter.nextElement();
527 if (count == parampos-1)
529 fInfo->length = elem->length;
530 fInfo->type =elem->type;
531 return OK;
533 count++;
535 return ErrNotFound;
538 DbRetVal SqlOdbcStatement::free()
540 if(!isPrepared) return OK;
541 ListIterator biter = bindList.getIterator();
542 BindSqlProjectField *elem = NULL;
543 while (biter.hasElement())
545 elem = (BindSqlProjectField*) biter.nextElement();
546 if(elem->targetvalue)
547 ::free(elem->targetvalue);
548 delete elem;
550 bindList.reset();
551 ListIterator piter = paramList.getIterator();
552 BindSqlField *bindField = NULL;
553 while (piter.hasElement())
555 bindField = (BindSqlField*) piter.nextElement();
556 ::free(bindField->value);
557 ::free(bindField->targetvalue);
558 delete bindField;
560 paramList.reset();
561 if(len){ ::free(len); len = NULL;}
562 if(paramlen) {::free(paramlen); paramlen = NULL;}
563 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
564 isPrepared = false;
565 isProcedureCallStmt = false;
566 return OK;
568 void SqlOdbcStatement::setShortParam(int paramPos, short value)
570 if (!isPrepared) return ;
571 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
572 AllDataType::convertToString(bindField->value, &value, typeShort, 0,tdbname);
573 return;
575 void SqlOdbcStatement::setIntParam(int paramPos, int value)
577 if (!isPrepared) return ;
578 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
579 //Note: MySQL Bug
580 //Bug #1382 SQLDescribeParam returns the same type information, varchar
581 AllDataType::convertToString(bindField->value, &value, typeInt,0,tdbname);
582 return;
585 void SqlOdbcStatement::setLongParam(int paramPos, long value)
587 if (!isPrepared) return ;
588 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
589 //Note: MySQL Bug
590 //Bug #1382 SQLDescribeParam returns the same type information, varchar
591 AllDataType::convertToString(bindField->value, &value, typeLong,0,tdbname);
592 return;
595 void SqlOdbcStatement::setLongLongParam(int paramPos, long long value)
597 if (!isPrepared) return ;
598 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
599 AllDataType::convertToString(bindField->value, &value, typeLongLong,0,tdbname);
600 return;
602 void SqlOdbcStatement::setByteIntParam(int paramPos, ByteInt value)
604 if (!isPrepared) return ;
605 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
606 AllDataType::convertToString(bindField->value, &value, typeByteInt,0,tdbname);
607 return;
609 void SqlOdbcStatement::setFloatParam(int paramPos, float value)
611 if (!isPrepared) return ;
612 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
613 AllDataType::convertToString(bindField->value, &value, typeFloat,0, tdbname);
614 return;
616 void SqlOdbcStatement::setDoubleParam(int paramPos, double value)
618 if (!isPrepared) return ;
619 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
620 AllDataType::convertToString(bindField->value, &value, typeDouble,0,tdbname);
621 return;
623 void SqlOdbcStatement::setStringParam(int paramPos, char *value)
625 if (!isPrepared) return ;
626 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
627 if (bindField->type != typeString) return;
628 char *dest = (char*)bindField->value;
629 strncpy(dest, value, bindField->length);
630 dest[ bindField->length - 1] ='\0';
631 return;
633 void SqlOdbcStatement::setDateParam(int paramPos, Date value)
635 if (!isPrepared) return ;
636 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
637 AllDataType::convertToString(bindField->value, &value, typeDate,0,tdbname);
638 return;
640 void SqlOdbcStatement::setTimeParam(int paramPos, Time value)
642 if (!isPrepared) return ;
643 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
644 AllDataType::convertToString(bindField->value, &value, typeTime,0,tdbname);
645 return;
647 void SqlOdbcStatement::setTimeStampParam(int paramPos, TimeStamp value)
649 if (!isPrepared) return ;
650 BindSqlField *bindField = (BindSqlField*) paramList.get(paramPos);
651 AllDataType::convertToString(bindField->value, &value, typeTimeStamp,0, tdbname);
652 return;
654 void SqlOdbcStatement::setBinaryParam(int paramPos, void *value, int length)
656 if (!isPrepared) return;
657 BindSqlField *bindField = (BindSqlField*) paramList.get(paramPos);
658 AllDataType::convertToString(bindField->value, value, typeBinary, bindField->length,tdbname);
659 return;
662 void SqlOdbcStatement::getPrimaryKeyFieldName(char *tablename, char *pkfieldname)
664 if (pkfieldname == NULL) return;
665 SQLCHAR outstr[1024];
666 SQLSMALLINT outstrlen;
667 int retValue =0;
668 SQLHENV henv;
669 SQLHDBC hdbc;
670 SQLHSTMT hstmt;
671 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
672 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
673 if (retValue) {
674 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
676 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetEnvAttrPtr)(henv, SQL_ATTR_ODBC_VERSION,(void *) SQL_OV_ODBC3, 0);
677 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_DBC, henv, &hdbc);
678 if (retValue) {
679 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
681 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDriverConnectPtr)(hdbc, NULL, (SQLCHAR*)conn->dsn, SQL_NTS, outstr, sizeof(outstr), &outstrlen,SQL_DRIVER_NOPROMPT);
682 if (SQL_SUCCEEDED(retValue)) {
683 printDebug(DM_Gateway, "Connected to target database using dsn = %s\n", conn->dsn);
684 } else {
685 printError(ErrSysInit, "Failed to connect to target database\n");
687 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, hdbc, &hstmt);
688 if (retValue) {
689 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
691 char columnname[IDENTIFIER_LENGTH];
692 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLPrimaryKeysPtr)(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, (SQLCHAR*) tablename, SQL_NTS);
693 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, 4, SQL_C_CHAR,columnname, 129,NULL);
694 bool isPkExists=false;
695 if((*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr)( hstmt ) == SQL_SUCCESS)
697 Util::str_tolower(columnname);
698 strcpy(pkfieldname, columnname);
699 isPkExists = true;
701 tdbname = conn->getTrDbName();
702 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
703 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
704 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
705 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
706 return;
709 bool SqlOdbcStatement::isFldNull(int pos)
711 if( len[pos] == SQL_NULL_DATA )
712 return true;
713 else
714 return false;
716 bool SqlOdbcStatement::isFldNull(char *name)
718 ListIterator iter = bindList.getIterator();
719 BindSqlProjectField *bindField = NULL;
720 int pos=1;
721 while (iter.hasElement())
723 bindField = (BindSqlProjectField*)iter.nextElement();
724 if(strcmp(name,bindField->fName)==0)
726 break;
728 pos++;
730 if( len[pos] == SQL_NULL_DATA )
731 return true;
732 else
733 return false;
736 void SqlOdbcStatement::setNull(int pos)
738 paramlen[pos] = SQL_NULL_DATA ;
741 bool SqlOdbcStatement::isTableExists( char *name)
744 SQLCHAR outstr[1024];
745 SQLSMALLINT outstrlen;
746 int retValue =0;
747 SQLHENV henv;
748 SQLHDBC hdbc;
749 SQLHSTMT hstmt;
750 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
751 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
752 if (retValue) {
753 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
756 (*SqlOdbcConnection::ODBCFuncPtrs.SQLSetEnvAttrPtr)(henv, SQL_ATTR_ODBC_VERSION,(void *) SQL_OV_ODBC3, 0);
757 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_DBC, henv, &hdbc);
758 if (retValue) {
759 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
761 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDriverConnectPtr)(hdbc, NULL, (SQLCHAR*)conn->dsn, SQL_NTS, outstr, sizeof(outstr), &outstrlen,SQL_DRIVER_NOPROMPT);
762 if (SQL_SUCCEEDED(retValue)) {
763 printDebug(DM_Gateway, "Connected to target database using dsn = %s\n", conn->dsn);
764 } else {
765 printError(ErrSysInit, "Failed to connect to target database\n");
768 retValue=(*SqlOdbcConnection::ODBCFuncPtrs.SQLAllocHandlePtr) (SQL_HANDLE_STMT, hdbc, &hstmt);
769 if (retValue) {
770 printError(ErrSysInit, "Unable to allocate ODBC handle \n");
772 char tablename[IDENTIFIER_LENGTH];
773 //retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLTablesPtr)(hstmt, (SQLCHAR*)"test", SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"", SQL_NTS, (SQLCHAR*)"TABLE", SQL_NTS );
774 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLTablesPtr)(hstmt, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS, NULL, SQL_NTS );
775 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt,3,SQL_C_CHAR,tablename,sizeof(tablename),NULL);
776 while(SQL_SUCCEEDED(retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLFetchPtr)(hstmt)))
778 if(strcmp(tablename,name)==0){
779 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
780 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
781 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
782 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
783 return true;
787 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_STMT, hstmt);
788 (*SqlOdbcConnection::ODBCFuncPtrs.SQLDisconnectPtr)(hdbc);
789 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_DBC, hdbc);
790 (*SqlOdbcConnection::ODBCFuncPtrs.SQLFreeHandlePtr)(SQL_HANDLE_ENV, henv);
791 return false;
793 void SqlOdbcStatement::setErrorState(SQLHSTMT hStmt)
795 SQLINTEGER i = 0;
796 SQLINTEGER native;
797 SQLCHAR state[ 7 ];
798 SQLCHAR text[256];
799 SQLSMALLINT len;
800 SQLRETURN ret;
801 ret = (*SqlOdbcConnection::ODBCFuncPtrs.SQLGetDiagRecPtr)(SQL_HANDLE_STMT, hStmt, ++i,
802 state, &native, text, sizeof(text), &len );
804 if (SQL_SUCCEEDED(ret)){
805 printf("%s:%ld:%ld:%s\n", state, i, native, text);
806 strcpy(errState,(char*)state);
810 DbRetVal SqlOdbcStatement::resolveForBindField(SQLHSTMT hstmt)
812 short totalFields=0;
813 int retValue = 0;
814 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLNumResultColsPtr) (hstmt, &totalFields);
815 if (retValue){ return ErrBadCall; }
816 BindSqlProjectField *bindProjField = NULL;
817 UWORD icol;
818 UCHAR colName[IDENTIFIER_LENGTH];
819 SWORD colNameMax;
820 SWORD nameLength;
821 SWORD colType;
822 SQLULEN colLength;
823 SWORD scale;
824 SWORD nullable;
825 icol = 1; colNameMax = IDENTIFIER_LENGTH;
826 if(totalFields != 0)
828 if(isProcedureCallStmt) isSelStmt = true;
829 len = (SQLINTEGER *)malloc((totalFields+1)*sizeof(SQLINTEGER));
830 for(int i=0;i<=totalFields;i++) { len[i] = SQL_NTS ;}
832 while (icol <= totalFields)
834 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLDescribeColPtr)(hstmt, icol, colName, colNameMax,
835 &nameLength, &colType, &colLength,
836 &scale, &nullable);
837 if (retValue) return ErrBadCall;
838 bindProjField = new BindSqlProjectField();
839 strcpy(bindProjField->fName, (char*)colName);
840 bindProjField->type = AllDataType::convertFromSQLType(colType,colLength,scale,tdbname);
841 bindProjField->length = AllDataType::size(bindProjField->type, colLength+1);
842 bindProjField->value = NULL;
843 bindProjField->targetvalue = NULL;
844 int fieldsize =0;
845 if(tdbname==postgres && -5 == colType) {
846 bindProjField->targetvalue = AllDataType::alloc(typeString, 128);
847 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, icol,
848 AllDataType::convertToSQLType(typeString),
849 bindProjField->targetvalue, 128, &len[icol]);
850 }else{
851 switch(bindProjField->type)
853 case typeString:
854 fieldsize = colLength+1;
855 bindProjField->targetvalue = malloc(fieldsize);
856 break;
857 case typeDate:
858 fieldsize = sizeof(DATE_STRUCT);
859 bindProjField->targetvalue = malloc(sizeof(DATE_STRUCT));
860 break;
861 case typeTime:
862 fieldsize = sizeof(TIME_STRUCT);
863 bindProjField->targetvalue = malloc(sizeof(TIME_STRUCT));
864 break;
865 case typeTimeStamp:
866 fieldsize = sizeof(TIMESTAMP_STRUCT);
867 bindProjField->targetvalue = malloc(sizeof(TIMESTAMP_STRUCT));
868 break;
869 default:
870 bindProjField->targetvalue = AllDataType::alloc(bindProjField->type, bindProjField->length);
872 retValue = (*SqlOdbcConnection::ODBCFuncPtrs.SQLBindColPtr)(hstmt, icol,
873 AllDataType::convertToSQL_C_Type(bindProjField->type,tdbname),
874 bindProjField->targetvalue, fieldsize, &len[icol]);
876 if (retValue) return ErrBadCall;
877 bindList.append(bindProjField);
878 icol++;
880 totalFld = totalFields;
881 return OK;