libdballe 9.13
mysql.h
Go to the documentation of this file.
1
4#ifndef DBALLE_SQL_MYSQL_H
5#define DBALLE_SQL_MYSQL_H
6
7#include <cstdlib>
8#include <dballe/sql/sql.h>
9#include <functional>
10#include <mysql.h>
11#include <vector>
12
13namespace dballe {
14namespace sql {
15struct MySQLStatement;
16
20struct error_mysql : public error_db
21{
22 std::string msg;
23
24 error_mysql(MYSQL* db, const std::string& msg);
25 error_mysql(const std::string& dbmsg, const std::string& msg);
26 ~error_mysql() throw() {}
27
28 const char* what() const noexcept override { return msg.c_str(); }
29
30 static void throwf(MYSQL* db, const char* fmt, ...)
32};
33
34namespace mysql {
35
37{
38 std::string host;
39 std::string user;
40 bool has_passwd = false;
41 std::string passwd;
42 bool has_dbname = false;
43 std::string dbname;
44 unsigned port = 0;
45 std::string unix_socket;
46
47 // Reset everything to defaults
48 void reset();
49 void parse_url(const std::string& url);
50 // Modeled after
51 // http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
52 std::string to_url() const;
53};
54
55struct Row
56{
57 MYSQL_RES* res = nullptr;
58 MYSQL_ROW row = nullptr;
59
60 Row(MYSQL_RES* res, MYSQL_ROW row) : res(res), row(row) {}
61
62 operator bool() const { return row != nullptr; }
63 operator MYSQL_ROW() { return row; }
64 operator MYSQL_ROW() const { return row; }
65
66 int as_int(unsigned col) const { return strtol(row[col], 0, 10); }
67 unsigned as_unsigned(unsigned col) const
68 {
69 return strtoul(row[col], 0, 10);
70 }
71 const char* as_cstring(unsigned col) const { return row[col]; }
72 std::string as_string(unsigned col) const
73 {
74 return std::string(row[col], mysql_fetch_lengths(res)[col]);
75 }
76 std::vector<uint8_t> as_blob(unsigned col) const
77 {
78 return std::vector<uint8_t>(row[col],
79 row[col] + mysql_fetch_lengths(res)[col]);
80 }
81 Datetime as_datetime(int col) const;
82 bool isnull(unsigned col) const { return row[col] == nullptr; }
83};
84
85struct Result
86{
87 MYSQL_RES* res = nullptr;
88
89 Result() : res(nullptr) {}
90 Result(MYSQL_RES* res) : res(res) {}
91 ~Result()
92 {
93 if (res)
94 mysql_free_result(res);
95 }
96
98 Result(Result&& o) : res(o.res) { o.res = nullptr; }
99 Result& operator=(Result&& o)
100 {
101 if (this == &o)
102 return *this;
103 if (res)
104 mysql_free_result(res);
105 res = o.res;
106 o.res = nullptr;
107 return *this;
108 }
109
110 operator bool() const { return res != nullptr; }
111
112 operator MYSQL_RES*() { return res; }
113 operator const MYSQL_RES*() const { return res; }
114
115 unsigned rowcount() const { return mysql_num_rows(res); }
116 unsigned colcount() const { return mysql_num_fields(res); }
117
120
130 Row fetch() { return Row(res, mysql_fetch_row(res)); }
131
132 // Prevent copy
133 Result(const Result&) = delete;
134 Result& operator=(const Result&) = delete;
135};
136
137} // namespace mysql
138
140class MySQLConnection : public Connection
141{
142protected:
144 MYSQL* db = nullptr;
146 bool forked = false;
147
148 void send_result(mysql::Result&& res,
149 std::function<void(const mysql::Row&)> dest);
150
151protected:
152 void init_after_connect();
153
154 // See https://dev.mysql.com/doc/refman/5.0/en/mysql-real-connect.html
155 void open(const mysql::ConnectInfo& info);
156
157 MySQLConnection();
158
159 void fork_prepare() override;
160 void fork_parent() override;
161 void fork_child() override;
162
163 void check_connection();
164
165public:
166 MySQLConnection(const MySQLConnection&) = delete;
167 MySQLConnection(const MySQLConnection&&) = delete;
168 ~MySQLConnection();
169 MySQLConnection& operator=(const MySQLConnection&) = delete;
170 MySQLConnection& operator=(const MySQLConnection&&) = delete;
171
172 static std::shared_ptr<MySQLConnection> create();
173
174 operator MYSQL*() { return db; }
175
176 // See
177 // http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
178 void open_url(const std::string& url);
179 void open_test();
180
182 std::string escape(const char* str);
184 std::string escape(const std::string& str);
186 std::string escape(const std::vector<uint8_t>& str);
187
192 void exec_no_data_nothrow(const char* query) noexcept;
193 // Run a query, checking that it is successful and it gives no results
194 void exec_no_data(const char* query);
195 // Run a query, checking that it is successful and it gives no results
196 void exec_no_data(const std::string& query);
197 // Run a query, with a locally stored result
198 mysql::Result exec_store(const char* query);
199 // Run a query, with a locally stored result
200 mysql::Result exec_store(const std::string& query);
201 // Run a query, with a remotely fetched result
202 void exec_use(const char* query,
203 std::function<void(const mysql::Row&)> dest);
204 // Run a query, with a remotely fetched result
205 void exec_use(const std::string& query,
206 std::function<void(const mysql::Row&)> dest);
207
208 std::unique_ptr<Transaction> transaction(bool readonly = false) override;
209 bool has_table(const std::string& name) override;
210 std::string get_setting(const std::string& key) override;
211 void set_setting(const std::string& key, const std::string& value) override;
212 void drop_settings() override;
213 void execute(const std::string& query) override;
214 void explain(const std::string& query, FILE* out) override;
215
219 void drop_table_if_exists(const char* name);
220
228};
229
230} // namespace sql
231} // namespace dballe
232#endif
std::string get_setting(const std::string &key) override
Get a value from the settings table.
std::string escape(const std::vector< uint8_t > &str)
Escape a byte buffer.
bool has_table(const std::string &name) override
Check if the database contains a table.
MYSQL * db
Database connection.
Definition mysql.h:144
std::unique_ptr< Transaction > transaction(bool readonly=false) override
Begin a transaction.
void drop_table_if_exists(const char *name)
Delete a table in the database if it exists, otherwise do nothing.
int get_last_insert_id()
Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for the current database,...
void execute(const std::string &query) override
Execute a query without reading its results.
std::string escape(const std::string &str)
Escape a string.
void set_setting(const std::string &key, const std::string &value) override
Set a value in the settings table.
bool forked
Marker to catch attempts to reuse connections in forked processes.
Definition mysql.h:146
void exec_no_data_nothrow(const char *query) noexcept
Run a query throwing no exceptions, warning on stderr if it is not successful or if it gives a nonemp...
void drop_settings() override
Drop the settings table.
void explain(const std::string &query, FILE *out) override
Format and print the EXPLAIN output for the query to the given file.
std::string escape(const char *str)
Escape a C string.
#define WREPORT_THROWF_ATTRS(a, b)
MySQL DB connector.
Common infrastructure for talking with SQL databases.
Date and time.
Definition types.h:164
Error in case of failed database operations.
Definition error.h:22
Definition mysql.h:37
Definition mysql.h:86
Row fetch()
Fetch one row.
Definition mysql.h:130
Row expect_one_result()
Check that the function returned only one row, and return that row.
Result(Result &&o)
Implement move.
Definition mysql.h:98
Definition mysql.h:56