mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -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);
|
g_return_if_fail (book != nullptr);
|
||||||
|
|
||||||
ENTER ("book=%p, primary=%p", book, be->m_book);
|
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(), "");
|
||||||
auto table_list = conn->m_provider->get_table_list (conn->conn(), dbname);
|
|
||||||
if (!conn->table_operation (table_list, backup))
|
if (!conn->table_operation (table_list, backup))
|
||||||
{
|
{
|
||||||
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
|
qof_backend_set_error (qbe, ERR_BACKEND_SERVER_ERR);
|
||||||
|
@ -42,7 +42,7 @@ class GncDbiProvider
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~GncDbiProvider() = default;
|
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,
|
virtual void append_col_def(std::string& ddl,
|
||||||
const GncSqlColumnInfo& info) = 0;
|
const GncSqlColumnInfo& info) = 0;
|
||||||
virtual StrVec get_index_list (dbi_conn conn) = 0;
|
virtual StrVec get_index_list (dbi_conn conn) = 0;
|
||||||
|
@ -34,7 +34,7 @@ template <DbType T>
|
|||||||
class GncDbiProviderImpl : public GncDbiProvider
|
class GncDbiProviderImpl : public GncDbiProvider
|
||||||
{
|
{
|
||||||
public:
|
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);
|
void append_col_def(std::string& ddl, const GncSqlColumnInfo& info);
|
||||||
StrVec get_index_list (dbi_conn conn);
|
StrVec get_index_list (dbi_conn conn);
|
||||||
void drop_index(dbi_conn conn, const std::string& index);
|
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
|
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;
|
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)
|
while (dbi_result_next_row (tables) != 0)
|
||||||
{
|
{
|
||||||
std::string table_name {dbi_result_get_string_idx (tables, 1)};
|
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
|
template<> StrVec
|
||||||
GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
|
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
|
/* Return the list, but remove the tables that sqlite3 adds for
|
||||||
* its own use. */
|
* 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");
|
auto end = std::remove(list.begin(), list.end(), "sqlite_sequence");
|
||||||
list.erase(end, list.end());
|
list.erase(end, list.end());
|
||||||
return list;
|
return list;
|
||||||
@ -239,16 +242,18 @@ GncDbiProviderImpl<DbType::DBI_SQLITE>::get_table_list (dbi_conn conn,
|
|||||||
|
|
||||||
template<> StrVec
|
template<> StrVec
|
||||||
GncDbiProviderImpl<DbType::DBI_MYSQL>::get_table_list (dbi_conn conn,
|
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
|
template<> StrVec
|
||||||
GncDbiProviderImpl<DbType::DBI_PGSQL>::get_table_list (dbi_conn conn,
|
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(),
|
auto end = std::remove_if (list.begin(), list.end(),
|
||||||
[](std::string& table_name){
|
[](std::string& table_name){
|
||||||
return table_name == "sql_features" ||
|
return table_name == "sql_features" ||
|
||||||
@ -289,19 +294,12 @@ GncDbiProviderImpl<DbType::DBI_MYSQL>::get_index_list (dbi_conn conn)
|
|||||||
{
|
{
|
||||||
StrVec retval;
|
StrVec retval;
|
||||||
const char* errmsg;
|
const char* errmsg;
|
||||||
auto dbname = dbi_conn_get_option (conn, "dbname");
|
auto tables = get_table_list(conn, "");
|
||||||
auto table_list = dbi_conn_get_table_list (conn, dbname, nullptr);
|
for (auto table_name : tables)
|
||||||
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
|
|
||||||
{
|
{
|
||||||
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,
|
auto result = dbi_conn_queryf (conn,
|
||||||
"SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
|
"SHOW INDEXES IN %s WHERE Key_name != 'PRIMARY'",
|
||||||
table_name);
|
table_name.c_str());
|
||||||
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
|
if (dbi_conn_error (conn, &errmsg) != DBI_ERROR_NONE)
|
||||||
{
|
{
|
||||||
PWARN ("Index Table Retrieval Error: %s on table %s\n",
|
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"
|
#include "gnc-dbiproviderimpl.hpp"
|
||||||
|
|
||||||
static const unsigned int DBI_MAX_CONN_ATTEMPTS = 5;
|
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
|
class GncDbiSqlStatement : public GncSqlStatement
|
||||||
@ -91,21 +91,13 @@ GncDbiSqlConnection::GncDbiSqlConnection (DbType type, QofBackend* qbe,
|
|||||||
bool
|
bool
|
||||||
GncDbiSqlConnection::lock_database (bool ignore_lock)
|
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;
|
const char *errstr;
|
||||||
if (result) {
|
auto tables = m_provider->get_table_list(m_conn, lock_table);
|
||||||
numrows = dbi_result_get_numrows (result);
|
if (tables.empty())
|
||||||
dbi_result_free (result);
|
|
||||||
result = nullptr;
|
|
||||||
}
|
|
||||||
if (numrows == 0)
|
|
||||||
{
|
{
|
||||||
result = dbi_conn_queryf (m_conn,
|
auto result = dbi_conn_queryf (m_conn,
|
||||||
"CREATE TABLE %s ( Hostname varchar(%d), PID int )", lock_table_name,
|
"CREATE TABLE %s ( Hostname varchar(%d), PID int )",
|
||||||
|
lock_table.c_str(),
|
||||||
GNC_HOST_NAME_MAX);
|
GNC_HOST_NAME_MAX);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@ -121,7 +113,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Protect everything with a single transaction to prevent races */
|
/* 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))
|
if (dbi_conn_error (m_conn, &errstr))
|
||||||
{
|
{
|
||||||
/* Couldn't get a transaction (probably couldn't get a lock), so fail */
|
/* 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;
|
result = nullptr;
|
||||||
/* Check for an existing entry; delete it if ignore_lock is true, otherwise fail */
|
/* Check for an existing entry; delete it if ignore_lock is true, otherwise fail */
|
||||||
char hostname[ GNC_HOST_NAME_MAX + 1 ];
|
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))
|
if (result && dbi_result_get_numrows (result))
|
||||||
{
|
{
|
||||||
dbi_result_free (result);
|
dbi_result_free (result);
|
||||||
@ -147,7 +139,7 @@ GncDbiSqlConnection::lock_database (bool ignore_lock)
|
|||||||
dbi_conn_query (m_conn, "ROLLBACK");
|
dbi_conn_query (m_conn, "ROLLBACK");
|
||||||
return false;
|
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)
|
if (!result)
|
||||||
{
|
{
|
||||||
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
|
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);
|
gethostname (hostname, GNC_HOST_NAME_MAX);
|
||||||
result = dbi_conn_queryf (m_conn,
|
result = dbi_conn_queryf (m_conn,
|
||||||
"INSERT INTO %s VALUES ('%s', '%d')",
|
"INSERT INTO %s VALUES ('%s', '%d')",
|
||||||
lock_table_name, hostname, (int)GETPID ());
|
lock_table.c_str(), hostname, (int)GETPID ());
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
|
qof_backend_set_error (m_qbe, ERR_BACKEND_SERVER_ERR);
|
||||||
@ -198,23 +190,13 @@ GncDbiSqlConnection::unlock_database ()
|
|||||||
if (m_conn == nullptr) return;
|
if (m_conn == nullptr) return;
|
||||||
g_return_if_fail (dbi_conn_error (m_conn, nullptr) == 0);
|
g_return_if_fail (dbi_conn_error (m_conn, nullptr) == 0);
|
||||||
|
|
||||||
auto dbname = dbi_conn_get_option (m_conn, "dbname");
|
auto tables = m_provider->get_table_list (m_conn, lock_table);
|
||||||
/* Check if the lock table exists */
|
if (tables.empty())
|
||||||
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)))
|
|
||||||
{
|
{
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
dbi_result_free (result);
|
|
||||||
result = nullptr;
|
|
||||||
}
|
|
||||||
PWARN ("No lock table in database, so not unlocking it.");
|
PWARN ("No lock table in database, so not unlocking it.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dbi_result_free (result);
|
auto result = dbi_conn_query (m_conn, "BEGIN");
|
||||||
|
|
||||||
result = dbi_conn_query (m_conn, "BEGIN");
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
/* Delete the entry if it's our hostname and PID */
|
/* Delete the entry if it's our hostname and PID */
|
||||||
@ -225,7 +207,7 @@ GncDbiSqlConnection::unlock_database ()
|
|||||||
memset (hostname, 0, sizeof (hostname));
|
memset (hostname, 0, sizeof (hostname));
|
||||||
gethostname (hostname, GNC_HOST_NAME_MAX);
|
gethostname (hostname, GNC_HOST_NAME_MAX);
|
||||||
result = dbi_conn_queryf (m_conn,
|
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 ());
|
(int)GETPID ());
|
||||||
if (result && dbi_result_get_numrows (result))
|
if (result && dbi_result_get_numrows (result))
|
||||||
{
|
{
|
||||||
@ -234,7 +216,8 @@ GncDbiSqlConnection::unlock_database ()
|
|||||||
dbi_result_free (result);
|
dbi_result_free (result);
|
||||||
result = nullptr;
|
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)
|
if (!result)
|
||||||
{
|
{
|
||||||
PERR ("Failed to delete the lock entry");
|
PERR ("Failed to delete the lock entry");
|
||||||
@ -349,17 +332,7 @@ bool
|
|||||||
GncDbiSqlConnection::does_table_exist (const std::string& table_name)
|
GncDbiSqlConnection::does_table_exist (const std::string& table_name)
|
||||||
const noexcept
|
const noexcept
|
||||||
{
|
{
|
||||||
auto dbname = dbi_conn_get_option (m_conn, "dbname");
|
return ! m_provider->get_table_list(m_conn, table_name).empty();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -660,8 +633,6 @@ bool
|
|||||||
GncDbiSqlConnection::table_operation(const StrVec& table_names,
|
GncDbiSqlConnection::table_operation(const StrVec& table_names,
|
||||||
TableOpType op) noexcept
|
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);
|
g_return_val_if_fail (!table_names.empty(), FALSE);
|
||||||
bool retval{true};
|
bool retval{true};
|
||||||
for (auto table : table_names)
|
for (auto table : table_names)
|
||||||
@ -679,7 +650,7 @@ GncDbiSqlConnection::table_operation(const StrVec& table_names,
|
|||||||
{
|
{
|
||||||
case rollback:
|
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(),
|
if (std::find(all_tables.begin(),
|
||||||
all_tables.end(), table) != all_tables.end())
|
all_tables.end(), table) != all_tables.end())
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user