[glom] libglom: ConnectionPool: Simplify code.



commit 7f6b199d44d2b88a9f053eb54c1157cfd2b419ca
Author: Murray Cumming <murrayc murrayc com>
Date:   Sun Jun 20 19:04:42 2010 +0200

    libglom: ConnectionPool: Simplify code.
    
    * glom/libglom/connectionpool_backends/backend.[h|cc]:
    * glom/libglom/connectionpool_backends/postgres.[h|cc]:
    * glom/libglom/connectionpool_backends/postgres_central.[h|cc]:
    * glom/libglom/connectionpool_backends/postgres_self.[h|cc]:
    * glom/libglom/connectionpool_backends/sqlite.[h|cc]: Remove the
    query_execute(), create_server_operation(), perform_server_operation(),
    begin_transaction(), commit_transaction() and rollback_transaction()
    convenience methods, which just hide the no-exceptions ifdefs.
    But gtkmm-3.0 does not support that anyway, so we don't need it.
    Just call the libgdamm methods directly.
    add_column(), drop_column(), change_columns(), connect():
    Remove the error output parameters which were there for the same reason.
    Now they just throw.
    * glom/libglom/connectionpool.[h|cc]: Adapted code, hopefully making it
    simpler.

 ChangeLog                                          |   20 +
 glom/libglom/connectionpool.cc                     |  189 ++------
 glom/libglom/connectionpool.h                      |   36 +--
 glom/libglom/connectionpool_backends/backend.cc    |  231 +---------
 glom/libglom/connectionpool_backends/backend.h     |   24 +-
 glom/libglom/connectionpool_backends/postgres.cc   |  476 +++++++++-----------
 glom/libglom/connectionpool_backends/postgres.h    |    8 +-
 .../connectionpool_backends/postgres_central.cc    |   43 ++-
 .../connectionpool_backends/postgres_central.h     |    4 +-
 .../connectionpool_backends/postgres_self.cc       |   36 +-
 .../connectionpool_backends/postgres_self.h        |    4 +-
 glom/libglom/connectionpool_backends/sqlite.cc     |  163 +++----
 glom/libglom/connectionpool_backends/sqlite.h      |   16 +-
 13 files changed, 438 insertions(+), 812 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 933aebb..0282211 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2010-06-20  Murray Cumming  <murrayc murrayc com>
+
+	libglom: ConnectionPool: Simplify code.
+	
+	* glom/libglom/connectionpool_backends/backend.[h|cc]:
+	* glom/libglom/connectionpool_backends/postgres.[h|cc]:
+	* glom/libglom/connectionpool_backends/postgres_central.[h|cc]:
+	* glom/libglom/connectionpool_backends/postgres_self.[h|cc]:
+	* glom/libglom/connectionpool_backends/sqlite.[h|cc]: Remove the 
+	query_execute(), create_server_operation(), perform_server_operation(), 
+	begin_transaction(), commit_transaction() and rollback_transaction() 
+	convenience methods, which just hide the no-exceptions ifdefs.
+	But gtkmm-3.0 does not support that anyway, so we don't need it.
+	Just call the libgdamm methods directly.
+	add_column(), drop_column(), change_columns(), connect():
+	Remove the error output parameters which were there for the same reason.
+	Now they just throw.
+	* glom/libglom/connectionpool.[h|cc]: Adapted code, hopefully making it 
+	simpler.
+
 2010-06-19  Murray Cumming  <murrayc murrayc com>
 
 	Use Gnome::Gda::SqlBuilder::Id
diff --git a/glom/libglom/connectionpool.cc b/glom/libglom/connectionpool.cc
index dfb560b..380e460 100644
--- a/glom/libglom/connectionpool.cc
+++ b/glom/libglom/connectionpool.cc
@@ -27,7 +27,7 @@
 
 #include <libglom/connectionpool_backends/postgres_central.h>
 #include <libglom/connectionpool_backends/postgres_self.h>
-# include <libglom/connectionpool_backends/sqlite.h>
+#include <libglom/connectionpool_backends/sqlite.h>
 
 #ifdef G_OS_WIN32
 # include <windows.h>
@@ -209,11 +209,7 @@ const ConnectionPool::Backend* ConnectionPool::get_backend() const
 
 
 //static:
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
 sharedptr<SharedConnection> ConnectionPool::get_and_connect()
-#else
-sharedptr<SharedConnection> ConnectionPool::get_and_connect(std::auto_ptr<ExceptionConnection>& error)
-#endif // GLIBMM_EXCEPTIONS_ENABLED
 {
   sharedptr<SharedConnection> result(0);
 
@@ -227,11 +223,7 @@ sharedptr<SharedConnection> ConnectionPool::get_and_connect(std::auto_ptr<Except
     return result; //TODO: Return a FAILURE_NO_BACKEND error?, though that would be tedious.
   }
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   result = connection_pool->connect();
-#else
-  result = connection_pool->connect(error);
-#endif // GLIBMM_EXCEPTIONS_ENABLED
 
   return result;
 }
@@ -257,11 +249,7 @@ static bool on_connection_pool_cache_timeout()
 }
 
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
 sharedptr<SharedConnection> ConnectionPool::connect()
