| Kea 3.0.2-git

mysql_connection.h
Go to the documentation of this file.
1// Copyright (C) 2012-2025 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
7#ifndef MYSQL_CONNECTION_H
8#define MYSQL_CONNECTION_H
9
10#include <asiolink/io_service.h>
11#include <database/database_connection.h>
12#include <database/db_exceptions.h>
13#include <database/db_log.h>
14#include <exceptions/exceptions.h>
15#include <mysql/mysql_binding.h>
16#include <mysql/mysql_constants.h>
17#include <boost/scoped_ptr.hpp>
18#include <mysql.h>
19#include <mysqld_error.h>
20#include <errmsg.h>
21#include <functional>
22#include <vector>
23#include <stdint.h>
24
25 namespace isc {
26 namespace db {
27
28
42
43 class MySqlFreeResult {
44 public:
45
56 MySqlFreeResult(MYSQL_STMT* statement) : statement_(statement)
57 {}
58
62 ~MySqlFreeResult() {
63 (void) mysql_stmt_free_result(statement_);
64 }
65
66 private:
67 MYSQL_STMT* statement_;
68};
69
74 struct TaggedStatement {
75 uint32_t index;
76 const char* text;
77};
78
88 template <typename Fun, typename... Args>
89 int retryOnDeadlock(Fun& fun, Args... args) {
90 int status;
91 for (unsigned count = 0; count < 5; ++count) {
92 status = fun(args...);
93 if (status != ER_LOCK_DEADLOCK) {
94 break;
95 }
96 }
97 return (status);
98}
99
106 inline int MysqlExecuteStatement(MYSQL_STMT* stmt) {
107 return (retryOnDeadlock(mysql_stmt_execute, stmt));
108}
109
117 inline int MysqlQuery(MYSQL* mysql, const char* stmt) {
118 return (retryOnDeadlock(mysql_query, mysql, stmt));
119}
120
132 class MySqlHolder : public boost::noncopyable {
133 public:
134
140 MySqlHolder() : mysql_(mysql_init(NULL)) {
141 if (mysql_ == NULL) {
142 isc_throw(db::DbOpenError, "unable to initialize MySQL");
143 }
144 }
145
149 ~MySqlHolder() {
150 if (mysql_ != NULL) {
151 mysql_close(mysql_);
152 }
153 }
154
159 operator MYSQL*() const {
160 return (mysql_);
161 }
162
163 private:
165 static int atexit_;
166
168 MYSQL* mysql_;
169};
170
172 class MySqlConnection;
173
194 class MySqlTransaction : public boost::noncopyable {
195 public:
196
205 MySqlTransaction(MySqlConnection& conn);
206
210 ~MySqlTransaction();
211
213 void commit();
214
215 private:
216
218 MySqlConnection& conn_;
219
224 bool committed_;
225};
226
227
235 class MySqlConnection : public db::DatabaseConnection {
236 public:
237
239 typedef std::function<void(MySqlBindingCollection&)> ConsumeResultFun;
240
248 MySqlConnection(const ParameterMap& parameters,
249 IOServiceAccessorPtr io_accessor = IOServiceAccessorPtr(),
250 DbCallback callback = DbCallback())
251 : DatabaseConnection(parameters, callback),
252 io_service_accessor_(io_accessor), io_service_(),
253 transaction_ref_count_(0), tls_(false) {
254 }
255
257 virtual ~MySqlConnection();
258
264 static std::vector<std::string>
265 toKeaAdminParameters(ParameterMap const& params);
266
281 static std::pair<uint32_t, uint32_t>
282 getVersion(const ParameterMap& parameters,
283 const IOServiceAccessorPtr& ac = IOServiceAccessorPtr(),
284 const DbCallback& cb = DbCallback(),
285 const std::string& timer_name = std::string(),
286 unsigned int id = 0);
287
300 static void
301 ensureSchemaVersion(const ParameterMap& parameters,
302 const DbCallback& cb = DbCallback(),
303 const std::string& timer_name = std::string());
304
311 static void
312 initializeSchema(const ParameterMap& parameters);
313
327 void prepareStatement(uint32_t index, const char* text);
328
343 void prepareStatements(const TaggedStatement* start_statement,
344 const TaggedStatement* end_statement);
345
355 template<typename StatementIndex>
356 MYSQL_STMT* getStatement(StatementIndex index) const {
357 if (statements_[index]->mysql == 0) {
358 isc_throw(db::DbConnectionUnusable,
359 "MySQL pointer for the prepared statement is NULL as a result of connectivity loss");
360 }
361 return (statements_[index]);
362 }
363
371 void openDatabase();
372
380
386 static
387 void convertToDatabaseTime(const time_t input_time, MYSQL_TIME& output_time);
388
408 static
409 void convertToDatabaseTime(const time_t cltt, const uint32_t valid_lifetime,
410 MYSQL_TIME& expire);
411
429 static
430 void convertFromDatabaseTime(const MYSQL_TIME& expire,
431 uint32_t valid_lifetime, time_t& cltt);
433
447 void startTransaction();
448
452 bool isTransactionStarted() const;
453
481 template<typename StatementIndex>
482 void selectQuery(const StatementIndex& index,
483 const MySqlBindingCollection& in_bindings,
484 MySqlBindingCollection& out_bindings,
485 ConsumeResultFun process_result) {
486 checkUnusable();
487 // Extract native input bindings.
488 std::vector<MYSQL_BIND> in_bind_vec;
489 for (const MySqlBindingPtr& in_binding : in_bindings) {
490 in_bind_vec.push_back(in_binding->getMySqlBinding());
491 }
492
493 int status = 0;
494 if (!in_bind_vec.empty()) {
495 // Bind parameters to the prepared statement.
496 status = mysql_stmt_bind_param(getStatement(index),
497 in_bind_vec.empty() ? 0 : &in_bind_vec[0]);
498 checkError(status, index, "unable to bind parameters for select");
499 }
500
501 // Bind variables that will receive results as well.
502 std::vector<MYSQL_BIND> out_bind_vec;
503 for (const MySqlBindingPtr& out_binding : out_bindings) {
504 out_bind_vec.push_back(out_binding->getMySqlBinding());
505 }
506 if (!out_bind_vec.empty()) {
507 status = mysql_stmt_bind_result(getStatement(index), &out_bind_vec[0]);
508 checkError(status, index, "unable to bind result parameters for select");
509 }
510
511 // Execute query.
512 status = MysqlExecuteStatement(getStatement(index));
513 checkError(status, index, "unable to execute");
514
515 status = mysql_stmt_store_result(getStatement(index));
516 checkError(status, index, "unable to set up for storing all results");
517
518 // Fetch results.
519 MySqlFreeResult fetch_release(getStatement(index));
520 while ((status = mysql_stmt_fetch(getStatement(index))) ==
521 MLM_MYSQL_FETCH_SUCCESS) {
522 try {
523 // For each returned row call user function which should
524 // consume the row and copy the data to a safe place.
525 process_result(out_bindings);
526
527 } catch (const std::exception& ex) {
528 // Rethrow the exception with a bit more data.
529 isc_throw(BadValue, ex.what() << ". Statement is <" <<
530 text_statements_[index] << ">");
531 }
532 }
533
534 // How did the fetch end?
535 // If mysql_stmt_fetch return value is equal to 1 an error occurred.
536 if (status == MLM_MYSQL_FETCH_FAILURE) {
537 // Error - unable to fetch results
538 checkError(status, index, "unable to fetch results");
539
540 } else if (status == MYSQL_DATA_TRUNCATED) {
541 // Data truncated - throw an exception indicating what was at fault
542 isc_throw(DataTruncated, text_statements_[index]
543 << " returned truncated data");
544 }
545 }
546
561 template<typename StatementIndex>
562 void insertQuery(const StatementIndex& index,
563 const MySqlBindingCollection& in_bindings) {
564 checkUnusable();
565 std::vector<MYSQL_BIND> in_bind_vec;
566 for (const MySqlBindingPtr& in_binding : in_bindings) {
567 in_bind_vec.push_back(in_binding->getMySqlBinding());
568 }
569
570 // Bind the parameters to the statement
571 int status = mysql_stmt_bind_param(getStatement(index),
572 in_bind_vec.empty() ? 0 : &in_bind_vec[0]);
573 checkError(status, index, "unable to bind parameters");
574
575 // Execute the statement
576 status = MysqlExecuteStatement(getStatement(index));
577
578 if (status != 0) {
579 // Failure: check for the special case of duplicate entry.
580 if (mysql_errno(mysql_) == ER_DUP_ENTRY) {
581 isc_throw(DuplicateEntry, "Database duplicate entry error");
582 }
583 // Failure: check for the special case of WHERE returning NULL.
584 if (mysql_errno(mysql_) == ER_BAD_NULL_ERROR) {
585 isc_throw(NullKeyError, "Database bad NULL error");
586 }
587 checkError(status, index, "unable to execute");
588 }
589 }
590
605 template<typename StatementIndex>
606 uint64_t updateDeleteQuery(const StatementIndex& index,
607 const MySqlBindingCollection& in_bindings) {
608 checkUnusable();
609 std::vector<MYSQL_BIND> in_bind_vec;
610 for (const MySqlBindingPtr& in_binding : in_bindings) {
611 in_bind_vec.push_back(in_binding->getMySqlBinding());
612 }
613
614 // Bind the parameters to the statement
615 int status = mysql_stmt_bind_param(getStatement(index),
616 in_bind_vec.empty() ? 0 : &in_bind_vec[0]);
617 checkError(status, index, "unable to bind parameters");
618
619 // Execute the statement
620 status = MysqlExecuteStatement(getStatement(index));
621
622 if (status != 0) {
623 // Failure: check for the special case of duplicate entry.
624 if ((mysql_errno(mysql_) == ER_DUP_ENTRY)
625#ifdef ER_FOREIGN_DUPLICATE_KEY
626 || (mysql_errno(mysql_) == ER_FOREIGN_DUPLICATE_KEY)
627#endif
628#ifdef ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO
629 || (mysql_errno(mysql_) == ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO)
630#endif
631#ifdef ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO
632 || (mysql_errno(mysql_) == ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO)
633#endif
634 ) {
635 isc_throw(DuplicateEntry, "Database duplicate entry error");
636 }
637 checkError(status, index, "unable to execute");
638 }
639
640 // Let's return how many rows were affected.
641 return (static_cast<uint64_t>(mysql_stmt_affected_rows(getStatement(index))));
642 }
643
654 void commit();
655
666 void rollback();
667
696 template<typename StatementIndex>
697 void checkError(const int status, const StatementIndex& index,
698 const char* what) {
699 if (status != 0) {
700 switch(mysql_errno(mysql_)) {
701 // These are the ones we consider fatal. Remember this method is
702 // used to check errors of API calls made subsequent to successfully
703 // connecting. Errors occurring while attempting to connect are
704 // checked in the connection code. An alternative would be to call
705 // mysql_ping() - assuming autoreconnect is off. If that fails
706 // then we know connection is toast.
707 case CR_SERVER_GONE_ERROR:
708 case CR_SERVER_LOST:
709 case CR_OUT_OF_MEMORY:
710 case CR_CONNECTION_ERROR: {
711 DB_LOG_ERROR(db::MYSQL_FATAL_ERROR)
712 .arg(what)
713 .arg(text_statements_[static_cast<int>(index)])
714 .arg(mysql_error(mysql_))
715 .arg(mysql_errno(mysql_));
716
717 // Mark this connection as no longer usable.
718 markUnusable();
719
720 // Start the connection recovery.
721 startRecoverDbConnection();
722
723 // We still need to throw so caller can error out of the current
724 // processing.
725 isc_throw(db::DbConnectionUnusable,
726 "fatal database error or connectivity lost");
727 }
728 default:
729 // Connection is ok, so it must be an SQL error
730 isc_throw(db::DbOperationError, what << " for <"
731 << text_statements_[static_cast<int>(index)]
732 << ">, reason: "
733 << mysql_error(mysql_) << " (error code "
734 << mysql_errno(mysql_) << ")");
735 }
736 }
737 }
738
744 void startRecoverDbConnection() {
745 if (callback_) {
746 if (!io_service_ && io_service_accessor_) {
747 io_service_ = (*io_service_accessor_)();
748 io_service_accessor_.reset();
749 }
750
751 if (io_service_) {
752 io_service_->post(std::bind(callback_, reconnectCtl()));
753 }
754 }
755 }
756
760 bool getTls() const {
761 return (tls_);
762 }
763
767 std::string getTlsCipher() {
768 const char* cipher = mysql_get_ssl_cipher(mysql_);
769 return (cipher ? std::string(cipher) : "");
770 }
771
772 private:
773
788 template<typename T>
789 void setIntParameterValue(const std::string& name, int64_t min, int64_t max, T& value);
790
795 std::vector<MYSQL_STMT*> statements_;
796
797 public:
798
803 std::vector<std::string> text_statements_;
804
809 MySqlHolder mysql_;
810
818 IOServiceAccessorPtr io_service_accessor_;
819
821 isc::asiolink::IOServicePtr io_service_;
822
829 int transaction_ref_count_;
830
832 bool tls_;
833
836 static std::string KEA_ADMIN_;
837};
838
839} // end of isc::db namespace
840} // end of isc namespace
841
842#endif // MYSQL_CONNECTION_H
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition exceptions/exceptions.h:132
isc::db::DataTruncated
Data is truncated.
Definition db_exceptions.h:23
isc::db::DatabaseConnection
Common database connection class.
Definition database_connection.h:125
isc::db::DatabaseConnection::reconnectCtl
util::ReconnectCtlPtr reconnectCtl()
The reconnect settings.
Definition database_connection.h:162
isc::db::DatabaseConnection::markUnusable
void markUnusable()
Sets the unusable flag to true.
Definition database_connection.h:302
isc::db::DatabaseConnection::DatabaseConnection
DatabaseConnection(const ParameterMap &parameters, DbCallback callback=DbCallback())
Constructor.
Definition database_connection.h:144
isc::db::DatabaseConnection::checkUnusable
void checkUnusable()
Throws an exception if the connection is not usable.
Definition database_connection.h:266
isc::db::DatabaseConnection::ParameterMap
std::map< std::string, std::string > ParameterMap
Database configuration parameter map.
Definition database_connection.h:137
isc::db::DatabaseConnection::callback_
DbCallback callback_
The callback used to recover the connection.
Definition database_connection.h:316
isc::db::DbConnectionUnusable
Exception thrown when a specific connection has been rendered unusable either through loss of connect...
Definition database_connection.h:53
isc::db::DbOpenError
Exception thrown on failure to open database.
Definition database_connection.h:31
isc::db::DbOperationError
Exception thrown on failure to execute a database function.
Definition database_connection.h:45
isc::db::DuplicateEntry
Database duplicate entry error.
Definition db_exceptions.h:30
isc::db::MySqlConnection
Common MySQL Connector Pool.
Definition mysql_connection.h:235
isc::db::MySqlConnection::io_service_
isc::asiolink::IOServicePtr io_service_
IOService object, used for all ASIO operations.
Definition mysql_connection.h:821
isc::db::MySqlConnection::KEA_ADMIN_
static std::string KEA_ADMIN_
Holds location to kea-admin.
Definition mysql_connection.h:836
isc::db::MySqlConnection::mysql_
MySqlHolder mysql_
MySQL connection handle.
Definition mysql_connection.h:809
isc::db::MySqlConnection::getVersion
static std::pair< uint32_t, uint32_t > getVersion(const ParameterMap &parameters, const IOServiceAccessorPtr &ac=IOServiceAccessorPtr(), const DbCallback &cb=DbCallback(), const std::string &timer_name=std::string(), unsigned int id=0)
Get the schema version.
Definition mysql_connection.cc:330
isc::db::MySqlConnection::prepareStatement
void prepareStatement(uint32_t index, const char *text)
Prepare Single Statement.
Definition mysql_connection.cc:537
isc::db::MySqlConnection::isTransactionStarted
bool isTransactionStarted() const
Checks if there is a transaction in progress.
Definition mysql_connection.cc:640
isc::db::MySqlConnection::text_statements_
std::vector< std::string > text_statements_
Raw text of statements.
Definition mysql_connection.h:803
isc::db::MySqlConnection::insertQuery
void insertQuery(const StatementIndex &index, const MySqlBindingCollection &in_bindings)
Executes INSERT prepared statement.
Definition mysql_connection.h:562
isc::db::MySqlConnection::tls_
bool tls_
TLS flag (true when TLS was required, false otherwise).
Definition mysql_connection.h:832
isc::db::MySqlConnection::convertToDatabaseTime
static void convertToDatabaseTime(const time_t input_time, MYSQL_TIME &output_time)
Convert time_t value to database time.
Definition mysql_connection.cc:603
isc::db::MySqlConnection::io_service_accessor_
IOServiceAccessorPtr io_service_accessor_
Accessor function which returns the IOService that can be used to recover the connection.
Definition mysql_connection.h:818
isc::db::MySqlConnection::convertFromDatabaseTime
static void convertFromDatabaseTime(const MYSQL_TIME &expire, uint32_t valid_lifetime, time_t &cltt)
Convert Database Time to Lease Times.
Definition mysql_connection.cc:616
isc::db::MySqlConnection::commit
void commit()
Commits current transaction.
Definition mysql_connection.cc:645
isc::db::MySqlConnection::MySqlConnection
MySqlConnection(const ParameterMap &parameters, IOServiceAccessorPtr io_accessor=IOServiceAccessorPtr(), DbCallback callback=DbCallback())
Constructor.
Definition mysql_connection.h:248
isc::db::MySqlConnection::startRecoverDbConnection
void startRecoverDbConnection()
The recover connection.
Definition mysql_connection.h:744
isc::db::MySqlConnection::initializeSchema
static void initializeSchema(const ParameterMap &parameters)
Initialize schema.
Definition mysql_connection.cc:459
isc::db::MySqlConnection::updateDeleteQuery
uint64_t updateDeleteQuery(const StatementIndex &index, const MySqlBindingCollection &in_bindings)
Executes UPDATE or DELETE prepared statement and returns the number of affected rows.
Definition mysql_connection.h:606
isc::db::MySqlConnection::toKeaAdminParameters
static std::vector< std::string > toKeaAdminParameters(ParameterMap const &params)
Convert MySQL library parameters to kea-admin parameters.
Definition mysql_connection.cc:492
isc::db::MySqlConnection::openDatabase
void openDatabase()
Open Database.
Definition mysql_connection.cc:65
isc::db::MySqlConnection::getTlsCipher
std::string getTlsCipher()
Get the TLS cipher.
Definition mysql_connection.h:767
isc::db::MySqlConnection::prepareStatements
void prepareStatements(const TaggedStatement *start_statement, const TaggedStatement *end_statement)
Prepare statements.
Definition mysql_connection.cc:562
isc::db::MySqlConnection::transaction_ref_count_
int transaction_ref_count_
Reference counter for transactions.
Definition mysql_connection.h:829
isc::db::MySqlConnection::startTransaction
void startTransaction()
Starts new transaction.
Definition mysql_connection.cc:622
isc::db::MySqlConnection::~MySqlConnection
virtual ~MySqlConnection()
Destructor.
Definition mysql_connection.cc:578
isc::db::MySqlConnection::ConsumeResultFun
std::function< void(MySqlBindingCollection &)> ConsumeResultFun
Function invoked to process fetched row.
Definition mysql_connection.h:239
isc::db::MySqlConnection::checkError
void checkError(const int status, const StatementIndex &index, const char *what)
Check Error and Throw Exception.
Definition mysql_connection.h:697
isc::db::MySqlConnection::getTls
bool getTls() const
Get the TLS flag.
Definition mysql_connection.h:760
isc::db::MySqlConnection::getStatement
MYSQL_STMT * getStatement(StatementIndex index) const
Returns a prepared statement by an index.
Definition mysql_connection.h:356
isc::db::MySqlConnection::selectQuery
void selectQuery(const StatementIndex &index, const MySqlBindingCollection &in_bindings, MySqlBindingCollection &out_bindings, ConsumeResultFun process_result)
Executes SELECT query using prepared statement.
Definition mysql_connection.h:482
isc::db::MySqlConnection::rollback
void rollback()
Rollbacks current transaction.
Definition mysql_connection.cc:663
isc::db::MySqlConnection::ensureSchemaVersion
static void ensureSchemaVersion(const ParameterMap &parameters, const DbCallback &cb=DbCallback(), const std::string &timer_name=std::string())
Retrieve schema version, validate it against the hardcoded version, and attempt to initialize the sch...
Definition mysql_connection.cc:413
isc::db::MySqlFreeResult
Fetch and Release MySQL Results.
Definition mysql_connection.h:43
isc::db::MySqlFreeResult::~MySqlFreeResult
~MySqlFreeResult()
Destructor.
Definition mysql_connection.h:62
isc::db::MySqlFreeResult::MySqlFreeResult
MySqlFreeResult(MYSQL_STMT *statement)
Constructor.
Definition mysql_connection.h:56
isc::db::MySqlHolder
MySQL Handle Holder.
Definition mysql_connection.h:132
isc::db::MySqlHolder::MySqlHolder
MySqlHolder()
Constructor.
Definition mysql_connection.h:140
isc::db::MySqlHolder::~MySqlHolder
~MySqlHolder()
Destructor.
Definition mysql_connection.h:149
isc::db::MySqlTransaction::~MySqlTransaction
~MySqlTransaction()
Destructor.
Definition mysql_connection.cc:48
isc::db::MySqlTransaction::commit
void commit()
Commits transaction.
Definition mysql_connection.cc:57
isc::db::MySqlTransaction::MySqlTransaction
MySqlTransaction(MySqlConnection &conn)
Constructor.
Definition mysql_connection.cc:43
isc::db::NullKeyError
Key is NULL but was specified NOT NULL.
Definition db_exceptions.h:37
database_connection.h
db_exceptions.h
db_log.h
We want to reuse the database backend connection and exchange code for other uses,...
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
io_service.h
mysql_binding.h
mysql_constants.h
isc::asiolink::IOServicePtr
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
Definition io_service.h:28
isc::cb
Definition base_config_backend.h:18
isc::db
Definition audit_entry.cc:14
isc::db::MySqlBindingPtr
boost::shared_ptr< MySqlBinding > MySqlBindingPtr
Shared pointer to the Binding class.
Definition mysql_binding.h:139
isc::db::MYSQL_FATAL_ERROR
@ MYSQL_FATAL_ERROR
Definition db_log.h:65
isc::db::IOServiceAccessorPtr
boost::shared_ptr< IOServiceAccessor > IOServiceAccessorPtr
Pointer to an instance of IOServiceAccessor.
Definition database_connection.h:115
isc::db::MLM_MYSQL_FETCH_FAILURE
const int MLM_MYSQL_FETCH_FAILURE
MySQL fetch failure code.
Definition mysql_constants.h:49
isc::db::MysqlQuery
int MysqlQuery(MYSQL *mysql, const char *stmt)
Execute a literal statement.
Definition mysql_connection.h:117
isc::db::MySqlBindingCollection
std::vector< MySqlBindingPtr > MySqlBindingCollection
Collection of bindings.
Definition mysql_binding.h:665
isc::db::MLM_MYSQL_FETCH_SUCCESS
const int MLM_MYSQL_FETCH_SUCCESS
check for bool size
Definition mysql_constants.h:46
isc::db::retryOnDeadlock
int retryOnDeadlock(Fun &fun, Args... args)
Retry on InnoDB deadlock.
Definition mysql_connection.h:89
isc::db::DbCallback
std::function< bool(util::ReconnectCtlPtr db_reconnect_ctl)> DbCallback
Defines a callback prototype for propagating events upward.
Definition database_connection.h:103
isc::db::MysqlExecuteStatement
int MysqlExecuteStatement(MYSQL_STMT *stmt)
Execute a prepared statement.
Definition mysql_connection.h:106
isc
Defines the logger used by the top-level component of kea-lfc.
Definition agent_parser.cc:148
isc::db::DB_LOG_ERROR
Definition db_log.h:186
isc::db::DB_LOG::arg
DB_LOG & arg(T first, Args... args)
Pass parameters to replace logger placeholders.
Definition db_log.h:144
isc::db::TaggedStatement
MySQL Selection Statements.
Definition mysql_connection.h:74
isc::db::TaggedStatement::index
uint32_t index
Definition mysql_connection.h:75
isc::db::TaggedStatement::text
const char * text
Definition mysql_connection.h:76