Commit 765c0d79 authored by Andrei Pavel's avatar Andrei Pavel

boost::any for CHDS

parent 4cd773d5
...@@ -89,10 +89,6 @@ struct StatementTagHash { ...@@ -89,10 +89,6 @@ struct StatementTagHash {
} }
}; };
/// Define CQL schema version: 2.0
const uint32_t CQL_SCHEMA_VERSION_MAJOR = 2;
const uint32_t CQL_SCHEMA_VERSION_MINOR = 0;
/// @brief Equality function for StatementMap keys /// @brief Equality function for StatementMap keys
struct StatementTagEqual { struct StatementTagEqual {
bool operator()(StatementTag const& lhs, StatementTag const& rhs) const { bool operator()(StatementTag const& lhs, StatementTag const& rhs) const {
......
// Copyright (C) 2016 Deutsche Telekom AG. // Copyright (C) 2016-2017 Deutsche Telekom AG.
// //
// Author: Andrei Pavel <andrei.pavel@qualitance.com> // Author: Andrei Pavel <andrei.pavel@qualitance.com>
// //
...@@ -16,29 +16,31 @@ ...@@ -16,29 +16,31 @@
#include <config.h> #include <config.h>
#include <dhcpsrv/cql_host_data_source.h>
#include <dhcp/libdhcp++.h> #include <dhcp/libdhcp++.h>
#include <dhcp/option.h> #include <dhcp/option.h>
#include <dhcp/option_definition.h> #include <dhcp/option_definition.h>
#include <dhcpsrv/cfg_option.h> #include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/cfgmgr.h> #include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/cql_host_data_source.h> #include <dhcpsrv/cql_exchange.h>
#include <dhcpsrv/cql_lease_mgr.h>
#include <dhcpsrv/db_exceptions.h> #include <dhcpsrv/db_exceptions.h>
#include <dhcpsrv/dhcpsrv_log.h> #include <dhcpsrv/dhcpsrv_log.h>
#include <util/buffer.h> #include <util/buffer.h>
#include <util/optional_value.h> #include <util/optional_value.h>
#include <boost/algorithm/string/classification.hpp> #include <openssl/md5.h> // for MD5_DIGEST_LENGTH
#include <boost/algorithm/string/split.hpp> #include <stdint.h> // for uint64_t
#include <boost/tuple/tuple.hpp>
#include <boost/unordered_map.hpp>
#include <openssl/md5.h> #include <boost/algorithm/string/classification.hpp> // for boost::is_any_of
#include <boost/algorithm/string/split.hpp> // for split
#include <boost/assert.hpp> // for BOOST_ASSERT
#include <boost/unordered_map.hpp> // for std::unordered_map
#include <list> #include <iosfwd> // for size_t, std::stringstream
#include <vector> #include <memory> // for std::unique_ptr
#include <string> // for std::string
using namespace isc;
using namespace isc::asiolink; using namespace isc::asiolink;
using namespace isc::dhcp; using namespace isc::dhcp;
using namespace isc::util; using namespace isc::util;
...@@ -48,72 +50,85 @@ namespace { ...@@ -48,72 +50,85 @@ namespace {
/// @brief Host identifier consisting of DUID or hardware address /// @brief Host identifier consisting of DUID or hardware address
typedef std::vector<uint8_t> HostIdentifier; typedef std::vector<uint8_t> HostIdentifier;
/// @brief Host identifier converted to Cassandra data type
typedef std::vector<cass_byte_t> CassHostIdentifier;
/// @brief Host identifier converted to Cassandra data type
typedef std::vector<cass_byte_t> CassOptionBuffer;
/// @brief key for HostMap containing objects which uniquely identify a /// @brief key for HostMap containing objects which uniquely identify a
/// host: host identifier, host identifier type, subnets for IPv4 and IPv6 /// host: host identifier, host identifier type, subnets for IPv4 and IPv6
typedef boost::tuple<HostIdentifier, /// and the IPv4 reservation
Host::IdentifierType, typedef std::
SubnetID, tuple<HostIdentifier, Host::IdentifierType, SubnetID, SubnetID, IOAddress>
SubnetID, HostKey;
asiolink::IOAddress>
HostKey; enum HostKeyComponent {
HOST_IDENTIFIER,
HOST_IDENTIFIER_TYPE,
IPv4_SUBNET_ID,
IPv6_SUBNET_ID,
IPv4_RESERVATION
};
/// @brief Map used to merge reservations and options into a single host on /// @brief Map used to merge reservations and options into a single host on
/// retrieve from database /// retrieve from database
typedef boost::unordered_map<HostKey, HostPtr, boost::hash<HostKey> > HostMap; typedef std::unordered_map<HostKey, HostPtr, boost::hash<HostKey>> HostMap;
typedef std::pair<HostKey, HostPtr> HostPair;
/// @brief Wrapper used to specify option space alongside option descriptor
struct OptionWrapper {
OptionWrapper(OptionDescriptorPtr option_descriptor,
std::string option_space)
: option_descriptor_(option_descriptor), option_space_(option_space) {
}
OptionDescriptorPtr option_descriptor_;
std::string option_space_;
};
/// @brief Maximum size of an IPv4 address represented as a text string. 12 /// @brief Maximum size of an IPv4 address represented as a text string. 12
/// digits plus 3 full stops (dots). /// digits plus 3 full stops (dots).
static const size_t ADDRESS4_TEXT_MAX_LENGTH = 15U; static constexpr size_t ADDRESS4_TEXT_MAX_LENGTH = 15u;
/// @brief Maximum size of an IPv6 address represented as a text string. 32 /// @brief Maximum size of an IPv6 address represented as a text string. 32
/// hexadecimal characters written in 8 groups of four, plus 7 colon /// hexadecimal characters written in 8 groups of four, plus 7 colon
/// separators. /// separators.
static const size_t ADDRESS6_TEXT_MAX_LENGTH = 39U; static constexpr size_t ADDRESS6_TEXT_MAX_LENGTH = 39u;
/// @brief Maximum length of classes stored in a host_ipv4/6_client_classes /// @brief Maximum length of classes stored in a host_ipv4/6_client_classes
/// column. /// column.
static const size_t CLIENT_CLASSES_MAX_LENGTH = 255U; static constexpr size_t CLIENT_CLASSES_MAX_LENGTH = 255u;
/// @brief Maximum length of the hostname stored in DNS. This length is /// @brief Maximum length of the hostname stored in DNS. This length is
/// restricted by the length of the domain-name carried in the Client FQDN /// restricted by the length of the domain-name carried in the Client FQDN
/// Option (see RFC4702 and RFC4704). /// Option (see RFC4702 and RFC4704).
static const size_t HOSTNAME_MAX_LENGTH = 255U; static constexpr size_t HOSTNAME_MAX_LENGTH = 255u;
/// @brief Maximum length of option value /// @brief Maximum length of option value
static const size_t OPTION_VALUE_MAX_LENGTH = 4096U; static constexpr size_t OPTION_VALUE_MAX_LENGTH = 4096u;
/// @brief Maximum length of option value specified in textual format /// @brief Maximum length of option value specified in textual format
static const size_t OPTION_FORMATTED_VALUE_MAX_LENGTH = 8192U; static constexpr size_t OPTION_FORMATTED_VALUE_MAX_LENGTH = 8192u;
/// @brief Maximum length of option space name /// @brief Maximum length of option space name
static const size_t OPTION_SPACE_MAX_LENGTH = 128U; static constexpr size_t OPTION_SPACE_MAX_LENGTH = 128u;
/// @brief Numeric value representing the last supported identifier. This value /// @brief Numeric value representing the last supported identifier. This value
/// is used to validate whether the identifier type stored in a database is /// is used to validate whether the identifier type stored in a database is
/// within bounds of supported identifiers. /// within bounds of supported identifiers.
static const cass_int8_t MAX_IDENTIFIER_TYPE = static constexpr cass_int32_t MAX_IDENTIFIER_TYPE =
static_cast<cass_int8_t>(Host::IDENT_CIRCUIT_ID); static_cast<cass_int32_t>(Host::IDENT_CIRCUIT_ID);
/// @{ /// @{
/// @brief Invalid values in the Cassandra database /// @brief Invalid values in the Cassandra database
static const char NULL_RESERVED_IPV6_PREFIX_ADDRESS[] = ""; static constexpr char NULL_RESERVED_IPV6_PREFIX_ADDRESS[] = "::";
static const cass_int32_t NULL_RESERVED_IPV6_PREFIX_LENGTH = 0; static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_LENGTH = 0;
static const cass_int32_t NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE = -1; static constexpr cass_int32_t NULL_RESERVED_IPV6_PREFIX_ADDRESS_TYPE = -1;
static const cass_int32_t NULL_IAID = -1; static constexpr cass_int32_t NULL_IAID = -1;
static const cass_int32_t NULL_OPTION_UNIVERSE = -1; static constexpr cass_int32_t NULL_OPTION_UNIVERSE = -1;
static const cass_int32_t NULL_OPTION_CODE = -1; static constexpr cass_int32_t NULL_OPTION_CODE = -1;
static const CassOptionBuffer NULL_OPTION_VALUE = CassOptionBuffer(); static const CassBlob NULL_OPTION_VALUE = CassBlob();
static const char NULL_OPTION_FORMATTED_VALUE[] = ""; static constexpr char NULL_OPTION_FORMATTED_VALUE[] = "";
static const char NULL_OPTION_SPACE[] = ""; static constexpr char NULL_OPTION_SPACE[] = "";
static const cass_bool_t NULL_OPTION_IS_PERSISTENT = cass_false; static constexpr cass_bool_t NULL_OPTION_IS_PERSISTENT = cass_false;
static const char NULL_OPTION_CLIENT_CLASS[] = ""; static constexpr char NULL_OPTION_CLIENT_CLASS[] = "";
static const cass_int32_t NULL_OPTION_SUBNET_ID = -1; static constexpr cass_int32_t NULL_OPTION_SUBNET_ID = -1;
// static constexpr CassCollection* NULL_COLLECTION = NULL;
/// @} /// @}
/// @brief Invalid reservation used to check for an invalid IPv6Resrv formed /// @brief Invalid reservation used to check for an invalid IPv6Resrv formed
...@@ -121,377 +136,19 @@ static const cass_int32_t NULL_OPTION_SUBNET_ID = -1; ...@@ -121,377 +136,19 @@ static const cass_int32_t NULL_OPTION_SUBNET_ID = -1;
static const IPv6Resrv NULL_IPV6_RESERVATION = static const IPv6Resrv NULL_IPV6_RESERVATION =
IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("::"), 128); IPv6Resrv(IPv6Resrv::TYPE_NA, IOAddress("::"), 128);
} // anonymous namespace } // namespace
namespace isc { namespace isc {
namespace dhcp { namespace dhcp {
/// @{
/// @brief Statement parameters
// INSERT_HOST
static const char* INSERT_HOST_PARAMS[] = {
static_cast<const char*>("id"),
static_cast<const char*>("host_identifier"),
static_cast<const char*>("host_identifier_type"),
static_cast<const char*>("host_ipv4_subnet_id"),
static_cast<const char*>("host_ipv6_subnet_id"),
static_cast<const char*>("host_ipv4_address"),
static_cast<const char*>("hostname"),
static_cast<const char*>("host_ipv4_client_classes"),
static_cast<const char*>("host_ipv6_client_classes"),
static_cast<const char*>("reserved_ipv6_prefix_address"),
static_cast<const char*>("reserved_ipv6_prefix_length"),
static_cast<const char*>("reserved_ipv6_prefix_address_type"),
static_cast<const char*>("iaid"),
static_cast<const char*>("option_universe"),
static_cast<const char*>("option_code"),
static_cast<const char*>("option_value"),
static_cast<const char*>("option_formatted_value"),
static_cast<const char*>("option_space"),
static_cast<const char*>("option_is_persistent"),
static_cast<const char*>("option_client_class"),
static_cast<const char*>("option_subnet_id"),
NULL};
// GET_HOST_BY_HOST_ID
static const char* GET_HOST_BY_HOST_ID_PARAMS[] = {
static_cast<const char*>("host_identifier"),
static_cast<const char*>("host_identifier_type"),
NULL};
// GET_HOST_BY_IPV4_ADDRESS
static const char* GET_HOST_BY_IPV4_ADDRESS_PARAMS[] = {
static_cast<const char*>("host_ipv4_address"),
NULL};
// GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID
static const char* GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID_PARAMS[] = {
static_cast<const char*>("host_ipv4_subnet_id"),
static_cast<const char*>("host_identifier"),
static_cast<const char*>("host_identifier_type"),
NULL};
// GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID,
static const char* GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID_PARAMS[] = {
static_cast<const char*>("host_ipv6_subnet_id"),
static_cast<const char*>("host_identifier"),
static_cast<const char*>("host_identifier_type"),
NULL};
// GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS,
static const char* GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS_PARAMS[] = {
static_cast<const char*>("host_ipv4_subnet_id"),
static_cast<const char*>("host_ipv4_address"),
NULL};
// GET_HOST_BY_IPV6_PREFIX
static const char* GET_HOST_BY_IPV6_PREFIX_PARAMS[] = {
static_cast<const char*>("reserved_ipv6_prefix_address"),
static_cast<const char*>("reserved_ipv6_prefix_length"),
NULL};
// GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS
static const char* GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS_PARAMS[] = {
static_cast<const char*>("host_ipv6_subnet_id"),
static_cast<const char*>("reserved_ipv6_prefix_address"),
NULL};
// GET_VERSION
static const char* GET_VERSION_PARAMS[] = {NULL};
/// @}
/// @brief Prepared CQL statements used by the backend to insert and retrieve
/// hosts from the database.
static CqlTaggedStatement tagged_statements[] = {
// INSERT_HOST
{INSERT_HOST_PARAMS, "INSERT_HOST",
"INSERT INTO host_reservations ( "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
") "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
"IF NOT EXISTS "
},
// GET_HOST_BY_HOST_ID
{GET_HOST_BY_HOST_ID_PARAMS, "GET_HOST_BY_HOST_ID",
"SELECT "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
"FROM host_reservations "
"WHERE host_identifier = ? "
"AND host_identifier_type = ? "
"ALLOW FILTERING "
},
// GET_HOST_BY_IPV4_ADDRESS
{GET_HOST_BY_IPV4_ADDRESS_PARAMS, "GET_HOST_BY_IPV4_ADDRESS",
"SELECT "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
"FROM host_reservations "
"WHERE host_ipv4_address = ? "
"ALLOW FILTERING "
},
// GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID
{GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID_PARAMS,
"GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID",
"SELECT "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
"FROM host_reservations "
"WHERE host_ipv4_subnet_id = ? "
"AND host_identifier = ? "
"AND host_identifier_type = ? "
"ALLOW FILTERING "
},
// GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID
{GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID_PARAMS,
"GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID",
"SELECT "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
"FROM host_reservations "
"WHERE host_ipv6_subnet_id = ? "
"AND host_identifier = ? "
"AND host_identifier_type = ? "
"ALLOW FILTERING "
},
// GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS
{GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS_PARAMS,
"GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS",
"SELECT "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
"FROM host_reservations "
"WHERE host_ipv4_subnet_id = ? "
"AND host_ipv4_address = ? "
"ALLOW FILTERING "
},
// GET_HOST_BY_IPV6_PREFIX
{GET_HOST_BY_IPV6_PREFIX_PARAMS, "GET_HOST_BY_IPV6_PREFIX",
"SELECT "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
"FROM host_reservations "
"WHERE reserved_ipv6_prefix_address = ? "
"AND reserved_ipv6_prefix_length = ? "
"ALLOW FILTERING "
},
// GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS
{GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS_PARAMS,
"GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS",
"SELECT "
"id, "
"host_identifier, "
"host_identifier_type, "
"host_ipv4_subnet_id, "
"host_ipv6_subnet_id, "
"host_ipv4_address, "
"hostname, "
"host_ipv4_client_classes, "
"host_ipv6_client_classes, "
"reserved_ipv6_prefix_address, "
"reserved_ipv6_prefix_length, "
"reserved_ipv6_prefix_address_type, "
"iaid, "
"option_universe, "
"option_code, "
"option_value, "
"option_formatted_value, "
"option_space, "
"option_is_persistent, "
"option_client_class, "
"option_subnet_id "
"FROM host_reservations "
"WHERE host_ipv6_subnet_id = ? "
"AND reserved_ipv6_prefix_address = ? "
"ALLOW FILTERING "
},
// GET_VERSION
{GET_VERSION_PARAMS, "GET_VERSION",
"SELECT version, minor FROM schema_version"},
// End of list sentinel
{NULL, NULL, NULL}}; // tagged_statements
/// @brief Provides mechanisms for sending and retrieving data from the /// @brief Provides mechanisms for sending and retrieving data from the
/// host_reservations table. /// host_reservations table.
class CqlHostExchange : public virtual CqlExchange { class CqlHostExchange : public virtual CqlExchange {
public: public:
/// @brief Statement Tags
///
/// The contents of the enum are indexes into the list of CQL statements
enum StatementIndex {
// Inserts all options belonging to any reservation from a single host.
INSERT_HOST,
// Retrieves host information, IPv6 reservations and both IPv4 and IPv6
// options associated with the host.
GET_HOST_BY_HOST_ID,
// Retrieves host information along with the IPv4 options associated
// with it.
GET_HOST_BY_IPV4_ADDRESS,
// Retrieves host information and IPv4 options using subnet identifier
// and client's identifier (i.e. hardware address or DUID).
GET_HOST_BY_IPV4_SUBNET_ID_AND_HOST_ID,
// Retrieves host information, IPv6 reservations and IPv6 options
// associated with a host using subnet identifier and client's
// identifier (i.e. hardware address or DUID).
GET_HOST_BY_IPV6_SUBNET_ID_AND_HOST_ID,
// Retrieves host information and IPv4 options for the host using subnet
// identifier and IPv4 reservation.
GET_HOST_BY_IPV4_SUBNET_ID_AND_ADDRESS,
// Retrieves host information, IPv6 reservations and IPv6 options
// associated with a host using prefix and prefix length. This query
// returns host information for a single host. However, multiple rows
// are returned due to left joining IPv6 reservations and IPv6 options.
// The number of rows returned is multiplication of number of existing
// IPv6 reservations and IPv6 options.
GET_HOST_BY_IPV6_PREFIX,
// Retrieves host information and IPv6 options for the host using subnet
// identifier and IPv6 reservation.
GET_HOST_BY_IPV6_SUBNET_ID_AND_ADDRESS,
// Get CQL schema version.
GET_VERSION,
// Number of statements
NUM_STATEMENTS
};
/// @brief Constructor /// @brief Constructor
/// ///
/// Specifies table columns. /// Specifies table columns.
CqlHostExchange(); CqlHostExchange(CqlConnection& connection);
/// @brief Virtual destructor. /// @brief Virtual destructor.
virtual ~CqlHostExchange(); virtual ~CqlHostExchange();
...@@ -501,13 +158,14 @@ public: ...@@ -501,13 +158,14 @@ public:
/// Creates a bind array to receive @ref Host data from the Cassandra /// Creates a bind array to receive @ref Host data from the Cassandra
/// database. After data is successfully received, @ref retrieve() can be /// database. After data is successfully received, @ref retrieve() can be
/// called to retrieve the @ref Host object. Called in @ref /// called to retrieve the @ref Host object. Called in @ref
/// CqlExchange::executeRead(). /// CqlExchange::executeSelect().
/// ///
/// @param data array of objects representing data being retrieved /// @param data array of objects representing data being retrieved
/// @param statement_index prepared statement being executed; defaults to an /// @param statement_tag prepared statement being executed; defaults to an
/// invalid statement /// invalid statement
virtual void createBindForReceive(CqlDataArray& data, virtual void
const int statement_index = -1); createBindForSelect(AnyArray& data,
StatementTag statement_tag = NULL) override;
/// @brief Binds @ref Host to data array to send data to the Cassandra /// @brief Binds @ref Host to data array to send data to the Cassandra
/// database. /// database.
...@@ -521,12 +179,14 @@ public: ...@@ -521,12 +179,14 @@ public:
/// @param option_space option space /// @param option_space option space
/// @param option_descriptor structure used to hold option information /// @param option_descriptor structure used to hold option information
/// @param data array being filled with data from to the Host object /// @param data array being filled with data from to the Host object
void createBindForSend(const HostPtr& host, /// @param statement_tag tag of the statement being executed