00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <SqlOdbcStatement.h>
00021
00022
00023
00024
00025
00026 DbRetVal SqlOdbcStatement::prepare(char *stmtstr)
00027 {
00028 DbRetVal rv = OK;
00029 if (innerStmt) rv = ErrBadCall;
00030 if (rv != OK) return rv;
00031 int retValue;
00032 isPrepared = false;
00033 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
00034 retValue=SQLAllocHandle (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
00035 if (retValue) return ErrBadCall;
00036 retValue = SQLPrepare (hstmt, (unsigned char *) stmtstr, SQL_NTS);
00037 if (retValue) return ErrBadCall;
00038 isPrepared = true;
00039 short totalFields=0;
00040 retValue = SQLNumResultCols (hstmt, &totalFields);
00041 if (retValue) return ErrBadCall;
00042 BindSqlProjectField *bindProjField = NULL;
00043 UWORD icol;
00044 UCHAR colName[IDENTIFIER_LENGTH];
00045 SWORD colNameMax;
00046 SWORD nameLength;
00047 SWORD colType;
00048 SQLULEN colLength;
00049 SWORD scale;
00050 SWORD nullable;
00051 icol = 1; colNameMax = IDENTIFIER_LENGTH;
00052 while (icol <= totalFields)
00053 {
00054 retValue = SQLDescribeCol(hstmt, icol, colName, colNameMax,
00055 &nameLength, &colType, &colLength,
00056 &scale, &nullable);
00057 if (retValue) return ErrBadCall;
00058
00059 bindProjField = new BindSqlProjectField();
00060 strncpy(bindProjField->fName, (char*)colName, IDENTIFIER_LENGTH);
00061 bindProjField->fName[IDENTIFIER_LENGTH] = '\0';
00062 bindProjField->type = AllDataType::convertFromSQLType(colType);
00063 bindProjField->length = colLength +1;
00064 bindProjField->value = NULL;
00065 bindProjField->targetvalue = NULL;
00066 int fieldsize =0;
00067 switch(bindProjField->type)
00068 {
00069 case typeString:
00070 fieldsize = colLength+1;
00071 bindProjField->targetvalue = malloc(fieldsize);
00072 break;
00073 case typeDate:
00074 fieldsize = sizeof(DATE_STRUCT);
00075 bindProjField->targetvalue = malloc(sizeof(DATE_STRUCT));
00076 break;
00077 case typeTime:
00078 fieldsize = sizeof(TIME_STRUCT);
00079 bindProjField->targetvalue = malloc(sizeof(TIME_STRUCT));
00080 break;
00081 case typeTimeStamp:
00082 fieldsize = sizeof(TIMESTAMP_STRUCT);
00083 bindProjField->targetvalue = malloc(sizeof(TIMESTAMP_STRUCT));
00084 break;
00085 default:
00086 bindProjField->targetvalue = AllDataType::alloc(bindProjField->type, bindProjField->length);
00087 }
00088 retValue = SQLBindCol(hstmt, icol,
00089 AllDataType::convertToSQLType(bindProjField->type),
00090 bindProjField->targetvalue, fieldsize, NULL);
00091 if (retValue) return ErrBadCall;
00092 bindList.append(bindProjField);
00093 icol++;
00094
00095 }
00096 totalFields =0;
00097 BindSqlField *bindField;
00098 retValue = SQLNumParams (hstmt, &totalFields);
00099 if (retValue) return ErrBadCall;
00100 icol = 1; colNameMax = IDENTIFIER_LENGTH;
00101 SWORD cType=0;
00102 SQLULEN cLength=0;
00103 while (icol <= totalFields)
00104 {
00105 retValue = SQLDescribeParam(hstmt, icol, &cType, &cLength,
00106 &scale, &nullable);
00107
00108
00109
00110 if (retValue) return ErrBadCall;
00111
00112 bindField = new BindSqlField();
00113 bindField->type = AllDataType::convertFromSQLType(cType);
00114 bindField->length = cLength;
00115 bindField->value = AllDataType::alloc(bindField->type, cLength);
00116 bindField->targetvalue = NULL;
00117 int fieldsize =0;
00118 switch(bindField->type)
00119 {
00120 case typeString:
00121 fieldsize = cLength;
00122 bindField->targetvalue = malloc(fieldsize);
00123 break;
00124 case typeDate:
00125 fieldsize = sizeof(DATE_STRUCT);
00126 bindField->targetvalue = malloc(sizeof(DATE_STRUCT));
00127 break;
00128 case typeTime:
00129 fieldsize = sizeof(TIME_STRUCT);
00130 bindField->targetvalue = malloc(sizeof(TIME_STRUCT));
00131 break;
00132 case typeTimeStamp:
00133 fieldsize = sizeof(TIMESTAMP_STRUCT);
00134 bindField->targetvalue = malloc(sizeof(TIMESTAMP_STRUCT));
00135 break;
00136 default:
00137 bindField->targetvalue = AllDataType::alloc(bindField->type, cLength);
00138 break;
00139
00140 }
00141 retValue = SQLBindParameter(hstmt, icol, SQL_PARAM_INPUT,
00142 AllDataType::convertToSQL_C_Type(bindField->type),
00143 cType, fieldsize, scale, bindField->targetvalue,
00144 fieldsize, NULL);
00145 if (retValue) return ErrBadCall;
00146 paramList.append(bindField);
00147 icol++;
00148 }
00149
00150
00151 return OK;
00152 }
00153
00154 bool SqlOdbcStatement::isSelect()
00155 {
00156
00157 return false;
00158 }
00159
00160 DbRetVal SqlOdbcStatement::execute(int &rowsAffected)
00161 {
00162 DbRetVal rv = OK;
00163 if (!isPrepared) return OK;
00164 ListIterator iter = paramList.getIterator();
00165 BindSqlField *bindField = NULL;
00166 while (iter.hasElement())
00167 {
00168 bindField = (BindSqlField*)iter.nextElement();
00169 switch(bindField->type)
00170 {
00171 case typeDate: {
00172 Date *dtCSQL = (Date*) bindField->value;
00173 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
00174 dtTarget->year= dtCSQL->year();
00175 dtTarget->month= dtCSQL->month();
00176 dtTarget->day = dtCSQL->dayOfMonth();
00177 break;
00178 }
00179 case typeTime: {
00180 Time *dtCSQL = (Time*) bindField->value;
00181 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
00182 dtTarget->hour = dtCSQL->hours();
00183 dtTarget->minute = dtCSQL->minutes();
00184 dtTarget->second = dtCSQL->seconds();
00185 break;
00186 }
00187 case typeTimeStamp: {
00188 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
00189 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
00190 dtTarget->year= dtCSQL->year();
00191 dtTarget->month= dtCSQL->month();
00192 dtTarget->day = dtCSQL->dayOfMonth();
00193 dtTarget->hour = dtCSQL->hours();
00194 dtTarget->minute = dtCSQL->minutes();
00195 dtTarget->second = dtCSQL->seconds();
00196 break;
00197 }
00198 default: {
00199 AllDataType::copyVal(bindField->targetvalue, bindField->value,
00200 bindField->type, bindField->length);
00201 break;
00202 }
00203 }
00204 }
00205 int retValue = SQLExecute (hstmt);
00206 if (retValue) return ErrBadCall;
00207 return rv;
00208 }
00209
00210 DbRetVal SqlOdbcStatement::bindParam(int pos, void* value)
00211 {
00212 DbRetVal rv = OK;
00213 printError(ErrWarning, "Deprecated. Use setParamXXX instead\n");
00214 return rv;
00215 }
00216
00217 DbRetVal SqlOdbcStatement::bindField(int pos, void* value)
00218 {
00219 if (!isPrepared) return OK;
00220 BindSqlProjectField *bindField = (BindSqlProjectField*)bindList.get(pos);
00221 if (NULL == bindField)
00222 {
00223 printError(ErrBadArg, "Could not get the projection list. Should be called only for SELECT statement");
00224 return ErrBadArg;
00225 }
00226 bindField->value = value;
00227 return OK;
00228 }
00229 void* SqlOdbcStatement::fetch()
00230 {
00231 if (!isPrepared) return NULL;
00232 int retValue = SQLFetch (hstmt);
00233 if (retValue) return NULL;
00234 ListIterator iter = bindList.getIterator();
00235 BindSqlProjectField *bindField = NULL;
00236 void *ptrToFirstField = NULL;
00237 while (iter.hasElement())
00238 {
00239 bindField = (BindSqlProjectField*)iter.nextElement();
00240 switch(bindField->type)
00241 {
00242 case typeDate: {
00243 Date *dtCSQL = (Date*) bindField->value;
00244 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
00245 dtCSQL->set(dtTarget->year,dtTarget->month,dtTarget->day);
00246 break;
00247 }
00248 case typeTime: {
00249 Time *dtCSQL = (Time*) bindField->value;
00250 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
00251 dtCSQL->set(dtTarget->hour,dtTarget->minute,dtTarget->second);
00252 break;
00253 }
00254 case typeTimeStamp: {
00255 TimeStamp *dtCSQL = (TimeStamp*) bindField->value;
00256 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
00257 dtCSQL->setDate(dtTarget->year,dtTarget->month,dtTarget->day);
00258 dtCSQL->setTime(dtTarget->hour,dtTarget->minute,
00259 dtTarget->second, dtTarget->fraction);
00260 break;
00261 }
00262 default: {
00263 AllDataType::copyVal(bindField->value, bindField->targetvalue,
00264 bindField->type, bindField->length);
00265 break;
00266 }
00267 }
00268 if (ptrToFirstField == NULL) ptrToFirstField=bindField->value;
00269 }
00270 return ptrToFirstField;
00271 }
00272
00273 void* SqlOdbcStatement::fetchAndPrint(bool SQL)
00274 {
00275 if (!isPrepared) return NULL;
00276 int retValue = SQLFetch (hstmt);
00277 if (retValue) return NULL;
00278 ListIterator iter = bindList.getIterator();
00279 BindSqlProjectField *bindField = NULL;
00280 void *ptrToFirstField = NULL;
00281 while (iter.hasElement())
00282 {
00283 bindField = (BindSqlProjectField*)iter.nextElement();
00284 switch(bindField->type)
00285 {
00286 case typeDate: {
00287 Date dtCSQL;
00288 DATE_STRUCT *dtTarget = (DATE_STRUCT*) bindField->targetvalue;
00289 dtCSQL.set(dtTarget->year,dtTarget->month,dtTarget->day);
00290 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
00291 break;
00292 }
00293 case typeTime: {
00294 Time dtCSQL;
00295 TIME_STRUCT *dtTarget = (TIME_STRUCT*) bindField->targetvalue;
00296 dtCSQL.set(dtTarget->hour,dtTarget->minute,dtTarget->second);
00297 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
00298 break;
00299 }
00300 case typeTimeStamp: {
00301 TimeStamp dtCSQL;
00302 TIMESTAMP_STRUCT *dtTarget = (TIMESTAMP_STRUCT*) bindField->targetvalue;
00303 dtCSQL.setDate(dtTarget->year,dtTarget->month,dtTarget->day);
00304 dtCSQL.setTime(dtTarget->hour,dtTarget->minute,
00305 dtTarget->second, dtTarget->fraction);
00306 AllDataType::printVal(&dtCSQL, bindField->type, bindField->length);
00307 break;
00308 }
00309 default: {
00310 AllDataType::printVal(bindField->targetvalue,
00311 bindField->type, bindField->length);
00312 break;
00313 }
00314 }
00315 if (ptrToFirstField == NULL) ptrToFirstField=bindField->targetvalue;
00316 printf("\t");
00317 }
00318
00319 return ptrToFirstField;
00320 }
00321
00322 void* SqlOdbcStatement::next()
00323 {
00324 return fetch();
00325 }
00326
00327 DbRetVal SqlOdbcStatement::close()
00328 {
00329 if (!isPrepared) return OK;
00330 SQLCloseCursor(hstmt);
00331 return OK;
00332 }
00333
00334 void* SqlOdbcStatement::getFieldValuePtr( int pos )
00335 {
00336 return NULL;
00337 }
00338
00339 int SqlOdbcStatement::noOfProjFields()
00340 {
00341 if (!isPrepared) return 0;
00342 return bindList.size();
00343 }
00344
00345 int SqlOdbcStatement::noOfParamFields()
00346 {
00347 if (!isPrepared) return 0;
00348 return paramList.size();
00349 }
00350
00351 DbRetVal SqlOdbcStatement::getProjFldInfo (int projpos, FieldInfo *&fInfo)
00352 {
00353 ListIterator biter = bindList.getIterator();
00354 BindSqlProjectField *elem = NULL;
00355 int count =0;
00356 while (biter.hasElement())
00357 {
00358 elem = (BindSqlProjectField*) biter.nextElement();
00359 if (count == projpos)
00360 {
00361 strcpy(fInfo->fldName, elem->fName);
00362 fInfo->length = elem->length;
00363 fInfo->type =elem->type;
00364 return OK;
00365 }
00366 count++;
00367 }
00368 return ErrNotFound;
00369 }
00370
00371 DbRetVal SqlOdbcStatement::getParamFldInfo (int parampos, FieldInfo *&fInfo)
00372 {
00373 ListIterator biter = paramList.getIterator();
00374 BindSqlField *elem = NULL;
00375 int count =0;
00376 while (biter.hasElement())
00377 {
00378 elem = (BindSqlField*) biter.nextElement();
00379 if (count == parampos)
00380 {
00381 fInfo->length = elem->length;
00382 fInfo->type =elem->type;
00383 return OK;
00384 }
00385 count++;
00386 }
00387 return ErrNotFound;
00388 }
00389
00390 DbRetVal SqlOdbcStatement::free()
00391 {
00392 isPrepared = false;
00393 ListIterator biter = bindList.getIterator();
00394 BindSqlProjectField *elem = NULL;
00395 while (biter.hasElement())
00396 {
00397 elem = (BindSqlProjectField*) biter.nextElement();
00398 ::free(elem->targetvalue);
00399 delete elem;
00400 }
00401 bindList.reset();
00402 ListIterator piter = paramList.getIterator();
00403 BindSqlField *bindField = NULL;
00404 while (piter.hasElement())
00405 {
00406 bindField = (BindSqlField*) piter.nextElement();
00407 ::free(bindField->value);
00408 ::free(bindField->targetvalue);
00409 delete bindField;
00410 }
00411 paramList.reset();
00412
00413 SQLFreeHandle (SQL_HANDLE_STMT, hstmt);
00414 return OK;
00415 }
00416 void SqlOdbcStatement::setShortParam(int paramPos, short value)
00417 {
00418 if (!isPrepared) return ;
00419 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00420 if (bindField->type != typeShort) return;
00421 *(short*)(bindField->value) = value;
00422 return;
00423 }
00424 void SqlOdbcStatement::setIntParam(int paramPos, int value)
00425 {
00426 if (!isPrepared) return ;
00427 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00428
00429
00430
00431
00432
00433
00434 AllDataType::convertToString(bindField->value, &value, typeInt);
00435
00436 return;
00437
00438 }
00439 void SqlOdbcStatement::setLongParam(int paramPos, long value)
00440 {
00441 if (!isPrepared) return ;
00442 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00443
00444
00445
00446
00447 AllDataType::convertToString(bindField->value, &value, typeLong);
00448 return;
00449
00450 }
00451 void SqlOdbcStatement::setLongLongParam(int paramPos, long long value)
00452 {
00453 if (!isPrepared) return ;
00454 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00455
00456
00457 AllDataType::convertToString(bindField->value, &value, typeLongLong);
00458 return;
00459 }
00460 void SqlOdbcStatement::setByteIntParam(int paramPos, ByteInt value)
00461 {
00462 if (!isPrepared) return ;
00463 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00464
00465
00466 AllDataType::convertToString(bindField->value, &value, typeByteInt);
00467
00468 }
00469 void SqlOdbcStatement::setFloatParam(int paramPos, float value)
00470 {
00471 if (!isPrepared) return ;
00472 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00473
00474
00475 AllDataType::convertToString(bindField->value, &value, typeFloat);
00476 }
00477 void SqlOdbcStatement::setDoubleParam(int paramPos, double value)
00478 {
00479 if (!isPrepared) return ;
00480 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00481
00482
00483 AllDataType::convertToString(bindField->value, &value, typeDouble);
00484
00485 }
00486 void SqlOdbcStatement::setStringParam(int paramPos, char *value)
00487 {
00488 if (!isPrepared) return ;
00489 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00490 if (bindField->type != typeString) return;
00491 char *dest = (char*)bindField->value;
00492 strncpy(dest, value, bindField->length);
00493 dest[ bindField->length - 1] ='\0';
00494 return;
00495 }
00496 void SqlOdbcStatement::setDateParam(int paramPos, Date value)
00497 {
00498 if (!isPrepared) return ;
00499 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00500
00501
00502 AllDataType::convertToString(bindField->value, &value, typeDate);
00503
00504 }
00505 void SqlOdbcStatement::setTimeParam(int paramPos, Time value)
00506 {
00507 if (!isPrepared) return ;
00508 BindSqlField *bindField = (BindSqlField*)paramList.get(paramPos);
00509
00510
00511 AllDataType::convertToString(bindField->value, &value, typeTime);
00512
00513 }
00514 void SqlOdbcStatement::setTimeStampParam(int paramPos, TimeStamp value)
00515 {
00516 if (!isPrepared) return ;
00517 BindSqlField *bindField = (BindSqlField*) paramList.get(paramPos);
00518
00519
00520 AllDataType::convertToString(bindField->value, &value, typeTimeStamp);
00521 }
00522
00523 void SqlOdbcStatement::getPrimaryKeyFieldName(char *tablename, char *pkfieldname)
00524 {
00525 if (pkfieldname == NULL) return;
00526 SqlOdbcConnection *conn = (SqlOdbcConnection*)con;
00527 int retValue=SQLAllocHandle (SQL_HANDLE_STMT, conn->dbHdl, &hstmt);
00528 if (retValue) return ;
00529 char columnName[128];
00530 SQLINTEGER cbData;
00531 SQLPrimaryKeys(hstmt, NULL, 0, NULL, 0, (SQLCHAR*) tablename, SQL_NTS);
00532 SQLFetch(hstmt);
00533 SQLGetData(hstmt, 4, SQL_C_CHAR, (SQLCHAR*) columnName, sizeof(columnName),&cbData);
00534 strcpy(pkfieldname, columnName);
00535 SQLFreeHandle (SQL_HANDLE_STMT, hstmt);
00536 return;
00537 }