-#else
-sharedptr<SharedConnection> ConnectionPool::connect(std::auto_ptr<ExceptionConnection>& error)
-#endif
 {
   //Don't try to connect if we don't have a backend to connect to.
   g_return_val_if_fail(m_backend.get(), sharedptr<SharedConnection>(0));
@@ -300,24 +288,19 @@ sharedptr<SharedConnection> ConnectionPool::connect(std::auto_ptr<ExceptionConne
     }
     else
     {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-      std::auto_ptr<ExceptionConnection> error;
-#endif
-      m_refGdaConnection = m_backend->connect(m_database, get_user(), get_password(), error);
-
-      if(!m_refGdaConnection)
+      try
       {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-        throw *error;
-#endif
-        return sharedptr<SharedConnection>(0);
+        m_refGdaConnection = m_backend->connect(m_database, get_user(), get_password());
       }
-      else
+      catch(const Glib::Error& ex)
+      {
+        throw ex;
+      }
+
       {
         //Allow get_meta_store_data() to succeed:
         //Hopefully this (and the update_meta_store_for_table() calls) is all we need.
         //std::cout << "DEBUG: Calling update_meta_store_data_types() ..." << std::endl;
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
         try
         {
           m_refGdaConnection->update_meta_store_data_types();
@@ -327,14 +310,9 @@ sharedptr<SharedConnection> ConnectionPool::connect(std::auto_ptr<ExceptionConne
           std::cerr << "ConnectionPool::connect(): update_meta_store_data_types() failed: " << ex.what() << std::endl;
         }
         //std::cout << "DEBUG: ... update_meta_store_data_types() has finished." << std::endl;
-#else
-        std::auto_ptr<Glib::Error> ex;
-        m_refGdaConnection->update_meta_store_data_types(ex);
-        if (ex.get())
-          std::cerr << "ConnectionPool::connect(): update_meta_store_data_types() failed: " << ex->what() << std::endl;
-#endif
+
         //std::cout << "DEBUG: Calling update_meta_store_table_names() ..." << std::endl;
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
+
         try
         {
           //update_meta_store_table_names() has been known to throw an exception.
@@ -346,11 +324,6 @@ sharedptr<SharedConnection> ConnectionPool::connect(std::auto_ptr<ExceptionConne
           std::cerr << "ConnectionPool::connect(): update_meta_store_table_names() failed: " << ex.what() << std::endl;
         }
         //std::cout << "DEBUG: ... update_meta_store_table_names() has finished." << std::endl;
-#else
-        m_refGdaConnection->update_meta_store_table_names(m_backend->get_public_schema_name(), ex);
-        if (ex.get())
-          std::cerr << "ConnectionPool::connect(): update_meta_store_data_types() failed: " << ex->what() << std::endl;
-#endif
 
         // Connection succeeded
         // Create the fieldtypes member if it has not already been done:
@@ -368,11 +341,7 @@ sharedptr<SharedConnection> ConnectionPool::connect(std::auto_ptr<ExceptionConne
           avahi_start_publishing(); //Stopped in the signal_finished handler.
 #endif // !G_OS_WIN32
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
         return connect(); //Call this method recursively. This time m_refGdaConnection exists.
-#else
-        return connect(error); //Call this method recursively. This time m_refGdaConnection exists.
-#endif // GLIBMM_EXCEPTIONS_ENABLED
       }
     }
   }
@@ -384,21 +353,10 @@ sharedptr<SharedConnection> ConnectionPool::connect(std::auto_ptr<ExceptionConne
   return sharedptr<SharedConnection>(0);
 }
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
 void ConnectionPool::create_database(const Glib::ustring& database_name)
-#else
-void ConnectionPool::create_database(const Glib::ustring& database_name, std::auto_ptr<Glib::Error>& error)
-#endif
 {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  std::auto_ptr<Glib::Error> error;
-#endif
   if(m_backend.get())
-    m_backend->create_database(database_name, get_user(), get_password(), error);
-
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  if(error.get()) throw *error;
-#endif
+    m_backend->create_database(database_name, get_user(), get_password());
 }
 
 void ConnectionPool::set_user(const Glib::ustring& value)
@@ -502,13 +460,8 @@ void ConnectionPool::on_sharedconnection_finished()
 //static
 bool ConnectionPool::handle_error_cerr_only()
 {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   sharedptr<SharedConnection> sharedconnection = get_and_connect();
-#else
-  std::auto_ptr<ExceptionConnection> conn_error;
-  sharedptr<SharedConnection> sharedconnection = get_and_connect(conn_error);
-  // Ignore error, sharedconnection presence is checked below
-#endif
+
   if(sharedconnection)
   {
     Glib::RefPtr<Gnome::Gda::Connection> gda_connection = sharedconnection->get_gda_connection();
@@ -630,134 +583,78 @@ bool ConnectionPool::set_network_shared(const SlotProgress& slot_progress, bool
     return false;
 }
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-bool ConnectionPool::add_column(const Glib::ustring& table_name, const sharedptr<const Field>& field)
-#else
-bool ConnectionPool::add_column(const Glib::ustring& table_name, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error)
-#endif
+bool ConnectionPool::add_column(const Glib::ustring& table_name, const sharedptr<const Field>& field) throw()
 {
   sharedptr<SharedConnection> conn;
   if(!m_refGdaConnection)
   {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
     conn = connect();
-#else
-    std::auto_ptr<ExceptionConnection> local_error;
-    // TODO: We can't rethrow local_error here since ExceptionConnection does
-    // not derive from Glib::Error
-    conn = connect(local_error);
-#endif
   }
 
   if(!m_refGdaConnection)
     return false;
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  std::auto_ptr<Glib::Error> error;
-#endif
-  const bool result = m_backend->add_column(m_refGdaConnection, table_name, field, error);
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  if(error.get()) throw *error;
-  m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name());
-#else
-  if(error.get())
-    std::cerr << "Error: " << error->what() << std::endl;
-  m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name(), error);
-  if(error.get())
-    std::cerr << "Error: " << error->what() << std::endl;
-#endif
-  return result;
+  
+  try
+  {
+    m_backend->add_column(m_refGdaConnection, table_name, field);
+    m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name());
+    return true;
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << "ConnectionPool::add_column(): exception:" << ex.what() << std::endl;
+  }
+  
+  return false;
 }
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-bool ConnectionPool::drop_column(const Glib::ustring& table_name, const Glib::ustring& field_name)
-#else
-bool ConnectionPool::drop_column(const Glib::ustring& table_name, const Glib::ustring& field_name, std::auto_ptr<Glib::Error>& error)
-#endif
+bool ConnectionPool::drop_column(const Glib::ustring& table_name, const Glib::ustring& field_name) throw()
 {
   sharedptr<SharedConnection> conn;
   if(!m_refGdaConnection)
   {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
     conn = connect();
-#else
-    std::auto_ptr<ExceptionConnection> local_error;
-    // TODO: We can't rethrow local_error here since ExceptionConnection does
-    // not derive from Glib::Error
-    conn = connect(local_error);
-#endif
   }
 
   if(!m_refGdaConnection)
     return false;
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  std::auto_ptr<Glib::Error> error;
-#endif
-  const bool result = m_backend->drop_column(m_refGdaConnection, table_name, field_name, error);
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  if(error.get()) throw *error;
-  m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name());
-#else
-  if(error.get())
-    std::cerr << "Error: " << error->what() << std::endl;
-  m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name(), error);
-  if(error.get())
-    std::cerr << "Error: " << error->what() << std::endl;
-#endif
-  return result;
+  try
+  {
+    m_backend->drop_column(m_refGdaConnection, table_name, field_name);
+    m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name());
+    return true;
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << "ConnectionPool::drop_column(): exception:" << ex.what() << std::endl;
+  }
+  
+  return false;
 }
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-bool ConnectionPool::change_column(const Glib::ustring& table_name, const sharedptr<const Field>& field_old, const sharedptr<const Field>& field)
-#else
-bool ConnectionPool::change_column(const Glib::ustring& table_name, const sharedptr<const Field>& field_old, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error)
-#endif
+bool ConnectionPool::change_column(const Glib::ustring& table_name, const sharedptr<const Field>& field_old, const sharedptr<const Field>& field) throw()
 {
   type_vec_const_fields old_fields(1, field_old);
   type_vec_const_fields new_fields(1, field);
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   return change_columns(table_name, old_fields, new_fields);
-#else
-  return change_columns(table_name, old_fields, new_fields, error);
-#endif
 }
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-bool ConnectionPool::change_columns(const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields)
-#else
-bool ConnectionPool::change_columns(const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error)
-#endif
+bool ConnectionPool::change_columns(const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields) throw()
 {
   sharedptr<SharedConnection> conn;
   if(!m_refGdaConnection)
   {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
     conn = connect();
-#else
-    std::auto_ptr<ExceptionConnection> local_error;
-    // TODO: We can't rethrow local_error here since ExceptionConnection does
-    // not derive from Glib::Error
-    conn = connect(local_error);
-#endif
   }
 
   if(!m_refGdaConnection)
     return false;
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  std::auto_ptr<Glib::Error> error;
-#endif
-  const bool result = m_backend->change_columns(m_refGdaConnection, table_name, old_fields, new_fields, error);
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  if(error.get()) throw *error;
+  const bool result = m_backend->change_columns(m_refGdaConnection, table_name, old_fields, new_fields);
   m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name());
 
-#else
-  if(error.get())
-    std::cerr << "Error: " << error->what() << std::endl;
-  m_refGdaConnection->update_meta_store_table(table_name, m_backend->get_public_schema_name(), error);
-#endif
   return result;
 }
 
@@ -818,7 +715,7 @@ gboolean ConnectionPool::on_publisher_document_authentication(EpcAuthContext* co
 
   //Attempt a connection with this username/password:
   std::auto_ptr<ExceptionConnection> error;
-  Glib::RefPtr<Gnome::Gda::Connection> connection = connection_pool->m_backend->connect(connection_pool->get_database(), user_name, password, error);
+  Glib::RefPtr<Gnome::Gda::Connection> connection = connection_pool->m_backend->connect(connection_pool->get_database(), user_name, password);
 
   if(connection)
   {
diff --git a/glom/libglom/connectionpool.h b/glom/libglom/connectionpool.h
index b02fe35..8d42fa5 100644
--- a/glom/libglom/connectionpool.h
+++ b/glom/libglom/connectionpool.h
@@ -137,25 +137,13 @@ public:
    *
    * @throws an ExceptionConnection when the connection fails.
    */
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   sharedptr<SharedConnection> connect();
-#else
-  sharedptr<SharedConnection> connect(std::auto_ptr<ExceptionConnection>& error);
-#endif
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   static sharedptr<SharedConnection> get_and_connect();
-#else
-  static sharedptr<SharedConnection> get_and_connect(std::auto_ptr<ExceptionConnection>& error);
-#endif
 
   /** Creates a new database.
    */
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   void create_database(const Glib::ustring& database_name);
-#else
-  void create_database(const Glib::ustring& database_name, std::auto_ptr<Glib::Error>& error);
-#endif
 
   void set_user(const Glib::ustring& value);
   void set_password(const Glib::ustring& value);
@@ -215,29 +203,13 @@ public:
    */
   virtual bool set_network_shared(const SlotProgress& slot_progress, bool network_shared = true);
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  bool add_column(const Glib::ustring& table_name, const sharedptr<const Field>& field);
-#else
-  bool add_column(const Glib::ustring& field_name, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error);
-#endif
+  bool add_column(const Glib::ustring& table_name, const sharedptr<const Field>& field) throw();
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  bool drop_column(const Glib::ustring& table_name, const Glib::ustring& field_name);
-#else
-  bool drop_column(const Glib::ustring& table_name, const Glib::ustring& field_name, std::auto_ptr<Glib::Error>& error);
-#endif
+  bool drop_column(const Glib::ustring& table_name, const Glib::ustring& field_name) throw();
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  bool change_column(const Glib::ustring& table_name, const sharedptr<const Field>& field_old, const sharedptr<const Field>& field);
-#else
-  bool change_column(const Glib::ustring& table_name, const sharedptr<const Field>& field_old, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error);
-#endif
+  bool change_column(const Glib::ustring& table_name, const sharedptr<const Field>& field_old, const sharedptr<const Field>& field) throw();
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  bool change_columns(const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& fields);
-#else
-  bool change_columns(const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& fields, std::auto_ptr<Glib::Error>& error);
-#endif
+  bool change_columns(const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& fields) throw();
 
   /** Specify a callback that the ConnectionPool can call to get a pointer to the document.
    * This callback avoids Connection having to link to Application,
diff --git a/glom/libglom/connectionpool_backends/backend.cc b/glom/libglom/connectionpool_backends/backend.cc
index 201786c..76df895 100644
--- a/glom/libglom/connectionpool_backends/backend.cc
+++ b/glom/libglom/connectionpool_backends/backend.cc
@@ -65,235 +65,30 @@ bool Backend::set_network_shared(const SlotProgress& /* slot_progress */, bool /
   return true; //Success at doing nothing.
 }
 
-bool Backend::set_server_operation_value(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const Glib::ustring& path, const Glib::ustring& value, std::auto_ptr<Glib::Error>& error)
-{
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    operation->set_value_at(path, value);
-    return true;
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return false;
-  }
-#else
-  operation->set_value_at(path, value, error);
-  if(error.get()) return false;
-  return true;
-#endif
-}
-
-Glib::RefPtr<Gnome::Gda::ServerOperation> Backend::create_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, Gnome::Gda::ServerOperationType type, std::auto_ptr<Glib::Error>& error)
-{
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    return provider->create_operation(connection, type);
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return Glib::RefPtr<Gnome::Gda::ServerOperation>();
-  }
-#else
-  return provider->create_operation(connection, type, error);
-#endif
-}
-
-bool Backend::perform_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, std::auto_ptr<Glib::Error>& error)
-{
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    provider->perform_operation(connection, operation);
-    return true;
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return false;
-  }
-#else
-  provider->perform_operation(connection, operation, error);
-  if(error.get()) return false;
-  return true;
-#endif
-}
-
-bool Backend::begin_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, Gnome::Gda::TransactionIsolation level, std::auto_ptr<Glib::Error>& error)
-{
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    return connection->begin_transaction(name, level);
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return false;
-  }
-#else
-  return connection->begin_transaction(name, level, error);
-#endif
-}
-
-bool Backend::commit_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error)
-{
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    return connection->commit_transaction(name);
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return false;
-  }
-#else
-  return connection->commit_transaction(name, error);
-#endif
-}
-
-bool Backend::rollback_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error)
-{
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    return connection->rollback_transaction(name);
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return false;
-  }
-#else
-  return connection->rollback_transaction(name, error);
-#endif
-}
-
-bool Backend::query_execute(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& sql_query, std::auto_ptr<Glib::Error>& error)
-{
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    return connection->statement_execute_non_select(sql_query) != -1;
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return false;
-  }
-#else
-  return connection->statement_execute_non_select(sql_query, error) != -1;
-#endif
-}
-
-bool Backend::add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error)
+void Backend::add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field)
 {
   Glib::RefPtr<Gnome::Gda::ServerProvider> provider = connection->get_provider();
-  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = create_server_operation(provider, connection, Gnome::Gda::SERVER_OPERATION_ADD_COLUMN, error);
-  if(!operation) return false;
+  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = provider->create_operation(connection, Gnome::Gda::SERVER_OPERATION_ADD_COLUMN);
 
   //TODO: Quote table_name and field_name?
-  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/TABLE_NAME", table_name, error))
-    return false;
+  operation->set_value_at("/COLUMN_DEF_P/TABLE_NAME", table_name);
+  operation->set_value_at("/COLUMN_DEF_P/COLUMN_NAME", field->get_name());
+  operation->set_value_at("/COLUMN_DEF_P/COLUMN_TYPE", field->get_sql_type());
+  operation->set_value_at("/COLUMN_DEF_P/COLUMN_PKEY", field->get_primary_key() ? "TRUE" : "FALSE"); //TODO: Just use bool?
+  operation->set_value_at("/COLUMN_DEF_P/COLUMN_UNIQUE", field->get_unique_key() ? "TRUE" : "FALSE");
 
-  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_NAME", field->get_name(), error))
-    return false;
-
-  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_TYPE", field->get_sql_type(), error))
-    return false;
-
-  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_PKEY", field->get_primary_key() ? "TRUE" : "FALSE", error))
-    return false;
-
-  if(!set_server_operation_value(operation, "/COLUMN_DEF_P/COLUMN_UNIQUE", field->get_unique_key() ? "TRUE" : "FALSE", error))
-    return false;
-
-  if(!perform_server_operation(provider, connection, operation, error))
-    return false;
-
-  return true;
+  provider->perform_operation(connection, operation);
 }
 
