Use GncDbiProvider::get_table_list instead of calling out to libdbi.

GncDbiProvider can figure out the dbname for itself so change the
function signature to replace dbname with a particular table to
search for. Pass an empty string ("" works) to get the full list.
This commit is contained in:
John Ralls 2016-08-09 09:30:46 -07:00
parent 02d173d2e7
commit 7ff6e51a72
4 changed files with 39 additions and 71 deletions

View File

@ -921,8 +921,7 @@ gnc_dbi_safe_sync_all (QofBackend* qbe, QofBook* book)
g_return_if_fail (book != nullptr);
ENTER ("book=%p, primary=%p", book, be->m_book);
auto dbname = dbi_conn_get_option (conn->conn(), "dbname");
auto table_list = conn->m_provider->get_table_list (conn->conn(), dbname);
auto table_list = conn->m_provider->get_table_list (conn->conn(), "");
if (!conn->table_operation (table_list, backup))
{
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);

View File

@ -42,7 +42,7 @@ class GncDbiProvider
{
public:
virtual ~GncDbiProvider() = default;
virtual StrVec get_table_list(dbi_conn conn, const std::string& dbname) = 0;
virtual StrVec get_table_list(dbi_conn conn, const std::string& table) = 0;
virtual void append_col_def(std::string& ddl,
const GncSqlColumnInfo& info) = 0;
virtual StrVec get_index_list (dbi_conn conn) = 0;

View File

@ -34,7 +34,7 @@ template <DbType T>
class GncDbiProviderImpl : public GncDbiProvider
{
public:
StrVec get_table_list(dbi_conn conn, const std::string& dbname);
StrVec get_table_list(dbi_conn conn, const std::string& table);
void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
StrVec get_index_list (dbi_conn conn);
void drop_index(dbi_conn conn, const std::string& index);
@ -212,10 +212,12 @@ GncDbiProviderImpl<DbType::DBI_PGSQL>::append_col_def (std::string& ddl,
}
static StrVec
conn_get_table_list (dbi_conn conn, const std::string& dbname)
conn_get_table_list (dbi_conn conn, const std::string& dbname,
const std::string& table)
{
StrVec retval;
auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), nullptr);
const char* tableptr = (table.empty() ? nullptr : table.c_str());
auto tables = dbi_conn_get_table_list (conn, dbname.c_str(), tableptr);
while (dbi_result_next_row (tables) != 0)
{
std::string table_name {dbi_result_get_string_idx (tables, 1)};
@ -227,11 +229,12 @@ conn_get_table_list (dbi_conn conn, const std::string& dbname)
template<> StrVec
GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
const std::string& dbname)
const std::string& table)
{
/* Return the list, but remove the tables that sqlite3 adds for
* its own use. */
auto list = conn_get_table_list (conn, dbname);
std::string dbname (dbi_conn_get_option (conn, "dbname"));
auto list = conn_get_table_list (conn, dbname, table);
auto end = std::remove(list.begin(), list.end(), "sqlite_sequence");
list.erase(end, list.end());
return list;
@ -239,16 +242,18 @@ GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
template<> StrVec
GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
const std::string& dbname)
const std::string& table)
{
return conn_get_table_list (conn, dbname);
std::string dbname (dbi_conn_get_option (conn, "dbname"));
return conn_get_table_list (conn, dbname, table);
}
template<> StrVec
GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
const std::string& dbname)
const std::string& table)
{
auto list = conn_get_table_list (conn, dbname);
std::string dbname (dbi_conn_get_option (conn, "dbname"));
auto list = conn_get_table_list (conn, dbname, table);
auto end = std::remove_if (list.begin(), list.end(),
[](std::string& table_name){
return table_name == "sql_features" ||
@ -289,19 +294,12 @@ GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
{
StrVec retval;
const char* errmsg;
auto dbname = dbi_conn_get_option (conn, "dbname");
auto table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
auto tables = get_table_list(conn, "");
for (auto table_name : tables)
{
PWARN ("Table Retrieval Error: %s\n", errmsg);
return retval;
}
while (dbi_result_next_row (table_list) != 0)
{
auto table_name = dbi_result_get_string_idx (table_list, 1);
auto result = dbi_conn_queryf (conn,
"SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
table_name);
table_name.c_str());
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
{
PWARN ("Index Table Retrieval Error: %s on table %s\n",

View File

@ -35,7 +35,7 @@ static QofLogModule log_module = G_LOG_DOMAIN;
#include "gnc-dbiproviderimpl.hpp"
static const unsigned int DBI_MAX_CONN_ATTEMPTS = 5;
constexpr const char *lock_table_name = "gnclock";
const std::string lock_table = "gnclock";
/* --------------------------------------------------------- */
class GncDbiSqlStatement : public GncSqlStatement
@ -91,22 +91,14 @@ GncDbiSqlConnection::GncDbiSqlConnection (DbType type, QofBackend* qbe,
bool
GncDbiSqlConnection::lock_database (bool ignore_lock)
{
auto dbname = dbi_conn_get_option (m_conn, "dbname");
/* Create the table if it doesn't exist */
auto result = dbi_conn_get_table_list (m_conn, dbname, lock_table_name);
int numrows = 0;
const char* errstr;
if (result) {
numrows = dbi_result_get_numrows (result);
dbi_result_free (result);
result = nullptr;
}
if (numrows == 0)
const char *errstr;
auto tables = m_provider->get_table_list(m_conn, lock_table);
if (tables.empty())
{
result = dbi_conn_queryf (m_conn,
"CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table_name,
GNC_HOST_NAME_MAX);
auto result = dbi_conn_queryf (m_conn,
"CREATE TABLE %s ( Hostname varchar(%d), PID int )",
lock_table.c_str(),
GNC_HOST_NAME_MAX);
if (result)
{
dbi_result_free (result);
@ -121,7 +113,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
}
/* Protect everything with a single transaction to prevent races */
result = dbi_conn_query (m_conn, "BEGIN");
auto result = dbi_conn_query (m_conn, "BEGIN");
if (dbi_conn_error (m_conn, &errstr))
{
/* Couldn't get a transaction (probably couldn't get a lock), so fail */
@ -135,7 +127,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
result = nullptr;
/* Check for an existing entry; delete it if ignore_lock is true, otherwise fail */
char hostname[ GNC_HOST_NAME_MAX + 1 ];
result = dbi_conn_queryf (m_conn, "SELECT * FROM %s", lock_table_name);
result = dbi_conn_queryf (m_conn, "SELECT * FROM %s", lock_table.c_str());
if (result && dbi_result_get_numrows (result))
{
dbi_result_free (result);
@ -147,7 +139,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
dbi_conn_query (m_conn, "ROLLBACK");
return false;
}
result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table_name);
result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table.c_str());
if (!result)
{
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
@ -165,7 +157,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
gethostname (hostname, GNC_HOST_NAME_MAX);
result = dbi_conn_queryf (m_conn,
"INSERT INTO %s VALUES ('%s', '%d')",
lock_table_name, hostname, (int)GETPID ());
lock_table.c_str(), hostname, (int)GETPID ());
if (!result)
{
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
@ -198,23 +190,13 @@ GncDbiSqlConnection::unlock_database ()
if (m_conn == nullptr) return;
g_return_if_fail (dbi_conn_error (m_conn, nullptr) == 0);
auto dbname = dbi_conn_get_option (m_conn, "dbname");
/* Check if the lock table exists */
g_return_if_fail (dbname != nullptr);
auto result = dbi_conn_get_table_list (m_conn, dbname, lock_table_name);
if (! (result && dbi_result_get_numrows (result)))
auto tables = m_provider->get_table_list (m_conn, lock_table);
if (tables.empty())
{
if (result)
{
dbi_result_free (result);
result = nullptr;
}
PWARN ("No lock table in database, so not unlocking it.");
return;
}
dbi_result_free (result);
result = dbi_conn_query (m_conn, "BEGIN");
auto result = dbi_conn_query (m_conn, "BEGIN");
if (result)
{
/* Delete the entry if it's our hostname and PID */
@ -225,7 +207,7 @@ GncDbiSqlConnection::unlock_database ()
memset (hostname, 0, sizeof (hostname));
gethostname (hostname, GNC_HOST_NAME_MAX);
result = dbi_conn_queryf (m_conn,
"SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", lock_table_name, hostname,
"SELECT * FROM %s WHERE Hostname = '%s' AND PID = '%d'", lock_table.c_str(), hostname,
(int)GETPID ());
if (result && dbi_result_get_numrows (result))
{
@ -234,7 +216,8 @@ GncDbiSqlConnection::unlock_database ()
dbi_result_free (result);
result = nullptr;
}
result = dbi_conn_queryf (m_conn, "DELETE FROM %s", lock_table_name);
result = dbi_conn_queryf (m_conn, "DELETE FROM %s",
lock_table.c_str());
if (!result)
{
PERR ("Failed to delete the lock entry");
@ -349,17 +332,7 @@ bool
GncDbiSqlConnection::does_table_exist (const std::string& table_name)
const noexcept
{
auto dbname = dbi_conn_get_option (m_conn, "dbname");
auto tables = dbi_conn_get_table_list (m_conn, dbname, table_name.c_str());
auto nTables = dbi_result_get_numrows (tables);
auto status = dbi_result_free (tables);
if (status < 0)
{
PERR ("Error in dbi_result_free() result\n");
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
}
return nTables == 1;
return ! m_provider->get_table_list(m_conn, table_name).empty();
}
bool
@ -660,8 +633,6 @@ bool
GncDbiSqlConnection::table_operation(const StrVec& table_names,
TableOpType op) noexcept
{
const char* dbname = dbi_conn_get_option (m_conn, "dbname");
std::string lock_table{lock_table_name};
g_return_val_if_fail (!table_names.empty(), FALSE);
bool retval{true};
for (auto table : table_names)
@ -679,7 +650,7 @@ GncDbiSqlConnection::table_operation(const StrVec& table_names,
{
case rollback:
{
auto all_tables = m_provider->get_table_list(m_conn, dbname);
auto all_tables = m_provider->get_table_list(m_conn, "");
if (std::find(all_tables.begin(),
all_tables.end(), table) != all_tables.end())
{