libdballe 9.6
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 <dballe/sql/sql.h>
8#include <mysql.h>
9#include <cstdlib>
10#include <vector>
11#include <functional>
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, ...) WREPORT_THROWF_ATTRS(2, 3);
31};
32
33namespace mysql {
34
36{
37 std::string host;
38 std::string user;
39 bool has_passwd = false;
40 std::string passwd;
41 bool has_dbname = false;
42 std::string dbname;
43 unsigned port = 0;
44 std::string unix_socket;
45
46 // Reset everything to defaults
47 void reset();
48 void parse_url(const std::string& url);
49 // Modeled after http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
50 std::string to_url() const;
51};
52
53struct Row
54{
55 MYSQL_RES* res = nullptr;
56 MYSQL_ROW row = nullptr;
57
58 Row(MYSQL_RES* res, MYSQL_ROW row) : res(res), row(row) {}
59
60 operator bool() const { return row != nullptr; }
61 operator MYSQL_ROW() { return row; }
62 operator MYSQL_ROW() const { return row; }
63
64 int as_int(unsigned col) const { return strtol(row[col], 0, 10); }
65 unsigned as_unsigned(unsigned col) const { return strtoul(row[col], 0, 10); }
66 const char* as_cstring(unsigned col) const { return row[col]; }
67 std::string as_string(unsigned col) const { return std::string(row[col], mysql_fetch_lengths(res)[col]); }
68 std::vector<uint8_t> as_blob(unsigned col) const
69 {
70 return std::vector<uint8_t>(row[col], row[col] + mysql_fetch_lengths(res)[col]);
71 }
72 Datetime as_datetime(int col) const;
73 bool isnull(unsigned col) const { return row[col] == nullptr; }
74};
75
76struct Result
77{
78 MYSQL_RES* res = nullptr;
79
80 Result() : res(nullptr) {}
81 Result(MYSQL_RES* res) : res(res) {}
82 ~Result() { if (res) mysql_free_result(res); }
83
85 Result(Result&& o) : res(o.res) { o.res = nullptr; }
86 Result& operator=(Result&& o)
87 {
88 if (this == &o) return *this;
89 if (res) mysql_free_result(res);
90 res = o.res;
91 o.res = nullptr;
92 return *this;
93 }
94
95 operator bool() const { return res != nullptr; }
96
97 operator MYSQL_RES*() { return res; }
98 operator const MYSQL_RES*() const { return res; }
99
100 unsigned rowcount() const { return mysql_num_rows(res); }
101 unsigned colcount() const { return mysql_num_fields(res); }
102
105
115 Row fetch() { return Row(res, mysql_fetch_row(res)); }
116
117 // Prevent copy
118 Result(const Result&) = delete;
119 Result& operator=(const Result&) = delete;
120};
121
122}
123
124
127{
128protected:
130 MYSQL* db = nullptr;
132 bool forked = false;
133
134 void send_result(mysql::Result&& res, std::function<void(const mysql::Row&)> dest);
135
136protected:
137 void init_after_connect();
138
139 // See https://dev.mysql.com/doc/refman/5.0/en/mysql-real-connect.html
140 void open(const mysql::ConnectInfo& info);
141
143
144 void fork_prepare() override;
145 void fork_parent() override;
146 void fork_child() override;
147
148 void check_connection();
149
150public:
151 MySQLConnection(const MySQLConnection&) = delete;
152 MySQLConnection(const MySQLConnection&&) = delete;
154 MySQLConnection& operator=(const MySQLConnection&) = delete;
155 MySQLConnection& operator=(const MySQLConnection&&) = delete;
156
157 static std::shared_ptr<MySQLConnection> create();
158
159 operator MYSQL*() { return db; }
160
161 // See http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
162 void open_url(const std::string& url);
163 void open_test();
164
166 std::string escape(const char* str);
168 std::string escape(const std::string& str);
170 std::string escape(const std::vector<uint8_t>& str);
171
176 void exec_no_data_nothrow(const char* query) noexcept;
177 // Run a query, checking that it is successful and it gives no results
178 void exec_no_data(const char* query);
179 // Run a query, checking that it is successful and it gives no results
180 void exec_no_data(const std::string& query);
181 // Run a query, with a locally stored result
182 mysql::Result exec_store(const char* query);
183 // Run a query, with a locally stored result
184 mysql::Result exec_store(const std::string& query);
185 // Run a query, with a remotely fetched result
186 void exec_use(const char* query, std::function<void(const mysql::Row&)> dest);
187 // Run a query, with a remotely fetched result
188 void exec_use(const std::string& query, std::function<void(const mysql::Row&)> dest);
189
190 std::unique_ptr<Transaction> transaction(bool readonly=false) override;
191 bool has_table(const std::string& name) override;
192 std::string get_setting(const std::string& key) override;
193 void set_setting(const std::string& key, const std::string& value) override;
194 void drop_settings() override;
195 void execute(const std::string& query) override;
196 void explain(const std::string& query, FILE* out) override;
197
201 void drop_table_if_exists(const char* name);
202
210};
211
212}
213}
214#endif
215
Definition: sql.h:53
Database connection.
Definition: mysql.h:127
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:130
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:132
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:165
Error in case of failed database operations.
Definition: error.h:22
Report a MySQL error.
Definition: mysql.h:21
Definition: mysql.h:36
Definition: mysql.h:77
Row fetch()
Fetch one row.
Definition: mysql.h:115
Row expect_one_result()
Check that the function returned only one row, and return that row.
Result(Result &&o)
Implement move.
Definition: mysql.h:85
Definition: mysql.h:54