-bool Backend::drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name, std::auto_ptr<Glib::Error>& error)
+void Backend::drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name)
 {
   Glib::RefPtr<Gnome::Gda::ServerProvider> provider = connection->get_provider();
-  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = create_server_operation(provider, connection, Gnome::Gda::SERVER_OPERATION_DROP_COLUMN, error);
-  if(!operation)
-    return false;
+  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = provider->create_operation(connection, Gnome::Gda::SERVER_OPERATION_DROP_COLUMN);
 
   //TODO: Quote table name and column name?
-  if(!set_server_operation_value(operation, "/COLUMN_DESC_P/TABLE_NAME", table_name, error))
-    return false;
-
-  if(!set_server_operation_value(operation, "/COLUMN_DESC_P/COLUMN_NAME", field_name, error))
-    return false;
-  
-  if(!perform_server_operation(provider, connection, operation, error))
-    return false;
-
-  return true;
-}
-
-//TODO: Why/When do we need to change multiple columns instead of a single one? murrayc.
-//When changing a table's primary key, we unset the primary key for the old
-//column and set it for the new column. Using a single call to the
-//ConnectionPoolBackend for this, the backend can do all the required
-//operations at once, maybe optimizing them. For example, for SQLite we need
-//to recreate the whole table when changing columns, so we only need to do
-//this once instead of twice when changing the primary key. armin.
-bool Backend::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error)
-{
-  static const char* TRANSACTION_NAME = "glom_change_columns_transaction";
-  static const gchar* TEMP_COLUMN_NAME = "glom_temp_column"; // TODO: Find a unique name.
-
-  if(!begin_transaction(connection, TRANSACTION_NAME, Gnome::Gda::TRANSACTION_ISOLATION_UNKNOWN, error)) return false; // TODO: What does the transaction isolation do?
-
-  for(unsigned int i = 0; i < old_fields.size(); ++ i)
-  {
-    // TODO: Don't create an intermediate column if the name of the column
-    // changes anyway.
-    sharedptr<Field> temp_field = glom_sharedptr_clone(new_fields[i]);
-    temp_field->set_name(TEMP_COLUMN_NAME);
-    // The temporary column must not be a primary key, otherwise
-    // we might end up with two primary key columns temporarily, which most
-    // database systems do not allow.
-    temp_field->set_primary_key(false);
-
-    if(!add_column(connection, table_name, temp_field, error))
-      break;
-
-    const Glib::ustring temp_move_query = "UPDATE " + table_name + " SET " + TEMP_COLUMN_NAME + " = CAST(" + old_fields[i]->get_name() + " AS " + new_fields[i]->get_sql_type() + ")";
-    if(!query_execute(connection, temp_move_query, error))
-      break;
-    // TODO: If this CAST was not successful, then just go on,
-    // dropping the data in the column?
-
-    if(!drop_column(connection, table_name, old_fields[i]->get_name(), error))
-      return false;
-
-    if(!add_column(connection, table_name, new_fields[i], error))
-      break;
-
-    const Glib::ustring final_move_query = "UPDATE " + table_name + " SET " + new_fields[i]->get_name() + " = " + TEMP_COLUMN_NAME; // TODO: Do we need a cast here, even though the type matches?
-    if(!query_execute(connection, final_move_query, error))
-      break;
-
-    if(!drop_column(connection, table_name, TEMP_COLUMN_NAME, error))
-      break;
-  }
-
-  if(error.get() || !commit_transaction(connection, TRANSACTION_NAME, error))
-  {
-    std::auto_ptr<Glib::Error> rollback_error;
-    rollback_transaction(connection, TRANSACTION_NAME, rollback_error);
-    return false;
-  }
-
-  return true;
+  operation->set_value_at("/COLUMN_DESC_P/TABLE_NAME", table_name);
+  operation->set_value_at("/COLUMN_DESC_P/COLUMN_NAME", field_name);
+  provider->perform_operation(connection, operation);
 }
 
 } // namespace ConnectionPoolBackends
diff --git a/glom/libglom/connectionpool_backends/backend.h b/glom/libglom/connectionpool_backends/backend.h
index ed85395..418b00a 100644
--- a/glom/libglom/connectionpool_backends/backend.h
+++ b/glom/libglom/connectionpool_backends/backend.h
@@ -78,16 +78,6 @@ public:
   };
   
 protected:
-  /** Helper functions for backend implementations to use, so that these don't
-   * need to worry whether glibmm was compiled with exceptions or not.
-   */
-  bool query_execute(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& sql_query, std::auto_ptr<Glib::Error>& error);
-  bool set_server_operation_value(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const Glib::ustring& path, const Glib::ustring& value, std::auto_ptr<Glib::Error>& error);
-  Glib::RefPtr<Gnome::Gda::ServerOperation> create_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, Gnome::Gda::ServerOperationType type, std::auto_ptr<Glib::Error>& error);
-  bool perform_server_operation(const Glib::RefPtr<Gnome::Gda::ServerProvider>& provider, const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, std::auto_ptr<Glib::Error>& error);
-  bool begin_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, Gnome::Gda::TransactionIsolation level, std::auto_ptr<Glib::Error>& error);
-  bool commit_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error);
-  bool rollback_transaction(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& name, std::auto_ptr<Glib::Error>& error);
 
   /* TODO: Merge create_database() and initialize() into a single function?
    */
@@ -169,17 +159,21 @@ protected:
    * If this method doesn't return a connection handle then error will be
    * non-zero (and vice versa).
    */
-  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) = 0;
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password) = 0;
 
-  virtual bool add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error);
+  /** @throws Glib::Error (from libgdamm)
+   */
+  virtual void add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field);
 
-  virtual bool drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name, std::auto_ptr<Glib::Error>& error);
+  /** @throws Glib::Error (from libgdamm)
+   */
+  virtual void drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name);
 
-  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error);
+  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields) throw() = 0;
 
   /** This method is called to create a new database on the
    * database server. */
-  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error) = 0;
+  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password) = 0;
 };
 
 } // namespace ConnectionPoolBackends
diff --git a/glom/libglom/connectionpool_backends/postgres.cc b/glom/libglom/connectionpool_backends/postgres.cc
index 2a75d5f..b70669a 100644
--- a/glom/libglom/connectionpool_backends/postgres.cc
+++ b/glom/libglom/connectionpool_backends/postgres.cc
@@ -57,7 +57,7 @@ float Postgres::get_postgres_server_version() const
   return m_postgres_server_version;
 }
 
-Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) throw()
+Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password)
 {
   //We must specify _some_ database even when we just want to create a database.
   //This _might_ be different on some systems. I hope not. murrayc
@@ -77,7 +77,6 @@ Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustri
   std::cout << "  DEBUG: auth_string=" << auth_string << std::endl;
 #endif
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   try
   {
     connection = Gnome::Gda::Connection::open_from_string("PostgreSQL", 
@@ -89,32 +88,15 @@ Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustri
   }
   catch(const Glib::Error& ex)
   {
-#else
-  std::auto_ptr<Glib::Error> ex;
-  connection = Gnome::Gda::Connection::open_from_string("PostgreSQL", 
-    cnc_string, auth_string,
-    Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE,
-    ex);
-  
-  if(!ex.get())
-    connection->statement_execute_non_select("SET DATESTYLE = 'ISO'", ex);
-
-  if(!ex.get())
-    data_model = connection->statement_execute_select("SELECT version()", Gnome::Gda::STATEMENT_MODEL_RANDOM_ACCESS, ex);
-
-  if(!ex.get())
-  {
-#endif
 
 #ifdef GLOM_CONNECTION_DEBUG
     std::cout << "ConnectionPoolBackends::Postgres::attempt_connect(): Attempt to connect to database failed on port=" << port << ", database=" << database << ": " << ex.what() << std::endl;
     std::cout << "ConnectionPoolBackends::Postgres::attempt_connect(): Attempting to connect without specifying the database." << std::endl;
 #endif
 
-    Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + default_database;
+    const Glib::ustring cnc_string = cnc_string_main + ";DB_NAME=" + default_database;
     Glib::RefPtr<Gnome::Gda::Connection> temp_conn;
     Glib::ustring auth_string = create_auth_string(username, password);
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
     try
     {
       temp_conn = Gnome::Gda::Connection::open_from_string("PostgreSQL", 
@@ -123,11 +105,6 @@ Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustri
     }
     catch(const Glib::Error& ex)
     {}
-#else
-    temp_conn = Gnome::Gda::Connection::open_from_string("PostgreSQL", 
-      cnc_string, auth_string, 
-      Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE, ex);
-#endif
 
 #ifdef GLOM_CONNECTION_DEBUG
     if(temp_conn)
@@ -136,17 +113,13 @@ Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustri
       std::cerr << "  (Could not connect even to the default database, database=" << database  << std::endl;
 #endif
 
-    error.reset(new ExceptionConnection(temp_conn ? ExceptionConnection::FAILURE_NO_DATABASE : ExceptionConnection::FAILURE_NO_SERVER));
+    throw ExceptionConnection(temp_conn ? ExceptionConnection::FAILURE_NO_DATABASE : ExceptionConnection::FAILURE_NO_SERVER);
     return Glib::RefPtr<Gnome::Gda::Connection>();
   }
 
   if(data_model && data_model->get_n_rows() && data_model->get_n_columns())
   {
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
     Gnome::Gda::Value value = data_model->get_value_at(0, 0);
-#else
-    Gnome::Gda::Value value = data_model->get_value_at(0, 0, ex);
-#endif
     if(value.get_value_type() == G_TYPE_STRING)
     {
       const Glib::ustring version_text = value.get_string();
@@ -168,240 +141,232 @@ Glib::RefPtr<Gnome::Gda::Connection> Postgres::attempt_connect(const Glib::ustri
   return connection;
 }
 
-bool Postgres::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error)
+bool Postgres::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields) throw()
 {
   static const char* TRANSACTION_NAME = "glom_change_columns_transaction";
   static const gchar* TEMP_COLUMN_NAME = "glom_temp_column"; // TODO: Find a unique name.
 
-  if(!begin_transaction(connection, TRANSACTION_NAME, Gnome::Gda::TRANSACTION_ISOLATION_UNKNOWN, error)) return false; // TODO: What does the transaction isolation do?
-
-  for(unsigned int i = 0; i < old_fields.size(); ++ i)
+  try
   {
-    // If the type did change, then we need to recreate the column. See
-    // http://www.postgresql.org/docs/faqs.FAQ.html#item4.3
-    if(old_fields[i]->get_field_info()->get_g_type() != new_fields[i]->get_field_info()->get_g_type())
-    {
-      // Create a temporary column
-      sharedptr<Field> temp_field = glom_sharedptr_clone(new_fields[i]);
-      temp_field->set_name(TEMP_COLUMN_NAME);
-      // The temporary column must not be primary key as long as the original
-      // (primary key) column is still present, because there cannot be two
-      // primary key columns.
-      temp_field->set_primary_key(false);
-
-      if(!add_column(connection, table_name, temp_field, error)) break;
-
-      Glib::ustring conversion_command;
-      const Glib::ustring field_name_old_quoted = "\"" + old_fields[i]->get_name() + "\"";
-      const Field::glom_field_type old_field_type = old_fields[i]->get_glom_type();
-
-      if(Field::get_conversion_possible(old_fields[i]->get_glom_type(), new_fields[i]->get_glom_type()))
-      {
-        //TODO: postgres seems to give an error if the data cannot be converted (for instance if the text is not a numeric digit when converting to numeric) instead of using 0.
-        /*
-        Maybe, for instance:
-        http://groups.google.de/groups?hl=en&lr=&ie=UTF-8&frame=right&th=a7a62337ad5a8f13&seekm=23739.1073660245%40sss.pgh.pa.us#link5
-        UPDATE _table
-        SET _bbb = to_number(substring(_aaa from 1 for 5), '99999')
-        WHERE _aaa <> '     ';  
-        */
-
-        switch(new_fields[i]->get_glom_type())
-        {
-          case Field::TYPE_BOOLEAN:
-          {
-            if(old_field_type == Field::TYPE_NUMERIC)
-            {
-              conversion_command = "(CASE WHEN " + field_name_old_quoted + " > 0 THEN true "
-                                         "WHEN " + field_name_old_quoted + " = 0 THEN false "
-                                         "WHEN " + field_name_old_quoted + " IS NULL THEN false END)";
-            }
-            else if(old_field_type == Field::TYPE_TEXT)
-              conversion_command = '(' + field_name_old_quoted + " !~~* \'false\')"; // !~~* means ! ILIKE
-            else // Dates and Times:
-              conversion_command = '(' + field_name_old_quoted + " IS NOT NULL)";
-            break;
-          }
-
-          case Field::TYPE_NUMERIC: // CAST does not work if the destination type is numeric
-          {
-            if(old_field_type == Field::TYPE_BOOLEAN)
-            {
-              conversion_command = "(CASE WHEN " + field_name_old_quoted + " = true THEN 1 "
-                                         "WHEN " + field_name_old_quoted + " = false THEN 0 "
-                                         "WHEN " + field_name_old_quoted + " IS NULL THEN 0 END)";
-            }
-            else
-            {
-              //We use to_number, with textcat() so that to_number always has usable data.
-              //Otherwise, it says 
-              //invalid input syntax for type numeric: " "
-              //
-              //We must use single quotes with the 0, otherwise it says "column 0 does not exist.".
-              conversion_command = "to_number( textcat(\'0\', " + field_name_old_quoted + "), '999999999.99999999' )";
-            }
-
-            break;
-          }
-
-          case Field::TYPE_DATE: // CAST does not work if the destination type is date.
-          {
-            conversion_command = "to_date( " + field_name_old_quoted + ", 'YYYYMMDD' )"; // TODO: Standardise date storage format.
-            break;
-          }
-          case Field::TYPE_TIME: // CAST does not work if the destination type is timestamp.
-          {
-            conversion_command = "to_timestamp( " + field_name_old_quoted + ", 'HHMMSS' )"; // TODO: Standardise time storage format.
-            break;
-          }
-
-          default:
-          {
-            // To Text:
-
-            // bool to text:
-            if(old_field_type == Field::TYPE_BOOLEAN)
-            {
-              conversion_command = "(CASE WHEN " + field_name_old_quoted + " = true THEN \'true\' "
-                                         "WHEN " + field_name_old_quoted + " = false THEN \'false\' "
-                                         "WHEN " + field_name_old_quoted + " IS NULL THEN \'false\' END)";
-            }
-            else
-            {
-              // This works for most to-text conversions:
-              conversion_command = "CAST(" + field_name_old_quoted + " AS " + new_fields[i]->get_sql_type() + ")";
-            }
-
-            break;
-          }
-        }
-
-        if(!query_execute(connection, "UPDATE \"" + table_name + "\" SET \"" + TEMP_COLUMN_NAME + "\" = " + conversion_command, error))
-          break;
-      }
-      else
-      {
-        // The conversion is not possible, so drop data in that column
-      }
-
-      if(!drop_column(connection, table_name, old_fields[i]->get_name(), error))
-        break;
-
-      if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" RENAME COLUMN \"" + TEMP_COLUMN_NAME + "\" TO \"" + new_fields[i]->get_name() + "\"", error))
-        break;
-
-      // Readd primary key constraint
-      if(new_fields[i]->get_primary_key())
-      {
-        if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" ADD PRIMARY KEY (\"" + new_fields[i]->get_name() + "\")", error))
-          break;
-      }
-    }
-    else
-    {
-      // The type did not change. What could have changed: The field being a
-      // unique key, primary key, its name or its default value.
-
-      // Primary key
-      // TODO: Test whether this is able to remove unique key constraints
-      // added via libgda's DDL API in add_column(). Maybe override
-      // add_column() if we can't.
-      bool primary_key_was_set = false;
-      bool primary_key_was_unset = false;
-      if(old_fields[i]->get_primary_key() != new_fields[i]->get_primary_key())
-      {
-        if(new_fields[i]->get_primary_key())
-        {
-          primary_key_was_set = true;
-
-          // Primary key was added
-          if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" ADD PRIMARY KEY (\"" + old_fields[i]->get_name() + "\")", error))
-            break;
-
-          // Remove unique key constraint, because this is already implied in
-          // the field being primary key.
-          if(old_fields[i]->get_unique_key())
-            if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" DROP CONSTRAINT \"" + old_fields[i]->get_name() + "_key", error))
-              break;
-        }
-        else
-        {
-          primary_key_was_unset = true;
-
-          // Primary key was removed
-          if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" DROP CONSTRAINT \"" + table_name + "_pkey\"", error))
-            break;
-        }
-      }
-
-      // Uniqueness
-      if(old_fields[i]->get_unique_key() != new_fields[i]->get_unique_key())
-      {
-        // Postgres automatically makes primary keys unique, so we do not need
-        // to do that separately if we already made it a primary key
-        if(!primary_key_was_set && new_fields[i]->get_unique_key())
-        {
-          if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" ADD CONSTRAINT \"" + old_fields[i]->get_name() + "_key\" UNIQUE (\"" + old_fields[i]->get_name() + "\")", error))
-            break;
-        }
-        else if(!primary_key_was_unset && !new_fields[i]->get_unique_key() && !new_fields[i]->get_primary_key())
-        {
-          if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" DROP CONSTRAINT \"" + old_fields[i]->get_name() + "_key\"", error))
-            break;
-        }
-      }
-
-      if(!new_fields[i]->get_auto_increment()) // Auto-increment fields have special code as their default values.
-      {
-        if(old_fields[i]->get_default_value() != new_fields[i]->get_default_value())
-        {
-          if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" ALTER COLUMN \"" + old_fields[i]->get_name() + "\" SET DEFAULT " + new_fields[i]->sql(new_fields[i]->get_default_value(), connection), error))
-            break;
-        }
-      }
-
-      if(old_fields[i]->get_name() != new_fields[i]->get_name())
-      {
-        if(!query_execute(connection, "ALTER TABLE \"" + table_name + "\" RENAME COLUMN \"" + old_fields[i]->get_name() + "\" TO \"" + new_fields[i]->get_name() + "\"", error))
-          break;
-      }
-    }
+    connection->begin_transaction(TRANSACTION_NAME, Gnome::Gda::TRANSACTION_ISOLATION_UNKNOWN); // TODO: What does the transaction isolation do?
   }
