Coverage Report

Created: 2026-06-30 07:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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