Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

pqxx-object/transaction_proxy.cc

Go to the documentation of this file.
00001 // database transaction convenience wrapper                      -*- C++ -*-
00002 // $Id: transaction.cc,v 1.4 2004/01/07 14:29:39 roger Exp $
00003 //
00004 // Copyright (C) 2003  Roger Leigh <rleigh@debian.org>
00005 //
00006 //
00007 // This program is free software; you can redistribute it and/or modify
00008 // it under the terms of the GNU General Public License as published by
00009 // the Free Software Foundation; either version 2 of the License, or
00010 // (at your option) any later version.
00011 //
00012 // This program is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021 #include <cassert>
00022 
00023 #include <sigc++/object.h>
00024 
00025 #include <pqxx-object/transaction.h>
00026 
00027 using namespace pqxxobject;
00028 
00029 transaction::transaction(pqxx::connection& connection,
00030                          pqxx::transaction<>*& transaction):
00031   m_connection(connection),
00032   m_transaction(transaction),
00033   m_autocommit(true),
00034   m_state(STATE_NONE)
00035 {
00036   // Set up database.
00037   // Turn off auto-committing of changes if the creator gave us a transaction.
00038   if (m_transaction != NULL)
00039     m_autocommit = false;
00040 }
00041 
00042 transaction::~transaction()
00043 {
00044 }
00045 
00046 SigC::Signal0<void>&
00047 transaction::signal_commit()
00048 {
00049   return m_signal_commit;
00050 }
00051 
00052 SigC::Signal0<void>&
00053 transaction::signal_abort()
00054 {
00055   return m_signal_abort;
00056 }
00057 
00058 void
00059 transaction::begin(const std::string& name)
00060 {
00061   assert ((m_transaction == NULL && m_autocommit == true) ||
00062           (m_transaction != NULL && m_autocommit == false));
00063 
00064   try
00065     {
00066       if (m_transaction == NULL)
00067         {
00068           assert (m_state != STATE_EXECUTING); // can't be executing without a transaction
00069           m_transaction = new pqxx::transaction<> (m_connection, name);
00070           m_state = STATE_EXECUTING;
00071         }
00072     }
00073   catch (const std::exception& e)
00074     {
00075       end();
00076       throw DatabaseError(e.what());
00077     }
00078   catch (...)
00079     {
00080       end();
00081       throw DatabaseError("An unknown exception occured in transaction::begin().");
00082     }
00083 }
00084 
00085 void
00086 transaction::end()
00087 {
00088   try
00089     {
00090       if (m_autocommit == true)
00091         {
00092           if (m_state == STATE_EXECUTING) // abort a running transaction
00093             abort();
00094           if (m_transaction) // abort() might delete the transaction
00095             {
00096               delete m_transaction;
00097               m_transaction = NULL;
00098             }
00099           m_state = STATE_NONE;
00100         }
00101     }
00102   catch (const std::exception& e)
00103     {
00104       throw DatabaseError(e.what());
00105     }
00106   catch (...)
00107     {
00108       throw DatabaseError("An unknown exception occured in transaction::end().");
00109     }
00110 }
00111 
00112 pqxx::result *
00113 transaction::exec(const std::string& query)
00114 {
00115   pqxx::result *R = NULL;
00116   try
00117     {
00118       R = new pqxx::result(m_transaction->exec(query));
00119       return R;
00120     }
00121   catch (const std::exception& e)
00122     {
00123       delete R;
00124       throw DatabaseError(e.what());
00125     }
00126   catch (...)
00127     {
00128       delete R;
00129       throw DatabaseError("An unknown exception occured in transaction::exec().");
00130     }
00131 }
00132 
00133 pqxx::result::size_type
00134 transaction::exec_noresult(const std::string& query)
00135 {
00136   pqxx::result *R = NULL;
00137   try
00138     {
00139       R = exec(query);
00140       pqxx::result::size_type rows = R->affected_rows();
00141 
00142       delete R;
00143 
00144       return rows;
00145     }
00146   catch (const std::exception& e)
00147     {
00148       delete R;
00149       throw DatabaseError(e.what());
00150     }
00151   catch (...)
00152     {
00153       delete R;
00154       throw DatabaseError("An unknown exception occured in transaction::exec_noresult().");
00155     }
00156 }
00157 
00158 pqxx::result::size_type
00159 transaction::perform(const std::string& query,
00160                      pqxx::result::size_type min_rows,
00161                      pqxx::result::size_type max_rows)
00162 {
00163   try
00164     {
00165       begin("transaction::perform()");
00166 
00167       pqxx::result::size_type rows;
00168       rows = exec_noresult(query);
00169 
00170       // Commit if the number of altered rows is greater or equal to
00171       // min_rows, or if min_rows is 0.
00172       if ((rows >= min_rows || min_rows == 0) &&
00173           (rows <= max_rows || max_rows == 0))
00174         commit();
00175       else
00176         abort();
00177 
00178       end();
00179 
00180       return rows;
00181     }
00182   catch (const std::exception& e)
00183     {
00184       end();
00185       throw DatabaseError(e.what());
00186     }
00187   catch (...)
00188     {
00189       end();
00190       throw DatabaseError("An unknown exception occured in transaction::perform().");
00191     }
00192 
00193       // This should never be reached.
00194       return 0;
00195     }
00196 
00197 void
00198 transaction::commit()
00199 {
00200   try
00201     {
00202       if (m_autocommit == true)
00203         {
00204           if (m_autocommit == true)
00205             m_transaction->commit();
00206         }
00207       m_state = STATE_COMMITTED;
00208       end();
00209       m_signal_commit.emit();
00210     }
00211   catch (const std::exception& e)
00212     {
00213       end();
00214       throw DatabaseError(e.what());
00215     }
00216   catch (...)
00217     {
00218       end();
00219       throw DatabaseError("An unknown exception occured in transaction::commit().");
00220     }
00221 }
00222 
00223 void
00224 transaction::abort()
00225 {
00226   try
00227     {
00228       if (m_autocommit == true)
00229         {
00230           if (m_autocommit == true)
00231             m_transaction->abort();
00232         }
00233       m_state = STATE_ABORTED;
00234       end();
00235       m_signal_abort.emit();
00236     }
00237   catch (const std::exception& e)
00238     {
00239       end();
00240       throw DatabaseError(e.what());
00241     }
00242   catch (...)
00243     {
00244       end();
00245       throw DatabaseError("An unknown exception occured in transaction::abort().");
00246     }
00247 }

Generated on Sat Jan 17 20:58:25 2004 for pqxx-object API Reference by doxygen 1.3.4