-
-  if(error.get() || !commit_transaction(connection, TRANSACTION_NAME, error))
+  catch(const Glib::Error& ex)
   {
-    std::auto_ptr<Glib::Error> rollback_error;
-    rollback_transaction(connection, TRANSACTION_NAME, rollback_error);
-    return false;
+    std::cerr << "Postgres::change_columns(): begin_transaction failed: " << ex.what() << std::endl;
   }
 
-  return true;
-}
-
-bool Postgres::attempt_create_database(const Glib::ustring& database_name, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error)
-{
-  Glib::RefPtr<Gnome::Gda::ServerOperation> op;
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
+  //Do this all in one big try/catch, block, 
+  //reverting the transaction if anything fails:
   try
   {
-    op = Gnome::Gda::ServerOperation::prepare_create_database("PostgreSQL",
-                                                              database_name);
+		for(unsigned int i = 0; i < old_fields.size(); ++ i)
+		{
+		  // If the type did change, then we need to recreate the column. See
+		  // http://www.postgresql.org/docs/faqs.FAQ.html#item4.3
+		  if(old_fields[i]->get_field_info()->get_g_type() != new_fields[i]->get_field_info()->get_g_type())
+		  {
+		    // Create a temporary column
+		    sharedptr<Field> temp_field = glom_sharedptr_clone(new_fields[i]);
+		    temp_field->set_name(TEMP_COLUMN_NAME);
+		    // The temporary column must not be primary key as long as the original
+		    // (primary key) column is still present, because there cannot be two
+		    // primary key columns.
+		    temp_field->set_primary_key(false);
+
+		    add_column(connection, table_name, temp_field);
+
+		    Glib::ustring conversion_command;
+		    const Glib::ustring field_name_old_quoted = "\"" + old_fields[i]->get_name() + "\"";
+		    const Field::glom_field_type old_field_type = old_fields[i]->get_glom_type();
+
+		    if(Field::get_conversion_possible(old_fields[i]->get_glom_type(), new_fields[i]->get_glom_type()))
+		    {
+		      //TODO: postgres seems to give an error if the data cannot be converted (for instance if the text is not a numeric digit when converting to numeric) instead of using 0.
+		      /*
+		      Maybe, for instance:
+		      http://groups.google.de/groups?hl=en&lr=&ie=UTF-8&frame=right&th=a7a62337ad5a8f13&seekm=23739.1073660245%40sss.pgh.pa.us#link5
+		      UPDATE _table
+		      SET _bbb = to_number(substring(_aaa from 1 for 5), '99999')
+		      WHERE _aaa <> '     ';  
+		      */
+
+		      switch(new_fields[i]->get_glom_type())
+		      {
+		        case Field::TYPE_BOOLEAN:
+		        {
+		          if(old_field_type == Field::TYPE_NUMERIC)
+		          {
+		            conversion_command = "(CASE WHEN " + field_name_old_quoted + " > 0 THEN true "
+		                                       "WHEN " + field_name_old_quoted + " = 0 THEN false "
+		                                       "WHEN " + field_name_old_quoted + " IS NULL THEN false END)";
+		          }
+		          else if(old_field_type == Field::TYPE_TEXT)
+		            conversion_command = '(' + field_name_old_quoted + " !~~* \'false\')"; // !~~* means ! ILIKE
+		          else // Dates and Times:
+		            conversion_command = '(' + field_name_old_quoted + " IS NOT NULL)";
+		          break;
+		        }
+
+		        case Field::TYPE_NUMERIC: // CAST does not work if the destination type is numeric
+		        {
+		          if(old_field_type == Field::TYPE_BOOLEAN)
+		          {
+		            conversion_command = "(CASE WHEN " + field_name_old_quoted + " = true THEN 1 "
+		                                       "WHEN " + field_name_old_quoted + " = false THEN 0 "
+		                                       "WHEN " + field_name_old_quoted + " IS NULL THEN 0 END)";
+		          }
+		          else
+		          {
+		            //We use to_number, with textcat() so that to_number always has usable data.
+		            //Otherwise, it says 
+		            //invalid input syntax for type numeric: " "
+		            //
+		            //We must use single quotes with the 0, otherwise it says "column 0 does not exist.".
+		            conversion_command = "to_number( textcat(\'0\', " + field_name_old_quoted + "), '999999999.99999999' )";
+		          }
+
+		          break;
+		        }
+
+		        case Field::TYPE_DATE: // CAST does not work if the destination type is date.
+		        {
+		          conversion_command = "to_date( " + field_name_old_quoted + ", 'YYYYMMDD' )"; // TODO: Standardise date storage format.
+		          break;
+		        }
+		        case Field::TYPE_TIME: // CAST does not work if the destination type is timestamp.
+		        {
+		          conversion_command = "to_timestamp( " + field_name_old_quoted + ", 'HHMMSS' )"; // TODO: Standardise time storage format.
+		          break;
+		        }
+
+		        default:
+		        {
+		          // To Text:
+
+		          // bool to text:
+		          if(old_field_type == Field::TYPE_BOOLEAN)
+		          {
+		            conversion_command = "(CASE WHEN " + field_name_old_quoted + " = true THEN \'true\' "
+		                                       "WHEN " + field_name_old_quoted + " = false THEN \'false\' "
+		                                       "WHEN " + field_name_old_quoted + " IS NULL THEN \'false\' END)";
+		          }
+		          else
+		          {
+		            // This works for most to-text conversions:
+		            conversion_command = "CAST(" + field_name_old_quoted + " AS " + new_fields[i]->get_sql_type() + ")";
+		          }
+
+		          break;
+		        }
+		      }
+
+		      connection->statement_execute_non_select("UPDATE \"" + table_name + "\" SET \"" + TEMP_COLUMN_NAME + "\" = " + conversion_command);
+		    }
+		    else
+		    {
+		      // The conversion is not possible, so drop data in that column
+		    }
+
+		    drop_column(connection, table_name, old_fields[i]->get_name());
+
+		    connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" RENAME COLUMN \"" + TEMP_COLUMN_NAME + "\" TO \"" + new_fields[i]->get_name() + "\"");
+
+		    // Read primary key constraint
+		    if(new_fields[i]->get_primary_key())
+		    {
+		      connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" ADD PRIMARY KEY (\"" + new_fields[i]->get_name() + "\")");
+		    }
+		  }
+		  else
+		  {
+		    // The type did not change. What could have changed: The field being a
+		    // unique key, primary key, its name or its default value.
+
+		    // Primary key
+		    // TODO: Test whether this is able to remove unique key constraints
+		    // added via libgda's DDL API in add_column(). Maybe override
+		    // add_column() if we can't.
+		    bool primary_key_was_set = false;
+		    bool primary_key_was_unset = false;
+		    if(old_fields[i]->get_primary_key() != new_fields[i]->get_primary_key())
+		    {
+		      if(new_fields[i]->get_primary_key())
+		      {
+		        primary_key_was_set = true;
+
+		        // Primary key was added
+		       connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" ADD PRIMARY KEY (\"" + old_fields[i]->get_name() + "\")");
+
+		        // Remove unique key constraint, because this is already implied in
+		        // the field being primary key.
+		        if(old_fields[i]->get_unique_key())
+		          connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" DROP CONSTRAINT \"" + old_fields[i]->get_name() + "_key");
+		      }
+		      else
+		      {
+		        primary_key_was_unset = true;
+
+		        // Primary key was removed
+		        connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" DROP CONSTRAINT \"" + table_name + "_pkey\"");
+		      }
+		    }
+
+		    // Uniqueness
+		    if(old_fields[i]->get_unique_key() != new_fields[i]->get_unique_key())
+		    {
+		      // Postgres automatically makes primary keys unique, so we do not need
+		      // to do that separately if we already made it a primary key
+		      if(!primary_key_was_set && new_fields[i]->get_unique_key())
+		      {
+		        connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" ADD CONSTRAINT \"" + old_fields[i]->get_name() + "_key\" UNIQUE (\"" + old_fields[i]->get_name() + "\")");
+		      }
+		      else if(!primary_key_was_unset && !new_fields[i]->get_unique_key() && !new_fields[i]->get_primary_key())
+		      {
+		        connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" DROP CONSTRAINT \"" + old_fields[i]->get_name() + "_key\"");
+		      }
+		    }
+
+		    if(!new_fields[i]->get_auto_increment()) // Auto-increment fields have special code as their default values.
+		    {
+		      if(old_fields[i]->get_default_value() != new_fields[i]->get_default_value())
+		      {
+		        connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" ALTER COLUMN \"" + old_fields[i]->get_name() + "\" SET DEFAULT " + new_fields[i]->sql(new_fields[i]->get_default_value(), connection));
+		      }
+		    }
+
+		    if(old_fields[i]->get_name() != new_fields[i]->get_name())
+		    {
+		      connection->statement_execute_non_select("ALTER TABLE \"" + table_name + "\" RENAME COLUMN \"" + old_fields[i]->get_name() + "\" TO \"" + new_fields[i]->get_name() + "\"");
+		    }
+		  }
+		}
+		
+		connection->commit_transaction(TRANSACTION_NAME);
+		return true;
   }
   catch(const Glib::Error& ex)
   {
-    error.reset(new Glib::Error(ex));
-    return false;
+    std::cerr << "Exception: " << ex.what() << std::endl;
+    std::cerr << "Reverting the transaction." << std::endl;
+    
+    try
+    {
+      connection->rollback_transaction(TRANSACTION_NAME);
+    }
+    catch(const Glib::Error& ex)
+    {
+      std::cerr << "Could not rollback the transaction: Exception: " << ex.what() << std::endl;
+    }
   }
