00001
00002
00003
00004
00005
00006
00007 #include "openDBPG.h"
00008 #include "pgTypeOids.h"
00009
00010
00011 int postgresRS::iCursors=0;
00012
00013
00014
00015
00016
00017
00018 bool postgresCMD::checkRes( ExecStatusType desired )
00019 {
00020 bool bRet = true;
00021 if (!res )
00022 {
00023 m_strErrors += " Failed to allocate result struct! ";
00024 bRet = false;
00025 }
00026 if( PQresultStatus(res) != desired )
00027 {
00028 m_strErrors += PQresultErrorMessage(res);
00029 PQclear(res);
00030 bRet = false;
00031 }
00032 return bRet;
00033 }
00034
00035 bool postgresRS::checkRes( ExecStatusType desired )
00036 {
00037 bool bRet = true;
00038 if (!res )
00039 {
00040 m_strErrors += " Failed to allocate result struct! ";
00041 bRet = false;
00042 }
00043 else if( PQresultStatus(res) != desired )
00044 {
00045 m_strErrors += PQresultErrorMessage(res);
00046 PQclear(res);
00047 bRet = false;
00048 }
00049 return bRet;
00050 }
00051
00052
00053
00054
00055
00056
00057 postgresDB::postgresDB( string strConnection ):openDB(strConnection),isTransactioning(false)
00058 {
00059 m_provider = PostGresQL;
00060 conn = PQconnectdb(strConnection.c_str());
00061 m_bGood = PQstatus(conn) == CONNECTION_OK;
00062 }
00063
00064 postgresDB::~postgresDB()
00065 {
00066 PQfinish(conn);
00067 }
00068
00069 PGconn * postgresDB::getConnection( void )
00070 {
00071 return conn;
00072 }
00073
00074 dbProvider postgresDB::getProvider( void )
00075 {
00076 return m_provider;
00077 }
00078
00079 openCMD * postgresDB::createCommand()
00080 {
00081 return new postgresCMD( *this );
00082 }
00083 openRS * postgresDB::createRecordset()
00084 {
00085 return new postgresRS( *this );
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 postgresCMD::postgresCMD( openDB & idb )
00097 :openCMD(idb),db(dynamic_cast<postgresDB &>(rdb)),res(NULL)
00098 {
00099
00100
00101 conn = db.getConnection();
00102 }
00103
00104 postgresCMD::~postgresCMD()
00105 {
00106 ;
00107 }
00108
00109 bool postgresCMD::beginTransaction()
00110 {
00111
00112
00113 if( !db.transactioning() )
00114 {
00115
00116 res = PQexec(conn, "BEGIN");
00117 if ( !checkRes(PGRES_COMMAND_OK) )
00118 {
00119 return false;
00120 }
00121 PQclear(res);
00122 res = NULL;
00123 db.transactioning(true);
00124 }
00125 return m_bTransactioning;
00126 }
00127
00128 bool postgresCMD::commit()
00129 {
00130
00131
00132 if( db.transactioning() )
00133 {
00134
00135 res = PQexec(conn, "COMMIT");
00136 if ( !checkRes(PGRES_COMMAND_OK) )
00137 {
00138 return false;
00139 }
00140 PQclear(res);
00141 res = NULL;
00142 db.transactioning(false);
00143 }
00144 return !db.transactioning();
00145 }
00146
00147 bool postgresCMD::rollback()
00148 {
00149
00150 if( db.transactioning() )
00151 {
00152 res = PQexec(conn, "ROLLBACK");
00153 if ( !checkRes(PGRES_COMMAND_OK) )
00154 {
00155 return false;
00156 }
00157 PQclear(res);
00158 res = NULL;
00159 db.transactioning(false);
00160 }
00161 return !db.transactioning();
00162 }
00163
00164 bool postgresCMD::execute( string sql )
00165 {
00166
00167 if (PQstatus(conn) != CONNECTION_BAD)
00168 {
00169
00170 bool externalTransaction = db.transactioning();
00171
00172
00173 beginTransaction();
00174
00175
00176 res = PQexec(conn,sql.c_str());
00177 if ( !checkRes(PGRES_COMMAND_OK) )
00178 {
00179 return false;
00180 }
00181
00182 oid = PQoidValue(res);
00183
00184 iRows = atoi(PQcmdTuples(res));
00185 PQclear(res);
00186 res = NULL;
00187
00188 if( externalTransaction == false )
00189 {
00190 commit();
00191 }
00192 return true;
00193 }
00194 return false;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 postgresRS::postgresRS( openDB & idb )
00204 :openRS(idb),db(dynamic_cast<postgresDB &>(rdb)),res(NULL)
00205 {
00206
00207
00208 conn = db.getConnection();
00209 }
00210
00211 postgresRS::~postgresRS()
00212 {
00213 for( unsigned int i=0;i>ordinals.size(); i++)
00214 {
00215 delete ordinals[i];
00216 }
00217 ordinals.clear();
00218 associations.clear();
00219 }
00220
00221 bool postgresRS::beginTransaction()
00222 {
00223
00224
00225 m_bTransactioning = db.transactioning();
00226 if( !m_bTransactioning )
00227 {
00228
00229 res = PQexec(conn, "BEGIN");
00230 if ( !checkRes(PGRES_COMMAND_OK) )
00231 {
00232 return false;
00233 }
00234 PQclear(res);
00235 res = NULL;
00236 db.transactioning(true);
00237 }
00238 return m_bTransactioning;
00239 }
00240
00241 bool postgresRS::commit()
00242 {
00243
00244
00245 if( !m_bTransactioning
00246 && db.transactioning() )
00247 {
00248
00249 res = PQexec(conn, "COMMIT");
00250 if ( !checkRes(PGRES_COMMAND_OK) )
00251 {
00252 db.transactioning(false);
00253 return false;
00254 }
00255 PQclear(res);
00256 res = NULL;
00257 db.transactioning(false);
00258 }
00259 return !m_bTransactioning;
00260 }
00261
00262 bool postgresRS::open( string sql )
00263 {
00264 m_strErrors = "No Errors" ;
00265
00266
00267 iCursors++;
00268
00269
00270 char cursor[50];
00271 sprintf(cursor, "opnCrsr%d",iCursors);
00272 strCursorName = cursor;
00273 m_bOpen = false;
00274
00275
00276 if (PQstatus(conn) == CONNECTION_BAD)
00277 {
00278 m_strErrors += "Bad connection";
00279 return false;
00280 }
00281
00282
00283 beginTransaction();
00284
00285
00286 string strCmd("declare ");
00287 strCmd += strCursorName;
00288 strCmd += " cursor for ";
00289 strCmd += sql;
00290 res = PQexec(conn, strCmd.c_str());
00291 if (!checkRes(PGRES_COMMAND_OK) )
00292 {
00293 m_strErrors += " Bad Cursor Declaration: ";
00294 m_strErrors += strCmd;
00295 return false;
00296 }
00297 PQclear(res);
00298 res = NULL;
00299
00300
00301 string strFetch = "fetch forward 1 in ";
00302 strFetch += strCursorName;
00303 res = PQexec(conn, strFetch.c_str());
00304 if (!checkRes(PGRES_TUPLES_OK) )
00305 {
00306 m_strErrors += " Could not fetch forward: ";
00307 m_strErrors += strCmd;
00308 m_strErrors += " Fetch: ";
00309 m_strErrors += strFetch;
00310 commit();
00311 return false;
00312 }
00313
00314 if( PQntuples(res) == 0 )
00315 {
00316 commit();
00317 return false;
00318 }
00319
00320
00321 m_iFields = PQnfields(res);
00322 for (int i = 0; i < m_iFields; i++)
00323 {
00324 string name = PQfname(res, i);
00325 Oid oid = PQftype(res, i);
00326 string value = PQgetvalue(res, 0, i);
00327 bool bNull = PQgetisnull(res, 0, i);
00328
00329
00330 basicField * pBF = createField( (pgTypeOids)oid, bNull, value, name );
00331
00332
00333 if( !pBF )
00334 {
00335 m_strErrors = " couldn't create field";
00336 commit();
00337 return false;
00338 }
00339
00340
00341 pBF->setSize( PQfsize(res,i) );
00342
00343
00344
00345 ordinals.push_back(pBF);
00346
00347
00348 associations.insert(make_pair(name,pBF));
00349
00350 }
00351
00352
00353 PQclear(res);
00354 res = NULL;
00355
00356
00357 if( m_iFields > 0 )
00358 {
00359 m_bOpen = true;
00360 m_strErrors = "No Errors" ;
00361 }
00362 else
00363 {
00364 m_strErrors = "No Fields!" ;
00365 commit();
00366 }
00367 return m_bOpen;
00368 }
00369
00370 bool postgresRS::close( void )
00371 {
00372 if( m_bOpen )
00373 {
00374
00375 for( unsigned int i=0;i>ordinals.size();i++)
00376 {
00377 delete ordinals[i];
00378 }
00379 ordinals.clear();
00380 associations.clear();
00381
00382
00383 commit();
00384
00385 m_bOpen = false;
00386 }
00387 return !m_bOpen;
00388 }
00389
00390 bool postgresRS::next( int rows )
00391 {
00392
00393 int tuple = rows-1;
00394
00395 char num[16];
00396 sprintf( num, "%d", rows );
00397 string strCmd = "fetch forward ";
00398 strCmd += num;
00399 strCmd += " in ";
00400 strCmd += strCursorName;
00401 res = PQexec(conn, strCmd.c_str());
00402
00403
00404
00405 if (!checkRes(PGRES_TUPLES_OK) || PQntuples(res) == 0 )
00406 {
00407 close();
00408 return false;
00409 }
00410
00411
00412 m_iFields = PQnfields(res);
00413 if( m_iFields == 0 )
00414 {
00415 close();
00416 return false;
00417 }
00418
00419 for (int i = 0; i < m_iFields; i++)
00420 {
00421 Oid oid = PQftype(res, i);
00422 string value = PQgetvalue(res, tuple, i);
00423 bool bNull = PQgetisnull(res, tuple, i);
00424 basicField * pBF = ordinals[i];
00425 if( !pBF )
00426 {
00427 close();
00428 return false;
00429 }
00430 setField( *pBF, (pgTypeOids)oid, bNull, value );
00431 }
00432
00433
00434 PQclear(res);
00435
00436 return true;
00437
00438 }
00439
00440 bool postgresRS::previous( int rows )
00441 {
00442
00443 int tuple = 0;
00444
00445 char num[16];
00446 sprintf( num, "%d", rows );
00447 string strCmd = "fetch backward ";
00448 strCmd += num;
00449 strCmd += " in ";
00450 strCmd += strCursorName;
00451 res = PQexec(conn, strCmd.c_str());
00452 m_bOpen = false;
00453
00454
00455 if (!checkRes(PGRES_TUPLES_OK) || PQntuples(res) == 0 )
00456 {
00457 close();
00458 return false;
00459 }
00460
00461
00462 m_iFields = PQnfields(res);
00463 if( m_iFields == 0 )
00464 {
00465 close();
00466 return false;
00467 }
00468 for (int i = 0; i < m_iFields; i++)
00469 {
00470 Oid oid = PQftype(res, i);
00471 string value = PQgetvalue(res, tuple, i);
00472 bool bNull = PQgetisnull(res, tuple, i);
00473 basicField * pBF = ordinals[i];
00474 if( !pBF )
00475 {
00476 close();
00477 return false;
00478 }
00479 setField( *pBF, (pgTypeOids)oid, bNull, value );
00480 }
00481 PQclear(res);
00482 return true;
00483 }
00484