CellModules
Connection.hpp
Go to the documentation of this file.
1#pragma once
2
3
4#if __has_include(<libpq-fe.h>)
5# include <libpq-fe.h>
6#else
7# include <postgresql/libpq-fe.h>
8#endif
9#include <stdexcept>
10#include <string>
11#include <functional>
12#include <arpa/inet.h>
13#include <cstring>
14
15namespace PluginSQL {
16
18 PGconn* conn = nullptr;
20
21public:
22 Connection(const std::string& user,
23 const std::string& pass,
24 const std::string& host,
25 int port,
26 const std::string& dbname)
27 {
28 std::string conninfo =
29 "user=" + user +
30 " password="+ pass +
31 " host=" + host +
32 " port=" + std::to_string(port) +
33 " dbname=" + dbname;
34 conn = PQconnectdb(conninfo.c_str());
35 if (PQstatus(conn) != CONNECTION_OK)
36 throw std::runtime_error(PQerrorMessage(conn));
37 }
38
40 if (conn) PQfinish(conn);
41 }
42
43 void Execute(const std::string &sql) {
44 PGresult* res = PQexec(conn, sql.c_str());
45 if (PQresultStatus(res) != PGRES_COMMAND_OK) {
46 std::string err = PQerrorMessage(conn);
47 PQclear(res);
48 throw std::runtime_error(err);
49 }
50 PQclear(res);
51 }
52
53 // Lance COPY BINARY sur la table en mode binaire
55 const std::string &table,
56 const std::string &columns,
57 const std::function<void()> &writeRows
58 ) {
59 std::string stmt =
60 "COPY " + table + " " + columns + " FROM STDIN WITH (FORMAT binary)";
61 PGresult* res = PQexec(conn, stmt.c_str());
62 if (PQresultStatus(res) != PGRES_COPY_IN) {
63 std::string err = PQerrorMessage(conn);
64 PQclear(res);
65 throw std::runtime_error("COPY start failed: " + err);
66 }
67 PQclear(res);
68
69 writeRows(); // header, lignes, trailer
70
71 if (PQputCopyEnd(conn, nullptr) != 1)
72 throw std::runtime_error("COPY end failed");
73
74 res = PQgetResult(conn);
75 if (PQresultStatus(res) != PGRES_COMMAND_OK) {
76 std::string err = PQerrorMessage(conn);
77 PQclear(res);
78 throw std::runtime_error("COPY finalization failed: " + err);
79 }
80 PQclear(res);
81 }
82
83 // Écrit l'en-tête global du protocole COPY BINARY
84 inline void headerCopy(size_t N, size_t rowSize) {
85 //static const char sig[] = "PGCOPY\n\377\r\n\0";
86 prepareBuffer(N, rowSize);
87
88 static const unsigned char sig[11] = { 'P','G','C','O','P','Y','\n', 0xFF, '\r', '\n', '\0' };
89 appendRaw(sig, sizeof(sig));
90
91 int32_t zero = htonl(0);
92 appendRaw(&zero, sizeof(zero));
93 appendRaw(&zero, sizeof(zero));
94 }
95
96 // Écrit le trailer (fin de flux COPY)
97 inline void footerCopy() {
98 int16_t tr = htons(-1);
99 appendRaw(&tr, sizeof(tr));
100 PQputCopyData(conn, rowBuf.data(), (int)rowBuf.size());
101 rowBuf.clear();
102 }
103
104 void prepareBuffer(size_t N, size_t rowSize) {
105 size_t headerSize = 19; // 11 for signature + 4 for flags + 4 for zero
106 size_t footerSize = 2; // 2 for trailer
107 size_t totalSize = headerSize + N * rowSize + footerSize;
108 rowBuf.reserve(totalSize);
109 }
110
111 void beginRow(int16_t nCols) {
112 int16_t be = htons(nCols);
113 appendRaw(&be, sizeof(be));
114 }
115
116 // b) append d’un bloc brut
117 void appendRaw(const void* data, size_t len) {
118 auto p = reinterpret_cast<const char*>(data);
119 rowBuf.insert(rowBuf.end(), p, p + len);
120 }
121
122 // c) append d’un champ (length + data)
123 void appendField(const void* data, size_t len) {
124 int32_t len_be = htonl((int32_t)len);
125 appendRaw(&len_be, sizeof(len_be));
126 appendRaw(data, len);
127 }
128
129inline void appendBool(bool b) {
130 int32_t len_be = htonl(1);
131 appendRaw(&len_be, sizeof(len_be));
132 unsigned char v = b ? 1 : 0;
133 appendRaw(&v, sizeof(v));
134}
135 inline void appendInt(int v) {
136 int32_t v_be = htonl(static_cast<int32_t>(v));
137 appendField(&v_be, sizeof(v_be));
138 }
139
140 inline void appendDouble(double d) {
141 uint64_t u;
142 std::memcpy(&u, &d, sizeof(u));
143 u = __builtin_bswap64(u);
144 appendField(&u, sizeof(u));
145 }
146};
147
148} // namespace PluginSQL
Connection(const std::string &user, const std::string &pass, const std::string &host, int port, const std::string &dbname)
Definition: Connection.hpp:22
void prepareBuffer(size_t N, size_t rowSize)
Definition: Connection.hpp:104
void CopyBinary(const std::string &table, const std::string &columns, const std::function< void()> &writeRows)
Definition: Connection.hpp:54
void appendField(const void *data, size_t len)
Definition: Connection.hpp:123
std::vector< char > rowBuf
Definition: Connection.hpp:19
void appendDouble(double d)
Definition: Connection.hpp:140
void headerCopy(size_t N, size_t rowSize)
Definition: Connection.hpp:84
void appendBool(bool b)
Definition: Connection.hpp:129
void appendRaw(const void *data, size_t len)
Definition: Connection.hpp:117
void beginRow(int16_t nCols)
Definition: Connection.hpp:111
void Execute(const std::string &sql)
Definition: Connection.hpp:43
void reserve(size_t newCapacity)
Reserves storage for the specified number of elements.
Definition: std.hpp:406
void clear()
Clears the contents of the vector.
Definition: std.hpp:388
iterator end()
Returns an iterator to the last element.
Definition: std.hpp:452
size_t size() const
Returns the number of elements in the vector.
Definition: std.hpp:354
void insert(iterator position, const T &value)
Inserts an element at the specified position.
Definition: std.hpp:425