4 #ifndef DBALLE_SQL_POSTGRESQL_H 5 #define DBALLE_SQL_POSTGRESQL_H 12 #include <unordered_set> 29 const char* what()
const noexcept
override {
return msg.c_str(); }
32 static void throwf(PGresult* db,
const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3);
35 namespace postgresql {
37 int64_t encode_datetime(
const Datetime& arg);
38 int64_t encode_int64_t(int64_t arg);
41 template<
typename... ARGS>
struct Params 43 static const int count =
sizeof...(ARGS);
44 const char* args[
sizeof...(ARGS)];
45 int lengths[
sizeof...(ARGS)];
46 int formats[
sizeof...(ARGS)];
47 void* local[
sizeof...(ARGS)];
49 Params(
const ARGS&... args)
71 template<
typename... REST>
72 void _add(
unsigned pos, std::nullptr_t arg,
const REST&... rest)
78 _add(pos + 1, rest...);
82 template<
typename... REST>
83 void _add(
unsigned pos, int32_t arg,
const REST&... rest)
85 local[pos] = malloc(
sizeof(int32_t));
86 *(int32_t*)local[pos] = (int32_t)htonl((uint32_t)arg);
87 args[pos] = (
const char*)local[pos];
88 lengths[pos] =
sizeof(int32_t);
90 _add(pos + 1, rest...);
94 template<
typename... REST>
95 void _add(
unsigned pos, uint64_t arg,
const REST&... rest)
97 local[pos] = malloc(
sizeof(int64_t));
98 *(int64_t*)local[pos] = encode_int64_t(arg);
99 args[pos] = (
const char*)local[pos];
100 lengths[pos] =
sizeof(int64_t);
102 _add(pos + 1, rest...);
106 template<
typename... REST>
107 void _add(
unsigned pos,
const char* arg,
const REST&... rest)
109 local[pos] =
nullptr;
113 _add(pos + 1, rest...);
117 template<
typename... REST>
118 void _add(
unsigned pos,
const std::string& arg,
const REST&... rest)
120 local[pos] =
nullptr;
121 args[pos] = arg.data();
122 lengths[pos] = arg.size();
124 _add(pos + 1, rest...);
128 template<
typename... REST>
129 void _add(
unsigned pos,
const std::vector<uint8_t>& arg,
const REST&... rest)
131 local[pos] =
nullptr;
132 args[pos] = (
const char*)arg.data();
133 lengths[pos] = arg.size();
135 _add(pos + 1, rest...);
139 template<
typename... REST>
142 local[pos] = malloc(
sizeof(int64_t));
143 *(int64_t*)local[pos] = encode_datetime(arg);
144 args[pos] = (
const char*)local[pos];
145 lengths[pos] =
sizeof(int64_t);
147 _add(pos + 1, rest...);
156 Result() : res(
nullptr) {}
157 Result(PGresult* res) : res(res) {}
158 ~
Result() { PQclear(res); }
164 if (
this == &o)
return *
this;
171 operator bool()
const {
return res !=
nullptr; }
172 operator PGresult*() {
return res; }
173 operator const PGresult*()
const {
return res; }
176 void expect_no_data(
const std::string& query);
179 void expect_result(
const std::string& query);
182 void expect_one_row(
const std::string& query);
185 void expect_success(
const std::string& query);
188 unsigned rowcount()
const {
return PQntuples(res); }
191 bool is_null(
unsigned row,
unsigned col)
const 193 return PQgetisnull(res, row, col);
199 char* val = PQgetvalue(res, row, col);
204 uint16_t
get_int2(
unsigned row,
unsigned col)
const 206 char* val = PQgetvalue(res, row, col);
207 return ntohs(*(uint16_t*)val);
211 uint32_t
get_int4(
unsigned row,
unsigned col)
const 213 char* val = PQgetvalue(res, row, col);
214 return ntohl(*(uint32_t*)val);
218 uint64_t get_int8(
unsigned row,
unsigned col)
const;
221 std::vector<uint8_t> get_bytea(
unsigned row,
unsigned col)
const;
226 return PQgetvalue(res, row, col);
230 Datetime get_timestamp(
unsigned row,
unsigned col)
const;
245 PGconn* db =
nullptr;
246 std::unordered_set<std::string> prepared_names;
249 void init_after_connect();
259 operator PGconn*() {
return db; }
267 void open_url(
const std::string& connection_string);
270 std::unique_ptr<Transaction> transaction(
bool readonly=
false)
override;
273 void prepare(
const std::string& name,
const std::string& query);
277 return PQexecParams(db, query, 0,
nullptr,
nullptr,
nullptr,
nullptr, 1);
282 return PQexecParams(db, query.c_str(), 0,
nullptr,
nullptr,
nullptr,
nullptr, 1);
285 template<
typename STRING>
286 void exec_no_data(STRING query)
289 res.expect_no_data(query);
292 template<
typename STRING>
296 res.expect_result(query);
300 template<
typename STRING>
304 res.expect_one_row(query);
308 template<
typename ...ARGS>
312 return PQexecParams(db, query, params.count,
nullptr, params.args, params.lengths, params.formats, 1);
315 template<
typename ...ARGS>
319 return PQexecParams(db, query.c_str(), params.count,
nullptr, params.args, params.lengths, params.formats, 1);
322 template<
typename STRING,
typename ...ARGS>
323 void exec_no_data(STRING query, ARGS... args)
326 res.expect_no_data(query);
329 template<
typename STRING,
typename ...ARGS>
333 res.expect_result(query);
337 template<
typename STRING,
typename ...ARGS>
341 res.expect_one_row(query);
347 return PQexecPrepared(db, name, 0,
nullptr,
nullptr,
nullptr, 1);
352 return PQexecPrepared(db, name.c_str(), 0,
nullptr,
nullptr,
nullptr, 1);
355 template<
typename STRING>
356 void exec_prepared_no_data(STRING name)
359 res.expect_no_data(name);
362 template<
typename STRING>
366 res.expect_result(name);
370 template<
typename STRING>
374 res.expect_one_row(name);
378 template<
typename ...ARGS>
382 return PQexecPrepared(db, name, params.count, params.args, params.lengths, params.formats, 1);
385 template<
typename ...ARGS>
389 return PQexecPrepared(db, name.c_str(), params.count, params.args, params.lengths, params.formats, 1);
392 template<
typename STRING,
typename ...ARGS>
393 void exec_prepared_no_data(STRING name, ARGS... args)
396 res.expect_no_data(name);
399 template<
typename STRING,
typename ...ARGS>
403 res.expect_result(name);
407 template<
typename STRING,
typename ...ARGS>
411 res.expect_one_row(name);
416 void cancel_running_query_nothrow() noexcept;
419 void discard_all_input_nothrow() noexcept;
421 bool has_table(const
std::
string& name) override;
422 std::
string get_setting(const
std::
string& key) override;
423 void set_setting(const
std::
string& key, const
std::
string& value) override;
424 void drop_settings() override;
425 void execute(const
std::
string& query) override;
426 void explain(const
std::
string& query, FILE* out) override;
431 void drop_table_if_exists(const
char* name);
437 void pqexec(const
std::
string& query);
445 void pqexec_nothrow(const
std::
string& query) noexcept;
448 void run_single_row_mode(const
std::
string& query_desc,
std::function<
void(const postgresql::Result&)> dest);
451 void append_escaped(
Querybuf& qb, const
char* str);
454 void append_escaped(
Querybuf& qb, const
std::
string& str);
457 void append_escaped(
Querybuf& qb, const
std::vector<uint8_t>& buf);
Database connection.
Definition: postgresql.h:241
Result(Result &&o)
Implement move.
Definition: postgresql.h:161
Argument list for PQexecParams built at compile time.
Definition: postgresql.h:41
void _add(unsigned pos, const char *arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:107
void _add(unsigned pos, uint64_t arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:95
unsigned rowcount() const
Get the number of rows in the result.
Definition: postgresql.h:188
void _add(unsigned pos)
Terminating condition for compile-time arg expansion.
Definition: postgresql.h:66
void _add(unsigned pos, const std::vector< uint8_t > &arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:129
uint16_t get_int2(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a 2 bit integer.
Definition: postgresql.h:204
bool is_null(unsigned row, unsigned col) const
Check if a result value is null.
Definition: postgresql.h:191
uint32_t get_int4(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a 4 bit integer.
Definition: postgresql.h:211
Wrap a PGresult, taking care of its memory management.
Definition: postgresql.h:152
bool get_bool(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a byte (?)
Definition: postgresql.h:197
void _add(unsigned pos, int32_t arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:83
Report an PostgreSQL error.
Definition: postgresql.h:20
Common infrastructure for talking with SQL databases.
Error in case of failed database operations.
Definition: error.h:21
void _add(unsigned pos, const std::string &arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:118
void _add(unsigned pos, const Datetime &arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:140
Date and time.
Definition: types.h:164
#define WREPORT_THROWF_ATTRS(a, b)
void _add(unsigned pos, std::nullptr_t arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:72
const char * get_string(unsigned row, unsigned col) const
Return a result value, transmitted as a string.
Definition: postgresql.h:224
String buffer for composing database queries.
Definition: querybuf.h:15