22 #ifndef DBALLE_DB_POSTGRESQL_INTERNALS_H
23 #define DBALLE_DB_POSTGRESQL_INTERNALS_H
26 #include <dballe/db/sql.h>
28 #include <arpa/inet.h>
49 wreport::ErrorCode code()
const throw () {
return wreport::WR_ERR_ODBC; }
51 virtual const char* what()
const throw () {
return msg.c_str(); }
53 static void throwf(PGconn* db,
const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3);
54 static void throwf(PGresult* db,
const char* fmt, ...) WREPORT_THROWF_ATTRS(2, 3);
57 namespace postgresql {
59 int64_t encode_datetime(
const Datetime& arg);
60 int64_t encode_int64_t(int64_t arg);
63 template<
typename... ARGS>
struct Params
65 static const int count =
sizeof...(ARGS);
66 const char* args[
sizeof...(ARGS)];
67 int lengths[
sizeof...(ARGS)];
68 int formats[
sizeof...(ARGS)];
69 void* local[
sizeof...(ARGS)];
71 Params(
const ARGS&... args)
93 template<
typename... REST>
94 void _add(
unsigned pos, std::nullptr_t arg,
const REST&... rest)
100 _add(pos + 1, rest...);
104 template<
typename... REST>
105 void _add(
unsigned pos, int32_t arg,
const REST&... rest)
107 local[pos] = malloc(
sizeof(int32_t));
108 *(int32_t*)local[pos] = (int32_t)htonl((uint32_t)arg);
109 args[pos] = (
const char*)local[pos];
110 lengths[pos] =
sizeof(int32_t);
112 _add(pos + 1, rest...);
116 template<
typename... REST>
117 void _add(
unsigned pos, uint64_t arg,
const REST&... rest)
119 local[pos] = malloc(
sizeof(int64_t));
120 *(int64_t*)local[pos] = encode_int64_t(arg);
121 args[pos] = (
const char*)local[pos];
122 lengths[pos] =
sizeof(int64_t);
124 _add(pos + 1, rest...);
128 template<
typename... REST>
129 void _add(
unsigned pos,
const char* arg,
const REST&... rest)
131 local[pos] =
nullptr;
135 _add(pos + 1, rest...);
139 template<
typename... REST>
140 void _add(
unsigned pos,
const std::string& arg,
const REST&... rest)
142 local[pos] =
nullptr;
143 args[pos] = arg.data();
144 lengths[pos] = arg.size();
146 _add(pos + 1, rest...);
150 template<
typename... REST>
153 local[pos] = malloc(
sizeof(int64_t));
154 *(int64_t*)local[pos] = encode_datetime(arg);
155 args[pos] = (
const char*)local[pos];
156 lengths[pos] =
sizeof(int64_t);
158 _add(pos + 1, rest...);
167 Result() : res(
nullptr) {}
168 Result(PGresult* res) : res(res) {}
169 ~
Result() { PQclear(res); }
175 if (
this == &o)
return *
this;
182 operator bool()
const {
return res !=
nullptr; }
183 operator PGresult*() {
return res; }
184 operator const PGresult*()
const {
return res; }
199 unsigned rowcount()
const {
return PQntuples(res); }
202 bool is_null(
unsigned row,
unsigned col)
const
204 return PQgetisnull(res, row, col);
210 char* val = PQgetvalue(res, row, col);
215 uint16_t
get_int2(
unsigned row,
unsigned col)
const
217 char* val = PQgetvalue(res, row, col);
218 return ntohs(*(uint16_t*)val);
222 uint32_t
get_int4(
unsigned row,
unsigned col)
const
224 char* val = PQgetvalue(res, row, col);
225 return ntohl(*(uint32_t*)val);
229 uint64_t
get_int8(
unsigned row,
unsigned col)
const;
234 return PQgetvalue(res, row, col);
253 PGconn*
db =
nullptr;
256 void init_after_connect();
266 operator PGconn*() {
return db; }
274 void open_url(
const std::string& connection_string);
277 std::unique_ptr<Transaction>
transaction()
override;
280 void prepare(
const std::string& name,
const std::string& query);
284 return PQexecParams(db, query, 0,
nullptr,
nullptr,
nullptr,
nullptr, 1);
287 postgresql::Result exec_unchecked(
const std::string& query)
289 return PQexecParams(db, query.c_str(), 0,
nullptr,
nullptr,
nullptr,
nullptr, 1);
292 template<
typename STRING>
293 void exec_no_data(STRING query)
295 postgresql::Result res(exec_unchecked(query));
296 res.expect_no_data(query);
299 template<
typename STRING>
300 postgresql::Result exec(STRING query)
302 postgresql::Result res(exec_unchecked(query));
303 res.expect_result(query);
307 template<
typename STRING>
308 postgresql::Result exec_one_row(STRING query)
310 postgresql::Result res(exec_unchecked(query));
311 res.expect_one_row(query);
315 template<
typename ...ARGS>
316 postgresql::Result exec_unchecked(
const char* query, ARGS... args)
318 postgresql::Params<ARGS...> params(args...);
319 return PQexecParams(db, query, params.count,
nullptr, params.args, params.lengths, params.formats, 1);
322 template<
typename ...ARGS>
323 postgresql::Result exec_unchecked(
const std::string& query, ARGS... args)
325 postgresql::Params<ARGS...> params(args...);
326 return PQexecParams(db, query.c_str(), params.count,
nullptr, params.args, params.lengths, params.formats, 1);
329 template<
typename STRING,
typename ...ARGS>
330 void exec_no_data(STRING query, ARGS... args)
332 postgresql::Result res(exec_unchecked(query, args...));
333 res.expect_no_data(query);
336 template<
typename STRING,
typename ...ARGS>
337 postgresql::Result exec(STRING query, ARGS... args)
339 postgresql::Result res(exec_unchecked(query, args...));
340 res.expect_result(query);
344 template<
typename STRING,
typename ...ARGS>
345 postgresql::Result exec_one_row(STRING query, ARGS... args)
347 postgresql::Result res(exec_unchecked(query, args...));
348 res.expect_one_row(query);
352 postgresql::Result exec_prepared_unchecked(
const char* name)
354 return PQexecPrepared(db, name, 0,
nullptr,
nullptr,
nullptr, 1);
357 postgresql::Result exec_prepared_unchecked(
const std::string& name)
359 return PQexecPrepared(db, name.c_str(), 0,
nullptr,
nullptr,
nullptr, 1);
362 template<
typename STRING>
363 void exec_prepared_no_data(STRING name)
365 postgresql::Result res(exec_prepared_unchecked(name));
366 res.expect_no_data(name);
369 template<
typename STRING>
370 postgresql::Result exec_prepared(STRING name)
372 postgresql::Result res(exec_prepared_unchecked(name));
373 res.expect_result(name);
377 template<
typename STRING>
378 postgresql::Result exec_prepared_one_row(STRING name)
380 postgresql::Result res(exec_prepared_unchecked(name));
381 res.expect_one_row(name);
385 template<
typename ...ARGS>
386 postgresql::Result exec_prepared_unchecked(
const char* name, ARGS... args)
388 postgresql::Params<ARGS...> params(args...);
389 return PQexecPrepared(db, name, params.count, params.args, params.lengths, params.formats, 1);
392 template<
typename ...ARGS>
393 postgresql::Result exec_prepared_unchecked(
const std::string& name, ARGS... args)
395 postgresql::Params<ARGS...> params(args...);
396 return PQexecPrepared(db, name.c_str(), params.count, params.args, params.lengths, params.formats, 1);
399 template<
typename STRING,
typename ...ARGS>
400 void exec_prepared_no_data(STRING name, ARGS... args)
402 postgresql::Result res(exec_prepared_unchecked(name, args...));
403 res.expect_no_data(name);
406 template<
typename STRING,
typename ...ARGS>
407 postgresql::Result exec_prepared(STRING name, ARGS... args)
409 postgresql::Result res(exec_prepared_unchecked(name, args...));
410 res.expect_result(name);
414 template<
typename STRING,
typename ...ARGS>
415 postgresql::Result exec_prepared_one_row(STRING name, ARGS... args)
417 postgresql::Result res(exec_prepared_unchecked(name, args...));
418 res.expect_one_row(name);
429 bool has_table(const std::
string& name) override;
436 std::
string get_setting(const std::
string& key) override;
443 void set_setting(const std::
string& key, const std::
string& value) override;
457 void pqexec(const std::
string& query);
void _add(unsigned pos, const Datetime &arg, const REST &...rest)
Fill in the argument structures.
Definition: postgresql/internals.h:151
int changes()
Count the number of rows modified by the last query that was run.
Argument list for PQexecParams built at compile time.
Definition: postgresql/internals.h:63
bool get_bool(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a byte (?)
Definition: postgresql/internals.h:208
void open_url(const std::string &connection_string)
Connect to PostgreSQL using a connection URI.
PGconn * db
Database connection.
Definition: postgresql/internals.h:253
Report an PostgreSQL error.
Definition: postgresql/internals.h:36
void pqexec(const std::string &query)
Wrap PQexec.
void expect_result(const std::string &query)
Check that the result successfully returned some (possibly empty) data.
void cancel_running_query_nothrow() noexcept
Send a cancellation command to the server.
uint64_t get_int8(unsigned row, unsigned col) const
Return a result value, transmitted in binary as an 8 bit integer.
void _add(unsigned pos, uint64_t arg, const REST &...rest)
Fill in the argument structures.
Definition: postgresql/internals.h:117
const char * get_string(unsigned row, unsigned col) const
Return a result value, transmitted as a string.
Definition: postgresql/internals.h:232
Wrap a PGresult, taking care of its memory management.
Definition: postgresql/internals.h:163
void _add(unsigned pos, const char *arg, const REST &...rest)
Fill in the argument structures.
Definition: postgresql/internals.h:129
void drop_settings() override
Drop the settings table.
bool has_table(const std::string &name) override
Check if the database contains a table.
std::unique_ptr< Transaction > transaction() override
Begin a transaction.
uint16_t get_int2(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a 2 bit integer.
Definition: postgresql/internals.h:215
Base exception for database errors.
Definition: db/defs.h:54
void expect_one_row(const std::string &query)
Check that the result successfully returned one row of data.
Copyright (C) 2008–2010 ARPA-SIM urpsim@smr.arpa.emr.it
Definition: cmdline.h:17
void expect_success(const std::string &query)
Check that the result was successful.
void pqexec_nothrow(const std::string &query) noexcept
Wrap PQexec but do not throw an exception in case of errors.
Functions used to connect to DB-All.e and insert, query and delete data.
void _add(unsigned pos)
Terminating condition for compile-time arg expansion.
Definition: postgresql/internals.h:88
void _add(unsigned pos, int32_t arg, const REST &...rest)
Fill in the argument structures.
Definition: postgresql/internals.h:105
void _add(unsigned pos, std::nullptr_t arg, const REST &...rest)
Fill in the argument structures.
Definition: postgresql/internals.h:94
void discard_all_input_nothrow() noexcept
Discard all input from an asynchronous request.
unsigned rowcount() const
Get the number of rows in the result.
Definition: postgresql/internals.h:199
Database connection.
Definition: postgresql/internals.h:249
error_postgresql(PGconn *db, const std::string &msg)
Copy informations from the ODBC diagnostic record to the dba error report.
void _add(unsigned pos, const std::string &arg, const REST &...rest)
Fill in the argument structures.
Definition: postgresql/internals.h:140
void set_setting(const std::string &key, const std::string &value) override
Set a value in the settings table.
Datetime get_timestamp(unsigned row, unsigned col) const
Return a result value, transmitted as a timestamp without timezone.
Date and time.
Definition: types.h:147
void prepare(const std::string &name, const std::string &query)
Precompile a query.
Result(Result &&o)
Implement move.
Definition: postgresql/internals.h:172
std::string get_setting(const std::string &key) override
Get a value from the settings table.
void drop_table_if_exists(const char *name)
Delete a table in the database if it exists, otherwise do nothing.
void expect_no_data(const std::string &query)
Check that the result successfully returned no data.
uint32_t get_int4(unsigned row, unsigned col) const
Return a result value, transmitted in binary as a 4 bit integer.
Definition: postgresql/internals.h:222
bool is_null(unsigned row, unsigned col) const
Check if a result value is null.
Definition: postgresql/internals.h:202