-#else
-  std::auto_ptr<Glib::Error> ex;
-  op = Gnome::Gda::ServerOperation::prepare_create_database("PostgreSQL",
-                                                            database_name,
-                                                            ex);
-  if(ex.get())
-    return false;
-#endif
+  
+  return false;
+}
+
+bool Postgres::attempt_create_database(const Glib::ustring& database_name, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& username, const Glib::ustring& password)
+{
+  Glib::RefPtr<Gnome::Gda::ServerOperation> op = Gnome::Gda::ServerOperation::prepare_create_database("PostgreSQL",
+                                                              database_name);
   g_assert(op);
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
   try
   {
     op->set_value_at("/SERVER_CNX_P/HOST", host);
@@ -412,22 +377,9 @@ bool Postgres::attempt_create_database(const Glib::ustring& database_name, const
   }
   catch(const Glib::Error& ex)
   {
-    error.reset(new Glib::Error(ex));
+    std::cerr << "Postgres::attempt_create_database(): exception: " << ex.what() << std::endl;
     return false;
   }
-#else //GLIBMM_EXCEPTIONS_ENABLED
-  op->set_value_at("/SERVER_CNX_P/HOST", host, error);
-  op->set_value_at("/SERVER_CNX_P/PORT", port, error);
-  op->set_value_at("/SERVER_CNX_P/ADM_LOGIN", username, error);
-  op->set_value_at("/SERVER_CNX_P/ADM_PASSWORD", password, error);
-
-  if(error.get() == 0)
-    op->perform_create_database("PostgreSQL", ex);
-  else
-    return false;
-  if (error.get())
-    return false;
-#endif //GLIBMM_EXCEPTIONS_ENABLED
 
   return true;
 }
diff --git a/glom/libglom/connectionpool_backends/postgres.h b/glom/libglom/connectionpool_backends/postgres.h
index 9386a6d..9faa899 100644
--- a/glom/libglom/connectionpool_backends/postgres.h
+++ b/glom/libglom/connectionpool_backends/postgres.h
@@ -58,15 +58,15 @@ private:
   virtual Glib::ustring get_string_find_operator() const { return "ILIKE"; } // ILIKE is a postgres extension for locale-dependent case-insensitive matches.
   virtual const char* get_public_schema_name() const { return "public"; }
 
-  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error);
+  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields) throw();
 
 protected:
-  bool attempt_create_database(const Glib::ustring& database_name, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
+  bool attempt_create_database(const Glib::ustring& database_name, const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& username, const Glib::ustring& password);
 
   /** Attempt to connect to the database with the specified criteria.
-   * @param error An error if the correction failed.
+   * @throws An ExceptionConnection if the correction failed.
    */ 
-  Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error) throw();
+  Glib::RefPtr<Gnome::Gda::Connection> attempt_connect(const Glib::ustring& host, const Glib::ustring& port, const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password);
 
 private:
   float m_postgres_server_version;
diff --git a/glom/libglom/connectionpool_backends/postgres_central.cc b/glom/libglom/connectionpool_backends/postgres_central.cc
index 3d242f8..ea5dc8f 100644
--- a/glom/libglom/connectionpool_backends/postgres_central.cc
+++ b/glom/libglom/connectionpool_backends/postgres_central.cc
@@ -99,7 +99,7 @@ bool PostgresCentralHosted::get_try_other_ports() const
   return m_try_other_ports;
 }
 
-Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
+Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password)
 {
   Glib::RefPtr<Gnome::Gda::Connection> connection;
 
@@ -111,15 +111,23 @@ Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::connect(const Glib::
   if(m_port == 0)
     port = *iter_port ++;
 
-  connection = attempt_connect(m_host, port, database, username, password, error);
-
-  // Remember port if only the database was missing
   bool connection_possible = false;
-  if(error.get() && error->get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+  try
   {
+    connection = attempt_connect(m_host, port, database, username, password);
     connection_possible = true;
     m_port = atoi(port.c_str());
   }
+  catch(const ExceptionConnection& ex)
+  {
+    // Remember port if only the database was missing
+    bool connection_possible = false;
+    if(ex.get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+    {
+      connection_possible = true;
+      m_port = atoi(port.c_str());
+    }
+  }
 
   // Try more ports if so desired, and we don't have a connection yet
   if(m_try_other_ports && !connection)
@@ -127,14 +135,23 @@ Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::connect(const Glib::
     while(!connection && iter_port != m_list_ports.end())
     {
       port = *iter_port;
-      connection = attempt_connect(m_host, port, database, username, password, error);
-
-      // Remember port if only the database was missing
-      if(error.get() && error->get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+      
+      try
       {
+        connection = attempt_connect(m_host, port, database, username, password);
         connection_possible = true;
         m_port = atoi(port.c_str());
       }
+      catch(const ExceptionConnection& ex)
+      {
+        connection_possible = false;
+        // Remember port if only the database was missing
+        if(ex.get_failure_type() == ExceptionConnection::FAILURE_NO_DATABASE)
+        {
+          connection_possible = true;
+          m_port = atoi(port.c_str());
+        }
+      }
 
       // Skip if we already tried this port
       if(iter_port != m_list_ports.end() && *iter_port == port)
@@ -150,17 +167,17 @@ Glib::RefPtr<Gnome::Gda::Connection> PostgresCentralHosted::connect(const Glib::
   else
   {
     if(connection_possible)
-      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_DATABASE));
+      throw ExceptionConnection(ExceptionConnection::FAILURE_NO_DATABASE);
     else
-      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_SERVER));
+      throw ExceptionConnection(ExceptionConnection::FAILURE_NO_SERVER);
   }
 
   return connection;
 }
 
-bool PostgresCentralHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error)
+bool PostgresCentralHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password)
 {
-  return attempt_create_database(database_name, get_host(), port_as_string(m_port), username, password, error);
+  return attempt_create_database(database_name, get_host(), port_as_string(m_port), username, password);
 }
 
 }
diff --git a/glom/libglom/connectionpool_backends/postgres_central.h b/glom/libglom/connectionpool_backends/postgres_central.h
index d40d9b4..ec10f66 100644
--- a/glom/libglom/connectionpool_backends/postgres_central.h
+++ b/glom/libglom/connectionpool_backends/postgres_central.h
@@ -48,9 +48,9 @@ public:
   bool get_try_other_ports() const;
 
 private:
-  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password);
 
-  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
+  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password);
 
 private:
   typedef std::list<Glib::ustring> type_list_ports;
diff --git a/glom/libglom/connectionpool_backends/postgres_self.cc b/glom/libglom/connectionpool_backends/postgres_self.cc
index 9689bbe..c6cd29a 100644
--- a/glom/libglom/connectionpool_backends/postgres_self.cc
+++ b/glom/libglom/connectionpool_backends/postgres_self.cc
@@ -614,11 +614,11 @@ static bool on_timeout_delay(const Glib::RefPtr<Glib::MainLoop>& mainloop)
 }
 
 
-Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
+Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password)
 {
   if(!get_self_hosting_active())
   {
-    error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_BACKEND)); //TODO: But there is a backend. It's just not ready.
+    throw ExceptionConnection(ExceptionConnection::FAILURE_NO_BACKEND); //TODO: But there is a backend. It's just not ready.
     return Glib::RefPtr<Gnome::Gda::Connection>();
   }
 
