00001 #include "../include/FirebirdResultSet.h"
00002 #include "../include/FirebirdResultSetMetaData.h"
00003 #include "../include/FirebirdDatabaseLayer.h"
00004 #include "../include/DatabaseErrorCodes.h"
00005 #include "../include/DatabaseLayerException.h"
00006
00007 FirebirdResultSet::FirebirdResultSet()
00008 : DatabaseResultSet()
00009 {
00010 m_pDatabase = NULL;
00011 m_pTransaction = NULL;
00012 m_pStatement = NULL;
00013 m_pFields = NULL;
00014 m_bManageStatement = false;
00015 m_bManageTransaction = false;
00016 }
00017
00018
00019 FirebirdResultSet::FirebirdResultSet(isc_db_handle pDatabase, isc_tr_handle pTransaction, isc_stmt_handle pStatement, XSQLDA* pFields, bool bManageStmt , bool bManageTrans )
00020 : DatabaseResultSet()
00021 {
00022 m_pDatabase = pDatabase;
00023 m_pTransaction = pTransaction;
00024 m_pStatement = pStatement;
00025 m_pFields = pFields;
00026 m_bManageStatement = bManageStmt;
00027 m_bManageTransaction = bManageTrans;
00028
00029 AllocateFieldSpace();
00030 PopulateFieldLookupMap();
00031 }
00032
00033 FirebirdResultSet::~FirebirdResultSet()
00034 {
00035 Close();
00036 }
00037
00038 bool FirebirdResultSet::Next()
00039 {
00040 ResetErrorCodes();
00041
00042 int nReturn = isc_dsql_fetch(m_Status, &m_pStatement, 1, m_pFields);
00043 if (nReturn == 0)
00044 {
00045 return true;
00046 }
00047 else if (nReturn == 100L)
00048 {
00049 return false;
00050 }
00051 else
00052 {
00053 wxLogError(_("Error retrieving Next record\n"));
00054 InterpretErrorCodes();
00055 ThrowDatabaseException();
00056 return false;
00057 }
00058 }
00059
00060 void FirebirdResultSet::Close()
00061 {
00062 CloseMetaData();
00063
00064 if (m_bManageTransaction && m_pTransaction)
00065 {
00066 int nReturn = isc_commit_transaction(m_Status, &m_pTransaction);
00067
00068 m_pTransaction = NULL;
00069 if (nReturn != 0)
00070 {
00071 InterpretErrorCodes();
00072 ThrowDatabaseException();
00073 }
00074 }
00075
00076
00077 if (m_bManageStatement && m_pStatement)
00078 {
00079 int nReturn = isc_dsql_free_statement(m_Status, &m_pStatement, DSQL_drop);
00080 m_pStatement = NULL;
00081 if (nReturn != 0)
00082 {
00083 InterpretErrorCodes();
00084 ThrowDatabaseException();
00085 }
00086 }
00087
00088
00089 if (m_pFields)
00090 {
00091 FreeFieldSpace();
00092 free(m_pFields);
00093 m_pFields = NULL;
00094 }
00095 }
00096
00097
00098
00099 int FirebirdResultSet::GetResultInt(int nField)
00100 {
00101 ResetErrorCodes();
00102
00103
00104 return GetResultLong(nField);
00105 }
00106
00107 wxString FirebirdResultSet::GetResultString(int nField)
00108 {
00109 ResetErrorCodes();
00110
00111 wxString strReturn = wxEmptyString;
00112 XSQLVAR* pVar = &(m_pFields->sqlvar[nField-1]);
00113 if (IsNull(pVar))
00114 {
00115
00116 strReturn = wxEmptyString;
00117 }
00118 else
00119 {
00120 short nType = pVar->sqltype & ~1;
00121 if (nType == SQL_TEXT)
00122 {
00123 strReturn = ConvertFromUnicodeStream(pVar->sqldata);
00124 }
00125 else if (nType == SQL_VARYING)
00126 {
00127 struct vary* pVary = (struct vary*) pVar->sqldata;
00128 pVary->vary_string[pVary->vary_length] = '\0';
00129 strReturn = ConvertFromUnicodeStream(pVary->vary_string);
00130 }
00131 else
00132 {
00133
00134
00135 strReturn = _("");
00136
00137 SetErrorMessage(_("Invalid field type"));
00138 SetErrorCode(DATABASE_LAYER_INCOMPATIBLE_FIELD_TYPE);
00139
00140 ThrowDatabaseException();
00141 }
00142 }
00143
00144 return strReturn;
00145 }
00146
00147 long FirebirdResultSet::GetResultLong(int nField)
00148 {
00149 ResetErrorCodes();
00150
00151 long nReturn = 0L;
00152 XSQLVAR* pVar = &(m_pFields->sqlvar[nField-1]);
00153 if (IsNull(pVar))
00154 {
00155
00156 nReturn = 0;
00157 }
00158 else
00159 {
00160 short nType = pVar->sqltype & ~1;
00161 if (nType == SQL_SHORT)
00162 {
00163 nReturn = *((short*)pVar->sqldata);
00164 }
00165 else if (nType == SQL_LONG)
00166 {
00167 nReturn = *((long*)pVar->sqldata);
00168 }
00169 else if (nType == SQL_INT64)
00170 {
00171 nReturn = *((ISC_INT64*)pVar->sqldata);
00172 }
00173 else
00174 {
00175
00176
00177 nReturn = 0;
00178
00179 SetErrorMessage(_("Invalid field type"));
00180 SetErrorCode(DATABASE_LAYER_INCOMPATIBLE_FIELD_TYPE);
00181
00182 ThrowDatabaseException();
00183 }
00184
00185
00186 if (nReturn != 0)
00187 {
00188 short nScale = pVar->sqlscale;
00189 if (nScale > 0)
00190 {
00191 int nMultiplier = nScale * 10;
00192 nReturn *= nMultiplier;
00193 }
00194 else if (nScale < 0)
00195 {
00196 int nMultiplier = abs(nScale) * 10;
00197 nReturn /= nMultiplier;
00198 }
00199 }
00200 }
00201
00202 return nReturn;
00203 }
00204
00205 bool FirebirdResultSet::GetResultBool(int nField)
00206 {
00207 ResetErrorCodes();
00208
00209
00210 int nValue = GetResultLong(nField);
00211 return (nValue != 0);
00212 }
00213
00214 wxDateTime FirebirdResultSet::GetResultDate(int nField)
00215 {
00216 ResetErrorCodes();
00217
00218 wxDateTime dateReturn = wxInvalidDateTime;
00219 XSQLVAR* pVar = &(m_pFields->sqlvar[nField-1]);
00220 if (IsNull(pVar))
00221 {
00222
00223 dateReturn = wxInvalidDateTime;
00224 }
00225 else
00226 {
00227 short nType = pVar->sqltype & ~1;
00228 if (nType == SQL_TIMESTAMP)
00229 {
00230 struct tm timeInTm;
00231 isc_decode_timestamp((ISC_TIMESTAMP *)pVar->sqldata, &timeInTm);
00232 SetDateTimeFromTm(dateReturn, timeInTm);
00233 }
00234 else if (nType == SQL_TYPE_DATE)
00235 {
00236 struct tm timeInTm;
00237 isc_decode_sql_date((ISC_DATE *)pVar->sqldata, &timeInTm);
00238 SetDateTimeFromTm(dateReturn, timeInTm);
00239 }
00240 else if (nType == SQL_TYPE_TIME)
00241 {
00242 struct tm timeInTm;
00243 isc_decode_sql_time((ISC_TIME *)pVar->sqldata, &timeInTm);
00244 SetDateTimeFromTm(dateReturn, timeInTm);
00245 }
00246 else
00247 {
00248
00249
00250 dateReturn = wxInvalidDateTime;
00251
00252 SetErrorMessage(_("Invalid field type"));
00253 SetErrorCode(DATABASE_LAYER_INCOMPATIBLE_FIELD_TYPE);
00254
00255 ThrowDatabaseException();
00256 }
00257 }
00258
00259 return dateReturn;
00260 }
00261
00262 void FirebirdResultSet::SetDateTimeFromTm(wxDateTime& dateReturn, struct tm& timeInTm)
00263 {
00264
00265 dateReturn.Set(timeInTm);
00266
00267 if (dateReturn == wxInvalidDateTime)
00268 dateReturn.Set(timeInTm.tm_mday, wxDateTime::Month(timeInTm.tm_mon), timeInTm.tm_year, timeInTm.tm_hour, timeInTm.tm_min, timeInTm.tm_sec);
00269 }
00270
00271 double FirebirdResultSet::GetResultDouble(int nField)
00272 {
00273 double dblReturn = 0.00;
00274 XSQLVAR* pVar = &(m_pFields->sqlvar[nField-1]);
00275 if (IsNull(pVar))
00276 {
00277
00278 dblReturn = 0.00;
00279 }
00280 else
00281 {
00282 short nType = pVar->sqltype & ~1;
00283 if (nType == SQL_FLOAT)
00284 {
00285 dblReturn = *(float *) (pVar->sqldata);
00286 }
00287 else if (nType == SQL_DOUBLE)
00288 {
00289 dblReturn = *(double *) (pVar->sqldata);
00290 }
00291 else
00292 {
00293
00294
00295 dblReturn = 0.00;
00296
00297 SetErrorMessage(_("Invalid field type"));
00298 SetErrorCode(DATABASE_LAYER_INCOMPATIBLE_FIELD_TYPE);
00299
00300 ThrowDatabaseException();
00301 }
00302 }
00303
00304 return dblReturn;
00305 }
00306
00307 void* FirebirdResultSet::GetResultBlob(int nField, wxMemoryBuffer& Buffer)
00308 {
00309 ResetErrorCodes();
00310
00311 XSQLVAR* pVar = &(m_pFields->sqlvar[nField-1]);
00312 if (IsNull(pVar))
00313 {
00314
00315 Buffer.SetDataLen(0);
00316 return NULL;
00317 }
00318 else
00319 {
00320 short nType = pVar->sqltype & ~1;
00321 if (nType == SQL_BLOB)
00322 {
00323 ISC_QUAD blobId = *(ISC_QUAD *) pVar->sqldata;
00324 isc_blob_handle pBlob = NULL;
00325 char szSegment[128];
00326 unsigned short nSegmentLength;
00327 isc_open_blob2(m_Status, &m_pDatabase, &m_pTransaction, &pBlob, &blobId, 0, NULL);
00328
00329 ISC_STATUS blobStatus = isc_get_segment(m_Status, &pBlob, &nSegmentLength, sizeof(szSegment), szSegment);
00330 while (blobStatus == 0 || m_Status[1] == isc_segment)
00331 {
00332 Buffer.AppendData(szSegment, nSegmentLength);
00333 blobStatus = isc_get_segment(m_Status, &pBlob, &nSegmentLength, sizeof(szSegment), szSegment);
00334 }
00335 isc_close_blob(m_Status, &pBlob);
00336 }
00337 else
00338 {
00339
00340
00341 Buffer.SetDataLen(0);
00342
00343 SetErrorMessage(_("Invalid field type"));
00344 SetErrorCode(DATABASE_LAYER_INCOMPATIBLE_FIELD_TYPE);
00345
00346 ThrowDatabaseException();
00347 }
00348 }
00349
00350 return Buffer.GetData();
00351 }
00352
00353 bool FirebirdResultSet::IsFieldNull(int nField)
00354 {
00355 XSQLVAR* pVar = &(m_pFields->sqlvar[nField-1]);
00356 return IsNull(pVar);
00357 }
00358
00359 bool FirebirdResultSet::IsNull(XSQLVAR* pVar)
00360 {
00361 return ((pVar->sqltype & 1) && (*pVar->sqlind < 0));
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371 void FirebirdResultSet::AllocateFieldSpace()
00372 {
00373 if (m_pFields == NULL)
00374 return;
00375
00376 for (int i = 0; i < m_pFields->sqld; i++)
00377 {
00378 XSQLVAR* pVar = &(m_pFields->sqlvar[i]);
00379 switch (pVar->sqltype & ~1)
00380 {
00381 case SQL_ARRAY:
00382 case SQL_BLOB:
00383 pVar->sqldata = (char*)new ISC_QUAD;
00384 memset(pVar->sqldata, 0, sizeof(ISC_QUAD));
00385 break;
00386 case SQL_TIMESTAMP:
00387 pVar->sqldata = (char*)new ISC_TIMESTAMP;
00388 memset(pVar->sqldata, 0, sizeof(ISC_TIMESTAMP));
00389 break;
00390 case SQL_TYPE_TIME:
00391 pVar->sqldata = (char*)new ISC_TIME;
00392 memset(pVar->sqldata, 0, sizeof(ISC_TIME));
00393 break;
00394 case SQL_TYPE_DATE:
00395 pVar->sqldata = (char*)new ISC_DATE;
00396 memset(pVar->sqldata, 0, sizeof(ISC_DATE));
00397 break;
00398 case SQL_TEXT:
00399 pVar->sqldata = new char[pVar->sqllen+1];
00400 memset(pVar->sqldata, '\0', pVar->sqllen);
00401 pVar->sqldata[pVar->sqllen] = '\0';
00402 break;
00403 case SQL_VARYING:
00404 pVar->sqldata = new char[pVar->sqllen+3];
00405 memset(pVar->sqldata, 0, 2);
00406 memset(pVar->sqldata+2, '\0', pVar->sqllen);
00407 pVar->sqldata[pVar->sqllen+2] = '\0';
00408 break;
00409 case SQL_SHORT:
00410 pVar->sqldata = (char*)new short(0);
00411 break;
00412 case SQL_LONG:
00413 pVar->sqldata = (char*)new long(0);
00414 break;
00415 case SQL_INT64:
00416 pVar->sqldata = (char*)new ISC_INT64(0);
00417 break;
00418 case SQL_FLOAT:
00419 pVar->sqldata = (char*)new float(0.0);
00420 break;
00421 case SQL_DOUBLE:
00422 pVar->sqldata = (char*)new double(0.0);
00423 break;
00424 default :
00425 break;
00426 }
00427 if (pVar->sqltype & 1)
00428 pVar->sqlind = new short(-1);
00429 }
00430 }
00431
00432 void FirebirdResultSet::FreeFieldSpace()
00433 {
00434 if (m_pFields == NULL)
00435 return;
00436
00437 for (int i = 0; i < m_pFields->sqln; i++)
00438 {
00439 XSQLVAR* pVar = &(m_pFields->sqlvar[i]);
00440 if (pVar->sqldata != 0)
00441 {
00442 switch (pVar->sqltype & ~1)
00443 {
00444 case SQL_ARRAY:
00445 case SQL_BLOB:
00446 wxDELETE(pVar->sqldata);
00447 break;
00448 case SQL_TIMESTAMP:
00449 wxDELETE(pVar->sqldata);
00450 break;
00451 case SQL_TYPE_TIME:
00452 wxDELETE(pVar->sqldata);
00453 break;
00454 case SQL_TYPE_DATE:
00455 wxDELETE(pVar->sqldata);
00456 break;
00457 case SQL_TEXT:
00458 case SQL_VARYING:
00459 wxDELETEA(pVar->sqldata);
00460 break;
00461 case SQL_SHORT:
00462 wxDELETE(pVar->sqldata);
00463 break;
00464 case SQL_LONG:
00465 wxDELETE(pVar->sqldata);
00466 break;
00467 case SQL_INT64:
00468 wxDELETE(pVar->sqldata);
00469 break;
00470 case SQL_FLOAT:
00471 wxDELETE(pVar->sqldata);
00472 break;
00473 case SQL_DOUBLE:
00474 wxDELETE(pVar->sqldata);
00475 break;
00476 default:
00477 break;
00478 }
00479 }
00480 if ((pVar->sqltype & 1) && (pVar->sqlind != 0))
00481 delete pVar->sqlind;
00482 }
00483
00484
00485
00486 wxDELETEA(m_pFields);
00487 }
00488
00489 void FirebirdResultSet::PopulateFieldLookupMap()
00490 {
00491 m_FieldLookupMap.clear();
00492
00493
00494 XSQLVAR* pVar = m_pFields->sqlvar;
00495 for (int i=0; i<m_pFields->sqld; i++, pVar++)
00496 {
00497 wxString strField = ConvertFromUnicodeStream(pVar->aliasname);
00498 m_FieldLookupMap[strField] = i;
00499 }
00500 }
00501
00502 int FirebirdResultSet::LookupField(const wxString& strField)
00503 {
00504 wxString strUpperCaseCopy = strField;
00505 strUpperCaseCopy.MakeUpper();
00506 StringToIntMap::iterator SearchIterator = m_FieldLookupMap.find(strUpperCaseCopy);
00507 if (SearchIterator == m_FieldLookupMap.end())
00508 {
00509 wxString msg(_("Field '") + strField + _("' not found in the resultset"));
00510 #ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
00511 DatabaseLayerException error(DATABASE_LAYER_FIELD_NOT_IN_RESULTSET, msg);
00512 throw error;
00513 #else
00514 wxLogError(msg);
00515 #endif
00516 return -1;
00517 }
00518 else
00519 {
00520 return ((*SearchIterator).second+1);
00521 }
00522 }
00523
00524 void FirebirdResultSet::InterpretErrorCodes()
00525 {
00526 wxLogError(_("FirebirdResultSet::InterpretErrorCodes()\n"));
00527
00528 long nSqlCode = isc_sqlcode(m_Status);
00529 SetErrorCode(FirebirdDatabaseLayer::TranslateErrorCode(nSqlCode));
00530 SetErrorMessage(FirebirdDatabaseLayer::TranslateErrorCodeToString(nSqlCode, m_Status));
00531 }
00532
00533 ResultSetMetaData* FirebirdResultSet::GetMetaData()
00534 {
00535 ResultSetMetaData* pMetaData = new FirebirdResultSetMetaData(m_pFields);
00536 LogMetaDataForCleanup(pMetaData);
00537 return pMetaData;
00538 }
00539
00540