mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-12-02 05:29:20 -06:00
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:
parent
02d173d2e7
commit
7ff6e51a72
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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())
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user