libdballe  9.14
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 
13 namespace dballe {
14 namespace sql {
15 struct MySQLStatement;
16 
20 struct 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 
34 namespace 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 
55 struct 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 
85 struct 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 
119  Row expect_one_result();
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 
141 {
142 protected:
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 
151 protected:
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 
165 public:
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 
227  int get_last_insert_id();
228 };
229 
230 } // namespace sql
231 } // namespace dballe
232 #endif
void execute(const std::string &query) override
Execute a query without reading its results.
MYSQL * db
Database connection.
Definition: mysql.h:144
Row fetch()
Fetch one row.
Definition: mysql.h:130
void drop_settings() override
Drop the settings table.
Report a MySQL error.
Definition: mysql.h:20
Result(Result &&o)
Implement move.
Definition: mysql.h:98
Definition: cmdline.h:18
MySQL DB connector.
bool forked
Marker to catch attempts to reuse connections in forked processes.
Definition: mysql.h:146
Definition: mysql.h:85
std::unique_ptr< Transaction > transaction(bool readonly=false) override
Begin a transaction.
int get_last_insert_id()
Return LAST_INSERT_ID or LAST_INSER_ROWID or whatever is appropriate for the current database...
Definition: sql.h:53
std::string escape(const char *str)
Escape a C string.
void drop_table_if_exists(const char *name)
Delete a table in the database if it exists, otherwise do nothing.
std::string get_setting(const std::string &key) override
Get a value from the settings table.
bool has_table(const std::string &name) override
Check if the database contains a table.
Common infrastructure for talking with SQL databases.
Error in case of failed database operations.
Definition: error.h:21
Definition: mysql.h:36
Date and time.
Definition: types.h:163
void explain(const std::string &query, FILE *out) override
Format and print the EXPLAIN output for the query to the given file.
#define WREPORT_THROWF_ATTRS(a, b)
Row expect_one_result()
Check that the function returned only one row, and return that row.
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 set_setting(const std::string &key, const std::string &value) override
Set a value in the settings table.
Definition: mysql.h:55
Database connection.
Definition: mysql.h:140