/src/kea/src/lib/pgsql/pgsql_connection.h
Line | Count | Source |
1 | | // Copyright (C) 2016-2026 Internet Systems Consortium, Inc. ("ISC") |
2 | | // |
3 | | // This Source Code Form is subject to the terms of the Mozilla Public |
4 | | // License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | // file, You can obtain one at http://mozilla.org/MPL/2.0/. |
6 | | #ifndef PGSQL_CONNECTION_H |
7 | | #define PGSQL_CONNECTION_H |
8 | | |
9 | | #include <asiolink/io_service.h> |
10 | | #include <pgsql/pgsql_exchange.h> |
11 | | |
12 | | #include <boost/scoped_ptr.hpp> |
13 | | |
14 | | #include <vector> |
15 | | #include <stdint.h> |
16 | | |
17 | | namespace isc { |
18 | | namespace db { |
19 | | |
20 | | /// @brief Define the PostgreSQL backend version. |
21 | | const uint32_t PGSQL_SCHEMA_VERSION_MAJOR = 34; |
22 | | const uint32_t PGSQL_SCHEMA_VERSION_MINOR = 0; |
23 | | |
24 | | // Maximum number of parameters that can be used a statement |
25 | | // @todo This allows us to use an initializer list (since we can't |
26 | | // require C++11). It's unlikely we'd go past this many a single |
27 | | // statement. |
28 | | const size_t PGSQL_MAX_PARAMETERS_IN_QUERY = 128; |
29 | | |
30 | | /// @brief Define a PostgreSQL statement. |
31 | | /// |
32 | | /// Each statement is associated with an index, which is used to reference the |
33 | | /// associated prepared statement. |
34 | | struct PgSqlTaggedStatement { |
35 | | /// Number of parameters for a given query |
36 | | int nbparams; |
37 | | |
38 | | /// @brief OID types |
39 | | /// |
40 | | /// Specify parameter types. See /usr/include/postgresql/catalog/pg_type.h. |
41 | | /// For some reason that header does not export those parameters. |
42 | | /// Those OIDs must match both input and output parameters. |
43 | | const Oid types[PGSQL_MAX_PARAMETERS_IN_QUERY]; |
44 | | |
45 | | /// Short name of the query. |
46 | | const char* name; |
47 | | |
48 | | /// Text representation of the actual query. |
49 | | const char* text; |
50 | | }; |
51 | | |
52 | | /// @{ |
53 | | /// @brief Constants for PostgreSQL data types |
54 | | /// These are defined by PostgreSQL in <catalog/pg_type.h>, but including |
55 | | /// this file is extraordinarily convoluted, so we'll use these to fill-in. |
56 | | /// @{ |
57 | | const size_t OID_NONE = 0; // PostgreSQL infers proper type |
58 | | const size_t OID_BOOL = 16; |
59 | | const size_t OID_BYTEA = 17; |
60 | | const size_t OID_INT8 = 20; // 8 byte int |
61 | | const size_t OID_INT2 = 21; // 2 byte int |
62 | | const size_t OID_INT4 = 23; // 4 byte int |
63 | | const size_t OID_TEXT = 25; |
64 | | const size_t OID_VARCHAR = 1043; |
65 | | const size_t OID_TIMESTAMP = 1114; |
66 | | /// @} |
67 | | |
68 | | /// @brief Postgresql connection handle Holder |
69 | | /// |
70 | | /// Small RAII object for safer initialization, will close the database |
71 | | /// connection upon destruction. This means that if an exception is thrown |
72 | | /// during database initialization, resources allocated to the database are |
73 | | /// guaranteed to be freed. |
74 | | /// |
75 | | /// It makes no sense to copy an object of this class. After the copy, both |
76 | | /// objects would contain pointers to the same PgSql context object. The |
77 | | /// destruction of one would invalid the context in the remaining object. |
78 | | /// For this reason, the class is declared noncopyable. |
79 | | class PgSqlHolder : public boost::noncopyable { |
80 | | public: |
81 | | |
82 | | /// @brief Constructor |
83 | | /// |
84 | | /// Sets the Postgresql API connector handle to NULL. |
85 | | /// |
86 | 20.8k | PgSqlHolder() : pgconn_(NULL) { |
87 | 20.8k | } |
88 | | |
89 | | /// @brief Destructor |
90 | | /// |
91 | | /// Frees up resources allocated by the connection. |
92 | 20.8k | ~PgSqlHolder() { |
93 | 20.8k | if (pgconn_ != NULL) { |
94 | 14.2k | PQfinish(pgconn_); |
95 | 14.2k | } |
96 | 20.8k | } |
97 | | |
98 | | /// @brief Sets the connection to the value given |
99 | | /// |
100 | | /// @param connection - pointer to the Postgresql connection instance |
101 | 14.2k | void setConnection(PGconn* connection) { |
102 | 14.2k | if (pgconn_ != NULL) { |
103 | | // Already set? Release the current connection first. |
104 | | // Maybe this should be an error instead? |
105 | 0 | PQfinish(pgconn_); |
106 | 0 | } |
107 | | |
108 | 14.2k | pgconn_ = connection; |
109 | 14.2k | } |
110 | | |
111 | | /// @brief Conversion Operator |
112 | | /// |
113 | | /// Allows the PgSqlHolder object to be passed as the context argument to |
114 | | /// PQxxxx functions. |
115 | 329k | operator PGconn*() const { |
116 | 329k | return (pgconn_); |
117 | 329k | } |
118 | | |
119 | | /// @brief Boolean Operator |
120 | | /// |
121 | | /// Allows testing the connection for emptiness: "if (holder)" |
122 | 20.8k | operator bool() const { |
123 | 20.8k | return (pgconn_); |
124 | 20.8k | } |
125 | | |
126 | | private: |
127 | | PGconn* pgconn_; ///< Postgresql connection |
128 | | }; |
129 | | |
130 | | /// @brief Forward declaration to @ref PgSqlConnection. |
131 | | class PgSqlConnection; |
132 | | |
133 | | /// @brief RAII object representing a PostgreSQL transaction. |
134 | | /// |
135 | | /// An instance of this class should be created in a scope where multiple |
136 | | /// INSERT statements should be executed within a single transaction. The |
137 | | /// transaction is started when the constructor of this class is invoked. |
138 | | /// The transaction is ended when the @ref PgSqlTransaction::commit is |
139 | | /// explicitly called or when the instance of this class is destroyed. |
140 | | /// The @ref PgSqlTransaction::commit commits changes to the database. |
141 | | /// If the class instance is destroyed before @ref PgSqlTransaction::commit |
142 | | /// has been called, the transaction is rolled back. The rollback on |
143 | | /// destruction guarantees that partial data is not stored in the database |
144 | | /// when an error occurs during any of the operations within a transaction. |
145 | | /// |
146 | | /// By default PostgreSQL performs a commit following each statement which |
147 | | /// alters the database (i.e. "autocommit"). Starting a transaction |
148 | | /// stops autocommit for the connection until the transaction is ended by |
149 | | /// either commit or rollback. Other connections are unaffected. |
150 | | class PgSqlTransaction : public boost::noncopyable { |
151 | | public: |
152 | | |
153 | | /// @brief Constructor. |
154 | | /// |
155 | | /// Starts transaction by executing the SQL statement: "START TRANSACTION" |
156 | | /// |
157 | | /// @param conn PostgreSQL connection to use for the transaction. This |
158 | | /// connection will be later used to commit or rollback changes. |
159 | | /// |
160 | | /// @throw DbOperationError if statement execution fails |
161 | | PgSqlTransaction(PgSqlConnection& conn); |
162 | | |
163 | | /// @brief Destructor. |
164 | | /// |
165 | | /// If the transaction has not been committed, it is rolled back |
166 | | /// by executing the SQL statement: "ROLLBACK" |
167 | | /// |
168 | | /// @throw DbOperationError if statement execution fails |
169 | | ~PgSqlTransaction(); |
170 | | |
171 | | /// @brief Commits transaction. |
172 | | /// |
173 | | /// Commits all changes made during the transaction by executing the |
174 | | /// SQL statement: "COMMIT" |
175 | | /// |
176 | | /// @throw DbOperationError if statement execution fails |
177 | | void commit(); |
178 | | |
179 | | private: |
180 | | |
181 | | /// @brief Holds reference to the PostgreSQL database connection. |
182 | | PgSqlConnection& conn_; |
183 | | |
184 | | /// @brief Boolean flag indicating if the transaction has been committed. |
185 | | /// |
186 | | /// This flag is used in the class destructor to assess if the |
187 | | /// transaction should be rolled back. |
188 | | bool committed_; |
189 | | }; |
190 | | |
191 | | /// @brief Defines a scoped pointer to a transaction. |
192 | | typedef boost::scoped_ptr<PgSqlTransaction> ScopedPgSqlTransactionPtr; |
193 | | |
194 | | /// @brief Common PgSql Connector Pool |
195 | | /// |
196 | | /// This class provides common operations for PgSql database connection |
197 | | /// used by both PgSqlLeaseMgr and PgSqlHostDataSource. It manages connecting |
198 | | /// to the database and preparing compiled statements. Its fields are |
199 | | /// public, because they are used (both set and retrieved) in classes |
200 | | /// that use instances of PgSqlConnection. |
201 | | class PgSqlConnection : public db::DatabaseConnection { |
202 | | public: |
203 | | /// @brief Define the PgSql error state for a duplicate key error. |
204 | | static const char DUPLICATE_KEY[]; |
205 | | /// @brief Define the PgSql error state for a null foreign key error. |
206 | | static const char NULL_KEY[]; |
207 | | |
208 | | /// @brief Function invoked to process fetched row. |
209 | | typedef std::function<void(PgSqlResult&, int)> ConsumeResultRowFun; |
210 | | |
211 | | /// @brief Emit the TLS support warning only once. |
212 | | static bool warned_about_tls; |
213 | | |
214 | | /// @brief Constructor |
215 | | /// |
216 | | /// Initialize PgSqlConnection object with parameters needed for connection. |
217 | | /// |
218 | | /// @param parameters Specify the connection details. |
219 | | /// @param io_accessor The IOService accessor function. |
220 | | /// @param callback The connection recovery callback. |
221 | | PgSqlConnection(const ParameterMap& parameters, |
222 | | IOServiceAccessorPtr io_accessor = IOServiceAccessorPtr(), |
223 | | DbCallback callback = DbCallback()) |
224 | 20.8k | : DatabaseConnection(parameters, callback), |
225 | 20.8k | io_service_accessor_(io_accessor), io_service_(), |
226 | 20.8k | transaction_ref_count_(0) { |
227 | 20.8k | } |
228 | | |
229 | | /// @brief Destructor |
230 | | virtual ~PgSqlConnection(); |
231 | | |
232 | | /// @brief Convert PostgreSQL library parameters to kea-admin parameters. |
233 | | /// |
234 | | /// @param params input PostgreSQL parameters |
235 | | /// |
236 | | /// @return tuple of (vector of kea-admin parameters, vector of PostgreSQL |
237 | | /// environment variables) |
238 | | static std::tuple<std::vector<std::string>, std::vector<std::string>> |
239 | | toKeaAdminParameters(ParameterMap const& params); |
240 | | |
241 | | /// @brief Get the schema version. |
242 | | /// |
243 | | /// @param parameters A data structure relating keywords and values |
244 | | /// concerned with the database. |
245 | | /// @param ac An IOServiceAccessor object. |
246 | | /// @param cb The dbReconnect callback. |
247 | | /// @param timer_name The DB reconnect timer name. |
248 | | /// @param id the ID of the manager. |
249 | | /// |
250 | | /// @return Version number as a pair of unsigned integers. "first" is the |
251 | | /// major version number, "second" the minor number. |
252 | | /// |
253 | | /// @throw isc::db::DbOperationError An operation on the open database has |
254 | | /// failed. |
255 | | static std::pair<uint32_t, uint32_t> |
256 | | getVersion(const ParameterMap& parameters, |
257 | | const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(), |
258 | | const DbCallback& cb = DbCallback(), |
259 | | const std::string& timer_name = std::string(), |
260 | | unsigned int id = 0); |
261 | | |
262 | | /// @brief Retrieve schema version, validate it against the hardcoded |
263 | | /// version, and attempt to initialize the schema if there is an |
264 | | /// error during retrieval. |
265 | | /// |
266 | | /// Properly handles retrying of the database connection. |
267 | | /// |
268 | | /// @param parameters A data structure relating keywords and values |
269 | | /// concerned with the database. |
270 | | /// @param cb The dbReconnect callback. |
271 | | /// @param timer_name The DB reconnect timer name. |
272 | | /// |
273 | | /// @throw isc::db::ScehamInitializationFailed if the initialization fails |
274 | | static void |
275 | | ensureSchemaVersion(const ParameterMap& parameters, |
276 | | const DbCallback& cb = DbCallback(), |
277 | | const std::string& timer_name = std::string()); |
278 | | |
279 | | /// @brief Initialize schema. |
280 | | /// |
281 | | /// @param parameters A data structure relating keywords and values |
282 | | /// concerned with the database. |
283 | | /// |
284 | | /// @throw isc::db::ScehamInitializationFailed if the initialization fails |
285 | | static void |
286 | | initializeSchema(const ParameterMap& parameters); |
287 | | |
288 | | /// @brief Prepare Single Statement |
289 | | /// |
290 | | /// Creates a prepared statement from the text given and adds it to the |
291 | | /// statements_ vector at the given index. |
292 | | /// |
293 | | /// @param statement SQL statement to be prepared. |
294 | | /// |
295 | | /// @throw isc::db::DbOperationError An operation on the open database has |
296 | | /// failed. |
297 | | void prepareStatement(const PgSqlTaggedStatement& statement); |
298 | | |
299 | | /// @brief Prepare statements |
300 | | /// |
301 | | /// Creates the prepared statements for all of the SQL statements used |
302 | | /// by the PostgreSQL backend. |
303 | | /// |
304 | | /// @param start_statement Pointer to the first statement in range of the |
305 | | /// statements to be compiled. |
306 | | /// @param end_statement Pointer to the statement marking end of the |
307 | | /// range of statements to be compiled. This last statement is not compiled. |
308 | | /// |
309 | | /// @throw isc::db::DbOperationError An operation on the open database has |
310 | | /// failed. |
311 | | void prepareStatements(const PgSqlTaggedStatement* start_statement, |
312 | | const PgSqlTaggedStatement* end_statement); |
313 | | |
314 | | /// @brief Creates connection string from specified parameters. |
315 | | /// |
316 | | /// This function is called from the unit tests. |
317 | | /// |
318 | | /// @return connection string for @c openDatabase. |
319 | | /// @throw NoDatabaseName Mandatory database name not given |
320 | | /// @throw DbInvalidTimeout when the database timeout is wrong. |
321 | | std::string getConnParameters(); |
322 | | |
323 | | private: |
324 | | |
325 | | /// @brief Creates connection string from the specified parameters. |
326 | | /// |
327 | | /// This is an internal implementation of the @c getConnParameters that |
328 | | /// allows for controlling logging. In some cases, a caller can disable |
329 | | /// logging warnings to avoid duplication of the log messages emitted |
330 | | /// when the invocation is a result of calling @c getVersion before |
331 | | /// opening the connection for the normal server operation. |
332 | | /// |
333 | | /// @param logging boolean parameter controlling if logging should be |
334 | | /// enabled (when true) or disabled (when false). |
335 | | /// |
336 | | /// @return connection string for @c openDatabase. |
337 | | /// @throw NoDatabaseName Mandatory database name not given |
338 | | /// @throw DbInvalidTimeout when the database timeout is wrong. |
339 | | std::string getConnParametersInternal(bool logging); |
340 | | |
341 | | public: |
342 | | |
343 | | /// @brief Open database with logging. |
344 | | /// |
345 | | /// Opens the database using the information supplied in the parameters |
346 | | /// passed to the constructor. It logs warnings resulting from the |
347 | | /// @c getConnParameters. |
348 | | /// |
349 | | /// @throw NoDatabaseName Mandatory database name not given |
350 | | /// @throw DbOpenError Error opening the database |
351 | | void openDatabase(); |
352 | | |
353 | | private: |
354 | | |
355 | | /// @brief Internal implementation of the database opening. |
356 | | /// |
357 | | /// It allows for controlling if the @c getConnParameterInternal function |
358 | | /// should log the warnings. |
359 | | /// |
360 | | /// @param logging boolean parameter controlling if logging should be |
361 | | /// enabled (when true) or disabled (when false). |
362 | | /// |
363 | | /// @throw NoDatabaseName Mandatory database name not given |
364 | | /// @throw DbOpenError Error opening the database |
365 | | void openDatabaseInternal(bool logging); |
366 | | |
367 | | public: |
368 | | |
369 | | /// @brief Starts new transaction |
370 | | /// |
371 | | /// This function begins a new transaction by sending the START TRANSACTION |
372 | | /// statement to the database. The transaction should be explicitly committed |
373 | | /// by calling @c commit() or rolled back by calling @c rollback(). |
374 | | /// |
375 | | /// PostgreSQL does not support nested transactions directly. Issuing a |
376 | | /// START TRANSACTION while already in a transaction will cause a warning to |
377 | | /// be emitted but otherwise does not alter the state of the current transaction. |
378 | | /// In other words, the transaction will still end upon the next COMMIT or |
379 | | /// ROLLBACK statement. |
380 | | /// |
381 | | /// Therefore, this function checks if a transaction has already started and |
382 | | /// does not start a new transaction. However, it increments a transaction |
383 | | /// reference counter which is later decremented when @c commit() or @c |
384 | | /// rollback() is called. When this mechanism is used properly, it |
385 | | /// guarantees that nested transactions are not attempted, thus avoiding |
386 | | /// unexpected commits or rollbacks of the pending transaction. |
387 | | void startTransaction(); |
388 | | |
389 | | /// @brief Checks if there is a transaction in progress. |
390 | | /// |
391 | | /// @return true if a transaction has been started, false otherwise. |
392 | | bool isTransactionStarted() const; |
393 | | |
394 | | /// @brief Commits current transaction |
395 | | /// |
396 | | /// Commits all pending database operations. On databases that don't |
397 | | /// support transactions, this is a no-op. |
398 | | /// |
399 | | /// When this method is called for a nested transaction it decrements the |
400 | | /// transaction reference counter incremented during the call to |
401 | | /// @c startTransaction. |
402 | | /// |
403 | | /// @throw DbOperationError If the commit failed. |
404 | | void commit(); |
405 | | |
406 | | /// @brief Rollbacks current transaction |
407 | | /// |
408 | | /// Rolls back all pending database operations. On databases that don't |
409 | | /// support transactions, this is a no-op. |
410 | | /// |
411 | | /// When this method is called for a nested transaction it decrements the |
412 | | /// transaction reference counter incremented during the call to |
413 | | /// @c startTransaction. |
414 | | /// |
415 | | /// @throw DbOperationError If the rollback failed. |
416 | | void rollback(); |
417 | | |
418 | | /// @brief Creates a savepoint within the current transaction |
419 | | /// |
420 | | /// Creates a named savepoint within the current transaction. |
421 | | /// |
422 | | /// @param name name of the savepoint to create. |
423 | | /// |
424 | | /// @throw InvalidOperation if called outside a transaction. |
425 | | /// @throw DbOperationError If the savepoint cannot be created. |
426 | | void createSavepoint(const std::string& name); |
427 | | |
428 | | /// @brief Rollbacks to the given savepoint |
429 | | /// |
430 | | /// Rolls back all pending database operations made after the |
431 | | /// named savepoint. |
432 | | /// |
433 | | /// @param name name of the savepoint to which to rollback. |
434 | | /// |
435 | | /// @throw InvalidOperation if called outside a transaction. |
436 | | /// @throw DbOperationError if the rollback failed. |
437 | | void rollbackToSavepoint(const std::string& name); |
438 | | |
439 | | /// @brief Executes the an SQL statement. |
440 | | /// |
441 | | /// It executes the given SQL text after first checking the |
442 | | /// connection for usability. After the statement is executed |
443 | | /// @c checkStatementError() is invoked to ensure we detect |
444 | | /// connectivity issues properly. |
445 | | /// It is intended to be used to execute utility statements such |
446 | | /// as commit, rollback et al, which have no parameters, return no |
447 | | /// results, and are not pre-compiled. |
448 | | /// |
449 | | /// @param sql SQL statement to execute. |
450 | | void executeSQL(const std::string& sql); |
451 | | |
452 | | /// @brief Checks a result set's SQL state against an error state. |
453 | | /// |
454 | | /// @param r result set to check |
455 | | /// @param error_state error state to compare against |
456 | | /// |
457 | | /// @return True if the result set's SQL state equals the error_state, |
458 | | /// false otherwise. |
459 | | bool compareError(const PgSqlResult& r, const char* error_state); |
460 | | |
461 | | /// @brief Checks result of the r object |
462 | | /// |
463 | | /// This function is used to determine whether or not the SQL statement |
464 | | /// execution succeeded, and in the event of failures, decide whether or |
465 | | /// not the failures are recoverable. |
466 | | /// |
467 | | /// If the error is recoverable, the function will throw a DbOperationError. |
468 | | /// If the error is deemed unrecoverable, such as a loss of connectivity |
469 | | /// with the server, the function will call startRecoverDbConnection() which |
470 | | /// will start the connection recovery. |
471 | | /// |
472 | | /// If the invocation returns true, this indicates the calling layer will |
473 | | /// attempt recovery, and the function throws a DbOperationError to allow |
474 | | /// the caller to error handle the failed db access attempt. |
475 | | /// |
476 | | /// @param r result of the last PostgreSQL operation |
477 | | /// @param statement - tagged statement that was executed |
478 | | /// |
479 | | /// @throw isc::db::DbOperationError Detailed PostgreSQL failure |
480 | | void checkStatementError(const PgSqlResult& r, |
481 | | PgSqlTaggedStatement& statement); |
482 | | |
483 | | /// @brief The recover connection |
484 | | /// |
485 | | /// This function starts the recover process of the connection. |
486 | | /// |
487 | | /// @note The recover function must be run on the IO Service thread. |
488 | 0 | void startRecoverDbConnection() { |
489 | 0 | if (callback_) { |
490 | 0 | if (!io_service_ && io_service_accessor_) { |
491 | 0 | io_service_ = (*io_service_accessor_)(); |
492 | 0 | io_service_accessor_.reset(); |
493 | 0 | } |
494 | |
|
495 | 0 | if (io_service_) { |
496 | 0 | io_service_->post(std::bind(callback_, reconnectCtl())); |
497 | 0 | } |
498 | 0 | } |
499 | 0 | } |
500 | | |
501 | | /// @brief Executes a prepared SQL statement. |
502 | | /// |
503 | | /// It executes the given prepared SQL statement, after checking |
504 | | /// for usability and input parameter sanity. After the statement |
505 | | /// is executed @c checkStatementError() is invoked to ensure we detect |
506 | | /// connectivity issues properly. Upon successful execution, the |
507 | | /// the result set is returned. It may be used for any form of |
508 | | /// prepared SQL statement (e.g query, insert, update, delete...), |
509 | | /// with or without input parameters. |
510 | | /// |
511 | | /// @param statement PgSqlTaggedStatement describing the prepared |
512 | | /// statement to execute. |
513 | | /// @param in_bindings array of input parameter bindings. If the SQL |
514 | | /// statement requires no input arguments, this parameter should either |
515 | | /// be omitted or an empty PsqlBindArray should be supplied. |
516 | | /// @throw InvalidOperation if the number of parameters expected |
517 | | /// by the statement does not match the size of the input bind array. |
518 | | PgSqlResultPtr executePreparedStatement(PgSqlTaggedStatement& statement, |
519 | | const PsqlBindArray& in_bindings |
520 | | = PsqlBindArray()); |
521 | | |
522 | | /// @brief Executes SELECT query using prepared statement. |
523 | | /// |
524 | | /// The statement parameter refers to an existing prepared statement |
525 | | /// associated with the connection. The @c in_bindings size must match |
526 | | /// the number of placeholders in the prepared statement. |
527 | | /// |
528 | | /// This method executes prepared statement using provided input bindings and |
529 | | /// calls @c process_result_row function for each returned row. The |
530 | | /// @c process_result_row function is implemented by the caller and should |
531 | | /// gather and store each returned row in an external data structure prior. |
532 | | /// |
533 | | /// @param statement reference to the precompiled tagged statement to execute |
534 | | /// @param in_bindings input bindings holding values to substitue placeholders |
535 | | /// in the query. |
536 | | /// @param process_result_row Pointer to the function to be invoked for each |
537 | | /// retrieved row. This function consumes the retrieved data from the |
538 | | /// result set. |
539 | | void selectQuery(PgSqlTaggedStatement& statement, |
540 | | const PsqlBindArray& in_bindings, |
541 | | ConsumeResultRowFun process_result_row); |
542 | | |
543 | | /// @brief Executes INSERT prepared statement. |
544 | | /// |
545 | | /// The @c statement must refer to an existing prepared statement |
546 | | /// associated with the connection. The @c in_bindings size must match |
547 | | /// the number of placeholders in the prepared statement. |
548 | | /// |
549 | | /// This method executes prepared statement using provided bindings to |
550 | | /// insert data into the database. |
551 | | /// |
552 | | /// @param statement reference to the precompiled tagged statement to execute |
553 | | /// @param in_bindings input bindings holding values to substitue placeholders |
554 | | /// in the query. |
555 | | void insertQuery(PgSqlTaggedStatement& statement, |
556 | | const PsqlBindArray& in_bindings); |
557 | | |
558 | | |
559 | | /// @brief Executes UPDATE or DELETE prepared statement and returns |
560 | | /// the number of affected rows. |
561 | | /// |
562 | | /// The @c statement must refer to an existing prepared statement |
563 | | /// associated with the connection. The @c in_bindings size must match |
564 | | /// the number of placeholders in the prepared statement. |
565 | | /// |
566 | | /// @param statement reference to the precompiled tagged statement to execute |
567 | | /// @param in_bindings Input bindings holding values to substitute placeholders |
568 | | /// in the query. |
569 | | /// |
570 | | /// @return Number of affected rows. |
571 | | uint64_t updateDeleteQuery(PgSqlTaggedStatement& statement, |
572 | | const PsqlBindArray& in_bindings); |
573 | | |
574 | | /// @brief PgSql connection handle |
575 | | /// |
576 | | /// This field is public, because it is used heavily from PgSqlLeaseMgr |
577 | | /// and from PgSqlHostDataSource. |
578 | | PgSqlHolder conn_; |
579 | | |
580 | | /// @brief Conversion Operator |
581 | | /// |
582 | | /// Allows the PgConnection object to be passed as the context argument to |
583 | | /// PQxxxx functions. |
584 | 0 | operator PGconn*() const { |
585 | 0 | return (conn_); |
586 | 0 | } |
587 | | |
588 | | /// @brief Boolean Operator |
589 | | /// |
590 | | /// Allows testing the PgConnection for initialized connection |
591 | 0 | operator bool() const { |
592 | 0 | return (conn_); |
593 | 0 | } |
594 | | |
595 | | private: |
596 | | |
597 | | /// @brief Convenience function parsing and setting an integer parameter, |
598 | | /// if it exists. |
599 | | /// |
600 | | /// If the parameter is not present, this function doesn't change the @c value. |
601 | | /// Otherwise, it tries to convert the parameter to the type @c T. Finally, |
602 | | /// it checks if the converted number is within the specified range. |
603 | | /// |
604 | | /// @param name Parameter name. |
605 | | /// @param min Expected minimal value. |
606 | | /// @param max Expected maximal value. |
607 | | /// @param [out] value Reference to a value returning the parsed parameter. |
608 | | /// @tparam T Parameter type. |
609 | | /// @throw BadValue if the parameter is not a valid number or if it is out |
610 | | /// of range. |
611 | | template<typename T> |
612 | | void setIntParameterValue(const std::string& name, int64_t min, int64_t max, T& value); |
613 | | |
614 | | public: |
615 | | |
616 | | /// @brief Accessor function which returns the IOService that can be used to |
617 | | /// recover the connection. |
618 | | /// |
619 | | /// This accessor is used to lazy retrieve the IOService when the connection |
620 | | /// is lost. It is useful to retrieve it at a later time to support hook |
621 | | /// libraries which create managers on load and set IOService later on by |
622 | | /// using the dhcp4_srv_configured and dhcp6_srv_configured hooks. |
623 | | IOServiceAccessorPtr io_service_accessor_; |
624 | | |
625 | | /// @brief IOService object, used for all ASIO operations. |
626 | | isc::asiolink::IOServicePtr io_service_; |
627 | | |
628 | | /// @brief Reference counter for transactions. |
629 | | /// |
630 | | /// It precludes starting and committing nested transactions. PostgreSQL |
631 | | /// logs but ignores START TRANSACTIONs (or BEGINs) issued from within an |
632 | | /// ongoing transaction. We do not want to start new transactions when one |
633 | | /// is already in progress. |
634 | | int transaction_ref_count_; |
635 | | |
636 | | /// @brief Holds location to kea-admin. By default, it points to kea-admin |
637 | | /// from installation. In tests, it points to kea-admin from sources. |
638 | | static std::string KEA_ADMIN_; |
639 | | }; |
640 | | |
641 | | /// @brief Defines a pointer to a PgSqlConnection |
642 | | typedef boost::shared_ptr<PgSqlConnection> PgSqlConnectionPtr; |
643 | | |
644 | | } // end of isc::db namespace |
645 | | } // end of isc namespace |
646 | | |
647 | | #endif // PGSQL_CONNECTION_H |