[glom] libglom: ConnectionPool: Simplify code.
- From: Murray Cumming <murrayc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glom] libglom: ConnectionPool: Simplify code.
- Date: Sun, 20 Jun 2010 19:55:28 +0000 (UTC)
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]