1 /********************************************************************
2  * gnc-backend-dbi.hpp: load and save data to SQL via libdbi     *
3  *                                                                  *
4  * This program is free software; you can redistribute it and/or    *
5  * modify it under the terms of the GNU General Public License as   *
6  * published by the Free Software Foundation; either version 2 of   *
7  * the License, or (at your option) any later version.              *
8  *                                                                  *
9  * This program is distributed in the hope that it will be useful,  *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
12  * GNU General Public License for more details.                     *
13  *                                                                  *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact:                        *
16  *                                                                  *
17  * Free Software Foundation           Voice:  +1-617-542-5942       *
18  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
19  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
20 \********************************************************************/
21 
22 /* Private structures and variables for gnc-backend-dbi.c and its unit tests */
23 #ifndef GNC_BACKEND_DBI_HPP
24 #define GNC_BACKEND_DBI_HPP
25 extern "C"
26 {
27 #include <dbi/dbi.h>
28 #ifdef G_OS_WIN32
29 #include <winsock2.h>
30 #define GETPID() GetCurrentProcessId()
31 #else
32 #include <limits.h>
33 #include <unistd.h>
34 #define GETPID() getpid()
35 #endif
36 }
37 #include <gnc-sql-backend.hpp>
38 #include <gnc-sql-connection.hpp>
39 
40 class GncSqlRow;
41 
42 #define GNC_HOST_NAME_MAX 255
43 
44 /**
45  * Options to conn_table_operation
46  * @var drop Drop (remove without recourse) the table from the database
47  * @var empty Delete all of the records from the table
48  * @var backup Rename the table "name" to "name_back"
49  * @var rollback drop the name table if it exists and rename name_back to name
50  * @var drop_backup Drop the backup table
51  */
52 enum TableOpType
53 {
54     backup = 0,
55     rollback,
56     drop_backup,
57     recover
58 };
59 
60 /**
61  * Return values from conn_test_dbi_library
62  * @var GNC_DBI_PASS Did not find the large numbers bug
63  * @var GNC_DBI_FAIL_SETUP Could not completed the test
64  * @var GNC_DBI_FAIL_TEST Found the large numbers bug
65  */
66 typedef enum
67 {
68     GNC_DBI_PASS = 0,
69     GNC_DBI_FAIL_SETUP,
70     GNC_DBI_FAIL_TEST
71 } GncDbiTestResult;
72 
73 /**
74  * Supported Dbi Backends.
75  */
76 enum class DbType
77 {
78     DBI_SQLITE, /**< Sqlite3 */
79     DBI_MYSQL,  /**< MySQL and probably MariaDB */
80     DBI_PGSQL   /**< Postgresql */
81 };
82 
83 /**
84  * Implementations of GncSqlBackend.
85  */
86 struct UriStrings;
87 
88 template <DbType Type>
89 class GncDbiBackend : public GncSqlBackend
90 {
91 public:
GncDbiBackend(GncSqlConnection * conn,QofBook * book)92     GncDbiBackend(GncSqlConnection *conn, QofBook* book) :
93         GncSqlBackend(conn, book), m_exists{false} {}
94     ~GncDbiBackend();
95     void session_begin(QofSession*, const char*, SessionOpenMode) override;
96     void session_end() override;
97     void load(QofBook*, QofBackendLoadType) override;
98     void safe_sync(QofBook*) override;
connected() const99     bool connected() const noexcept { return m_conn != nullptr; }
100     /** FIXME: Just a pass-through to m_conn: */
set_dbi_error(QofBackendError error,unsigned int repeat,bool retry)101     void set_dbi_error(QofBackendError error, unsigned int repeat,
102                        bool retry) noexcept
103     {
104         m_conn->set_error(error, repeat, retry);
105     }
retry_connection(const char * msg) const106     void retry_connection(const char* msg) const noexcept
107     {
108         m_conn->retry_connection(msg);
109     }
110     /*-----*/
exists()111     bool exists() { return m_exists; }
set_exists(bool exists)112     void set_exists(bool exists) { m_exists = exists; }
113 private:
114     dbi_conn conn_setup(PairVec& options, UriStrings& uri);
115     bool conn_test_dbi_library(dbi_conn conn);
116     bool set_standard_connection_options(dbi_conn conn, const UriStrings& uri);
117     bool create_database(dbi_conn conn, const char* db);
118     bool m_exists;         // Does the database exist?
119 };
120 
121 /* locale-stack */
122 inline std::string
gnc_push_locale(const int category,const std::string locale)123 gnc_push_locale(const int category, const std::string locale)
124 {
125     std::string retval(setlocale(category, nullptr));
126     setlocale(category, locale.c_str());
127     return retval;
128 }
129 
130 inline void
gnc_pop_locale(const int category,std::string locale)131 gnc_pop_locale(const int category, std::string locale)
132 {
133     setlocale(category, locale.c_str());
134 }
135 
136 /* external access required for tests */
137 std::string adjust_sql_options_string(const std::string&);
138 
139 
140 
141 #endif //GNC_BACKEND_DBI_HPP
142