4 #ifndef DBALLE_SQL_POSTGRESQL_H 5 #define DBALLE_SQL_POSTGRESQL_H 27 const char* what()
const noexcept
override {
return msg.c_str(); }
30 static void throwf(PGresult* db,
const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3);
33 namespace postgresql {
35 int64_t encode_datetime(
const Datetime& arg);
36 int64_t encode_int64_t(int64_t arg);
39 template<
typename... ARGS>
struct Params 41 static const int count =
sizeof...(ARGS);
42 const char* args[
sizeof...(ARGS)];
43 int lengths[
sizeof...(ARGS)];
44 int formats[
sizeof...(ARGS)];
45 void* local[
sizeof...(ARGS)];
47 Params(
const ARGS&... args)
69 template<
typename... REST>
70 void _add(
unsigned pos, std::nullptr_t arg,
const REST&... rest)
76 _add(pos + 1, rest...);
80 template<
typename... REST>
81 void _add(
unsigned pos, int32_t arg,
const REST&... rest)
83 local[pos] = malloc(
sizeof(int32_t));
84 *(int32_t*)local[pos] = (int32_t)htonl((uint32_t)arg);
85 args[pos] = (
const char*)local[pos];
86 lengths[pos] =
sizeof(int32_t);
88 _add(pos + 1, rest...);
92 template<
typename... REST>
93 void _add(
unsigned pos, uint64_t arg,
const REST&... rest)
95 local[pos] = malloc(
sizeof(int64_t));
96 *(int64_t*)local[pos] = encode_int64_t(arg);
97 args[pos] = (
const char*)local[pos];
98 lengths[pos] =
sizeof(int64_t);
100 _add(pos + 1, rest...);
104 template<
typename... REST>
105 void _add(
unsigned pos,
const char* arg,
const REST&... rest)
107 local[pos] =
nullptr;
111 _add(pos + 1, rest...);
115 template<
typename... REST>
116 void _add(
unsigned pos,
const std::string& arg,
const REST&... rest)
118 local[pos] =
nullptr;
119 args[pos] = arg.data();
120 lengths[pos] = arg.size();
122 _add(pos + 1, rest...);
126 template<
typename... REST>
127 void _add(
unsigned pos,
const std::vector<uint8_t>& arg,
const REST&... rest)
129 local[pos] =
nullptr;
130 args[pos] = (
const char*)arg.data();
131 lengths[pos] = arg.size();
133 _add(pos + 1, rest...);
137 template<
typename... REST>
140 local[pos] = malloc(
sizeof(int64_t));
141 *(int64_t*)local[pos] = encode_datetime(arg);
142 args[pos] = (
const char*)local[pos];
143 lengths[pos] =
sizeof(int64_t);
145 _add(pos + 1, rest...);
154 Result() : res(
nullptr) {}
155 Result(PGresult* res) : res(res) {}
156 ~
Result() { PQclear(res); }
162 if (
this == &o)
return *
this;
169 operator bool()
const {
return res !=
nullptr; }
170 operator PGresult*() {
return res; }
171 operator const PGresult*()
const {
return res; }
174 void expect_no_data(
const std::string& query);
177 void expect_result(
const std::string& query);
180 void expect_one_row(
const std::string& query);
183 void expect_success(
const std::string& query);
186 unsigned rowcount()
const {
return PQntuples(res); }
189 bool is_null(
unsigned row,
unsigned col)
const 191 return PQgetisnull(res, row, col);
197 char* val = PQgetvalue(res, row, col);
202 uint16_t
get_int2(
unsigned row,
unsigned col)
const 204 char* val = PQgetvalue(res, row, col);
205 return ntohs(*(uint16_t*)val);
209 uint32_t
get_int4(
unsigned row,
unsigned col)
const 211 char* val = PQgetvalue(res, row, col);
212 return ntohl(*(uint32_t*)val);
216 uint64_t get_int8(
unsigned row,
unsigned col)
const;
219 std::vector<uint8_t> get_bytea(
unsigned row,
unsigned col)
const;
224 return PQgetvalue(res, row, col);
228 Datetime get_timestamp(
unsigned row,
unsigned col)
const;
243 PGconn* db =
nullptr;
246 void init_after_connect();
256 operator PGconn*() {
return db; }
264 void open_url(
const std::string& connection_string);
267 std::unique_ptr<Transaction> transaction()
override;
270 void prepare(
const std::string& name,
const std::string& query);
274 if (profile) ++profile_query_count;
275 return PQexecParams(db, query, 0,
nullptr,
nullptr,
nullptr,
nullptr, 1);
280 if (profile) ++profile_query_count;
281 return PQexecParams(db, query.c_str(), 0,
nullptr,
nullptr,
nullptr,
nullptr, 1);
284 template<
typename STRING>
285 void exec_no_data(STRING query)
288 res.expect_no_data(query);
291 template<
typename STRING>
295 res.expect_result(query);
299 template<
typename STRING>
303 res.expect_one_row(query);
307 template<
typename ...ARGS>
311 if (profile) ++profile_query_count;
312 return PQexecParams(db, query, params.count,
nullptr, params.args, params.lengths, params.formats, 1);
315 template<
typename ...ARGS>
319 if (profile) ++profile_query_count;
320 return PQexecParams(db, query.c_str(), params.count,
nullptr, params.args, params.lengths, params.formats, 1);
323 template<
typename STRING,
typename ...ARGS>
324 void exec_no_data(STRING query, ARGS... args)
327 res.expect_no_data(query);
330 template<
typename STRING,
typename ...ARGS>
334 res.expect_result(query);
338 template<
typename STRING,
typename ...ARGS>
342 res.expect_one_row(query);
348 if (profile) ++profile_query_count;
349 return PQexecPrepared(db, name, 0,
nullptr,
nullptr,
nullptr, 1);
354 if (profile) ++profile_query_count;
355 return PQexecPrepared(db, name.c_str(), 0,
nullptr,
nullptr,
nullptr, 1);
358 template<
typename STRING>
359 void exec_prepared_no_data(STRING name)
362 res.expect_no_data(name);
365 template<
typename STRING>
369 res.expect_result(name);
373 template<
typename STRING>
377 res.expect_one_row(name);
381 template<
typename ...ARGS>
385 if (profile) ++profile_query_count;
386 return PQexecPrepared(db, name, params.count, params.args, params.lengths, params.formats, 1);
389 template<
typename ...ARGS>
393 if (profile) ++profile_query_count;
394 return PQexecPrepared(db, name.c_str(), params.count, params.args, params.lengths, params.formats, 1);
397 template<
typename STRING,
typename ...ARGS>
398 void exec_prepared_no_data(STRING name, ARGS... args)
401 res.expect_no_data(name);
404 template<
typename STRING,
typename ...ARGS>
408 res.expect_result(name);
412 template<
typename STRING,
typename ...ARGS>
416 res.expect_one_row(name);
421 void cancel_running_query_nothrow() noexcept;
424 void discard_all_input_nothrow() noexcept;
426 bool has_table(const std::
string& name) override;
427 std::
string get_setting(const std::
string& key) override;
428 void set_setting(const std::
string& key, const std::
string& value) override;
429 void drop_settings() override;
430 void execute(const std::
string& query) override;
431 void explain(const std::
string& query, FILE* out) override;
436 void drop_table_if_exists(const
char* name);
442 void pqexec(const std::
string& query);
450 void pqexec_nothrow(const std::
string& query) noexcept;
453 void run_single_row_mode(const std::
string& query_desc, std::function<
void(const postgresql::Result&)> dest);
456 void append_escaped(
Querybuf& qb, const
char* str);
459 void append_escaped(
Querybuf& qb, const std::
string& str);
462 void append_escaped(
Querybuf& qb, const std::vector<uint8_t>& buf);
Database connection.
Definition: postgresql.h:239
Result(Result &&o)
Implement move.
Definition: postgresql.h:159
Argument list for PQexecParams built at compile time.
Definition: postgresql.h:39
void _add(unsigned pos, const char *arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:105
void _add(unsigned pos, uint64_t arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:93
unsigned rowcount() const
Get the number of rows in the result.
Definition: postgresql.h:186
void _add(unsigned pos)
Terminating condition for compile-time arg expansion.
Definition: postgresql.h:64
void _add(unsigned pos, const std::vector< uint8_t > &arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:127
uint16_t get_int2(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a 2 bit integer.
Definition: postgresql.h:202
Copyright (C) 2008–2010 ARPA-SIM urpsim@smr.arpa.emr.it
Definition: cmdline.h:17
bool is_null(unsigned row, unsigned col) const
Check if a result value is null.
Definition: postgresql.h:189
uint32_t get_int4(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a 4 bit integer.
Definition: postgresql.h:209
Wrap a PGresult, taking care of its memory management.
Definition: postgresql.h:150
bool get_bool(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a byte (?)
Definition: postgresql.h:195
void _add(unsigned pos, int32_t arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:81
Report an PostgreSQL error.
Definition: postgresql.h:18
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:116
void _add(unsigned pos, const Datetime &arg, const REST &... rest)
Fill in the argument structures.
Definition: postgresql.h:138
Date and time.
Definition: types.h:158
#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:70
const char * get_string(unsigned row, unsigned col) const
Return a result value, transmitted as a string.
Definition: postgresql.h:222
String buffer for composing database queries.
Definition: querybuf.h:15