/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
/*************************************************************************
*
*
* PURPOSE:
* test class TransactionIF.
*
*
* COMMENTS:
* none
*
* PRECONDITIONS:
* - database exists and is accessible (PG & rasdaman server running)
* - reladminif/DatabaseIF works
*
***********************************************************************/
static const char rcsid[] = "@(#)reladminif,TransactionIf: $Id: testta.pgc,v 1.6 2003/12/27 23:11:43 rasdev Exp $";
#define DEBUG_MAIN
#include "debug.hh"
// constants:
#define DATABASE "RASBASE"
// pointers representing O2, database, ta and session
AdminIf* admin = NULL;
DatabaseIf* db = NULL;
TransactionIf* ta = NULL;
int main()
{
const char *prog = argv[0]; // this program's name
cout << prog << ": test for transactionif, generated on " << COMPDATE << endl;
// --- outmost exception catcher ------------------------
try
{
// --- (1) preparation: open connection
admin = AdminIf::instance();
if( !admin )
{
cout << prog << ": cannot create adminIf instance" << endl;
throw r_Error();
}
// connect to the database
db = new DatabaseIf();
if( !admin )
{
cout << prog << ": cannot create DatabaseIf instance" << endl;
throw r_Error();
}
db->open( DATABASE );
ta = new TransactionIf();
if( !admin )
{
cout << prog << ": cannot create TransactionIf instance" << endl;
throw r_Error();
}
ta->begin( db );
ta->abort( db );
ta->commit( db );
db->close();
}
catch(...)
{
cout << prog << ": error abort." << endl;
}
cout << prog << ": test for transactionif done." << endl;
}
void
TransactionIf::begin( bool readOnly ) throw ( r_Error )
{
RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ")");
ENTER( "TransactionIf::begin, readOnly=" << readOnly );
isReadOnly = readOnly;
AdminIf::setAborted(false);
AdminIf::setReadOnlyTA(readOnly);
TALK( "EXEC SQL BEGIN WORK" );
EXEC SQL BEGIN WORK;
if (sqlca.sqlwarn[2] == 'W') // real error, not just a warning
{
SQLCODE = 0; // FIXME: bad hack, as PG can't reset error state and SQLCODE is queried in many places -- PB 2005-jan-09
}
else
{
RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing BEGIN");
LEAVE( "TransactionIf::begin(): error during BEGIN: " << SQLCODE );
generateException();
}
if (readOnly)
{
TALK( "EXEC SQL SET TRANSACTION READ ONLY" );
EXEC SQL SET TRANSACTION READ ONLY;
// no error check, as this doesn't inhibit work
}
// prelim.:have additional libpq TA -- PB 2005-jan-09
TALK( "PQexec( pgConn, BEGIN )" );
PGresult *pgResult = PQexec( pgConn, "BEGIN" );
if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
{
LEAVE( "TransactionIf::begin() Error: cannot open libpq TA: " << PQerrorMessage(pgConn) );
generateException();
}
#ifdef RMANBENCHMARK
DBObject::readTimer.start();
DBObject::readTimer.pause();
DBObject::updateTimer.start();
DBObject::updateTimer.pause();
DBObject::deleteTimer.start();
DBObject::deleteTimer.pause();
DBObject::insertTimer.start();
DBObject::insertTimer.pause();
OId::oidAlloc.start();
OId::oidAlloc.pause();
OId::oidResolve.start();
OId::oidResolve.pause();
#endif
OId::initialize();
TypeFactory::initialize();
LEAVE( "TransactionIf::begin, SQLCODE=" << SQLCODE );
RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "begin(" << readOnly << ") ");
}
void
TransactionIf::commit() throw ( r_Error )
{
RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "commit()");
ENTER( "TransactionIf::commit" );
if (isReadOnly)
{
RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "read only: aborting");
TALK( "TA is readonly: aborting" );
abort();
}
else
{
AdminIf::setAborted(false);
RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "set aborted false");
TypeFactory::freeTempTypes();
RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "freed temp types");
ObjectBroker::clearBroker();
RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "cleared broker");
OId::deinitialize();
RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "wrote oid counters");
AdminIf::setReadOnlyTA(false);
RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "committing");
TALK( "EXEC SQL COMMIT WORK" );
EXEC SQL COMMIT WORK;
if (check("TransactionIf::begin() COMMIT\0"))
{
RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing COMMIT");
LEAVE( "TransactionIf::commit(): error during COMMIT:" << SQLCODE );
generateException();
}
// prelim.:have additional libpq TA -- PB 2005-jan-09
TALK( "PQexec( pgConn, END )" );
PGresult *pgResult = PQexec( pgConn, "END" );
if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
{
LEAVE( "TransactionIf::commit() Error: cannot commit libpq TA: " << PQerrorMessage(pgConn) );
generateException();
}
if (lastBase)
{
RMDBGMIDDLE(9, RMDebug::module_adminif, "TransactionIf", "closing dbms");
lastBase->baseDBMSClose();
}
}
#ifdef RMANBENCHMARK
DBObject::readTimer.stop();
DBObject::updateTimer.stop();
DBObject::deleteTimer.stop();
DBObject::insertTimer.stop();
OId::oidAlloc.stop();
OId::oidResolve.stop();
#endif
LEAVE( "TransactionIf::commit" );
RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "commit() " << endl << endl);
}
void
TransactionIf::abort()
{
RMDBGENTER(2, RMDebug::module_adminif, "TransactionIf", "abort()");
ENTER( "TransactionIf::abort" );
// prelim.:have additional libpq TA -- PB 2005-jan-09
TALK( "PQexec( pgConn, ABORT )" );
PGresult *pgResult = PQexec( pgConn, "ABORT" );
if (PQresultStatus(pgResult) != PGRES_COMMAND_OK)
{
LEAVE( "TransactionIf::abort() Error: cannot abort libpq TA: " << PQerrorMessage(pgConn) );
generateException();
}
AdminIf::setAborted(true);
TypeFactory::freeTempTypes();
ObjectBroker::clearBroker();
OId::deinitialize();
AdminIf::setReadOnlyTA(false);
TALK( "EXEC SQL ROLLBACK WORK" );
EXEC SQL ROLLBACK WORK;
if (check("TransactionIf::abort() ROLLBACK\0"))
{
RMDBGMIDDLE(4, RMDebug::module_adminif, "TransactionIf", "error occured while issuing ROLLBACK");
TALK( "TransactionIf::abort(): error during ROLLBACK, still continuing: " << SQLCODE );
}
if(lastBase)
lastBase->baseDBMSClose();
#ifdef RMANBENCHMARK
DBObject::readTimer.stop();
DBObject::updateTimer.stop();
DBObject::deleteTimer.stop();
DBObject::insertTimer.stop();
OId::oidAlloc.stop();
OId::oidResolve.stop();
#endif
LEAVE( "TransactionIf::abort, SQLCODE=" << SQLCODE );
RMDBGEXIT(2, RMDebug::module_adminif, "TransactionIf", "abort() " << endl << endl);
}