00001
00002
00003
00004
00005
00006
00007
00008 #include "openODBC.h"
00009 #include "ocString.h"
00010
00011
00012
00013
00014
00015
00016 bool odbcDB::error( SQLHSTMT hstmt )
00017 {
00018 UCHAR sqlstate[10];
00019 UCHAR errmsg[SQL_MAX_MESSAGE_LENGTH];
00020 SDWORD nativeerr;
00021 SWORD actualmsglen;
00022 RETCODE rc;
00023 bool bRet = true;
00024 m_bGood = false;
00025 do
00026 {
00027 rc = SQLError( henv, hdbc, hstmt,
00028 sqlstate, &nativeerr,
00029 errmsg,
00030 SQL_MAX_MESSAGE_LENGTH - 1,
00031 &actualmsglen );
00032
00033 if (rc == SQL_ERROR)
00034 {
00035 m_strErrors += "SQLError failed!\n";
00036 bRet = false;
00037 }
00038 else if( rc != SQL_NO_DATA_FOUND )
00039 {
00040
00041 errmsg[actualmsglen] = '\0';
00042 m_strErrors += "SQLSTATE = ";
00043 m_strErrors += (char *)sqlstate;
00044 m_strErrors += "\nNATIVE ERROR = ";
00045 m_strErrors += nativeerr;
00046 m_strErrors += "\nMSG = ";
00047 m_strErrors += (char *)errmsg;
00048 m_strErrors += "\n\n";
00049 }
00050 } while ( rc != SQL_NO_DATA_FOUND && rc != SQL_ERROR );
00051 if(hstmt != SQL_NULL_HSTMT)
00052 {
00053 SQLFreeStmt(hstmt, SQL_CLOSE) ;
00054 }
00055 return bRet;
00056 }
00057
00058
00059
00060
00061
00062
00063
00064 odbcDB::odbcDB( string strConnection ):openDB(strConnection)
00065 {
00066
00067
00068
00069
00070
00071 m_strErrors = "";
00072 m_provider = ODBC;
00073
00074 rc = SQLAllocEnv(&henv);
00075 if ( (rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO))
00076 {
00077 rc = SQLAllocConnect( henv, &hdbc);
00078 if( parseConnection( strConnection ) )
00079 {
00080 for ( int retries = 1; retries <= 3; retries++ )
00081 {
00082
00083 rc = SQLConnect( hdbc,
00084 (SQLCHAR*)dsn.c_str(), SQL_NTS,
00085 (SQLCHAR*)uid.c_str(), SQL_NTS,
00086 (SQLCHAR*)pwd.c_str(), SQL_NTS );
00087
00088 if( ( rc == SQL_SUCCESS) || (rc == SQL_SUCCESS_WITH_INFO) )
00089 {
00090 m_bGood = true;
00091 m_strErrors = "Connection OK\n";
00092 break;
00093 }
00094 else
00095 {
00096 error(SQL_NULL_HSTMT);
00097 }
00098 }
00099 }
00100 }
00101
00102
00103 }
00104
00105 bool odbcDB::parseConnection( string & strConnection )
00106 {
00107 bool bRet=false;
00108 dsn = uid = pwd = "";
00109
00110
00111 ocString connStr = strConnection;
00112 connStr.parseInit();
00113 for( string element=connStr.parse(";");
00114 !(element.length()==0 && connStr.endOfParse() );
00115 element=connStr.parse(";") )
00116 {
00117 ocString apair(element);
00118 string name = apair.parse("=");
00119 string value = apair.parse("=");
00120 transform(name.begin(),name.end(),name.begin(),(int(*)(int)) toupper );
00121 if( name == "DSN" )
00122 {
00123 dsn = value;
00124 }
00125 else if ( name == "UID" )
00126 {
00127 uid = value;
00128 }
00129 else if( name == "PWD" )
00130 {
00131 pwd = value;
00132 }
00133 }
00134 if( dsn.length() && uid.length() && pwd.length() )
00135 {
00136 bRet = true;
00137 }
00138
00139 return bRet;
00140 }
00141 dbProvider odbcDB::getProvider( void )
00142 {
00143 return m_provider;
00144 }
00145 odbcDB::~odbcDB()
00146 {
00147 SQLDisconnect(hdbc);
00148 SQLFreeConnect(hdbc);
00149 SQLFreeEnv(henv);
00150 }
00151
00152
00153 openCMD * odbcDB::createCommand()
00154 {
00155 return new odbcCMD( *this );
00156 }
00157
00158 openRS * odbcDB::createRecordset()
00159 {
00160 return new odbcRS( *this );
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 odbcCMD::odbcCMD( openDB & idb ):openCMD(idb)
00172 {
00173
00174 poDB = & dynamic_cast<odbcDB &>(rdb);
00175 }
00176
00177 odbcCMD::~odbcCMD()
00178 {
00179 ;
00180 }
00181
00182 bool odbcCMD::beginTransaction()
00183 {
00184
00185 if( !m_bTransactioning )
00186 {
00187
00188 m_bTransactioning = true;
00189 }
00190 return m_bTransactioning;
00191 }
00192
00193 bool odbcCMD::commit()
00194 {
00195
00196 if( m_bTransactioning )
00197 {
00198
00199 m_bTransactioning = false;
00200 }
00201 return !m_bTransactioning;
00202 }
00203
00204 bool odbcCMD::rollback()
00205 {
00206
00207 if( m_bTransactioning )
00208 {
00209
00210 m_bTransactioning = false;
00211 }
00212 return !m_bTransactioning;
00213 }
00214
00215 bool odbcCMD::execute( string sql )
00216 {
00217 bool bRet = false;
00218 rc = SQLAllocStmt( poDB->getDbConnHandle(), &hstmt );
00219 if ( (rc != SQL_SUCCESS) &&
00220 (rc != SQL_SUCCESS_WITH_INFO) )
00221 {
00222 poDB->error(SQL_NULL_HSTMT);
00223 }
00224 else
00225 {
00226
00227 rc = SQLExecDirect (hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
00228 if( (rc != SQL_SUCCESS) &&
00229 (rc != SQL_SUCCESS_WITH_INFO) )
00230 {
00231 poDB->error(hstmt);
00232 }
00233 else
00234 {
00235 bRet = true;
00236 }
00237 SQLFreeStmt ((SQLHSTMT)hstmt, SQL_CLOSE) ;
00238 }
00239 return bRet;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248 odbcRS::odbcRS( openDB & idb )
00249 :openRS(idb),hstmt(0),rc(0),numCols(0)
00250 {
00251
00252 poDB = dynamic_cast<odbcDB *>(&idb);
00253 }
00254
00255 odbcRS::~odbcRS()
00256 {
00257 for( unsigned int i=0;i>ordinals.size();i++)
00258 {
00259 delete ordinals[i];
00260 }
00261 ordinals.clear();
00262 associations.clear();
00263 }
00264
00265 bool odbcRS::open( string sql )
00266 {
00267 rc = SQLAllocStmt( poDB->getDbConnHandle(), &hstmt );
00268 if ( (rc != SQL_SUCCESS) &&
00269 (rc != SQL_SUCCESS_WITH_INFO) )
00270 {
00271 poDB->error(SQL_NULL_HSTMT);
00272 }
00273 else
00274 {
00275
00276 rc = SQLExecDirect (hstmt, (SQLCHAR*)sql.c_str(), SQL_NTS);
00277 if( (rc != SQL_SUCCESS) &&
00278 (rc != SQL_SUCCESS_WITH_INFO) )
00279 {
00280 poDB->error(hstmt);
00281 }
00282 else
00283 {
00284
00285
00286 numCols = 0 ;
00287 rc = SQLNumResultCols( hstmt, &numCols );
00288 if( (rc != SQL_SUCCESS) &&
00289 (rc != SQL_SUCCESS_WITH_INFO) )
00290 {
00291 poDB->error(hstmt);
00292 }
00293 else if (numCols == 0)
00294 {
00295
00296 m_bOpen = false;
00297 }
00298 else
00299 {
00300
00301 m_iFields = (int) numCols;
00302
00303
00304 UWORD icol;
00305
00306
00307 for( icol = 0 ; icol < numCols ; icol ++ )
00308 {
00309 odbcColInfo * pInfo = new odbcColInfo;
00310 rc = SQLDescribeCol( hstmt,
00311 icol + (UWORD)1,
00312 pInfo->szColName,
00313 cOL_nAMe_Len,
00314 &pInfo->cbColName,
00315 &pInfo->fSqlType,
00316 &pInfo->cbColDef,
00317 &pInfo->ibScale,
00318 &pInfo->fNullable) ;
00319 if ((rc != SQL_SUCCESS) &&
00320 (rc != SQL_SUCCESS_WITH_INFO))
00321 {
00322 delete pInfo;
00323 poDB->error(hstmt);
00324 break ;
00325 }
00326 else
00327 {
00328
00329
00330 colInfo.push_back(pInfo);
00331
00332 mapItem * pItem = colMap.data[pInfo->fSqlType];
00333
00334 if( pItem )
00335 {
00336
00337 basicField * pField = pItem->createField( pInfo );
00338 if( pField )
00339 {
00340
00341
00342
00343
00344
00345
00346
00347
00348 ordinals.push_back(pField);
00349
00350 associations.insert(make_pair((char*)pInfo->szColName,pField));
00351
00352 void * pVoid = pItem->thingToBind( pInfo , pField );
00353
00354
00355 rc = SQLBindCol( hstmt,
00356 icol + (UWORD)1,
00357 pItem->cType,
00358 pVoid,
00359 pInfo->cbColDef+1,
00360 &pInfo->length );
00361 if((rc != SQL_SUCCESS) &&
00362 (rc != SQL_SUCCESS_WITH_INFO))
00363 {
00364 poDB->error(hstmt);
00365 break;
00366 }
00367 }
00368 }
00369 else
00370 {
00371 poDB->errorString() += "\r\nUnable to find type in map\r\n";
00372 }
00373 }
00374 }
00375
00376
00377 m_bOpen = next();
00378 }
00379 }
00380 }
00381
00382 return m_bOpen;
00383 }
00384 bool odbcRS::beginTransaction()
00385 {
00386
00387 if( !m_bTransactioning )
00388 {
00389
00390 m_bTransactioning = true;
00391 }
00392 return m_bTransactioning;
00393 }
00394
00395 bool odbcRS::commit()
00396 {
00397
00398 if( m_bTransactioning )
00399 {
00400
00401 m_bTransactioning = false;
00402 }
00403 return !m_bTransactioning;
00404 }
00405 bool odbcRS::close( void )
00406 {
00407
00408 return !m_bOpen;
00409 }
00410
00411 bool odbcRS::next( int )
00412 {
00413
00414 rc = SQLFetch(hstmt);
00415 if((rc != SQL_SUCCESS) &&
00416 (rc != SQL_SUCCESS_WITH_INFO))
00417 {
00418 poDB->error(hstmt);
00419 return false;
00420 }
00421 UWORD icol;
00422
00423 for( icol = 0 ; icol < numCols; icol ++ )
00424 {
00425 odbcColInfo * pInfo = colInfo[icol];
00426 if( pInfo )
00427 {
00428 mapItem * pItem = colMap.data[pInfo->fSqlType];
00429 if( pItem )
00430 {
00431 basicField * pField = ordinals[icol];
00432 if( pField)
00433 {
00434 pItem->postFetchFixup(pInfo,pField);
00435 }
00436 }
00437 }
00438 }
00439
00440 return true;
00441 }
00442
00443 bool odbcRS::previous( int )
00444 {
00445
00446 return true;
00447 }