29 #include <glib/gstdio.h> 42 #include "qofquery-p.h" 43 #include "qofquerycore-p.h" 48 #include "Recurrence.h" 53 #include "gnc-locale-utils.h" 58 #include "splint-defs.h" 61 #include <boost/regex.hpp> 65 #include <qofsession.hpp> 66 #include <gnc-backend-prov.hpp> 68 #include "gnc-backend-dbi.hpp" 70 #include <gnc-sql-object-backend.hpp> 71 #include "gnc-dbisqlresult.hpp" 72 #include "gnc-dbisqlconnection.hpp" 74 #if LIBDBI_VERSION >= 900 75 #define HAVE_LIBDBI_R 1 76 static dbi_inst dbi_instance =
nullptr;
78 #define HAVE_LIBDBI_R 0 79 #define HAVE_LIBDBI_TO_LONGLONG 0 82 #define TRANSACTION_NAME "trans" 86 #define FILE_URI_TYPE "file" 87 #define FILE_URI_PREFIX (FILE_URI_TYPE "://") 88 #define SQLITE3_URI_TYPE "sqlite3" 89 #define SQLITE3_URI_PREFIX (SQLITE3_URI_TYPE "://") 90 #define PGSQL_DEFAULT_PORT 5432 92 static void adjust_sql_options (dbi_conn connection);
93 template<DbType Type>
bool save_may_clobber_data (dbi_conn conn,
94 const std::string& dbname);
96 template <DbType Type>
121 std::string basename()
const noexcept;
122 const char* dbname()
const noexcept;
123 std::string quote_dbname(DbType t)
const noexcept;
124 std::string m_protocol;
126 std::string m_dbname;
127 std::string m_username;
128 std::string m_password;
129 std::string m_basename;
133 UriStrings::UriStrings(
const std::string& uri)
135 gchar *scheme, *host, *username, *password, *dbname;
139 m_protocol = std::string{scheme};
140 m_host = std::string{host};
142 m_dbname = std::string{dbname};
144 m_username = std::string{username};
146 m_password = std::string{password};
156 UriStrings::basename() const noexcept
158 return m_protocol +
"_" + m_host +
"_" + m_username +
"_" + m_dbname;
162 UriStrings::dbname() const noexcept
164 return m_dbname.c_str();
168 UriStrings::quote_dbname(DbType t)
const noexcept
170 if (m_dbname.empty())
172 const char quote = (t == DbType::DBI_MYSQL ?
'`' :
'"');
173 std::string retval(1, quote);
174 retval += m_dbname + quote;
179 set_options(dbi_conn conn,
const PairVec& options)
181 for (
const auto& option : options)
183 auto opt = option.first.c_str();
184 auto val = option.second.c_str();
185 auto result = dbi_conn_set_option(conn, opt, val);
188 const char *msg =
nullptr;
189 dbi_conn_error(conn, &msg);
190 PERR(
"Error setting %s option to %s: %s", opt, val, msg);
191 throw std::runtime_error(msg);
203 template <DbType Type>
bool 209 options.push_back(std::make_pair(
"host", uri.m_host));
210 options.push_back(std::make_pair(
"dbname", uri.m_dbname));
211 options.push_back(std::make_pair(
"username", uri.m_username));
212 options.push_back(std::make_pair(
"password", uri.m_password));
213 options.push_back(std::make_pair(
"encoding",
"UTF-8"));
216 set_options(conn, options);
217 auto result = dbi_conn_set_option_numeric(conn,
"port", uri.m_portnum);
220 const char *msg =
nullptr;
221 auto err = dbi_conn_error(conn, &msg);
222 PERR(
"Error (%d) setting port option to %d: %s", err, uri.m_portnum, msg);
223 throw std::runtime_error(msg);
226 catch (std::runtime_error& err)
235 template <DbType Type>
void error_handler(dbi_conn conn,
void* data);
236 void error_handler(dbi_conn conn,
void* data);
238 template <DbType Type> dbi_conn
241 const char* dbstr = (Type == DbType::DBI_SQLITE ?
"sqlite3" :
242 Type == DbType::DBI_MYSQL ?
"mysql" :
"pgsql");
244 dbi_conn conn =
nullptr;
246 conn = dbi_conn_new_r (dbstr, dbi_instance);
248 PERR (
"Attempt to connect with an uninitialized dbi_instance");
250 auto conn = dbi_conn_new (dbstr);
255 PERR (
"Unable to create %s dbi connection", dbstr);
260 dbi_conn_error_handler (conn, error_handler<Type>,
this);
261 if (!uri.m_dbname.empty() &&
262 !set_standard_connection_options(conn, uri))
264 dbi_conn_close(conn);
270 set_options(conn, options);
272 catch (std::runtime_error& err)
274 dbi_conn_close(conn);
283 template <DbType Type>
bool 287 const char *dbcreate;
288 if (Type == DbType::DBI_MYSQL)
291 dbcreate =
"CREATE DATABASE %s CHARACTER SET utf8";
296 dbcreate =
"CREATE DATABASE %s WITH TEMPLATE template0 ENCODING 'UTF8'";
299 options.push_back(std::make_pair(
"dbname", dbname));
302 set_options(conn, options);
304 catch (std::runtime_error& err)
310 auto result = dbi_conn_connect (conn);
313 PERR (
"Unable to connect to %s database", dbname);
317 if (Type == DbType::DBI_MYSQL)
318 adjust_sql_options(conn);
319 auto dresult = dbi_conn_queryf (conn, dbcreate, db);
320 if (dresult ==
nullptr)
322 PERR (
"Unable to create database '%s'\n", db);
326 if (Type == DbType::DBI_PGSQL)
328 const char *alterdb =
"ALTER DATABASE %s SET " 329 "standard_conforming_strings TO on";
330 dbi_conn_queryf (conn, alterdb, db);
332 dbi_conn_close(conn);
338 error_handler<DbType::DBI_SQLITE> (dbi_conn conn,
void* user_data)
342 static_cast<decltype(dbi_be)
>(user_data);
343 int err_num = dbi_conn_error (conn, &msg);
349 if (err_num == DBI_ERROR_BADIDX)
return;
350 PERR (
"DBI error: %s\n", msg);
351 if (dbi_be->connected())
360 gboolean file_exists;
363 g_return_if_fail (session !=
nullptr);
364 g_return_if_fail (new_uri !=
nullptr);
370 std::string filepath{path};
372 GFileTest ftest =
static_cast<decltype (ftest)
> (
373 G_FILE_TEST_IS_REGULAR | G_FILE_TEST_EXISTS) ;
374 file_exists = g_file_test (filepath.c_str(), ftest);
376 if (!create && !file_exists)
379 std::string msg{
"Sqlite3 file "};
380 set_message (msg + filepath +
" not found");
381 PWARN (
"Sqlite3 file %s not found", filepath.c_str());
386 if (create && file_exists)
389 g_unlink (filepath.c_str());
393 auto msg =
"Might clobber, mode not SESSION_NEW_OVERWRITE";
402 options.push_back(std::make_pair(
"host",
"localhost"));
403 auto dirname = g_path_get_dirname (filepath.c_str());
404 auto basename = g_path_get_basename (filepath.c_str());
405 options.push_back(std::make_pair(
"dbname", basename));
406 options.push_back(std::make_pair(
"sqlite3_dbdir", dirname));
407 if (basename !=
nullptr) g_free (basename);
408 if (dirname !=
nullptr) g_free (dirname);
410 auto conn = conn_setup(options, uri);
417 auto result = dbi_conn_connect (conn);
421 dbi_conn_close(conn);
422 PERR (
"Unable to connect to %s: %d\n", new_uri, result);
428 if (!conn_test_dbi_library(conn))
430 if (create && !file_exists)
435 dbi_conn_close (conn);
437 g_unlink (filepath.c_str());
439 dbi_conn_close(conn);
440 LEAVE(
"Bad DBI Library");
449 catch (std::runtime_error& err)
457 PINFO (
"logpath=%s", filepath.c_str() ? filepath.c_str() :
"(null)");
463 error_handler<DbType::DBI_MYSQL> (dbi_conn conn,
void* user_data)
466 static_cast<decltype(dbi_be)
>(user_data);
469 auto err_num = dbi_conn_error (conn, &msg);
475 if (err_num == DBI_ERROR_BADIDX)
return;
486 PINFO (
"DBI error: %s\n", msg);
487 dbi_be->set_exists(
false);
495 if (!dbi_be->connected())
497 PINFO (
"DBI error: %s\n", msg);
498 PINFO (
"Note: GncDbiSqlConnection not yet initialized. Skipping further error processing.");
505 PINFO (
"DBI error: %s - Reconnecting...\n", msg);
507 dbi_be->retry_connection(msg);
509 else if (err_num == 2003)
512 dbi_be->retry_connection (msg);
514 else if (err_num == 1007)
516 dbi_be->set_exists(
true);
522 PERR (
"DBI error: %s\n", msg);
527 #define SQL_OPTION_TO_REMOVE "NO_ZERO_DATE" 534 adjust_sql_options_string(
const std::string& str)
539 boost::regex reg{
"(?:," SQL_OPTION_TO_REMOVE
"$|\\b" 540 SQL_OPTION_TO_REMOVE
"\\b,?)"};
541 return regex_replace(str, reg, std::string{
""});
546 adjust_sql_options (dbi_conn connection)
548 dbi_result result = dbi_conn_query( connection,
"SELECT @@sql_mode");
549 if (result ==
nullptr)
552 int err = dbi_conn_error(connection, &errmsg);
553 PERR(
"Unable to read sql_mode %d : %s", err, errmsg);
556 dbi_result_first_row(result);
557 std::string str{dbi_result_get_string_idx(result, 1)};
558 dbi_result_free(result);
562 int err = dbi_conn_error(connection, &errmsg);
564 PERR(
"Unable to get sql_mode %d : %s", err, errmsg);
566 PINFO(
"Sql_mode isn't set.");
569 PINFO(
"Initial sql_mode: %s", str.c_str());
570 if(str.find(SQL_OPTION_TO_REMOVE) != std::string::npos)
571 str = adjust_sql_options_string(str);
574 const char* backslash_option{
"NO_BACKSLASH_ESCAPES"};
576 if (str.find(backslash_option) == std::string::npos)
580 str.append(backslash_option);
583 PINFO(
"Setting sql_mode to %s", str.c_str());
584 std::string set_str{
"SET sql_mode='" + std::move(str) +
"'"};
585 dbi_result set_result = dbi_conn_query(connection,
589 dbi_result_free(set_result);
594 int err = dbi_conn_error(connection, &errmsg);
595 PERR(
"Unable to set sql_mode %d : %s", err, errmsg);
599 template <DbType Type>
bool 600 drop_database(dbi_conn conn,
const UriStrings& uri)
603 if (Type == DbType::DBI_PGSQL)
605 root_db =
"template1";
607 else if (Type == DbType::DBI_MYSQL)
613 PERR (
"Unknown database type, can't proceed.");
617 if (dbi_conn_select_db (conn, root_db) == -1)
619 PERR (
"Failed to switch out of %s, drop will fail.",
620 uri.quote_dbname(Type).c_str());
624 if (!dbi_conn_queryf (conn,
"DROP DATABASE %s",
625 uri.quote_dbname(Type).c_str()))
627 PERR (
"Failed to drop database %s prior to recreating it." 628 "Proceeding would combine old and new data.",
629 uri.quote_dbname(Type).c_str());
636 template <DbType Type>
void 642 g_return_if_fail (session !=
nullptr);
643 g_return_if_fail (new_uri !=
nullptr);
652 if (Type == DbType::DBI_PGSQL)
654 if (uri.m_portnum == 0)
655 uri.m_portnum = PGSQL_DEFAULT_PORT;
660 auto lcname = g_utf8_strdown (uri.dbname(), -1);
661 uri.m_dbname = std::string{lcname};
667 auto conn = conn_setup(options, uri);
675 auto result = dbi_conn_connect (conn);
678 if (Type == DbType::DBI_MYSQL)
679 adjust_sql_options (conn);
680 if(!conn_test_dbi_library(conn))
682 dbi_conn_close(conn);
688 if (create && save_may_clobber_data<Type>(conn, uri.quote_dbname(Type)))
692 if (!drop_database<Type>(conn, uri))
698 PWARN (
"Database already exists, Might clobber it.");
699 dbi_conn_close(conn);
710 PERR (
"Unable to connect to database '%s'\n", uri.dbname());
712 dbi_conn_close(conn);
718 PERR (
"Database '%s' does not exist\n", uri.dbname());
720 std::string msg{
"Database "};
721 set_message(msg + uri.dbname() +
" not found");
729 !create_database(conn, uri.quote_dbname(Type).c_str()))
731 dbi_conn_close(conn);
735 conn = conn_setup(options, uri);
736 result = dbi_conn_connect (conn);
739 PERR (
"Unable to create database '%s'\n", uri.dbname());
741 dbi_conn_close(conn);
745 if (Type == DbType::DBI_MYSQL)
746 adjust_sql_options (conn);
747 if (!conn_test_dbi_library(conn))
749 if (Type == DbType::DBI_PGSQL)
750 dbi_conn_select_db (conn,
"template1");
751 dbi_conn_queryf (conn,
"DROP DATABASE %s",
752 uri.quote_dbname(Type).c_str());
753 dbi_conn_close(conn);
763 catch (std::runtime_error& err)
771 PINFO (
"logpath=%s", translog_path ? translog_path :
"(null)");
772 g_free (translog_path);
778 error_handler<DbType::DBI_PGSQL> (dbi_conn conn,
void* user_data)
781 static_cast<decltype(dbi_be)
>(user_data);
784 auto err_num = dbi_conn_error (conn, &msg);
790 if (err_num == DBI_ERROR_BADIDX)
return;
791 if (g_str_has_prefix (msg,
"FATAL: database") &&
792 g_str_has_suffix (msg,
"does not exist\n"))
794 PINFO (
"DBI error: %s\n", msg);
795 dbi_be->set_exists(
false);
797 else if (g_strrstr (msg,
798 "server closed the connection unexpectedly"))
800 if (!dbi_be->connected())
802 PWARN (
"DBI Error: Connection lost, connection pointer invalid");
805 PINFO (
"DBI error: %s - Reconnecting...\n", msg);
807 dbi_be->retry_connection(msg);
809 else if (g_str_has_prefix (msg,
"connection pointer is NULL") ||
810 g_str_has_prefix (msg,
"could not connect to server"))
813 if (!dbi_be->connected())
819 dbi_be->retry_connection (msg);
824 PERR (
"DBI error: %s\n", msg);
825 if (dbi_be->connected())
832 template <DbType Type>
void 837 finalize_version_info ();
843 template <DbType Type>
861 template <DbType Type>
void 864 g_return_if_fail (book !=
nullptr);
866 ENTER (
"dbi_be=%p, book=%p",
this, book);
868 if (loadType == LOAD_TYPE_INITIAL_LOAD)
872 init_version_info ();
873 assert (m_book ==
nullptr);
879 if (Type == DbType::DBI_SQLITE)
882 if (GNUCASH_RESAVE_VERSION > get_table_version(
"Gnucash"))
889 else if (GNUCASH_RESAVE_VERSION < get_table_version(
"Gnucash-Resave"))
904 template <DbType T>
bool 905 save_may_clobber_data (dbi_conn conn,
const std::string& dbname)
909 auto result = dbi_conn_get_table_list (conn, dbname.c_str(),
nullptr);
913 retval = dbi_result_get_numrows (result) > 0;
914 dbi_result_free (result);
920 save_may_clobber_data <DbType::DBI_PGSQL>(dbi_conn conn,
921 const std::string& dbname)
925 const char* query =
"SELECT relname FROM pg_class WHERE relname !~ '^(pg|sql)_' AND relkind = 'r' ORDER BY relname";
926 auto result = dbi_conn_query (conn, query);
930 retval = dbi_result_get_numrows (result) > 0;
931 dbi_result_free (result);
945 template <DbType Type>
void 950 g_return_if_fail (conn !=
nullptr);
951 g_return_if_fail (book !=
nullptr);
953 ENTER (
"book=%p, primary=%p", book, m_book);
954 if (!conn->begin_transaction())
956 LEAVE(
"Failed to obtain a transaction.");
959 if (!conn->table_operation (TableOpType::backup))
961 conn->rollback_transaction();
962 LEAVE (
"Failed to rename tables");
965 if (!conn->drop_indexes())
967 conn->rollback_transaction();
968 LEAVE (
"Failed to drop indexes");
975 conn->rollback_transaction();
976 LEAVE (
"Failed to create new database tables");
979 conn->table_operation (TableOpType::drop_backup);
980 conn->commit_transaction();
981 LEAVE (
"book=%p", m_book);
993 g_return_if_fail (conn !=
nullptr);
994 g_return_if_fail (book !=
nullptr);
996 ENTER (
"book=%p, primary=%p", book, m_book);
997 if (!conn->table_operation (TableOpType::backup))
1000 conn->table_operation (TableOpType::rollback);
1001 LEAVE (
"Failed to rename tables");
1004 if (!conn->drop_indexes())
1006 conn->table_operation (TableOpType::rollback);
1008 set_message(
"Failed to drop indexes");
1009 LEAVE (
"Failed to drop indexes");
1016 conn->table_operation (TableOpType::rollback);
1017 LEAVE (
"Failed to create new database tables");
1020 conn->table_operation (TableOpType::drop_backup);
1021 LEAVE (
"book=%p", m_book);
1034 G_GNUC_UNUSED
size_t chars_read;
1039 g_return_val_if_fail (uri !=
nullptr, FALSE);
1042 f = g_fopen (filename,
"r");
1048 PINFO (
"doesn't exist (errno=%d) -> DBI", errno);
1053 chars_read = fread (buf,
sizeof (buf) - 1, 1, f);
1054 status = fclose (f);
1057 PERR (
"Error in fclose(): %d\n", errno);
1059 if (g_str_has_prefix (buf,
"SQLite format 3"))
1061 PINFO (
"has SQLite format string -> DBI");
1064 PINFO (
"exists, does not have SQLite format string -> not DBI");
1073 const char* driver_dir;
1075 gboolean have_sqlite3_driver = FALSE;
1076 gboolean have_mysql_driver = FALSE;
1077 gboolean have_pgsql_driver = FALSE;
1081 driver_dir = g_getenv (
"GNC_DBD_DIR");
1082 if (driver_dir ==
nullptr)
1084 PINFO (
"GNC_DBD_DIR not set: using libdbi built-in default\n");
1091 num_drivers = dbi_initialize_r (driver_dir, &dbi_instance);
1093 num_drivers = dbi_initialize (driver_dir);
1095 if (num_drivers <= 0)
1101 gchar *libdir = gnc_path_get_libdir ();
1102 gchar *dir = g_build_filename (libdir,
"dbd",
nullptr);
1105 num_drivers = dbi_initialize_r (dir, &dbi_instance);
1107 num_drivers = dbi_initialize (dir);
1111 if (num_drivers <= 0)
1113 PWARN (
"No DBD drivers found\n");
1117 dbi_driver driver =
nullptr;
1118 PINFO (
"%d DBD drivers found\n", num_drivers);
1123 driver = dbi_driver_list_r (driver, dbi_instance);
1125 driver = dbi_driver_list (driver);
1128 if (driver !=
nullptr)
1130 const gchar* name = dbi_driver_get_name (driver);
1132 PINFO (
"Driver: %s\n", name);
1133 if (strcmp (name,
"sqlite3") == 0)
1135 have_sqlite3_driver = TRUE;
1137 else if (strcmp (name,
"mysql") == 0)
1139 have_mysql_driver = TRUE;
1141 else if (strcmp (name,
"pgsql") == 0)
1143 have_pgsql_driver = TRUE;
1147 while (driver !=
nullptr);
1150 if (have_sqlite3_driver)
1152 const char* name =
"GnuCash Libdbi (SQLITE3) Backend";
1159 if (have_mysql_driver)
1161 const char *name =
"GnuCash Libdbi (MYSQL) Backend";
1166 if (have_pgsql_driver)
1168 const char* name =
"GnuCash Libdbi (POSTGRESQL) Backend";
1178 #ifndef GNC_NO_LOADABLE_MODULES 1179 G_MODULE_EXPORT
void 1185 G_MODULE_EXPORT
void 1186 qof_backend_module_finalize (
void)
1198 dbi_shutdown_r (dbi_instance);
1199 dbi_instance =
nullptr;
1209 log_failed_field(dbi_result result,
const char* fieldname)
1211 auto idx = dbi_result_get_field_idx(result, fieldname);
1212 if (dbi_result_field_is_null_idx(result, idx))
1213 PERR(
"Result field %s is NULL", fieldname);
1216 auto type = dbi_result_get_field_type_idx(result, idx);
1217 auto attribs = dbi_result_get_field_attribs_idx(result, idx);
1218 PERR(
"Result field %s has type %d and attribs %d",
1219 fieldname, type, attribs);
1232 static GncDbiTestResult
1233 dbi_library_test (dbi_conn conn)
1235 int64_t testlonglong = -9223372036854775807LL, resultlonglong = 0;
1236 uint64_t testulonglong = 9223372036854775807LLU, resultulonglong = 0;
1237 double testdouble = 1.7976921348623157E+307, resultdouble = 0.0;
1239 GncDbiTestResult retval = GNC_DBI_PASS;
1241 result = dbi_conn_query (conn,
"CREATE TEMPORARY TABLE numtest " 1242 "( test_int BIGINT, test_unsigned BIGINT," 1243 " test_double FLOAT8 )");
1244 if (result ==
nullptr)
1246 PWARN (
"Test_DBI_Library: Create table failed");
1247 return GNC_DBI_FAIL_SETUP;
1249 dbi_result_free (result);
1250 std::stringstream querystr;
1251 querystr <<
"INSERT INTO numtest VALUES (" << testlonglong <<
1252 ", " << testulonglong <<
", " << std::setprecision(12) <<
1254 auto query = querystr.str();
1255 result = dbi_conn_query (conn, query.c_str());
1256 if (result ==
nullptr)
1258 PWARN (
"Test_DBI_Library: Failed to insert test row into table");
1259 return GNC_DBI_FAIL_SETUP;
1261 dbi_result_free (result);
1262 auto locale = gnc_push_locale (LC_NUMERIC,
"C");
1263 result = dbi_conn_query (conn,
"SELECT * FROM numtest");
1264 if (result ==
nullptr || !dbi_result_get_numrows(result))
1267 dbi_conn_error (conn, &errmsg);
1268 PWARN (
"Test_DBI_Library: Failed to retrieve test row into table: %s",
1270 dbi_conn_query (conn,
"DROP TABLE numtest");
1271 gnc_pop_locale (LC_NUMERIC, locale);
1272 return GNC_DBI_FAIL_SETUP;
1274 while (dbi_result_next_row (result))
1276 resultlonglong = dbi_result_get_longlong (result,
"test_int");
1277 if (!resultlonglong)
1278 log_failed_field(result,
"test_int");
1279 resultulonglong = dbi_result_get_ulonglong (result,
"test_unsigned");
1280 if (!resultulonglong)
1281 log_failed_field(result,
"test_unsigned");
1282 resultdouble = dbi_result_get_double (result,
"test_double");
1284 log_failed_field(result,
"test_double");
1286 dbi_conn_query (conn,
"DROP TABLE numtest");
1287 gnc_pop_locale (LC_NUMERIC, locale);
1288 if (testlonglong != resultlonglong)
1290 PWARN (
"Test_DBI_Library: LongLong Failed %" PRId64
" != % " PRId64,
1291 testlonglong, resultlonglong);
1292 retval = GNC_DBI_FAIL_TEST;
1294 if (testulonglong != resultulonglong)
1296 PWARN (
"Test_DBI_Library: Unsigned longlong Failed %" PRIu64
" != %" 1297 PRIu64, testulonglong, resultulonglong);
1298 retval = GNC_DBI_FAIL_TEST;
1301 if (testdouble >= resultdouble + 0.000001e307 ||
1302 testdouble <= resultdouble - 0.000001e307)
1304 PWARN (
"Test_DBI_Library: Double Failed %17e != %17e",
1305 testdouble, resultdouble);
1306 retval = GNC_DBI_FAIL_TEST;
1311 template <DbType Type>
bool 1314 auto result = dbi_library_test (conn);
1320 case GNC_DBI_FAIL_SETUP:
1322 set_message (
"DBI library large number test incomplete");
1325 case GNC_DBI_FAIL_TEST:
1327 set_message (
"DBI library fails large number test");
1330 return result == GNC_DBI_PASS;
Lost connection to server.
QofBackend * create_backend(void)
Return a new, fully initialized backend.
load and save data to SQL via libdbi
void set_dbi_error(QofBackendError error, unsigned int repeat, bool retry) noexcept
FIXME: Just a pass-through to m_conn:
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
Print an informational note.
void qof_backend_register_provider(QofBackendProvider_ptr &&prov)
Let the system know about a new provider of backends.
void qof_backend_set_error(QofBackend *qof_be, QofBackendError err)
Set the error on the specified QofBackend.
void gnc_features_set_used(QofBook *book, const gchar *feature)
Indicate that the current book uses the given feature.
bool type_check(const char *type)
Distinguish two providers with same access method.
database is old and needs upgrading
gchar * gnc_uri_get_path(const gchar *uri)
Extracts the path part from a uri.
G_MODULE_EXPORT void qof_backend_module_init(void)
This is the standardized initialization function of a qof_backend GModule, but compiling this can be ...
Create a new store at the URI.
void gnc_uri_get_components(const gchar *uri, gchar **scheme, gchar **hostname, gint32 *port, gchar **username, gchar **password, gchar **path)
Converts a uri in separate components.
void load(QofBook *, QofBackendLoadType) override
Load the contents of an SQL database into a book.
#define PERR(format, args...)
Log a serious error.
#define ENTER(format, args...)
Print a function entry debugging message.
void gnc_module_finalize_backend_dbi(void)
Shutdown function which can be used when this module is statically linked into the application...
#define PWARN(format, args...)
Log a warning.
error in response from server
void safe_sync(QofBook *) override
Safely resave a database by renaming all of its tables, recreating everything, and then dropping the ...
database is newer, we can't write to it
Account handling public routines.
void load(QofBook *, QofBackendLoadType) override
Load the minimal set of application data needed for the application to be operable at initial startup...
void gnc_module_init_backend_dbi(void)
Initialization function which can be used when this module is statically linked into the application...
Anchor Scheduled Transaction info in a book.
LibDBI has numeric errors.
All type declarations for the whole Gnucash engine.
gchar * gnc_build_translog_path(const gchar *filename)
Make a path to filename in the translog subdirectory of the user's configuration directory.
the named database doesn't exist
Generic api to store and retrieve preferences.
Encapsulate a libdbi dbi_conn connection.
API for the transaction logger.
SessionOpenMode
Mode for opening sessions.
File exists, data would be destroyed.
void xaccLogSetBaseName(const char *basepath)
The xaccLogSetBaseName() method sets the base filepath and the root part of the journal file name...
bad dbname/login/passwd or network failure
#define LEAVE(format, args...)
Print a function exit debugging message.
Utility functions for convert uri in separate components and back.
could not complete test for LibDBI bug
void session_begin(QofSession *, const char *, SessionOpenMode) override
Open the file or connect to the server.
File path resolution utility functions.
Open will fail if the URI doesn't exist or is locked.
Utility functions for file access.