@@ -631,19 +631,24 @@ Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ust
   const guint MAX_RETRIES_EVER = 60; /* seconds */
   while(keep_trying)
   { 
-    result = attempt_connect("localhost", port_as_string(m_port), database, username, password, ex);
-    if(!result && 
-      ex.get() && (ex->get_failure_type() == ExceptionConnection::FAILURE_NO_SERVER))
+    try
     {
-      //It must be using a default password, so any failure would not be due to a wrong password.
-      //However, pg_ctl sometimes reports success before it is really ready to let us connect, 
-      //so in this case we can just keep trying until it works, with a very long timeout.
-      count_retries++;
-      const guint max_retries = m_network_shared ? MAX_RETRIES_EVER : MAX_RETRIES_KNOWN_PASSWORD;
-      if(count_retries > max_retries)
+      result = attempt_connect("localhost", port_as_string(m_port), database, username, password);
+    }
+    catch(const ExceptionConnection& ex)
+    {
+      if(ex.get_failure_type() == ExceptionConnection::FAILURE_NO_SERVER)
       {
-        keep_trying = false;
-        continue;
+        //It must be using a default password, so any failure would not be due to a wrong password.
+        //However, pg_ctl sometimes reports success before it is really ready to let us connect, 
+        //so in this case we can just keep trying until it works, with a very long timeout.
+        count_retries++;
+        const guint max_retries = m_network_shared ? MAX_RETRIES_EVER : MAX_RETRIES_KNOWN_PASSWORD;
+        if(count_retries > max_retries)
+        {
+          keep_trying = false;
+          continue;
+        }
       }
 
       std::cout << "DEBUG: Glom::PostgresSelfHosted::connect(): Waiting and retrying the connection due to suspected too-early success of pg_ctl." << std::endl; 
@@ -663,13 +668,12 @@ Glib::RefPtr<Gnome::Gda::Connection> PostgresSelfHosted::connect(const Glib::ust
     keep_trying = false;
   }
 
-  error = ex;
   return result;
 }
 
-bool PostgresSelfHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error)
+bool PostgresSelfHosted::create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password)
 {
-  return attempt_create_database(database_name, "localhost", port_as_string(m_port), username, password, error);
+  return attempt_create_database(database_name, "localhost", port_as_string(m_port), username, password);
 }
 
 int PostgresSelfHosted::discover_first_free_port(int start_port, int end_port)
diff --git a/glom/libglom/connectionpool_backends/postgres_self.h b/glom/libglom/connectionpool_backends/postgres_self.h
index d36769f..dc05395 100644
--- a/glom/libglom/connectionpool_backends/postgres_self.h
+++ b/glom/libglom/connectionpool_backends/postgres_self.h
@@ -68,9 +68,9 @@ private:
   virtual bool cleanup(const SlotProgress& slot_progress);
   virtual bool set_network_shared(const SlotProgress& slot_progress, bool network_shared = true);
 
-  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password);
 
-  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
+  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password);
 
 private:
   /** Examine ports one by one, starting at @a starting_port, in increasing
diff --git a/glom/libglom/connectionpool_backends/sqlite.cc b/glom/libglom/connectionpool_backends/sqlite.cc
index 8cdb0fb..73b64c6 100644
--- a/glom/libglom/connectionpool_backends/sqlite.cc
+++ b/glom/libglom/connectionpool_backends/sqlite.cc
@@ -44,7 +44,7 @@ const std::string& Sqlite::get_database_directory_uri() const
   return m_database_directory_uri;
 }
 
-Glib::RefPtr<Gnome::Gda::Connection> Sqlite::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error)
+Glib::RefPtr<Gnome::Gda::Connection> Sqlite::connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password)
 {
   Glib::RefPtr<Gnome::Gda::Connection> connection;
   if(m_database_directory_uri.empty())
@@ -65,25 +65,9 @@ Glib::RefPtr<Gnome::Gda::Connection> Sqlite::connect(const Glib::ustring& databa
     const Glib::ustring cnc_string = "DB_DIR=" + database_directory + ";DB_NAME=" + database;
     const Glib::ustring auth_string = Glib::ustring::compose("USERNAME=%1;PASSWORD=%2", username, password);
     
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-    try
-    {
-      connection = Gnome::Gda::Connection::open_from_string("SQLite", 
-        cnc_string, auth_string,
-        Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
-    }
-    catch(const Glib::Error& ex)
-    {
-#else
-    std::auto_ptr<Glib::Error> error;
     connection = Gnome::Gda::Connection::open_from_string("SQLite", 
-      cnc_string, auth_string, 
-      Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE, error);
-    if(error.get())
-    {
-      const Glib::Error& ex = *error.get();
-#endif
-    }
+      cnc_string, auth_string,
+      Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
   }
 
   if(!connection)
@@ -91,15 +75,15 @@ Glib::RefPtr<Gnome::Gda::Connection> Sqlite::connect(const Glib::ustring& databa
     // If the database directory is valid, then only the database (file) is
     // missing, otherwise we pretend the "server" is not running.
     if(db_dir->query_file_type() == Gio::FILE_TYPE_DIRECTORY)
-      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_DATABASE));
+      throw ExceptionConnection(ExceptionConnection::FAILURE_NO_DATABASE);
     else
-      error.reset(new ExceptionConnection(ExceptionConnection::FAILURE_NO_SERVER));
+      throw ExceptionConnection(ExceptionConnection::FAILURE_NO_SERVER);
   }
 
   return connection;
 }
 
-bool Sqlite::create_database(const Glib::ustring& database_name, const Glib::ustring& /* username */, const Glib::ustring& /* password */, std::auto_ptr<Glib::Error>& error)
+bool Sqlite::create_database(const Glib::ustring& database_name, const Glib::ustring& /* username */, const Glib::ustring& /* password */)
 {
   if(m_database_directory_uri.empty())
     return false;
@@ -108,33 +92,16 @@ bool Sqlite::create_database(const Glib::ustring& database_name, const Glib::ust
   const std::string database_directory = file->get_path(); 
   const Glib::ustring cnc_string = Glib::ustring::compose("DB_DIR=%1;DB_NAME=%2", database_directory, database_name);
 
-#ifdef GLIBMM_EXCEPTIONS_ENABLED
-  try
-  {
-    Glib::RefPtr<Gnome::Gda::Connection> cnc = 
-      Gnome::Gda::Connection::open_from_string("SQLite", 
-        cnc_string, "",
-        Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
-  }
-  catch(const Glib::Error& ex)
-  {
-    error.reset(new Glib::Error(ex));
-    return false;
-  }
-#else
   Glib::RefPtr<Gnome::Gda::Connection> cnc = 
     Gnome::Gda::Connection::open_from_string("SQLite", 
-      cnc_string, "", 
-      Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE, error);
-  if(error.get() != 0)
-    return false;
-#endif
+      cnc_string, "",
+      Gnome::Gda::CONNECTION_OPTIONS_SQL_IDENTIFIERS_CASE_SENSITIVE);
 
   return true;
 }
 
 
-bool Sqlite::add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, GdaMetaTableColumn* column, unsigned int i, std::auto_ptr<Glib::Error>& error)
+bool Sqlite::add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, GdaMetaTableColumn* column, unsigned int i)
 {
   //TODO: Quote column name?
   const Glib::ustring name_path = Glib::ustring::compose("/FIELDS_A/@COLUMN_NAME/%1", i);
@@ -144,21 +111,20 @@ bool Sqlite::add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::Serve
   // TODO: Find out whether the column is unique.
   const Glib::ustring default_path = Glib::ustring::compose("/FIELDS_A/@COLUMN_DEFAULT/%1", i);
 
-  if(!set_server_operation_value(operation, name_path, column->column_name, error)) return false;
-  if(!set_server_operation_value(operation, type_path, column->column_type, error)) return false;
-  if(!set_server_operation_value(operation, pkey_path, column->pkey ? "TRUE" : "FALSE", error)) return false;
-  if(!set_server_operation_value(operation, nnul_path, !column->nullok ? "TRUE" : "FALSE", error)) return false;
+  operation->set_value_at(name_path, column->column_name);
+  operation->set_value_at(type_path, column->column_type);
+  operation->set_value_at(pkey_path, column->pkey ? "TRUE" : "FALSE");
+  operation->set_value_at(nnul_path, !column->nullok ? "TRUE" : "FALSE");
 
   if(column->default_value)
   {
-    if(!set_server_operation_value(operation, default_path, column->default_value, error))
-      return false;
+    operation->set_value_at(default_path, column->default_value);
   }
   
   return true;
 }
 
-bool Sqlite::add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const sharedptr<const Field>& column, unsigned int i, std::auto_ptr<Glib::Error>& error)
+bool Sqlite::add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const sharedptr<const Field>& column, unsigned int i)
 {
   //TODO: Quote column name?
   const Glib::ustring name_path = Glib::ustring::compose("/FIELDS_A/@COLUMN_NAME/%1", i);
@@ -167,36 +133,33 @@ bool Sqlite::add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::Serve
   const Glib::ustring unique_path = Glib::ustring::compose("/FIELDS_A/@COLUMN_UNIQUE/%1", i);
   const Glib::ustring default_path = Glib::ustring::compose("/FIELDS_A/@COLUMN_DEFAULT/%1", i);
 
-  if(!set_server_operation_value(operation, name_path, column->get_name(), error)) return false;
-  if(!set_server_operation_value(operation, type_path, column->get_sql_type(), error)) return false;
-  if(!set_server_operation_value(operation, pkey_path, column->get_primary_key() ? "TRUE" : "FALSE", error)) return false;
-  if(!set_server_operation_value(operation, unique_path, column->get_unique_key() ? "TRUE" : "FALSE", error)) return false;
+  operation->set_value_at(name_path, column->get_name());
+  operation->set_value_at(type_path, column->get_sql_type());
+  operation->set_value_at(pkey_path, column->get_primary_key() ? "TRUE" : "FALSE");
+  operation->set_value_at(unique_path, column->get_unique_key() ? "TRUE" : "FALSE");
 
   return true;
 }
 
-bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_strings& fields_removed, const type_vec_const_fields& fields_added, const type_mapFieldChanges& fields_changed, std::auto_ptr<Glib::Error>& error)
+bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_strings& fields_removed, const type_vec_const_fields& fields_added, const type_mapFieldChanges& fields_changed) throw()
 {
   static const gchar* TEMPORARY_TABLE_NAME = "GLOM_TEMP_TABLE"; // TODO: Make sure this is unique.
   static const gchar* TRANSACTION_NAME = "GLOM_RECREATE_TABLE_TRANSACTION";
 
   Glib::RefPtr<Gnome::Gda::MetaStore> store = connection->get_meta_store();
   Glib::RefPtr<Gnome::Gda::MetaStruct> metastruct = Gnome::Gda::MetaStruct::create(store, Gnome::Gda::META_STRUCT_FEATURE_NONE);
-#ifdef GLIBMM_EXCEPTIONS_ENABLED  
+
   GdaMetaDbObject* object = metastruct->complement(Gnome::Gda::META_DB_TABLE, Gnome::Gda::Value(), Gnome::Gda::Value(), Gnome::Gda::Value(table_name));
-#else
-  GdaMetaDbObject* object = metastruct->complement(Gnome::Gda::META_DB_TABLE, Gnome::Gda::Value(), Gnome::Gda::Value(), Gnome::Gda::Value(table_name), error);
-#endif
   
   if(!object)
     return false;
 
-  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = create_server_operation(connection->get_provider(), connection, Gnome::Gda::SERVER_OPERATION_CREATE_TABLE, error);
+  Glib::RefPtr<Gnome::Gda::ServerOperation> operation = connection->get_provider()->create_operation(connection, Gnome::Gda::SERVER_OPERATION_CREATE_TABLE);
   if(!operation)
     return false;
 
   //TODO: Quote table name?
-  if(!set_server_operation_value(operation, "/TABLE_DEF_P/TABLE_NAME", TEMPORARY_TABLE_NAME, error)) return false;
+  operation->set_value_at("/TABLE_DEF_P/TABLE_NAME", TEMPORARY_TABLE_NAME);
 
   GdaMetaTable* table = GDA_META_TABLE(object);
   unsigned int i = 0;
@@ -290,14 +253,12 @@ bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connecti
         break;
       };
 
-      if(!add_column_to_server_operation(operation, changed_iter->second, i++, error))
-        return false;
+      add_column_to_server_operation(operation, changed_iter->second, i++);
     }
     else
     {
       trans_fields += column->column_name;
-      if(!add_column_to_server_operation(operation, column, i++, error))
-        return false;
+      add_column_to_server_operation(operation, column, i++);
     }
   }
 
@@ -309,8 +270,8 @@ bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connecti
     type_vec_strings::const_iterator removed_iter = std::find(fields_removed.begin(), fields_removed.end(), field->get_name());
     if(removed_iter == fields_removed.end())
     {
-      if(!add_column_to_server_operation(operation, field, i++, error))
-        return false;
+      add_column_to_server_operation(operation, field, i++);
+      
       if(!trans_fields.empty())
         trans_fields += ',';
       Gnome::Gda::Value default_value = field->get_default_value();
@@ -337,64 +298,78 @@ bool Sqlite::recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connecti
     }
   }
 
-  if(!begin_transaction(connection, TRANSACTION_NAME, Gnome::Gda::TRANSACTION_ISOLATION_UNKNOWN, error)) return false;
-
-  if(perform_server_operation(connection->get_provider(), connection, operation, error))
+  try
+  {
+    connection->begin_transaction(TRANSACTION_NAME, Gnome::Gda::TRANSACTION_ISOLATION_UNKNOWN);
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << "Sqlite::recreate_table(): Could not begin transaction: exception=" << ex.what() << std::endl;
+    return false;
+  }
+  
+  //Do everything in one big try/catch block,
+  //reverting the transaction if anything fail:
+  try
   {
-    if(trans_fields.empty() || query_execute(connection, Glib::ustring("INSERT INTO \"") + TEMPORARY_TABLE_NAME + "\" SELECT " + trans_fields + " FROM \"" + table_name + "\"", error))
+    connection->get_provider()->perform_operation(connection, operation);
+  
+    if(!trans_fields.empty())
     {
-      if(query_execute(connection, "DROP TABLE " + table_name, error))
-      {
-        if(query_execute(connection, Glib::ustring("ALTER TABLE \"") + TEMPORARY_TABLE_NAME + "\" RENAME TO \"" + table_name + "\"", error))
-        {
-          if(commit_transaction(connection, TRANSACTION_NAME, error))
-          {
-            return true;
-          }
-        }
-      }
+      connection->statement_execute_non_select(Glib::ustring("INSERT INTO \"") + TEMPORARY_TABLE_NAME + "\" SELECT " + trans_fields + " FROM \"" + table_name + "\"");
+      connection->statement_execute_non_select("DROP TABLE " + table_name);
+      connection->statement_execute_non_select(Glib::ustring("ALTER TABLE \"") + TEMPORARY_TABLE_NAME + "\" RENAME TO \"" + table_name + "\"");
+    
+      connection->commit_transaction(TRANSACTION_NAME);
+    
+      return true;
     }
   }
-
-  std::auto_ptr<Glib::Error> rollback_error;
-  if(!rollback_transaction(connection, TRANSACTION_NAME, rollback_error))
+  catch(const Glib::Error& ex)
   {
-    std::cerr << "Sqlite::recreate_table: Failed to rollback failed transaction";
-    if(rollback_error.get())
-      std::cerr << ": " << rollback_error->what();
-    std::cerr << std::endl;
+    std::cerr << "Sqlite::recreate_table(): exception=" << ex.what() << std::endl;
+    std::cerr << "Sqlite::recreate_table(): Reverting the transaction." << std::endl;
+    
+    try
+    {
+      connection->rollback_transaction(TRANSACTION_NAME);
+    }
+    catch(const Glib::Error& ex)
+    {
+       std::cerr << "Sqlite::recreate_table(): Could not revert the transaction. exception=" << ex.what() << std::endl;
+    }
   }
 
   return false;
 }
 
-bool Sqlite::add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error)
+void Sqlite::add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field)
 {
   // Sqlite does not support adding primary key columns. So recreate the table
   // in that case.
   if(!field->get_primary_key())
   {
-    return Backend::add_column(connection, table_name, field, error);
+    Backend::add_column(connection, table_name, field);
   }
   else
   {
-    return recreate_table(connection, table_name, type_vec_strings(), type_vec_const_fields(1, field), type_mapFieldChanges(), error);
+    recreate_table(connection, table_name, type_vec_strings(), type_vec_const_fields(1, field), type_mapFieldChanges());
   }
 }
 
-bool Sqlite::drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name, std::auto_ptr<Glib::Error>& error)
+void Sqlite::drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name)
 {
-  return recreate_table(connection, table_name, type_vec_strings(1, field_name), type_vec_const_fields(), type_mapFieldChanges(), error);
+  recreate_table(connection, table_name, type_vec_strings(1, field_name), type_vec_const_fields(), type_mapFieldChanges());
 }
 
-bool Sqlite::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error)
+bool Sqlite::change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields) throw()
 {
   type_mapFieldChanges fields_changed;
 
   for(type_vec_const_fields::size_type i = 0; i < old_fields.size(); ++ i)
     fields_changed[old_fields[i]->get_name()] = new_fields[i];
 
-  return recreate_table(connection, table_name, type_vec_strings(), type_vec_const_fields(), fields_changed, error);
+  return recreate_table(connection, table_name, type_vec_strings(), type_vec_const_fields(), fields_changed);
 }
 
 
diff --git a/glom/libglom/connectionpool_backends/sqlite.h b/glom/libglom/connectionpool_backends/sqlite.h
index bde1a29..3fbf6ea 100644
--- a/glom/libglom/connectionpool_backends/sqlite.h
+++ b/glom/libglom/connectionpool_backends/sqlite.h
@@ -46,24 +46,24 @@ private:
   virtual Glib::ustring get_string_find_operator() const { return "LIKE"; }
   virtual const char* get_public_schema_name() const { return "main"; }
 
-  bool add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, GdaMetaTableColumn* column, unsigned int i, std::auto_ptr<Glib::Error>& error);
-  bool add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const sharedptr<const Field>& column, unsigned int i, std::auto_ptr<Glib::Error>& error);
+  bool add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, GdaMetaTableColumn* column, unsigned int i);
+  bool add_column_to_server_operation(const Glib::RefPtr<Gnome::Gda::ServerOperation>& operation, const sharedptr<const Field>& column, unsigned int i);
 
   typedef std::vector<Glib::ustring> type_vec_strings;
   //typedef std::vector<sharedptr<const Field> > type_vec_fields;
   typedef std::map<Glib::ustring, sharedptr<const Field> > type_mapFieldChanges;
 
-  bool recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_strings& fields_removed, const type_vec_const_fields& fields_added, const type_mapFieldChanges& fields_changed, std::auto_ptr<Glib::Error>& error);
+  bool recreate_table(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_strings& fields_removed, const type_vec_const_fields& fields_added, const type_mapFieldChanges& fields_changed) throw();
 
-  virtual bool add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field, std::auto_ptr<Glib::Error>& error);
-  virtual bool drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name, std::auto_ptr<Glib::Error>& error);
-  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields, std::auto_ptr<Glib::Error>& error);
+  virtual void add_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const sharedptr<const Field>& field);
+  virtual void drop_column(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const Glib::ustring& field_name);
+  virtual bool change_columns(const Glib::RefPtr<Gnome::Gda::Connection>& connection, const Glib::ustring& table_name, const type_vec_const_fields& old_fields, const type_vec_const_fields& new_fields) throw();
 
-  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<ExceptionConnection>& error);
+  virtual Glib::RefPtr<Gnome::Gda::Connection> connect(const Glib::ustring& database, const Glib::ustring& username, const Glib::ustring& password);
 
   /** Creates a new database.
    */
-  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password, std::auto_ptr<Glib::Error>& error);
+  virtual bool create_database(const Glib::ustring& database_name, const Glib::ustring& username, const Glib::ustring& password);
 
 private:
   std::string m_database_directory_uri;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]