You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by is...@apache.org on 2018/03/19 11:27:00 UTC
[1/3] ignite git commit: IGNITE-7811: Implemented connection failover
for ODBC
Repository: ignite
Updated Branches:
refs/heads/master e666fc5dd -> 6ddc6d701
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/connection.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp
index 11105b6..7b06ea7 100644
--- a/modules/platforms/cpp/odbc/src/connection.cpp
+++ b/modules/platforms/cpp/odbc/src/connection.cpp
@@ -19,6 +19,7 @@
#include <cstddef>
#include <sstream>
+#include <algorithm>
#include <ignite/common/fixed_size_array.h>
@@ -27,11 +28,13 @@
#include "ignite/odbc/statement.h"
#include "ignite/odbc/connection.h"
#include "ignite/odbc/message.h"
-#include "ignite/odbc/config/configuration.h"
#include "ignite/odbc/ssl/ssl_mode.h"
#include "ignite/odbc/ssl/ssl_gateway.h"
#include "ignite/odbc/ssl/secure_socket_client.h"
#include "ignite/odbc/system/tcp_socket_client.h"
+#include "ignite/odbc/dsn_config.h"
+#include "ignite/odbc/config/configuration.h"
+#include "ignite/odbc/config/connection_string_parser.h"
// Uncomment for per-byte debug.
//#define PER_BYTE_DEBUG
@@ -104,16 +107,14 @@ namespace ignite
{
config::Configuration config;
- try
- {
- config.FillFromConnectString(connectStr);
- }
- catch (IgniteError& e)
- {
- AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, e.GetText());
+ config::ConnectionStringParser parser(config);
- return SqlResult::AI_ERROR;
- }
+ parser.ParseConnectionString(connectStr, &GetDiagnosticRecords());
+
+ std::string dsn = config.GetDsn();
+
+ if (!dsn.empty())
+ ReadDsnConfiguration(dsn.c_str(), config);
return InternalEstablish(config);
}
@@ -123,7 +124,7 @@ namespace ignite
IGNITE_ODBC_API_CALL(InternalEstablish(cfg));
}
- SqlResult::Type Connection::InternalEstablish(const config::Configuration cfg)
+ SqlResult::Type Connection::InternalEstablish(const config::Configuration& cfg)
{
using ssl::SslMode;
@@ -136,7 +137,14 @@ namespace ignite
return SqlResult::AI_ERROR;
}
- SslMode::T sslMode = SslMode::FromString(cfg.GetSslMode(), SslMode::DISABLE);
+ if (!config.IsHostSet() && config.IsAddressesSet() && config.GetAddresses().empty())
+ {
+ AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "No valid address to connect.");
+
+ return SqlResult::AI_ERROR;
+ }
+
+ SslMode::Type sslMode = config.GetSslMode();
if (sslMode != SslMode::DISABLE)
{
@@ -150,30 +158,24 @@ namespace ignite
return SqlResult::AI_ERROR;
}
- socket.reset(new ssl::SecureSocketClient(cfg.GetSslCertFile(), cfg.GetSslKeyFile(), cfg.GetSslCaFile()));
+ socket.reset(new ssl::SecureSocketClient(config.GetSslCertFile(),
+ config.GetSslKeyFile(), config.GetSslCaFile()));
}
else
socket.reset(new system::TcpSocketClient());
- bool connected = socket->Connect(cfg.GetHost().c_str(), cfg.GetTcpPort(), *this);
+ bool connected = TryRestoreConnection();
if (!connected)
{
AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with the host.");
- Close();
-
return SqlResult::AI_ERROR;
}
- SqlResult::Type res = MakeRequestHandshake();
-
- if (res == SqlResult::AI_ERROR)
- Close();
- else
- parser.SetProtocolVersion(config.GetProtocolVersion());
+ bool errors = GetDiagnosticRecords().GetStatusRecordsNumber() > 0;
- return res;
+ return errors ? SqlResult::AI_SUCCESS_WITH_INFO : SqlResult::AI_SUCCESS;
}
void Connection::Release()
@@ -513,30 +515,7 @@ namespace ignite
SqlResult::Type Connection::MakeRequestHandshake()
{
- bool distributedJoins = false;
- bool enforceJoinOrder = false;
- bool replicatedOnly = false;
- bool collocated = false;
- bool lazy = false;
- bool skipReducerOnUpdate = false;
- ProtocolVersion protocolVersion;
-
- try
- {
- protocolVersion = config.GetProtocolVersion();
- distributedJoins = config.IsDistributedJoins();
- enforceJoinOrder = config.IsEnforceJoinOrder();
- replicatedOnly = config.IsReplicatedOnly();
- collocated = config.IsCollocated();
- lazy = config.IsLazy();
- skipReducerOnUpdate = config.IsSkipReducerOnUpdate();
- }
- catch (const IgniteError& err)
- {
- AddStatusRecord(SqlState::S01S00_INVALID_CONNECTION_STRING_ATTRIBUTE, err.GetText());
-
- return SqlResult::AI_ERROR;
- }
+ ProtocolVersion protocolVersion = config.GetProtocolVersion();
if (!protocolVersion.IsSupported())
{
@@ -546,6 +525,13 @@ namespace ignite
return SqlResult::AI_ERROR;
}
+ bool distributedJoins = config.IsDistributedJoins();
+ bool enforceJoinOrder = config.IsEnforceJoinOrder();
+ bool replicatedOnly = config.IsReplicatedOnly();
+ bool collocated = config.IsCollocated();
+ bool lazy = config.IsLazy();
+ bool skipReducerOnUpdate = config.IsSkipReducerOnUpdate();
+
HandshakeRequest req(protocolVersion, distributedJoins, enforceJoinOrder, replicatedOnly, collocated, lazy,
skipReducerOnUpdate);
HandshakeResponse rsp;
@@ -554,7 +540,7 @@ namespace ignite
{
// Workaround for some Linux systems that report connection on non-blocking
// sockets as successful but fail to establish real connection.
- bool sent = SyncMessage(req, rsp, SocketClient::CONNECT_TIMEOUT);
+ bool sent = InternalSyncMessage(req, rsp, SocketClient::CONNECT_TIMEOUT);
if (!sent)
{
@@ -599,6 +585,74 @@ namespace ignite
return SqlResult::AI_SUCCESS;
}
+
+ void Connection::EnsureConnected()
+ {
+ if (socket.get() != 0)
+ return;
+
+ bool success = TryRestoreConnection();
+
+ if (!success)
+ throw OdbcError(SqlState::S08001_CANNOT_CONNECT,
+ "Failed to establish connection with any provided hosts");
+ }
+
+ bool Connection::TryRestoreConnection()
+ {
+ std::vector<EndPoint> addrs;
+
+ CollectAddresses(config, addrs);
+
+ bool connected = false;
+
+ while (!addrs.empty() && !connected)
+ {
+ const EndPoint& addr = addrs.back();
+
+ for (uint16_t port = addr.port; port <= addr.port + addr.range; ++port)
+ {
+ connected = socket->Connect(addr.host.c_str(), port, *this);
+
+ if (connected)
+ {
+ SqlResult::Type res = MakeRequestHandshake();
+
+ connected = res != SqlResult::AI_ERROR;
+
+ if (connected)
+ break;
+ }
+ }
+
+ addrs.pop_back();
+ }
+
+ if (!connected)
+ Close();
+ else
+ parser.SetProtocolVersion(config.GetProtocolVersion());
+
+ return connected;
+ }
+
+ void Connection::CollectAddresses(const config::Configuration& cfg, std::vector<EndPoint>& endPoints)
+ {
+ endPoints.clear();
+
+ if (!cfg.IsAddressesSet())
+ {
+ LOG_MSG("'Address' is not set. Using legacy connection method.");
+
+ endPoints.push_back(EndPoint(cfg.GetHost(), cfg.GetTcpPort()));
+
+ return;
+ }
+
+ endPoints = cfg.GetAddresses();
+
+ std::random_shuffle(endPoints.begin(), endPoints.end());
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp
index 4b90e44..dde1a94 100644
--- a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp
+++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp
@@ -50,6 +50,11 @@ namespace ignite
rowsAffected = 0;
}
+ void DiagnosticRecordStorage::AddStatusRecord(SqlState::Type sqlState, const std::string& message)
+ {
+ statusRecords.push_back(DiagnosticRecord(sqlState, message, "", "", 0, 0));
+ }
+
void DiagnosticRecordStorage::AddStatusRecord(const DiagnosticRecord& record)
{
statusRecords.push_back(record);
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/dsn_config.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/dsn_config.cpp b/modules/platforms/cpp/odbc/src/dsn_config.cpp
index 845c8bd..da9d61f 100644
--- a/modules/platforms/cpp/odbc/src/dsn_config.cpp
+++ b/modules/platforms/cpp/odbc/src/dsn_config.cpp
@@ -15,16 +15,18 @@
* limitations under the License.
*/
-#include <set>
+#include <ignite/common/fixed_size_array.h>
#include "ignite/odbc/utility.h"
+#include "ignite/odbc/config/connection_string_parser.h"
#include "ignite/odbc/system/odbc_constants.h"
-
#include "ignite/odbc/dsn_config.h"
+#include "ignite/odbc/config/config_tools.h"
+
-using ignite::odbc::config::Configuration;
+using namespace ignite::odbc::config;
-#define BUFFER_SIZE 1024
+#define BUFFER_SIZE (1024 * 1024)
#define CONFIG_FILE "ODBC.INI"
namespace ignite
@@ -34,13 +36,13 @@ namespace ignite
void ThrowLastSetupError()
{
DWORD code;
- char msg[BUFFER_SIZE];
+ common::FixedSizeArray<char> msg(BUFFER_SIZE);
- SQLInstallerError(1, &code, msg, sizeof(msg), NULL);
+ SQLInstallerError(1, &code, msg.GetData(), msg.GetSize(), NULL);
std::stringstream buf;
- buf << "Message: \"" << msg << "\", Code: " << code;
+ buf << "Message: \"" << msg.GetData() << "\", Code: " << code;
throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, buf.str().c_str());
}
@@ -51,98 +53,155 @@ namespace ignite
ThrowLastSetupError();
}
- std::string ReadDsnString(const char* dsn, const std::string& key, const std::string& dflt)
+ SettableValue<std::string> ReadDsnString(const char* dsn, const std::string& key, const std::string& dflt = "")
{
- char buf[BUFFER_SIZE];
+ static const char* unique = "35a920dd-8837-43d2-a846-e01a2e7b5f84";
- memset(buf, 0, sizeof(buf));
+ SettableValue<std::string> val(dflt);
- SQLGetPrivateProfileString(dsn, key.c_str(), dflt.c_str(), buf, sizeof(buf), CONFIG_FILE);
+ common::FixedSizeArray<char> buf(BUFFER_SIZE);
- return std::string(buf);
- }
+ int ret = SQLGetPrivateProfileString(dsn, key.c_str(), unique, buf.GetData(), buf.GetSize(), CONFIG_FILE);
- int ReadDsnInt(const char* dsn, const std::string& key, int dflt)
- {
- char buf[BUFFER_SIZE];
+ if (ret > BUFFER_SIZE)
+ {
+ buf.Reset(ret + 1);
- memset(buf, 0, sizeof(buf));
+ ret = SQLGetPrivateProfileString(dsn, key.c_str(), unique, buf.GetData(), buf.GetSize(), CONFIG_FILE);
+ }
- std::string dflt0 = common::LexicalCast<std::string>(dflt);
+ std::string res(buf.GetData());
- SQLGetPrivateProfileString(dsn, key.c_str(), dflt0.c_str(), buf, sizeof(buf), CONFIG_FILE);
+ if (res == unique)
+ return val;
- return common::LexicalCast<int, std::string>(buf);
+ val.SetValue(res);
+
+ return val;
}
- bool ReadDsnBool(const char* dsn, const std::string& key, bool dflt)
+ SettableValue<int32_t> ReadDsnInt(const char* dsn, const std::string& key, int32_t dflt = 0)
{
- char buf[BUFFER_SIZE];
+ SettableValue<std::string> str = ReadDsnString(dsn, key, "");
+
+ SettableValue<int32_t> res(dflt);
- memset(buf, 0, sizeof(buf));
+ if (str.IsSet())
+ res.SetValue(common::LexicalCast<int, std::string>(str.GetValue()));
- std::string dflt0 = dflt ? "true" : "false";
+ return res;
+ }
- SQLGetPrivateProfileString(dsn, key.c_str(), dflt0.c_str(), buf, sizeof(buf), CONFIG_FILE);
+ SettableValue<bool> ReadDsnBool(const char* dsn, const std::string& key, bool dflt = false)
+ {
+ SettableValue<std::string> str = ReadDsnString(dsn, key, "");
- return std::string(buf) == "true";
+ SettableValue<bool> res(dflt);
+
+ if (str.IsSet())
+ res.SetValue(str.GetValue() == "true");
+
+ return res;
}
void ReadDsnConfiguration(const char* dsn, Configuration& config)
{
- std::string address = ReadDsnString(dsn, Configuration::Key::address, config.GetAddress());
+ SettableValue<std::string> address = ReadDsnString(dsn, ConnectionStringParser::Key::address);
+
+ if (address.IsSet() && !config.IsAddressesSet())
+ {
+ std::vector<EndPoint> endPoints;
+
+ ParseAddress(address.GetValue(), endPoints, 0);
+
+ config.SetAddresses(endPoints);
+ }
+
+ SettableValue<std::string> server = ReadDsnString(dsn, ConnectionStringParser::Key::server);
+
+ if (server.IsSet() && !config.IsHostSet())
+ config.SetHost(server.GetValue());
+
+ SettableValue<int32_t> port = ReadDsnInt(dsn, ConnectionStringParser::Key::port);
+
+ if (port.IsSet() && !config.IsTcpPortSet())
+ config.SetTcpPort(static_cast<uint16_t>(port.GetValue()));
+
+ SettableValue<std::string> schema = ReadDsnString(dsn, ConnectionStringParser::Key::schema);
+
+ if (schema.IsSet() && !config.IsSchemaSet())
+ config.SetSchema(schema.GetValue());
+
+ SettableValue<bool> distributedJoins = ReadDsnBool(dsn, ConnectionStringParser::Key::distributedJoins);
+
+ if (distributedJoins.IsSet() && !config.IsDistributedJoinsSet())
+ config.SetDistributedJoins(distributedJoins.GetValue());
+
+ SettableValue<bool> enforceJoinOrder = ReadDsnBool(dsn, ConnectionStringParser::Key::enforceJoinOrder);
+
+ if (enforceJoinOrder.IsSet() && !config.IsEnforceJoinOrderSet())
+ config.SetEnforceJoinOrder(enforceJoinOrder.GetValue());
+
+ SettableValue<bool> replicatedOnly = ReadDsnBool(dsn, ConnectionStringParser::Key::replicatedOnly);
+
+ if (replicatedOnly.IsSet() && !config.IsReplicatedOnlySet())
+ config.SetReplicatedOnly(replicatedOnly.GetValue());
+
+ SettableValue<bool> collocated = ReadDsnBool(dsn, ConnectionStringParser::Key::collocated);
+
+ if (collocated.IsSet() && !config.IsCollocatedSet())
+ config.SetCollocated(collocated.GetValue());
+
+ SettableValue<bool> lazy = ReadDsnBool(dsn, ConnectionStringParser::Key::lazy);
+
+ if (lazy.IsSet() && !config.IsLazySet())
+ config.SetLazy(lazy.GetValue());
- std::string server = ReadDsnString(dsn, Configuration::Key::server, config.GetHost());
+ SettableValue<bool> skipReducerOnUpdate = ReadDsnBool(dsn, ConnectionStringParser::Key::skipReducerOnUpdate);
- uint16_t port = ReadDsnInt(dsn, Configuration::Key::port, config.GetTcpPort());
+ if (skipReducerOnUpdate.IsSet() && !config.IsSkipReducerOnUpdateSet())
+ config.SetSkipReducerOnUpdate(skipReducerOnUpdate.GetValue());
- std::string schema = ReadDsnString(dsn, Configuration::Key::schema, config.GetSchema());
+ SettableValue<std::string> versionStr = ReadDsnString(dsn, ConnectionStringParser::Key::protocolVersion);
- bool distributedJoins = ReadDsnBool(dsn, Configuration::Key::distributedJoins, config.IsDistributedJoins());
+ if (versionStr.IsSet() && !config.IsProtocolVersionSet())
+ {
+ ProtocolVersion version = ProtocolVersion::FromString(versionStr.GetValue());
- bool enforceJoinOrder = ReadDsnBool(dsn, Configuration::Key::enforceJoinOrder, config.IsEnforceJoinOrder());
+ if (!version.IsSupported())
+ version = Configuration::DefaultValue::protocolVersion;
- bool replicatedOnly = ReadDsnBool(dsn, Configuration::Key::replicatedOnly, config.IsReplicatedOnly());
+ config.SetProtocolVersion(version);
+ }
- bool collocated = ReadDsnBool(dsn, Configuration::Key::collocated, config.IsCollocated());
+ SettableValue<int32_t> pageSize = ReadDsnInt(dsn, ConnectionStringParser::Key::pageSize);
- bool lazy = ReadDsnBool(dsn, Configuration::Key::lazy, config.IsLazy());
+ if (pageSize.IsSet() && !config.IsPageSizeSet() && pageSize.GetValue() > 0)
+ config.SetPageSize(pageSize.GetValue());
- bool skipReducerOnUpdate =
- ReadDsnBool(dsn, Configuration::Key::skipReducerOnUpdate, config.IsSkipReducerOnUpdate());
+ SettableValue<std::string> sslModeStr = ReadDsnString(dsn, ConnectionStringParser::Key::sslMode);
- std::string version = ReadDsnString(dsn, Configuration::Key::protocolVersion,
- config.GetProtocolVersion().ToString());
+ if (sslModeStr.IsSet() && !config.IsSslModeSet())
+ {
+ ssl::SslMode::Type sslMode = ssl::SslMode::FromString(sslModeStr.GetValue(), ssl::SslMode::DISABLE);
- int32_t pageSize = ReadDsnInt(dsn, Configuration::Key::pageSize, config.GetPageSize());
+ config.SetSslMode(sslMode);
+ }
- if (pageSize <= 0)
- pageSize = config.GetPageSize();
+ SettableValue<std::string> sslKeyFile = ReadDsnString(dsn, ConnectionStringParser::Key::sslKeyFile);
- std::string sslMode = ReadDsnString(dsn, Configuration::Key::sslMode, config.GetSslMode());
+ if (sslKeyFile.IsSet() && !config.IsSslKeyFileSet())
+ config.SetSslKeyFile(sslKeyFile.GetValue());
- std::string sslKeyFile = ReadDsnString(dsn, Configuration::Key::sslKeyFile, config.GetSslKeyFile());
+ SettableValue<std::string> sslCertFile = ReadDsnString(dsn, ConnectionStringParser::Key::sslCertFile);
- std::string sslCertFile = ReadDsnString(dsn, Configuration::Key::sslCertFile, config.GetSslCertFile());
+ if (sslCertFile.IsSet() && !config.IsSslCertFileSet())
+ config.SetSslCertFile(sslCertFile.GetValue());
- std::string sslCaFile = ReadDsnString(dsn, Configuration::Key::sslCaFile, config.GetSslCaFile());
+ SettableValue<std::string> sslCaFile = ReadDsnString(dsn, ConnectionStringParser::Key::sslCaFile);
- config.SetAddress(address);
- config.SetHost(server);
- config.SetTcpPort(port);
- config.SetSchema(schema);
- config.SetDistributedJoins(distributedJoins);
- config.SetEnforceJoinOrder(enforceJoinOrder);
- config.SetReplicatedOnly(replicatedOnly);
- config.SetCollocated(collocated);
- config.SetLazy(lazy);
- config.SetSkipReducerOnUpdate(skipReducerOnUpdate);
- config.SetProtocolVersion(version);
- config.SetPageSize(pageSize);
- config.SetSslMode(sslMode);
- config.SetSslKeyFile(sslKeyFile);
- config.SetSslCertFile(sslCertFile);
- config.SetSslCaFile(sslCaFile);
+ if (sslCaFile.IsSet() && !config.IsSslCaFileSet())
+ config.SetSslCaFile(sslCaFile.GetValue());
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/environment.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/environment.cpp b/modules/platforms/cpp/odbc/src/environment.cpp
index 6182fa2..417fedc 100644
--- a/modules/platforms/cpp/odbc/src/environment.cpp
+++ b/modules/platforms/cpp/odbc/src/environment.cpp
@@ -15,6 +15,8 @@
* limitations under the License.
*/
+#include <cstdlib>
+
#include "ignite/odbc/system/odbc_constants.h"
#include "ignite/odbc/connection.h"
#include "ignite/odbc/environment.h"
@@ -24,9 +26,10 @@ namespace ignite
namespace odbc
{
Environment::Environment() :
- odbcVersion(SQL_OV_ODBC3), odbcNts(SQL_TRUE)
+ odbcVersion(SQL_OV_ODBC3),
+ odbcNts(SQL_TRUE)
{
- // No-op.
+ srand(common::GetRandSeed());
}
Environment::~Environment()
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/odbc.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/odbc.cpp b/modules/platforms/cpp/odbc/src/odbc.cpp
index dfa2dec..3aad52f 100644
--- a/modules/platforms/cpp/odbc/src/odbc.cpp
+++ b/modules/platforms/cpp/odbc/src/odbc.cpp
@@ -24,6 +24,7 @@
#include "ignite/odbc/utility.h"
#include "ignite/odbc/system/odbc_constants.h"
+#include "ignite/odbc/config/connection_string_parser.h"
#include "ignite/odbc/config/configuration.h"
#include "ignite/odbc/type_traits.h"
#include "ignite/odbc/environment.h"
@@ -270,16 +271,7 @@ namespace ignite
std::string connectStr = SqlStringToString(inConnectionString, inConnectionStringLen);
- odbc::config::Configuration config;
-
- config.FillFromConnectString(connectStr);
-
- std::string dsn = config.GetDsn();
-
- if (!dsn.empty())
- odbc::ReadDsnConfiguration(dsn.c_str(), config);
-
- connection->Establish(config);
+ connection->Establish(connectStr);
const DiagnosticRecordStorage& diag = connection->GetDiagnosticRecords();
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp b/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp
index 0bdbc60..3a8e923 100644
--- a/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp
+++ b/modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp
@@ -24,7 +24,7 @@ namespace ignite
{
namespace ssl
{
- SslMode::T SslMode::FromString(const std::string& val, T dflt)
+ SslMode::Type SslMode::FromString(const std::string& val, Type dflt)
{
std::string lowerVal = common::ToLower(val);
@@ -38,6 +38,22 @@ namespace ignite
return dflt;
}
+
+ std::string SslMode::ToString(Type val)
+ {
+ switch (val)
+ {
+ case SslMode::DISABLE:
+ return "disable";
+
+ case SslMode::REQUIRE:
+ return "require";
+
+ case SslMode::UNKNOWN:
+ default:
+ return "unknown";
+ }
+ }
}
}
}
[3/3] ignite git commit: IGNITE-7811: Implemented connection failover
for ODBC
Posted by is...@apache.org.
IGNITE-7811: Implemented connection failover for ODBC
This closes #3643
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/6ddc6d70
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/6ddc6d70
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/6ddc6d70
Branch: refs/heads/master
Commit: 6ddc6d701db10c51406a7ff02b5f8cc3c1e2397f
Parents: e666fc5
Author: Igor Sapego <is...@gridgain.com>
Authored: Mon Mar 19 14:17:33 2018 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Mon Mar 19 14:17:33 2018 +0300
----------------------------------------------------------------------
.../include/ignite/common/platform_utils.h | 7 +
.../os/linux/src/common/platform_utils.cpp | 15 +
.../common/os/win/src/common/platform_utils.cpp | 5 +
modules/platforms/cpp/odbc-test/Makefile.am | 8 +-
.../cpp/odbc-test/include/odbc_test_suite.h | 29 +
.../cpp/odbc-test/project/vs/odbc-test.vcxproj | 6 +
.../project/vs/odbc-test.vcxproj.filters | 20 +-
.../cpp/odbc-test/src/api_robustness_test.cpp | 25 -
.../cpp/odbc-test/src/attributes_test.cpp | 165 +++---
.../cpp/odbc-test/src/configuration_test.cpp | 223 +++++---
.../cpp/odbc-test/src/odbc_test_suite.cpp | 25 +
.../cpp/odbc-test/src/queries_test.cpp | 40 --
.../cpp/odbc-test/src/sql_get_info_test.cpp | 3 +-
modules/platforms/cpp/odbc/Makefile.am | 2 +
.../include/ignite/odbc/config/config_tools.h | 92 ++++
.../include/ignite/odbc/config/configuration.h | 527 +++++++++----------
.../odbc/config/connection_string_parser.h | 188 +++++++
.../include/ignite/odbc/config/settable_value.h | 101 ++++
.../cpp/odbc/include/ignite/odbc/connection.h | 61 ++-
.../odbc/diagnostic/diagnosable_adapter.h | 26 +-
.../odbc/diagnostic/diagnostic_record_storage.h | 13 +-
.../cpp/odbc/include/ignite/odbc/end_point.h | 72 +++
.../cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h | 13 +-
.../cpp/odbc/include/ignite/odbc/utility.h | 3 +-
.../src/system/ui/dsn_configuration_window.cpp | 127 +++--
.../cpp/odbc/os/win/src/system_dsn.cpp | 24 +-
.../platforms/cpp/odbc/project/vs/odbc.vcxproj | 6 +
.../cpp/odbc/project/vs/odbc.vcxproj.filters | 18 +
.../cpp/odbc/src/config/config_tools.cpp | 250 +++++++++
.../cpp/odbc/src/config/configuration.cpp | 507 +++++++++++-------
.../src/config/connection_string_parser.cpp | 452 ++++++++++++++++
modules/platforms/cpp/odbc/src/connection.cpp | 150 ++++--
.../diagnostic/diagnostic_record_storage.cpp | 5 +
modules/platforms/cpp/odbc/src/dsn_config.cpp | 183 ++++---
modules/platforms/cpp/odbc/src/environment.cpp | 7 +-
modules/platforms/cpp/odbc/src/odbc.cpp | 12 +-
modules/platforms/cpp/odbc/src/ssl/ssl_mode.cpp | 18 +-
37 files changed, 2521 insertions(+), 907 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/common/include/ignite/common/platform_utils.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/common/platform_utils.h b/modules/platforms/cpp/common/include/ignite/common/platform_utils.h
index 83da6ec..a46caba 100644
--- a/modules/platforms/cpp/common/include/ignite/common/platform_utils.h
+++ b/modules/platforms/cpp/common/include/ignite/common/platform_utils.h
@@ -104,6 +104,13 @@ namespace ignite
* @return The same stream for chaining.
*/
IGNITE_IMPORT_EXPORT StdCharOutStream& Dle(StdCharOutStream& ostr);
+
+ /**
+ * Get random seed.
+ *
+ * @return Random seed.
+ */
+ unsigned GetRandSeed();
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp b/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp
index 88ba8ed..2cbbd1d 100644
--- a/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp
+++ b/modules/platforms/cpp/common/os/linux/src/common/platform_utils.cpp
@@ -18,9 +18,11 @@
#include <time.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <dirent.h>
#include <dlfcn.h>
#include <glob.h>
+#include <unistd.h>
#include <ignite/common/utils.h>
@@ -104,5 +106,18 @@ namespace ignite
return ostr;
}
+
+ unsigned GetRandSeed()
+ {
+ timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ unsigned res = static_cast<unsigned>(ts.tv_sec);
+ res ^= static_cast<unsigned>(ts.tv_nsec);
+ res ^= static_cast<unsigned>(getpid());
+
+ return res;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp b/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp
index 057a3d4..c2244c5 100644
--- a/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp
+++ b/modules/platforms/cpp/common/os/win/src/common/platform_utils.cpp
@@ -106,5 +106,10 @@ namespace ignite
return ostr;
}
+
+ unsigned GetRandSeed()
+ {
+ return static_cast<unsigned>(GetTickCount() ^ GetCurrentProcessId());
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/Makefile.am b/modules/platforms/cpp/odbc-test/Makefile.am
index cda4071..89e27dd 100644
--- a/modules/platforms/cpp/odbc-test/Makefile.am
+++ b/modules/platforms/cpp/odbc-test/Makefile.am
@@ -86,12 +86,18 @@ ignite_odbc_tests_SOURCES = \
src/types_test.cpp \
../odbc/src/log.cpp \
../odbc/src/cursor.cpp \
+ ../odbc/src/diagnostic/diagnostic_record.cpp \
+ ../odbc/src/diagnostic/diagnostic_record_storage.cpp \
+ ../odbc/src/config/config_tools.cpp \
+ ../odbc/src/config/configuration.cpp \
../odbc/src/config/connection_info.cpp \
+ ../odbc/src/config/connection_string_parser.cpp \
../odbc/src/app/application_data_buffer.cpp \
- ../odbc/src/config/configuration.cpp \
+ ../odbc/src/ssl/ssl_mode.cpp \
../odbc/src/row.cpp \
../odbc/src/protocol_version.cpp \
../odbc/src/column.cpp \
+ ../odbc/src/common_types.cpp \
../odbc/src/utility.cpp \
../odbc/src/result_page.cpp
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
index c535679..33bd819 100644
--- a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
+++ b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
@@ -108,8 +108,37 @@ namespace ignite
*/
void InsertNonFullBatchSelect(int recordsNum, int splitAt);
+ /**
+ * Get test string.
+ *
+ * @param ind Index.
+ * @return Corresponding test string.
+ */
static std::string getTestString(int64_t ind);
+ /**
+ * Check that SQL error has expected SQL state.
+ *
+ * @param handleType Handle type.
+ * @param handle Handle.
+ * @param expectSqlState Expected state.
+ */
+ void CheckSQLDiagnosticError(int16_t handleType, SQLHANDLE handle, const std::string& expectSqlState);
+
+ /**
+ * Check that statement SQL error has expected SQL state.
+ *
+ * @param expectSqlState Expected state.
+ */
+ void CheckSQLStatementDiagnosticError(const std::string& expectSqlState);
+
+ /**
+ * Check that connection SQL error has expected SQL state.
+ *
+ * @param expectSqlState Expected state.
+ */
+ void CheckSQLConnectionDiagnosticError(const std::string& expectSqlState);
+
/** ODBC Environment. */
SQLHENV env;
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
index b1074b2..30cafa3 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
@@ -155,13 +155,19 @@
<ItemGroup>
<ClCompile Include="..\..\..\odbc\src\app\application_data_buffer.cpp" />
<ClCompile Include="..\..\..\odbc\src\column.cpp" />
+ <ClCompile Include="..\..\..\odbc\src\common_types.cpp" />
<ClCompile Include="..\..\..\odbc\src\config\configuration.cpp" />
+ <ClCompile Include="..\..\..\odbc\src\config\config_tools.cpp" />
<ClCompile Include="..\..\..\odbc\src\config\connection_info.cpp" />
+ <ClCompile Include="..\..\..\odbc\src\config\connection_string_parser.cpp" />
<ClCompile Include="..\..\..\odbc\src\cursor.cpp" />
+ <ClCompile Include="..\..\..\odbc\src\diagnostic\diagnostic_record.cpp" />
+ <ClCompile Include="..\..\..\odbc\src\diagnostic\diagnostic_record_storage.cpp" />
<ClCompile Include="..\..\..\odbc\src\log.cpp" />
<ClCompile Include="..\..\..\odbc\src\protocol_version.cpp" />
<ClCompile Include="..\..\..\odbc\src\result_page.cpp" />
<ClCompile Include="..\..\..\odbc\src\row.cpp" />
+ <ClCompile Include="..\..\..\odbc\src\ssl\ssl_mode.cpp" />
<ClCompile Include="..\..\..\odbc\src\utility.cpp" />
<ClCompile Include="..\..\src\api_robustness_test.cpp" />
<ClCompile Include="..\..\src\application_data_buffer_test.cpp" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
index 417fac9..bd0e200 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
@@ -142,6 +142,24 @@
<ClCompile Include="..\..\src\queries_ssl_test.cpp">
<Filter>Code</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\odbc\src\config\connection_string_parser.cpp">
+ <Filter>Externals</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\odbc\src\config\config_tools.cpp">
+ <Filter>Externals</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\odbc\src\ssl\ssl_mode.cpp">
+ <Filter>Externals</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\odbc\src\diagnostic\diagnostic_record_storage.cpp">
+ <Filter>Externals</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\odbc\src\diagnostic\diagnostic_record.cpp">
+ <Filter>Externals</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\odbc\src\common_types.cpp">
+ <Filter>Externals</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\test_type.h">
@@ -180,4 +198,4 @@
<Filter>Configs</Filter>
</None>
</ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
index 293d8bc..eca0e00 100644
--- a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
@@ -121,31 +121,6 @@ struct ApiRobustnessTestSuiteFixture : public odbc::OdbcTestSuite
CheckSQLStatementDiagnosticError("HY106");
}
- void CheckSQLDiagnosticError(int16_t handleType, SQLHANDLE handle, const std::string& expectSqlState)
- {
- SQLCHAR state[ODBC_BUFFER_SIZE];
- SQLINTEGER nativeError = 0;
- SQLCHAR message[ODBC_BUFFER_SIZE];
- SQLSMALLINT messageLen = 0;
-
- SQLRETURN ret = SQLGetDiagRec(handleType, handle, 1, state, &nativeError, message, sizeof(message), &messageLen);
-
- const std::string sqlState = reinterpret_cast<char*>(state);
- BOOST_REQUIRE_EQUAL(ret, SQL_SUCCESS);
- BOOST_REQUIRE_EQUAL(sqlState, expectSqlState);
- BOOST_REQUIRE(messageLen > 0);
- }
-
- void CheckSQLStatementDiagnosticError(const std::string& expectSqlState)
- {
- CheckSQLDiagnosticError(SQL_HANDLE_STMT, stmt, expectSqlState);
- }
-
- void CheckSQLConnectionDiagnosticError(const std::string& expectSqlState)
- {
- CheckSQLDiagnosticError(SQL_HANDLE_DBC, dbc, expectSqlState);
- }
-
/**
* Destructor.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
index c4c2433..3dc226d 100644
--- a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
@@ -37,6 +37,7 @@
#include "test_type.h"
#include "test_utils.h"
+#include "odbc_test_suite.h"
using namespace ignite;
using namespace ignite::cache;
@@ -51,74 +52,13 @@ using ignite::impl::binary::BinaryUtils;
/**
* Test setup fixture.
*/
-struct AttributesTestSuiteFixture
+struct AttributesTestSuiteFixture : odbc::OdbcTestSuite
{
- void Prepare()
- {
- // Allocate an environment handle
- SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
-
- BOOST_REQUIRE(env != NULL);
-
- // We want ODBC 3 support
- SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0);
-
- // Allocate a connection handle
- SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
-
- BOOST_REQUIRE(dbc != NULL);
- }
-
- /**
- * Establish connection to node.
- *
- * @param connectStr Connection string.
- */
- void Connect(const std::string& connectStr)
- {
- Prepare();
-
- // Connect string
- std::vector<SQLCHAR> connectStr0;
-
- connectStr0.reserve(connectStr.size() + 1);
- std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0));
-
- SQLCHAR outstr[ODBC_BUFFER_SIZE];
- SQLSMALLINT outstrlen;
-
- // Connecting to ODBC server.
- SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast<SQLSMALLINT>(connectStr0.size()),
- outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
-
- ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
-
- // Allocate a statement handle
- SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
-
- BOOST_REQUIRE(stmt != NULL);
- }
-
- void Disconnect()
- {
- // Releasing statement handle.
- SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-
- // Disconneting from the server.
- SQLDisconnect(dbc);
-
- // Releasing allocated handles.
- SQLFreeHandle(SQL_HANDLE_DBC, dbc);
- SQLFreeHandle(SQL_HANDLE_ENV, env);
- }
-
/**
* Constructor.
*/
AttributesTestSuiteFixture() :
- env(NULL),
- dbc(NULL),
- stmt(NULL)
+ grid()
{
const char* config = NULL;
@@ -131,26 +71,6 @@ struct AttributesTestSuiteFixture
grid = StartNode(config, "NodeMain");
}
- void CheckSQLDiagnosticError(int16_t handleType, SQLHANDLE handle, const std::string& expectSqlState)
- {
- SQLCHAR state[ODBC_BUFFER_SIZE];
- SQLINTEGER nativeError = 0;
- SQLCHAR message[ODBC_BUFFER_SIZE];
- SQLSMALLINT messageLen = 0;
-
- SQLRETURN ret = SQLGetDiagRec(handleType, handle, 1, state, &nativeError, message, sizeof(message), &messageLen);
-
- const std::string sqlState = reinterpret_cast<char*>(state);
- BOOST_REQUIRE_EQUAL(ret, SQL_SUCCESS);
- BOOST_REQUIRE_EQUAL(sqlState, expectSqlState);
- BOOST_REQUIRE(messageLen > 0);
- }
-
- void CheckSQLConnectionDiagnosticError(const std::string& expectSqlState)
- {
- CheckSQLDiagnosticError(SQL_HANDLE_DBC, dbc, expectSqlState);
- }
-
/**
* Destructor.
*/
@@ -163,18 +83,81 @@ struct AttributesTestSuiteFixture
/** Node started during the test. */
Ignite grid;
+};
- /** ODBC Environment. */
- SQLHENV env;
+BOOST_FIXTURE_TEST_SUITE(AttributesTestSuite, AttributesTestSuiteFixture)
- /** ODBC Connect. */
- SQLHDBC dbc;
+BOOST_AUTO_TEST_CASE(TestLegacyConnection)
+{
+ Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;SCHEMA=cache");
- /** ODBC Statement. */
- SQLHSTMT stmt;
-};
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
-BOOST_FIXTURE_TEST_SUITE(AttributesTestSuite, AttributesTestSuiteFixture)
+BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_1_0)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.1.0");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_1_5)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.1.5");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_3_0)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.3.0");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_3_2)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.3.2");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionRangeBegin)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110..11115;SCHEMA=cache");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionRangeEnd)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11108..11110;SCHEMA=cache");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionRangeMiddle)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11108..11115;SCHEMA=cache");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionMultipleAddresses)
+{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:4242,127.0.0.1:11109..11115,127.0.0.1;SCHEMA=cache");
+
+ InsertTestStrings(10, false);
+ InsertTestBatch(11, 20, 9);
+}
BOOST_AUTO_TEST_CASE(ConnectionAttributeConnectionDeadGet)
{
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/configuration_test.cpp b/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
index 3165c4d..4cfc940 100644
--- a/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
@@ -25,9 +25,13 @@
#include <boost/test/unit_test.hpp>
#include <ignite/odbc/config/configuration.h>
-#include <ignite/ignite_error.h>
+#include <ignite/odbc/config/connection_string_parser.h>
+#include <ignite/odbc/config/config_tools.h>
+#include <ignite/odbc/odbc_error.h>
#include <ignite/common/utils.h>
+#include "ignite/odbc/diagnostic/diagnostic_record_storage.h"
+using namespace ignite::odbc;
using namespace ignite::odbc::config;
namespace
@@ -45,7 +49,9 @@ namespace
const bool testLazy = true;
const bool testSkipReducerOnUpdate = true;
- const std::string testAddress = testServerHost + ':' + ignite::common::LexicalCast<std::string>(testServerPort);
+ const std::string testAddressStr = testServerHost + ':' + ignite::common::LexicalCast<std::string>(testServerPort);
+
+ const EndPoint testAddress(testServerHost, testServerPort, 10);
}
const char* BoolToStr(bool val, bool lowerCase = true)
@@ -56,77 +62,128 @@ const char* BoolToStr(bool val, bool lowerCase = true)
return val ? "TRUE" : "FALSE";
}
-void CheckValidAddress(const char* connectStr, uint16_t port)
+void ParseValidDsnString(const std::string& dsnStr, Configuration& cfg)
+{
+ ConnectionStringParser parser(cfg);
+
+ diagnostic::DiagnosticRecordStorage diag;
+
+ BOOST_CHECK_NO_THROW(parser.ParseConfigAttributes(dsnStr.c_str(), &diag));
+
+ if (diag.GetStatusRecordsNumber() != 0)
+ BOOST_FAIL(diag.GetStatusRecord(1).GetMessageText());
+}
+
+void ParseValidConnectString(const std::string& connectStr, Configuration& cfg)
+{
+ ConnectionStringParser parser(cfg);
+
+ diagnostic::DiagnosticRecordStorage diag;
+
+ BOOST_CHECK_NO_THROW(parser.ParseConnectionString(connectStr, &diag));
+
+ if (diag.GetStatusRecordsNumber() != 0)
+ BOOST_FAIL(diag.GetStatusRecord(1).GetMessageText());
+}
+
+void ParseConnectStringWithError(const std::string& connectStr, Configuration& cfg)
+{
+ ConnectionStringParser parser(cfg);
+
+ diagnostic::DiagnosticRecordStorage diag;
+
+ BOOST_CHECK_NO_THROW(parser.ParseConnectionString(connectStr, &diag));
+
+ BOOST_CHECK_NE(diag.GetStatusRecordsNumber(), 0);
+}
+
+void CheckValidAddress(const char* connectStr, const EndPoint& endPoint)
{
Configuration cfg;
- BOOST_CHECK_NO_THROW(cfg.FillFromConnectString(connectStr));
+ ParseValidConnectString(connectStr, cfg);
+
+ const std::vector<EndPoint>& addrs = cfg.GetAddresses();
- BOOST_CHECK_EQUAL(cfg.GetTcpPort(), port);
+ BOOST_REQUIRE_EQUAL(addrs.size(), 1);
+ BOOST_CHECK_EQUAL(addrs[0].host, endPoint.host);
+ BOOST_CHECK_EQUAL(addrs[0].port, endPoint.port);
}
-void CheckValidProtocolVersion(const char* connectStr, ignite::odbc::ProtocolVersion version)
+void CheckValidAddresses(const char* connectStr, const std::vector<EndPoint>& endPoints)
{
Configuration cfg;
- BOOST_CHECK_NO_THROW(cfg.FillFromConnectString(connectStr));
+ ParseValidConnectString(connectStr, cfg);
- BOOST_CHECK(cfg.GetProtocolVersion() == version);
+ const std::vector<EndPoint>& addrs = cfg.GetAddresses();
+
+ BOOST_REQUIRE_EQUAL(addrs.size(), endPoints.size());
+
+ for (size_t i = 0; i < addrs.size(); ++i)
+ {
+ BOOST_CHECK_EQUAL(addrs[i].host, endPoints[i].host);
+ BOOST_CHECK_EQUAL(addrs[i].port, endPoints[i].port);
+ }
}
-void CheckSupportedProtocolVersion(const char* connectStr)
+void CheckValidProtocolVersion(const char* connectStr, ProtocolVersion version)
{
Configuration cfg;
- BOOST_CHECK_NO_THROW(cfg.FillFromConnectString(connectStr));
+ ParseValidConnectString(connectStr, cfg);
- BOOST_CHECK(cfg.GetProtocolVersion().IsSupported());
+ BOOST_CHECK(cfg.GetProtocolVersion() == version);
}
-void CheckInvalidProtocolVersion(const char* connectStr)
+void CheckSupportedProtocolVersion(const char* connectStr)
{
Configuration cfg;
- cfg.FillFromConnectString(connectStr);
+ ParseValidConnectString(connectStr, cfg);
- BOOST_CHECK_THROW(cfg.GetProtocolVersion(), ignite::IgniteError);
+ BOOST_CHECK(cfg.GetProtocolVersion().IsSupported());
}
-void CheckUnsupportedProtocolVersion(const char* connectStr)
+void CheckInvalidProtocolVersion(const char* connectStr)
{
Configuration cfg;
- cfg.FillFromConnectString(connectStr);
+ ParseConnectStringWithError(connectStr, cfg);
- BOOST_CHECK(!cfg.GetProtocolVersion().IsSupported());
+ BOOST_CHECK(cfg.GetProtocolVersion() == Configuration::DefaultValue::protocolVersion);
}
void CheckValidBoolValue(const std::string& connectStr, const std::string& key, bool val)
{
Configuration cfg;
- BOOST_CHECK_NO_THROW(cfg.FillFromConnectString(connectStr));
+ ParseValidConnectString(connectStr, cfg);
+
+ Configuration::ArgumentMap map;
+ cfg.ToMap(map);
+
+ std::string expected = val ? "true" : "false";
- BOOST_CHECK_EQUAL(cfg.GetBoolValue(key, val), val);
+ BOOST_CHECK_EQUAL(map[key], expected);
}
void CheckInvalidBoolValue(const std::string& connectStr, const std::string& key)
{
Configuration cfg;
- cfg.FillFromConnectString(connectStr);
+ ParseConnectStringWithError(connectStr, cfg);
- BOOST_CHECK_THROW(cfg.GetBoolValue(key, false), ignite::IgniteError);
+ Configuration::ArgumentMap map;
+ cfg.ToMap(map);
+
+ BOOST_CHECK(map[key].empty());
}
void CheckConnectionConfig(const Configuration& cfg)
{
BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName);
- BOOST_CHECK_EQUAL(cfg.GetHost(), testServerHost);
- BOOST_CHECK_EQUAL(cfg.GetTcpPort(), testServerPort);
- BOOST_CHECK_EQUAL(cfg.GetAddress(), testAddress);
BOOST_CHECK_EQUAL(cfg.GetSchema(), testSchemaName);
- BOOST_CHECK_EQUAL(cfg.GetDsn(), std::string());
BOOST_CHECK_EQUAL(cfg.GetPageSize(), testPageSize);
BOOST_CHECK_EQUAL(cfg.IsDistributedJoins(), testDistributedJoins);
BOOST_CHECK_EQUAL(cfg.IsEnforceJoinOrder(), testEnforceJoinOrder);
@@ -135,9 +192,21 @@ void CheckConnectionConfig(const Configuration& cfg)
BOOST_CHECK_EQUAL(cfg.IsLazy(), testLazy);
BOOST_CHECK_EQUAL(cfg.IsSkipReducerOnUpdate(), testSkipReducerOnUpdate);
+ BOOST_CHECK(!cfg.IsDsnSet());
+ BOOST_CHECK(!cfg.IsHostSet());
+ BOOST_CHECK(!cfg.IsTcpPortSet());
+
+ BOOST_CHECK(cfg.IsAddressesSet());
+
+ const std::vector<EndPoint>& addrs = cfg.GetAddresses();
+
+ BOOST_REQUIRE(!addrs.empty());
+ BOOST_CHECK_EQUAL(addrs[0].host, testAddress.host);
+ BOOST_CHECK_EQUAL(addrs[0].port, testAddress.port);
+
std::stringstream constructor;
- constructor << "address=" << testAddress << ';'
+ constructor << "address=" << testAddressStr << ';'
<< "collocated=" << BoolToStr(testCollocated) << ';'
<< "distributed_joins=" << BoolToStr(testDistributedJoins) << ';'
<< "driver={" << testDriverName << "};"
@@ -158,7 +227,6 @@ void CheckDsnConfig(const Configuration& cfg)
BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName);
BOOST_CHECK_EQUAL(cfg.GetDsn(), testDsn);
BOOST_CHECK_EQUAL(cfg.GetSchema(), Configuration::DefaultValue::schema);
- BOOST_CHECK_EQUAL(cfg.GetAddress(), Configuration::DefaultValue::address);
BOOST_CHECK_EQUAL(cfg.GetHost(), std::string());
BOOST_CHECK_EQUAL(cfg.GetTcpPort(), Configuration::DefaultValue::port);
BOOST_CHECK_EQUAL(cfg.GetPageSize(), Configuration::DefaultValue::pageSize);
@@ -168,6 +236,7 @@ void CheckDsnConfig(const Configuration& cfg)
BOOST_CHECK_EQUAL(cfg.IsCollocated(), false);
BOOST_CHECK_EQUAL(cfg.IsLazy(), false);
BOOST_CHECK_EQUAL(cfg.IsSkipReducerOnUpdate(), false);
+ BOOST_CHECK(cfg.GetAddresses().empty());
}
BOOST_AUTO_TEST_SUITE(ConfigurationTestSuite)
@@ -175,7 +244,7 @@ BOOST_AUTO_TEST_SUITE(ConfigurationTestSuite)
BOOST_AUTO_TEST_CASE(CheckTestValuesNotEquealDefault)
{
BOOST_CHECK_NE(testDriverName, Configuration::DefaultValue::driver);
- BOOST_CHECK_NE(testAddress, Configuration::DefaultValue::address);
+ BOOST_CHECK_NE(testAddressStr, Configuration::DefaultValue::address);
BOOST_CHECK_NE(testServerPort, Configuration::DefaultValue::port);
BOOST_CHECK_NE(testSchemaName, Configuration::DefaultValue::schema);
BOOST_CHECK_NE(testDsn, Configuration::DefaultValue::dsn);
@@ -196,7 +265,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase)
constructor << "DRIVER={" << testDriverName << "};"
<< "LAZY=" << BoolToStr(testLazy, false) << ';'
- << "ADDRESS=" << testAddress << ';'
+ << "ADDRESS=" << testAddressStr << ';'
<< "DISTRIBUTED_JOINS=" << BoolToStr(testDistributedJoins, false) << ';'
<< "ENFORCE_JOIN_ORDER=" << BoolToStr(testEnforceJoinOrder, false) << ';'
<< "COLLOCATED=" << BoolToStr(testCollocated, false) << ';'
@@ -207,7 +276,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase)
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr);
+ ParseValidConnectString(connectStr, cfg);
CheckConnectionConfig(cfg);
}
@@ -220,7 +289,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase)
constructor << "driver={" << testDriverName << "};"
<< "lazy=" << BoolToStr(testLazy) << ';'
- << "address=" << testAddress << ';'
+ << "address=" << testAddressStr << ';'
<< "page_size=" << testPageSize << ';'
<< "distributed_joins=" << BoolToStr(testDistributedJoins) << ';'
<< "enforce_join_order=" << BoolToStr(testEnforceJoinOrder) << ';'
@@ -231,7 +300,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase)
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr);
+ ParseValidConnectString(connectStr, cfg);
CheckConnectionConfig(cfg);
}
@@ -243,7 +312,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated)
std::stringstream constructor;
constructor << "driver={" << testDriverName << "};"
- << "address=" << testAddress << ';'
+ << "address=" << testAddressStr << ';'
<< "lazy=" << BoolToStr(testLazy) << ';'
<< "page_size=" << testPageSize << ';'
<< "replicated_only=" << BoolToStr(testReplicatedOnly) << ';'
@@ -253,9 +322,11 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated)
<< "schema=" << testSchemaName << ';'
<< "skip_reducer_on_update=" << BoolToStr(testSkipReducerOnUpdate);
- const std::string& connectStr = constructor.str();
+ std::string connectStr = constructor.str();
+
+ connectStr.push_back(0);
- cfg.FillFromConnectString(connectStr.c_str(), connectStr.size() + 1);
+ ParseValidConnectString(connectStr, cfg);
CheckConnectionConfig(cfg);
}
@@ -268,7 +339,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed)
constructor << "Driver={" << testDriverName << "};"
<< "Lazy=" << BoolToStr(testLazy) << ';'
- << "Address=" << testAddress << ';'
+ << "Address=" << testAddressStr << ';'
<< "Page_Size=" << testPageSize << ';'
<< "Distributed_Joins=" << BoolToStr(testDistributedJoins, false) << ';'
<< "Enforce_Join_Order=" << BoolToStr(testEnforceJoinOrder) << ';'
@@ -279,7 +350,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed)
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr);
+ ParseValidConnectString(connectStr, cfg);
CheckConnectionConfig(cfg);
}
@@ -291,7 +362,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces)
std::stringstream constructor;
constructor << "DRIVER = {" << testDriverName << "} ;\n"
- << " ADDRESS =" << testAddress << "; "
+ << " ADDRESS =" << testAddressStr << "; "
<< " PAGE_SIZE= " << testPageSize << ';'
<< " DISTRIBUTED_JOINS=" << BoolToStr(testDistributedJoins, false) << ';'
<< "LAZY=" << BoolToStr(testLazy, false) << ';'
@@ -303,7 +374,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces)
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr);
+ ParseValidConnectString(connectStr, cfg);
CheckConnectionConfig(cfg);
}
@@ -312,22 +383,47 @@ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidAddress)
{
Configuration cfg;
- BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:0;"), ignite::IgniteError);
- BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:00000;"), ignite::IgniteError);
- BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:fdsf;"), ignite::IgniteError);
- BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:123:1;"), ignite::IgniteError);
- BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:12322221;"), ignite::IgniteError);
- BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:12322a;"), ignite::IgniteError);
- BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:;"), ignite::IgniteError);
+ ParseConnectStringWithError("Address=example.com:0;", cfg);
+ ParseConnectStringWithError("Address=example.com:00000;", cfg);
+ ParseConnectStringWithError("Address=example.com:fdsf;", cfg);
+ ParseConnectStringWithError("Address=example.com:123:1;", cfg);
+ ParseConnectStringWithError("Address=example.com:12322221;", cfg);
+ ParseConnectStringWithError("Address=example.com:12322a;", cfg);
+ ParseConnectStringWithError("Address=example.com:;", cfg);
}
BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress)
{
- CheckValidAddress("Address=example.com:1;", 1);
- CheckValidAddress("Address=example.com:31242;", 31242);
- CheckValidAddress("Address=example.com:55555;", 55555);
- CheckValidAddress("Address=example.com:110;", 110);
- CheckValidAddress("Address=example.com;", Configuration::DefaultValue::port);
+ CheckValidAddress("Address=example.com:1;", EndPoint("example.com", 1));
+ CheckValidAddress("Address=example.com:31242;", EndPoint("example.com", 31242));
+ CheckValidAddress("Address=example.com:55555;", EndPoint("example.com", 55555));
+ CheckValidAddress("Address=example.com:110;", EndPoint("example.com", 110));
+ CheckValidAddress("Address=example.com;", EndPoint("example.com", Configuration::DefaultValue::port));
+ CheckValidAddress("Address=example.com:1000..1010;", EndPoint("example.com", 1000, 10));
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress4)
+{
+ std::vector<EndPoint> addrs;
+
+ addrs.push_back(EndPoint("one.com", 1234));
+ addrs.push_back(EndPoint("two.net", 42, 53-42));
+ addrs.push_back(EndPoint("three.eu", Configuration::DefaultValue::port));
+ addrs.push_back(EndPoint("some.long.name.org", 50141));
+
+ CheckValidAddresses("Address=some.long.name.org:50141,three.eu,two.net:42..53,one.com:1234", addrs);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress4Spaces)
+{
+ std::vector<EndPoint> addrs;
+
+ addrs.push_back(EndPoint("one.com", 1234));
+ addrs.push_back(EndPoint("two.net", 42, 53 - 42));
+ addrs.push_back(EndPoint("three.eu", Configuration::DefaultValue::port));
+ addrs.push_back(EndPoint("some.long.name.org", 50141));
+
+ CheckValidAddresses("Address = some.long.name.org:50141, three.eu, two.net: 42 .. 53, one.com:1234", addrs);
}
BOOST_AUTO_TEST_CASE(TestConnectStringInvalidVersion)
@@ -340,22 +436,17 @@ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidVersion)
BOOST_AUTO_TEST_CASE(TestConnectStringUnsupportedVersion)
{
- CheckUnsupportedProtocolVersion("Protocol_Version=1.6.1;");
- CheckUnsupportedProtocolVersion("Protocol_Version=1.7.0;");
- CheckUnsupportedProtocolVersion("Protocol_Version=1.8.1;");
-}
-
-BOOST_AUTO_TEST_CASE(TestConnectStringValidVersion)
-{
- CheckValidProtocolVersion("Protocol_Version=2.1.0;", ignite::odbc::ProtocolVersion::VERSION_2_1_0);
- CheckValidProtocolVersion("Protocol_Version=1.6.1;", ignite::odbc::ProtocolVersion(1, 6, 1));
- CheckValidProtocolVersion("Protocol_Version=1.7.0;", ignite::odbc::ProtocolVersion(1, 7, 0));
- CheckValidProtocolVersion("Protocol_Version=1.8.1;", ignite::odbc::ProtocolVersion(1, 8, 1));
+ CheckInvalidProtocolVersion("Protocol_Version=1.6.1;");
+ CheckInvalidProtocolVersion("Protocol_Version=1.7.0;");
+ CheckInvalidProtocolVersion("Protocol_Version=1.8.1;");
}
BOOST_AUTO_TEST_CASE(TestConnectStringSupportedVersion)
{
CheckSupportedProtocolVersion("Protocol_Version=2.1.0;");
+ CheckSupportedProtocolVersion("Protocol_Version=2.1.5;");
+ CheckSupportedProtocolVersion("Protocol_Version=2.3.0;");
+ CheckSupportedProtocolVersion("Protocol_Version=2.3.2;");
}
BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys)
@@ -424,7 +515,7 @@ BOOST_AUTO_TEST_CASE(TestDsnStringUppercase)
const std::string& configStr = constructor.str();
- cfg.FillFromConfigAttributes(configStr.data());
+ ParseValidDsnString(configStr, cfg);
CheckDsnConfig(cfg);
}
@@ -440,7 +531,7 @@ BOOST_AUTO_TEST_CASE(TestDsnStringLowercase)
const std::string& configStr = constructor.str();
- cfg.FillFromConfigAttributes(configStr.data());
+ ParseValidDsnString(configStr, cfg);
CheckDsnConfig(cfg);
}
@@ -456,7 +547,7 @@ BOOST_AUTO_TEST_CASE(TestDsnStringMixed)
const std::string& configStr = constructor.str();
- cfg.FillFromConfigAttributes(configStr.data());
+ ParseValidDsnString(configStr, cfg);
CheckDsnConfig(cfg);
}
@@ -472,7 +563,7 @@ BOOST_AUTO_TEST_CASE(TestDsnStringWhitespaces)
const std::string& configStr = constructor.str();
- cfg.FillFromConfigAttributes(configStr.data());
+ ParseValidDsnString(configStr, cfg);
CheckDsnConfig(cfg);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
index fca3604..7e84aff 100644
--- a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
+++ b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
@@ -145,6 +145,31 @@ namespace ignite
return builder.str();
}
+ void OdbcTestSuite::CheckSQLDiagnosticError(int16_t handleType, SQLHANDLE handle, const std::string& expectSqlState)
+ {
+ SQLCHAR state[ODBC_BUFFER_SIZE];
+ SQLINTEGER nativeError = 0;
+ SQLCHAR message[ODBC_BUFFER_SIZE];
+ SQLSMALLINT messageLen = 0;
+
+ SQLRETURN ret = SQLGetDiagRec(handleType, handle, 1, state, &nativeError, message, sizeof(message), &messageLen);
+
+ const std::string sqlState = reinterpret_cast<char*>(state);
+ BOOST_REQUIRE_EQUAL(ret, SQL_SUCCESS);
+ BOOST_REQUIRE_EQUAL(sqlState, expectSqlState);
+ BOOST_REQUIRE(messageLen > 0);
+ }
+
+ void OdbcTestSuite::CheckSQLStatementDiagnosticError(const std::string& expectSqlState)
+ {
+ CheckSQLDiagnosticError(SQL_HANDLE_STMT, stmt, expectSqlState);
+ }
+
+ void OdbcTestSuite::CheckSQLConnectionDiagnosticError(const std::string& expectSqlState)
+ {
+ CheckSQLDiagnosticError(SQL_HANDLE_DBC, dbc, expectSqlState);
+ }
+
void OdbcTestSuite::InsertTestStrings(int recordsNum, bool merge)
{
SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)";
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/src/queries_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
index 45cf9dd..b47e9b7 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -239,46 +239,6 @@ struct QueriesTestSuiteFixture : odbc::OdbcTestSuite
BOOST_FIXTURE_TEST_SUITE(QueriesTestSuite, QueriesTestSuiteFixture)
-BOOST_AUTO_TEST_CASE(TestLegacyConnection)
-{
- Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;SCHEMA=cache");
-
- InsertTestStrings(10, false);
- InsertTestBatch(11, 20, 9);
-}
-
-BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_1_0)
-{
- Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.1.0");
-
- InsertTestStrings(10, false);
- InsertTestBatch(11, 20, 9);
-}
-
-BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_1_5)
-{
- Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.1.5");
-
- InsertTestStrings(10, false);
- InsertTestBatch(11, 20, 9);
-}
-
-BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_3_0)
-{
- Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.3.0");
-
- InsertTestStrings(10, false);
- InsertTestBatch(11, 20, 9);
-}
-
-BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_3_2)
-{
- Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.3.2");
-
- InsertTestStrings(10, false);
- InsertTestBatch(11, 20, 9);
-}
-
BOOST_AUTO_TEST_CASE(TestTwoRowsInt8)
{
CheckTwoRowsInt<signed char>(SQL_C_STINYINT);
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc-test/src/sql_get_info_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/sql_get_info_test.cpp b/modules/platforms/cpp/odbc-test/src/sql_get_info_test.cpp
index 10bcb0e..4d9c809 100644
--- a/modules/platforms/cpp/odbc-test/src/sql_get_info_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/sql_get_info_test.cpp
@@ -19,8 +19,7 @@
# include <windows.h>
#endif
-#include <sql.h>
-#include <sqlext.h>
+#include "ignite/odbc/system/odbc_constants.h"
#include <vector>
#include <string>
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/Makefile.am b/modules/platforms/cpp/odbc/Makefile.am
index ea74c34..90e4dc9 100644
--- a/modules/platforms/cpp/odbc/Makefile.am
+++ b/modules/platforms/cpp/odbc/Makefile.am
@@ -54,8 +54,10 @@ libignite_odbc_la_SOURCES = \
src/app/parameter.cpp \
src/app/parameter_set.cpp \
src/common_types.cpp \
+ src/config/config_tools.cpp \
src/config/configuration.cpp \
src/config/connection_info.cpp \
+ src/config/connection_string_parser.cpp \
src/connection.cpp \
src/cursor.cpp \
src/diagnostic/diagnosable_adapter.cpp \
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/config/config_tools.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/config/config_tools.h b/modules/platforms/cpp/odbc/include/ignite/odbc/config/config_tools.h
new file mode 100644
index 0000000..5731191
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/config_tools.h
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _IGNITE_ODBC_CONFIG_CONFIG_TOOLS
+#define _IGNITE_ODBC_CONFIG_CONFIG_TOOLS
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#include "ignite/odbc/end_point.h"
+
+namespace ignite
+{
+ namespace odbc
+ {
+ namespace diagnostic
+ {
+ // Forward declaration.
+ class DiagnosticRecordStorage;
+ }
+
+ namespace config
+ {
+ /**
+ * Convert address list to string.
+ *
+ * @param addresses Addresses.
+ * @return Resulting string.
+ */
+ std::string AddressesToString(const std::vector<EndPoint>& addresses);
+
+ /**
+ * Parse address.
+ *
+ * @param value String value to parse.
+ * @param endPoints End ponts list.
+ * @param diag Diagnostics collector.
+ */
+ void ParseAddress(const std::string& value, std::vector<EndPoint>& endPoints,
+ diagnostic::DiagnosticRecordStorage* diag);
+
+ /**
+ * Parse single address.
+ *
+ * @param value String value to parse.
+ * @param endPoint End pont.
+ * @param diag Diagnostics collector.
+ * @return @c true, if parsed successfully, and @c false otherwise.
+ */
+ bool ParseSingleAddress(const std::string& value, EndPoint& endPoint,
+ diagnostic::DiagnosticRecordStorage* diag);
+
+ /**
+ * Parse single network port.
+ *
+ * @param value String value to parse.
+ * @param port Port range begin.
+ * @param range Number of ports in range.
+ * @param diag Diagnostics collector.
+ * @return @c Port value on success and zero on failure.
+ */
+ bool ParsePortRange(const std::string& value, uint16_t& port, uint16_t& range,
+ diagnostic::DiagnosticRecordStorage* diag);
+
+ /**
+ * Parse single network port.
+ *
+ * @param value String value to parse.
+ * @param diag Diagnostics collector.
+ * @return @c Port value on success and zero on failure.
+ */
+ uint16_t ParsePort(const std::string& value, diagnostic::DiagnosticRecordStorage* diag);
+ }
+ }
+}
+
+#endif //_IGNITE_ODBC_CONFIG_CONFIG_TOOLS
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
index 89018f5..079008c 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
@@ -22,9 +22,10 @@
#include <string>
#include <map>
-#include <ignite/common/common.h>
-#include <ignite/common/utils.h>
#include "ignite/odbc/protocol_version.h"
+#include "ignite/odbc/config/settable_value.h"
+#include "ignite/odbc/ssl/ssl_mode.h"
+#include "ignite/odbc/end_point.h"
namespace ignite
{
@@ -38,67 +39,9 @@ namespace ignite
class Configuration
{
public:
- /** Map containing connect arguments. */
+ /** Argument map type. */
typedef std::map<std::string, std::string> ArgumentMap;
- /** Connection attribute keywords. */
- struct Key
- {
- /** Connection attribute keyword for DSN attribute. */
- static const std::string dsn;
-
- /** Connection attribute keyword for Driver attribute. */
- static const std::string driver;
-
- /** Connection attribute keyword for schema attribute. */
- static const std::string schema;
-
- /** Connection attribute keyword for address attribute. */
- static const std::string address;
-
- /** Connection attribute keyword for server attribute. */
- static const std::string server;
-
- /** Connection attribute keyword for port attribute. */
- static const std::string port;
-
- /** Connection attribute keyword for distributed joins attribute. */
- static const std::string distributedJoins;
-
- /** Connection attribute keyword for enforce join order attribute. */
- static const std::string enforceJoinOrder;
-
- /** Connection attribute keyword for protocol version attribute. */
- static const std::string protocolVersion;
-
- /** Connection attribute keyword for fetch results page size attribute. */
- static const std::string pageSize;
-
- /** Connection attribute keyword for replicated only attribute. */
- static const std::string replicatedOnly;
-
- /** Connection attribute keyword for collocated attribute. */
- static const std::string collocated;
-
- /** Connection attribute keyword for lazy attribute. */
- static const std::string lazy;
-
- /** Connection attribute keyword for skipReducerOnUpdate attribute. */
- static const std::string skipReducerOnUpdate;
-
- /** Connection attribute keyword for sslMode attribute. */
- static const std::string sslMode;
-
- /** Connection attribute keyword for sslKeyFile attribute. */
- static const std::string sslKeyFile;
-
- /** Connection attribute keyword for sslCertFile attribute. */
- static const std::string sslCertFile;
-
- /** Connection attribute keyword for sslCaFile attribute. */
- static const std::string sslCaFile;
- };
-
/** Default values for configuration. */
struct DefaultValue
{
@@ -118,7 +61,7 @@ namespace ignite
static const std::string server;
/** Default value for sslMode attribute. */
- static const std::string sslMode;
+ static const ssl::SslMode::Type sslMode;
/** Default value for sslKeyFile attribute. */
static const std::string sslKeyFile;
@@ -158,18 +101,6 @@ namespace ignite
};
/**
- * Connection end point structure.
- */
- struct EndPoint
- {
- /** Remote host. */
- std::string host;
-
- /** TCP port. */
- uint16_t port;
- };
-
- /**
* Default constructor.
*/
Configuration();
@@ -180,24 +111,6 @@ namespace ignite
~Configuration();
/**
- * Fill configuration data using connection string.
- *
- * @param str Pointer to string data.
- * @param len String length.
- */
- void FillFromConnectString(const char* str, size_t len);
-
- /**
- * Fill configuration data using connection string.
- *
- * @param str Connect string.
- */
- void FillFromConnectString(const std::string& str)
- {
- FillFromConnectString(str.data(), str.size());
- }
-
- /**
* Convert configure to connect string.
*
* @return Connect string.
@@ -205,22 +118,11 @@ namespace ignite
std::string ToConnectString() const;
/**
- * Fill configuration data using config attributes string.
- *
- * @param attributes Pointer to list of zero-terminated strings.
- * Terminated by two zero bytes.
- */
- void FillFromConfigAttributes(const char* attributes);
-
- /**
* Get server port.
*
* @return Server port.
*/
- uint16_t GetTcpPort() const
- {
- return endPoint.port;
- }
+ uint16_t GetTcpPort() const;
/**
* Set server port.
@@ -230,44 +132,53 @@ namespace ignite
void SetTcpPort(uint16_t port);
/**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsTcpPortSet() const;
+
+ /**
* Get DSN.
*
* @return Data Source Name.
*/
- const std::string& GetDsn(const std::string& dflt = DefaultValue::dsn) const
- {
- return GetStringValue(Key::dsn, dflt);
- }
+ const std::string& GetDsn(const std::string& dflt = DefaultValue::dsn) const;
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsDsnSet() const;
/**
* Set DSN.
*
* @param dsn Data Source Name.
*/
- void SetDsn(const std::string& dsn)
- {
- arguments[Key::dsn] = dsn;
- }
+ void SetDsn(const std::string& dsn);
/**
* Get Driver.
*
* @return Driver name.
*/
- const std::string& GetDriver() const
- {
- return GetStringValue(Key::driver, DefaultValue::driver);
- }
+ const std::string& GetDriver() const;
+
+ /**
+ * Set driver.
+ *
+ * @param driver Driver.
+ */
+ void SetDriver(const std::string& driver);
/**
* Get server host.
*
* @return Server host.
*/
- const std::string& GetHost() const
- {
- return endPoint.host;
- }
+ const std::string& GetHost() const;
/**
* Set server host.
@@ -277,241 +188,263 @@ namespace ignite
void SetHost(const std::string& server);
/**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsHostSet() const;
+
+ /**
* Get schema.
*
* @return Schema.
*/
- const std::string& GetSchema() const
- {
- return GetStringValue(Key::schema, DefaultValue::schema);
- }
+ const std::string& GetSchema() const;
/**
* Set schema.
*
* @param schema Schema name.
*/
- void SetSchema(const std::string& schema)
- {
- arguments[Key::schema] = schema;
- }
+ void SetSchema(const std::string& schema);
/**
- * Get address.
+ * Check if the value set.
*
- * @return Address.
+ * @return @true if the value set.
*/
- const std::string& GetAddress() const
- {
- return GetStringValue(Key::address, DefaultValue::address);
- }
+ bool IsSchemaSet() const;
+
+ /**
+ * Get addresses.
+ *
+ * @return Addresses.
+ */
+ const std::vector<EndPoint>& GetAddresses() const;
/**
- * Set address.
+ * Set addresses to connect to.
*
- * @param address Address.
+ * @param endPoints Addresses.
*/
- void SetAddress(const std::string& address);
+ void SetAddresses(const std::vector<EndPoint>& endPoints);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsAddressesSet() const;
/**
* Get SSL mode.
*
* @return SSL mode.
*/
- const std::string& GetSslMode() const
- {
- return GetStringValue(Key::sslMode, DefaultValue::sslMode);
- }
+ ssl::SslMode::Type GetSslMode() const;
/**
* Set SSL mode.
*
* @param sslMode SSL mode.
*/
- void SetSslMode(const std::string& sslMode)
- {
- arguments[Key::sslMode] = sslMode;
- }
+ void SetSslMode(ssl::SslMode::Type sslMode);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsSslModeSet() const;
/**
* Get SSL key file path.
*
* @return SSL key file path.
*/
- const std::string& GetSslKeyFile() const
- {
- return GetStringValue(Key::sslKeyFile, DefaultValue::sslKeyFile);
- }
+ const std::string& GetSslKeyFile() const;
/**
* Set SSL key file path.
*
* @param sslKeyFile SSL key file path.
*/
- void SetSslKeyFile(const std::string& sslKeyFile)
- {
- arguments[Key::sslKeyFile] = sslKeyFile;
- }
+ void SetSslKeyFile(const std::string& sslKeyFile);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsSslKeyFileSet() const;
/**
* Get SSL certificate file path.
*
* @return SSL certificate file path.
*/
- const std::string& GetSslCertFile() const
- {
- return GetStringValue(Key::sslCertFile, DefaultValue::sslCertFile);
- }
+ const std::string& GetSslCertFile() const;
/**
* Set SSL certificate file path.
*
* @param sslCertFile SSL certificate file path.
*/
- void SetSslCertFile(const std::string& sslCertFile)
- {
- arguments[Key::sslCertFile] = sslCertFile;
- }
+ void SetSslCertFile(const std::string& sslCertFile);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsSslCertFileSet() const;
/**
* Get SSL certificate authority file path.
*
* @return SSL certificate authority file path.
*/
- const std::string& GetSslCaFile() const
- {
- return GetStringValue(Key::sslCaFile, DefaultValue::sslCaFile);
- }
+ const std::string& GetSslCaFile() const;
/**
* Set SSL certificate authority file path.
*
* @param sslCaFile SSL certificate authority file path.
*/
- void SetSslCaFile(const std::string& sslCaFile)
- {
- arguments[Key::sslCaFile] = sslCaFile;
- }
+ void SetSslCaFile(const std::string& sslCaFile);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsSslCaFileSet() const;
/**
* Check distributed joins flag.
*
* @return True if distributed joins are enabled.
*/
- bool IsDistributedJoins() const
- {
- return GetBoolValue(Key::distributedJoins, DefaultValue::distributedJoins);
- }
+ bool IsDistributedJoins() const;
/**
* Set distributed joins.
*
* @param val Value to set.
*/
- void SetDistributedJoins(bool val)
- {
- SetBoolValue(Key::distributedJoins, val);
- }
+ void SetDistributedJoins(bool val);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsDistributedJoinsSet() const;
/**
* Check enforce join order flag.
*
* @return True if enforcing of join order is enabled.
*/
- bool IsEnforceJoinOrder() const
- {
- return GetBoolValue(Key::enforceJoinOrder, DefaultValue::enforceJoinOrder);
- }
+ bool IsEnforceJoinOrder() const;
/**
* Set enforce joins.
*
* @param val Value to set.
*/
- void SetEnforceJoinOrder(bool val)
- {
- SetBoolValue(Key::enforceJoinOrder, val);
- }
+ void SetEnforceJoinOrder(bool val);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsEnforceJoinOrderSet() const;
/**
* Check replicated only flag.
*
* @return True if replicated only is enabled.
*/
- bool IsReplicatedOnly() const
- {
- return GetBoolValue(Key::replicatedOnly, DefaultValue::replicatedOnly);
- }
+ bool IsReplicatedOnly() const;
/**
* Set replicated only flag.
*
* @param val Value to set.
*/
- void SetReplicatedOnly(bool val)
- {
- SetBoolValue(Key::replicatedOnly, val);
- }
+ void SetReplicatedOnly(bool val);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsReplicatedOnlySet() const;
/**
* Check collocated flag.
*
* @return True if collocated is enabled.
*/
- bool IsCollocated() const
- {
- return GetBoolValue(Key::collocated, DefaultValue::collocated);
- }
+ bool IsCollocated() const;
/**
* Set collocated.
*
* @param val Value to set.
*/
- void SetCollocated(bool val)
- {
- SetBoolValue(Key::collocated, val);
- }
+ void SetCollocated(bool val);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsCollocatedSet() const;
/**
* Check lazy flag.
*
* @return True if lazy is enabled.
*/
- bool IsLazy() const
- {
- return GetBoolValue(Key::lazy, DefaultValue::lazy);
- }
+ bool IsLazy() const;
/**
* Set lazy.
*
* @param val Value to set.
*/
- void SetLazy(bool val)
- {
- SetBoolValue(Key::lazy, val);
- }
+ void SetLazy(bool val);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsLazySet() const;
/**
* Check update on server flag.
*
* @return True if update on server.
*/
- bool IsSkipReducerOnUpdate() const
- {
- return GetBoolValue(Key::skipReducerOnUpdate, DefaultValue::skipReducerOnUpdate);
- }
+ bool IsSkipReducerOnUpdate() const;
/**
* Set update on server.
*
* @param val Value to set.
*/
- void SetSkipReducerOnUpdate(bool val)
- {
- SetBoolValue(Key::skipReducerOnUpdate, val);
- }
+ void SetSkipReducerOnUpdate(bool val);
+
+ /**
+ * Check if the value set.
+ *
+ * @return @true if the value set.
+ */
+ bool IsSkipReducerOnUpdateSet() const;
/**
* Get protocol version.
@@ -525,101 +458,137 @@ namespace ignite
*
* @param version Version to set.
*/
- void SetProtocolVersion(const std::string& version)
- {
- arguments[Key::protocolVersion] = version;
- }
+ void SetProtocolVersion(const ProtocolVersion& version);
/**
- * Get argument map.
+ * Check if the value set.
*
- * @return Argument map.
+ * @return @true if the value set.
*/
- const ArgumentMap& GetMap() const
- {
- return arguments;
- }
+ bool IsProtocolVersionSet() const;
/**
* Get fetch results page size.
*
* @return Fetch results page size.
*/
- int32_t GetPageSize() const
- {
- return static_cast<int32_t>(GetIntValue(Key::pageSize, DefaultValue::pageSize));
- }
+ int32_t GetPageSize() const;
+
/**
* Set fetch results page size.
*
* @param size Fetch results page size.
*/
- void SetPageSize(int32_t size)
- {
- arguments[Key::pageSize] = common::LexicalCast<std::string>(size);
- }
-
- /**
- * Get string value from the config.
- *
- * @param key Configuration key.
- * @param dflt Default value to be returned if there is no value stored.
- * @return Found or default value.
- */
- const std::string& GetStringValue(const std::string& key, const std::string& dflt) const;
+ void SetPageSize(int32_t size);
/**
- * Get int value from the config.
+ * Check if the value set.
*
- * @param key Configuration key.
- * @param dflt Default value to be returned if there is no value stored.
- * @return Found or default value.
+ * @return @true if the value set.
*/
- int64_t GetIntValue(const std::string& key, int64_t dflt) const;
+ bool IsPageSizeSet() const;
/**
- * Get bool value from the config.
+ * Get argument map.
*
- * @param key Configuration key.
- * @param dflt Default value to be returned if there is no value stored.
- * @return Found or default value.
+ * @param res Resulting argument map.
*/
- bool GetBoolValue(const std::string& key, bool dflt) const;
+ void ToMap(ArgumentMap& res) const;
- /**
- * Set bool value to the config.
- *
- * @param key Configuration key.
- * @param val Value to set.
- */
- void SetBoolValue(const std::string& key, bool val);
private:
/**
- * Parse connect string into key-value storage.
+ * Add key and value to the argument map.
*
- * @param str String to parse.
- * @param len String length.
- * @param args Parsing result.
+ * @param map Map.
+ * @param key Key.
+ * @param value Value.
*/
- static void ParseAttributeList(const char* str, size_t len, char delimeter, ArgumentMap& args);
+ template<typename T>
+ static void AddToMap(ArgumentMap& map, const std::string& key, const SettableValue<T>& value);
- /**
- * Parse address and extract connection end-point.
- *
- * @throw IgniteException if address can not be parsed.
- * @param address Address string to parse.
- * @param res Result is placed here.
- */
- static void ParseAddress(const std::string& address, EndPoint& res);
+ /** DSN. */
+ SettableValue<std::string> dsn;
+
+ /** Driver name. */
+ SettableValue<std::string> driver;
- /** Arguments. */
- ArgumentMap arguments;
+ /** Schema. */
+ SettableValue<std::string> schema;
- /** Connection end-point. */
- EndPoint endPoint;
+ /** Server. Deprecated. */
+ SettableValue<std::string> server;
+
+ /** TCP port. Deprecated. */
+ SettableValue<uint16_t> port;
+
+ /** Request and response page size. */
+ SettableValue<int32_t> pageSize;
+
+ /** Distributed joins flag. */
+ SettableValue<bool> distributedJoins;
+
+ /** Enforce join order flag. */
+ SettableValue<bool> enforceJoinOrder;
+
+ /** Replicated only flag. */
+ SettableValue<bool> replicatedOnly;
+
+ /** Collocated flag. */
+ SettableValue<bool> collocated;
+
+ /** Lazy flag. */
+ SettableValue<bool> lazy;
+
+ /** Skip reducer on update flag. */
+ SettableValue<bool> skipReducerOnUpdate;
+
+ /** Protocol version. */
+ SettableValue<ProtocolVersion> protocolVersion;
+
+ /** Connection end-points. */
+ SettableValue< std::vector<EndPoint> > endPoints;
+
+ /** SSL Mode. */
+ SettableValue<ssl::SslMode::Type> sslMode;
+
+ /** SSL private key file path. */
+ SettableValue<std::string> sslKeyFile;
+
+ /** SSL certificate file path. */
+ SettableValue<std::string> sslCertFile;
+
+ /** SSL certificate authority file path. */
+ SettableValue<std::string> sslCaFile;
};
- }
+ template<>
+ void Configuration::AddToMap<std::string>(ArgumentMap& map, const std::string& key,
+ const SettableValue<std::string>& value);
+
+ template<>
+ void Configuration::AddToMap<uint16_t>(ArgumentMap& map, const std::string& key,
+ const SettableValue<uint16_t>& value);
+
+ template<>
+ void Configuration::AddToMap<int32_t>(ArgumentMap& map, const std::string& key,
+ const SettableValue<int32_t>& value);
+
+ template<>
+ void Configuration::AddToMap<bool>(ArgumentMap& map, const std::string& key,
+ const SettableValue<bool>& value);
+
+ template<>
+ void Configuration::AddToMap<ProtocolVersion>(ArgumentMap& map, const std::string& key,
+ const SettableValue<ProtocolVersion>& value);
+
+ template<>
+ void Configuration::AddToMap< std::vector<EndPoint> >(ArgumentMap& map, const std::string& key,
+ const SettableValue< std::vector<EndPoint> >& value);
+
+ template<>
+ void Configuration::AddToMap<ssl::SslMode::Type>(ArgumentMap& map, const std::string& key,
+ const SettableValue<ssl::SslMode::Type>& value);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/config/connection_string_parser.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/config/connection_string_parser.h b/modules/platforms/cpp/odbc/include/ignite/odbc/config/connection_string_parser.h
new file mode 100644
index 0000000..ed31dcb
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/connection_string_parser.h
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _IGNITE_ODBC_CONFIG_CONNECTION_STRING_PARSER
+#define _IGNITE_ODBC_CONFIG_CONNECTION_STRING_PARSER
+
+#include <string>
+
+#include "ignite/odbc/config/configuration.h"
+#include "ignite/odbc/diagnostic/diagnostic_record_storage.h"
+
+namespace ignite
+{
+ namespace odbc
+ {
+ namespace config
+ {
+ /**
+ * ODBC configuration parser abstraction.
+ */
+ class ConnectionStringParser
+ {
+ public:
+ /** Connection attribute keywords. */
+ struct Key
+ {
+ /** Connection attribute keyword for DSN attribute. */
+ static const std::string dsn;
+
+ /** Connection attribute keyword for Driver attribute. */
+ static const std::string driver;
+
+ /** Connection attribute keyword for schema attribute. */
+ static const std::string schema;
+
+ /** Connection attribute keyword for address attribute. */
+ static const std::string address;
+
+ /** Connection attribute keyword for server attribute. */
+ static const std::string server;
+
+ /** Connection attribute keyword for port attribute. */
+ static const std::string port;
+
+ /** Connection attribute keyword for distributed joins attribute. */
+ static const std::string distributedJoins;
+
+ /** Connection attribute keyword for enforce join order attribute. */
+ static const std::string enforceJoinOrder;
+
+ /** Connection attribute keyword for protocol version attribute. */
+ static const std::string protocolVersion;
+
+ /** Connection attribute keyword for fetch results page size attribute. */
+ static const std::string pageSize;
+
+ /** Connection attribute keyword for replicated only attribute. */
+ static const std::string replicatedOnly;
+
+ /** Connection attribute keyword for collocated attribute. */
+ static const std::string collocated;
+
+ /** Connection attribute keyword for lazy attribute. */
+ static const std::string lazy;
+
+ /** Connection attribute keyword for skipReducerOnUpdate attribute. */
+ static const std::string skipReducerOnUpdate;
+
+ /** Connection attribute keyword for sslMode attribute. */
+ static const std::string sslMode;
+
+ /** Connection attribute keyword for sslKeyFile attribute. */
+ static const std::string sslKeyFile;
+
+ /** Connection attribute keyword for sslCertFile attribute. */
+ static const std::string sslCertFile;
+
+ /** Connection attribute keyword for sslCaFile attribute. */
+ static const std::string sslCaFile;
+ };
+
+ /**
+ * Constructor.
+ *
+ * @param cfg Configuration.
+ */
+ ConnectionStringParser(Configuration& cfg);
+
+ /**
+ * Destructor.
+ */
+ ~ConnectionStringParser();
+
+ /**
+ * Parse connect string.
+ *
+ * @param str String to parse.
+ * @param len String length.
+ * @param delimeter Delimeter.
+ * @param diag Diagnostics collector.
+ */
+ void ParseConnectionString(const char* str, size_t len, char delimeter,
+ diagnostic::DiagnosticRecordStorage* diag);
+
+ /**
+ * Parse connect string.
+ *
+ * @param str String to parse.
+ * @param diag Diagnostics collector.
+ */
+ void ParseConnectionString(const std::string& str, diagnostic::DiagnosticRecordStorage* diag);
+
+ /**
+ * Parse config attributes.
+ *
+ * @param str String to parse.
+ * @param diag Diagnostics collector.
+ */
+ void ParseConfigAttributes(const char* str, diagnostic::DiagnosticRecordStorage* diag);
+
+ private:
+ /**
+ * Result of parsing string value to bool.
+ */
+ struct BoolParseResult
+ {
+ enum Type
+ {
+ AI_FALSE,
+
+ AI_TRUE,
+
+ AI_UNRECOGNIZED
+ };
+ };
+
+ /**
+ * Handle new attribute pair callback.
+ *
+ * @param key Key.
+ * @param value Value.
+ * @param diag Diagnostics collector.
+ */
+ void HandleAttributePair(const std::string& key, const std::string& value,
+ diagnostic::DiagnosticRecordStorage* diag);
+
+ /**
+ * Convert string to boolean value.
+ *
+ * @param value Value to convert to bool.
+ * @return Result.
+ */
+ static BoolParseResult::Type StringToBool(const std::string& value);
+
+ /**
+ * Convert string to boolean value.
+ *
+ * @param msg Error message.
+ * @param key Key.
+ * @param value Value.
+ * @return Resulting error message.
+ */
+ static std::string MakeErrorMessage(const std::string& msg, const std::string& key,
+ const std::string& value);
+
+ /** Configuration. */
+ Configuration& cfg;
+ };
+ }
+
+ }
+}
+
+#endif //_IGNITE_ODBC_CONFIG_CONNECTION_STRING_PARSER
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/config/settable_value.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/config/settable_value.h b/modules/platforms/cpp/odbc/include/ignite/odbc/config/settable_value.h
new file mode 100644
index 0000000..78354d7
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/settable_value.h
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _IGNITE_ODBC_CONFIG_SETTABLE_VALUE
+#define _IGNITE_ODBC_CONFIG_SETTABLE_VALUE
+
+namespace ignite
+{
+ namespace odbc
+ {
+ namespace config
+ {
+ /**
+ * Simple abstraction for value, that have default value but can be
+ * set to a different value.
+ *
+ * @tparam T Type of the value.
+ */
+ template<typename T>
+ class SettableValue
+ {
+ public:
+ /** Type of the value. */
+ typedef T ValueType;
+
+ /**
+ * Constructor.
+ *
+ * @param defaultValue Default value to return when is not set.
+ */
+ SettableValue(const ValueType& defaultValue) :
+ val(defaultValue),
+ set(false)
+ {
+ // No-op.
+ }
+
+ /**
+ * Destructor.
+ */
+ ~SettableValue()
+ {
+ // No-op.
+ }
+
+ /**
+ * Set non-default value.
+ *
+ * @param value Value.
+ * @param dflt Set value as default or not.
+ */
+ void SetValue(const ValueType& value, bool dflt = false)
+ {
+ val = value;
+ set = !dflt;
+ }
+
+ /**
+ * Get value.
+ *
+ * @return Value or default value if not set.
+ */
+ const ValueType& GetValue() const
+ {
+ return val;
+ }
+
+ /**
+ * Check whether value is set to non-default.
+ */
+ bool IsSet() const
+ {
+ return set;
+ }
+
+ private:
+ /** Current value. */
+ ValueType val;
+
+ /** Flag showing whether value was set to non-default value. */
+ bool set;
+ };
+ }
+ }
+}
+
+#endif //_IGNITE_ODBC_CONFIG_SETTABLE_VALUE
\ No newline at end of file
[2/3] ignite git commit: IGNITE-7811: Implemented connection failover
for ODBC
Posted by is...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
index 025b855..0b1181d 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
@@ -165,6 +165,8 @@ namespace ignite
template<typename ReqT, typename RspT>
bool SyncMessage(const ReqT& req, RspT& rsp, int32_t timeout)
{
+ EnsureConnected();
+
std::vector<int8_t> tempBuffer;
parser.Encode(req, tempBuffer);
@@ -195,6 +197,8 @@ namespace ignite
template<typename ReqT, typename RspT>
void SyncMessage(const ReqT& req, RspT& rsp)
{
+ EnsureConnected();
+
std::vector<int8_t> tempBuffer;
parser.Encode(req, tempBuffer);
@@ -245,6 +249,39 @@ namespace ignite
IGNITE_NO_COPY_ASSIGNMENT(Connection);
/**
+ * Synchronously send request message and receive response.
+ * Uses provided timeout. Does not try to restore connection on
+ * fail.
+ *
+ * @param req Request message.
+ * @param rsp Response message.
+ * @param timeout Timeout.
+ * @return @c true on success, @c false on timeout.
+ * @throw OdbcError on error.
+ */
+ template<typename ReqT, typename RspT>
+ bool InternalSyncMessage(const ReqT& req, RspT& rsp, int32_t timeout)
+ {
+ std::vector<int8_t> tempBuffer;
+
+ parser.Encode(req, tempBuffer);
+
+ bool success = Send(tempBuffer.data(), tempBuffer.size(), timeout);
+
+ if (!success)
+ return false;
+
+ success = Receive(tempBuffer, timeout);
+
+ if (!success)
+ return false;
+
+ parser.Decode(rsp, tempBuffer);
+
+ return true;
+ }
+
+ /**
* Establish connection to ODBC server.
* Internal call.
*
@@ -260,7 +297,7 @@ namespace ignite
* @param cfg Configuration.
* @return Operation result.
*/
- SqlResult::Type InternalEstablish(const config::Configuration cfg);
+ SqlResult::Type InternalEstablish(const config::Configuration& cfg);
/**
* Release established connection.
@@ -363,6 +400,28 @@ namespace ignite
SqlResult::Type MakeRequestHandshake();
/**
+ * Ensure there is a connection to the cluster.
+ *
+ * @throw OdbcError on failure.
+ */
+ void EnsureConnected();
+
+ /**
+ * Try to restore connection to the cluster.
+ *
+ * @return @c true on success and @c false otherwise.
+ */
+ bool TryRestoreConnection();
+
+ /**
+ * Collect all addresses from config.
+ *
+ * @param cfg Configuration.
+ * @param endPoints End points.
+ */
+ static void CollectAddresses(const config::Configuration& cfg, std::vector<EndPoint>& endPoints);
+
+ /**
* Constructor.
*/
Connection();
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h
index 461bfc9..f1e9164 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h
@@ -45,6 +45,18 @@ namespace ignite
{
public:
/**
+ * Constructor.
+ *
+ * @param connection Pointer to connection. Used to create
+ * diagnostic records with connection info.
+ */
+ DiagnosableAdapter(const Connection* connection = 0) :
+ connection(connection)
+ {
+ // No-op.
+ }
+
+ /**
* Destructor.
*/
virtual ~DiagnosableAdapter()
@@ -99,20 +111,8 @@ namespace ignite
virtual void AddStatusRecord(const OdbcError& err);
protected:
- /**
- * Constructor.
- *
- * @param connection Pointer to connection. Used to create
- * diagnostic records with connection info.
- */
- DiagnosableAdapter(const Connection* connection = 0) :
- connection(connection)
- {
- // No-op.
- }
-
/** Diagnostic records. */
- diagnostic::DiagnosticRecordStorage diagnosticRecords;
+ DiagnosticRecordStorage diagnosticRecords;
private:
/** Connection. */
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnostic_record_storage.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnostic_record_storage.h b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnostic_record_storage.h
index 9a816da..c93eee7 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnostic_record_storage.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnostic_record_storage.h
@@ -62,11 +62,19 @@ namespace ignite
/**
* Set header record values.
*
- * @param retCode Operation return code.
+ * @param result Operation return code.
*/
void SetHeaderRecord(SqlResult::Type result);
/**
+ * Add new status record.
+ *
+ * @param sqlState SQL state.
+ * @param message Message.
+ */
+ void AddStatusRecord(SqlState::Type sqlState, const std::string& message);
+
+ /**
* Add status record to diagnostic records.
*
* @param record Status record.
@@ -169,7 +177,8 @@ namespace ignite
* @param buffer Buffer to put data to.
* @return Operation result.
*/
- SqlResult::Type GetField(int32_t recNum, DiagnosticField::Type field, app::ApplicationDataBuffer& buffer) const;
+ SqlResult::Type GetField(int32_t recNum, DiagnosticField::Type field,
+ app::ApplicationDataBuffer& buffer) const;
private:
IGNITE_NO_COPY_ASSIGNMENT(DiagnosticRecordStorage);
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/end_point.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/end_point.h b/modules/platforms/cpp/odbc/include/ignite/odbc/end_point.h
new file mode 100644
index 0000000..969b02f
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/end_point.h
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _IGNITE_ODBC_END_POINT
+#define _IGNITE_ODBC_END_POINT
+
+#include <stdint.h>
+#include <string>
+
+namespace ignite
+{
+ namespace odbc
+ {
+ /**
+ * Connection end point structure.
+ */
+ struct EndPoint
+ {
+ /**
+ * Default constructor.
+ */
+ EndPoint() :
+ host(),
+ port(),
+ range()
+ {
+ // No-op.
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param host Host.
+ * @param port Port.
+ * @param range Number of ports after the @c port that should be
+ * tried if the previous are unavailable.
+ */
+ EndPoint(const std::string& host, uint16_t port, uint16_t range = 0) :
+ host(host),
+ port(port),
+ range(range)
+ {
+ // No-op.
+ }
+
+ /** Remote host. */
+ std::string host;
+
+ /** TCP port. */
+ uint16_t port;
+
+ /** Number of ports after the port that should be tried if the previous are unavailable. */
+ uint16_t range;
+ };
+ }
+}
+
+#endif //_IGNITE_ODBC_END_POINT
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h
index 20472c3..0f2f2eb 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/ssl/ssl_mode.h
@@ -31,7 +31,7 @@ namespace ignite
/** SSL Mode enum. */
struct SslMode
{
- enum T
+ enum Type
{
DISABLE = 0,
@@ -42,11 +42,20 @@ namespace ignite
/**
* Convert mode from string.
+ *
* @param val String value.
* @param dflt Default value to return on error.
* @return Corresponding enum value.
*/
- static T FromString(const std::string& val, T dflt = UNKNOWN);
+ static Type FromString(const std::string& val, Type dflt = UNKNOWN);
+
+ /**
+ * Convert mode to string.
+ *
+ * @param val Value to convert.
+ * @return String value.
+ */
+ static std::string ToString(Type val);
};
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/include/ignite/odbc/utility.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/utility.h b/modules/platforms/cpp/odbc/include/ignite/odbc/utility.h
index 7ff5b23..d58479c 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/utility.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/utility.h
@@ -34,6 +34,7 @@
#include "ignite/impl/binary/binary_reader_impl.h"
#include "ignite/impl/binary/binary_writer_impl.h"
+#include <iterator>
namespace ignite
{
@@ -98,7 +99,7 @@ namespace ignite
res.reserve(skipped_trailing - skipped_leading);
- std::copy(skipped_leading, skipped_trailing, std::back_insert_iterator<std::string>(res));
+ std::copy(skipped_leading, skipped_trailing, std::back_inserter(res));
return res;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
index 0e742be..32bf61c 100644
--- a/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
+++ b/modules/platforms/cpp/odbc/os/win/src/system/ui/dsn_configuration_window.cpp
@@ -22,6 +22,8 @@
#include "ignite/odbc/ssl/ssl_mode.h"
#include "ignite/odbc/system/ui/dsn_configuration_window.h"
+#include "ignite/odbc/config/config_tools.h"
+#include "ignite/odbc/diagnostic/diagnosable_adapter.h"
namespace ignite
{
@@ -124,7 +126,9 @@ namespace ignite
rowPos += INTERVAL + ROW_HEIGHT;
- val = config.GetAddress().c_str();
+ std::string addr = config::AddressesToString(config.GetAddresses());
+
+ val = addr.c_str();
addressLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT,
"Address:", ChildId::ADDRESS_LABEL);
addressEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::ADDRESS_EDIT);
@@ -183,8 +187,10 @@ namespace ignite
int rowPos = posY + 2 * INTERVAL;
- const char* val = config.GetSslMode().c_str();
- SslMode::T sslMode = SslMode::FromString(val, SslMode::DISABLE);
+ SslMode::Type sslMode = config.GetSslMode();
+ std::string sslModeStr = SslMode::ToString(sslMode);
+
+ const char* val = sslModeStr.c_str();
sslModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Mode:", ChildId::SSL_MODE_LABEL);
sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, "", ChildId::SSL_MODE_COMBO_BOX);
@@ -385,7 +391,7 @@ namespace ignite
std::string sslModeStr;
sslModeComboBox->GetText(sslModeStr);
- SslMode::T sslMode = SslMode::FromString(sslModeStr, SslMode::DISABLE);
+ SslMode::Type sslMode = SslMode::FromString(sslModeStr, SslMode::DISABLE);
sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE);
sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE);
@@ -424,57 +430,76 @@ namespace ignite
void DsnConfigurationWindow::RetrieveConnectionParameters(config::Configuration& cfg) const
{
- std::string dsn;
- std::string address;
- std::string schema;
- std::string version;
-
- nameEdit->GetText(dsn);
- addressEdit->GetText(address);
- schemaEdit->GetText(schema);
- protocolVersionComboBox->GetText(version);
-
- common::StripSurroundingWhitespaces(address);
- common::StripSurroundingWhitespaces(dsn);
+ std::string dsnStr;
+ std::string addressStr;
+ std::string schemaStr;
+ std::string versionStr;
+
+ nameEdit->GetText(dsnStr);
+ addressEdit->GetText(addressStr);
+ schemaEdit->GetText(schemaStr);
+ protocolVersionComboBox->GetText(versionStr);
+
+ common::StripSurroundingWhitespaces(addressStr);
+ common::StripSurroundingWhitespaces(dsnStr);
// Stripping of whitespaces off the schema skipped intentionally
- LOG_MSG("Retriving arguments:");
- LOG_MSG("DSN: " << dsn);
- LOG_MSG("Address: " << address);
- LOG_MSG("Schema: " << schema);
- LOG_MSG("Protocol version: " << version);
+ LOG_MSG("Retrieving arguments:");
+ LOG_MSG("DSN: " << dsnStr);
+ LOG_MSG("Address: " << addressStr);
+ LOG_MSG("Schema: " << schemaStr);
+ LOG_MSG("Protocol version: " << versionStr);
- if (dsn.empty())
+ if (dsnStr.empty())
throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "DSN name can not be empty.");
- cfg.SetDsn(dsn);
- cfg.SetAddress(address);
- cfg.SetSchema(schema);
+ diagnostic::DiagnosticRecordStorage diag;
+
+ std::vector<EndPoint> addresses;
+
+ config::ParseAddress(addressStr, addresses, &diag);
+
+ if (diag.GetStatusRecordsNumber() > 0)
+ {
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
+ diag.GetStatusRecord(1).GetMessageText().c_str());
+ }
+
+ ProtocolVersion version = ProtocolVersion::FromString(versionStr);
+
+ if (!version.IsSupported())
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Protocol version is not supported.");
+
+ cfg.SetDsn(dsnStr);
+ cfg.SetAddresses(addresses);
+ cfg.SetSchema(schemaStr);
cfg.SetProtocolVersion(version);
}
void DsnConfigurationWindow::RetrieveSslParameters(config::Configuration& cfg) const
{
- std::string sslMode;
- std::string sslKey;
- std::string sslCert;
- std::string sslCa;
-
- sslModeComboBox->GetText(sslMode);
- sslKeyFileEdit->GetText(sslKey);
- sslCertFileEdit->GetText(sslCert);
- sslCaFileEdit->GetText(sslCa);
-
- LOG_MSG("Retriving arguments:");
- LOG_MSG("SSL Mode: " << sslMode);
- LOG_MSG("SSL Key: " << sslKey);
- LOG_MSG("SSL Certificate: " << sslCert);
- LOG_MSG("SSL CA: " << sslCa);
+ std::string sslModeStr;
+ std::string sslKeyStr;
+ std::string sslCertStr;
+ std::string sslCaStr;
+
+ sslModeComboBox->GetText(sslModeStr);
+ sslKeyFileEdit->GetText(sslKeyStr);
+ sslCertFileEdit->GetText(sslCertStr);
+ sslCaFileEdit->GetText(sslCaStr);
+
+ LOG_MSG("Retrieving arguments:");
+ LOG_MSG("SSL Mode: " << sslModeStr);
+ LOG_MSG("SSL Key: " << sslKeyStr);
+ LOG_MSG("SSL Certificate: " << sslCertStr);
+ LOG_MSG("SSL CA: " << sslCaStr);
+
+ ssl::SslMode::Type sslMode = ssl::SslMode::FromString(sslModeStr, ssl::SslMode::DISABLE);
cfg.SetSslMode(sslMode);
- cfg.SetSslKeyFile(sslKey);
- cfg.SetSslCertFile(sslCert);
- cfg.SetSslCaFile(sslCa);
+ cfg.SetSslKeyFile(sslKeyStr);
+ cfg.SetSslCertFile(sslCertStr);
+ cfg.SetSslCaFile(sslCaStr);
}
void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const
@@ -502,14 +527,14 @@ namespace ignite
lazy = lazyCheckBox->IsChecked();
skipReducerOnUpdate = skipReducerOnUpdateCheckBox->IsChecked();
- LOG_MSG("Retriving arguments:");
- LOG_MSG("Page size: " << pageSize);
- LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false"));
- LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false"));
- LOG_MSG("Replicated only: " << (replicatedOnly ? "true" : "false"));
- LOG_MSG("Collocated: " << (collocated ? "true" : "false"));
- LOG_MSG("Lazy: " << (lazy ? "true" : "false"));
- LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false"));
+ LOG_MSG("Retrieving arguments:");
+ LOG_MSG("Page size: " << pageSize);
+ LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false"));
+ LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false"));
+ LOG_MSG("Replicated only: " << (replicatedOnly ? "true" : "false"));
+ LOG_MSG("Collocated: " << (collocated ? "true" : "false"));
+ LOG_MSG("Lazy: " << (lazy ? "true" : "false"));
+ LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false"));
cfg.SetPageSize(pageSize);
cfg.SetDistributedJoins(distributedJoins);
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/os/win/src/system_dsn.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/os/win/src/system_dsn.cpp b/modules/platforms/cpp/odbc/os/win/src/system_dsn.cpp
index 3402aca..733d0cd 100644
--- a/modules/platforms/cpp/odbc/os/win/src/system_dsn.cpp
+++ b/modules/platforms/cpp/odbc/os/win/src/system_dsn.cpp
@@ -22,6 +22,9 @@
#include "ignite/odbc/dsn_config.h"
#include "ignite/odbc/system/ui/window.h"
#include "ignite/odbc/system/ui/dsn_configuration_window.h"
+#include "ignite/odbc/config/connection_string_parser.h"
+#include "ignite/odbc/diagnostic/diagnosable_adapter.h"
+#include "ignite/odbc/odbc_error.h"
using ignite::odbc::config::Configuration;
@@ -89,21 +92,18 @@ bool RegisterDsn(const Configuration& config, LPCSTR driver)
if (!SQLWriteDSNToIni(dsn, driver))
ignite::odbc::ThrowLastSetupError();
- const ArgMap& map = config.GetMap();
+ ArgMap map;
+
+ config.ToMap(map);
- std::set<std::string> ignore;
-
- ignore.insert(Configuration::Key::dsn);
- ignore.insert(Configuration::Key::driver);
+ map.erase(ConnectionStringParser::Key::dsn);
+ map.erase(ConnectionStringParser::Key::driver);
for (ArgMap::const_iterator it = map.begin(); it != map.end(); ++it)
{
const std::string& key = it->first;
const std::string& value = it->second;
- if (ignore.find(key) != ignore.end())
- continue;
-
ignite::odbc::WriteDsnString(dsn, key.c_str(), value.c_str());
}
@@ -154,14 +154,16 @@ BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR driver, LPCSTR attribut
LOG_MSG("Attributes: " << attributes);
- config.FillFromConfigAttributes(attributes);
+ config::ConnectionStringParser parser(config);
+
+ diagnostic::DiagnosticRecordStorage diag;
+
+ parser.ParseConfigAttributes(attributes, &diag);
if (!SQLValidDSN(config.GetDsn().c_str()))
return FALSE;
LOG_MSG("Driver: " << driver);
- LOG_MSG("Attributes: " << attributes);
-
LOG_MSG("DSN: " << config.GetDsn());
switch (req)
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj
index 239a30f..4f7c16e 100644
--- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj
+++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj
@@ -172,6 +172,8 @@
<ClCompile Include="..\..\src\column.cpp" />
<ClCompile Include="..\..\src\common_types.cpp" />
<ClCompile Include="..\..\src\config\configuration.cpp" />
+ <ClCompile Include="..\..\src\config\config_tools.cpp" />
+ <ClCompile Include="..\..\src\config\connection_string_parser.cpp" />
<ClCompile Include="..\..\src\config\connection_info.cpp" />
<ClCompile Include="..\..\src\connection.cpp" />
<ClCompile Include="..\..\src\cursor.cpp" />
@@ -215,7 +217,10 @@
<ClInclude Include="..\..\include\ignite\odbc\column.h" />
<ClInclude Include="..\..\include\ignite\odbc\common_types.h" />
<ClInclude Include="..\..\include\ignite\odbc\config\configuration.h" />
+ <ClInclude Include="..\..\include\ignite\odbc\config\connection_string_parser.h" />
<ClInclude Include="..\..\include\ignite\odbc\config\connection_info.h" />
+ <ClInclude Include="..\..\include\ignite\odbc\config\config_tools.h" />
+ <ClInclude Include="..\..\include\ignite\odbc\config\settable_value.h" />
<ClInclude Include="..\..\include\ignite\odbc\connection.h" />
<ClInclude Include="..\..\include\ignite\odbc\cursor.h" />
<ClInclude Include="..\..\include\ignite\odbc\diagnostic\diagnosable.h" />
@@ -223,6 +228,7 @@
<ClInclude Include="..\..\include\ignite\odbc\diagnostic\diagnostic_record.h" />
<ClInclude Include="..\..\include\ignite\odbc\diagnostic\diagnostic_record_storage.h" />
<ClInclude Include="..\..\include\ignite\odbc\dsn_config.h" />
+ <ClInclude Include="..\..\include\ignite\odbc\end_point.h" />
<ClInclude Include="..\..\include\ignite\odbc\environment.h" />
<ClInclude Include="..\..\include\ignite\odbc\message.h" />
<ClInclude Include="..\..\include\ignite\odbc\meta\column_meta.h" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters
index b203b21..b1956aa 100644
--- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters
+++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters
@@ -160,6 +160,12 @@
<ClCompile Include="..\..\src\ssl\ssl_gateway.cpp">
<Filter>Code\ssl</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\config\connection_string_parser.cpp">
+ <Filter>Code\config</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\config\config_tools.cpp">
+ <Filter>Code\config</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="module.def">
@@ -311,5 +317,17 @@
<ClInclude Include="..\..\include\ignite\odbc\ssl\ssl_bindings.h">
<Filter>Code\ssl</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\ignite\odbc\config\connection_string_parser.h">
+ <Filter>Code\config</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\ignite\odbc\config\settable_value.h">
+ <Filter>Code\config</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\ignite\odbc\config\config_tools.h">
+ <Filter>Code\config</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\ignite\odbc\end_point.h">
+ <Filter>Code</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/config/config_tools.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/config/config_tools.cpp b/modules/platforms/cpp/odbc/src/config/config_tools.cpp
new file mode 100644
index 0000000..f0d956f
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/config/config_tools.cpp
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cctype>
+#include <algorithm>
+
+#include "ignite/odbc/utility.h"
+#include "ignite/odbc/config/config_tools.h"
+#include "ignite/odbc/config/configuration.h"
+
+namespace ignite
+{
+ namespace odbc
+ {
+ namespace config
+ {
+ std::string AddressesToString(const std::vector<EndPoint>& addresses)
+ {
+ std::stringstream stream;
+
+ std::vector<EndPoint>::const_iterator it = addresses.begin();
+
+ if (it != addresses.end())
+ {
+ stream << it->host << ':' << it->port;
+ ++it;
+ }
+
+ for (; it != addresses.end(); ++it)
+ {
+ stream << ',' << it->host << ':' << it->port;
+ }
+
+ return stream.str();
+ }
+
+ void ParseAddress(const std::string& value, std::vector<EndPoint>& endPoints,
+ diagnostic::DiagnosticRecordStorage* diag)
+ {
+ size_t addrNum = std::count(value.begin(), value.end(), ',') + 1;
+
+ endPoints.reserve(endPoints.size() + addrNum);
+
+ std::string parsedAddr(value);
+
+ while (!parsedAddr.empty())
+ {
+ size_t addrBeginPos = parsedAddr.rfind(',');
+
+ if (addrBeginPos == std::string::npos)
+ addrBeginPos = 0;
+ else
+ ++addrBeginPos;
+
+ const char* addrBegin = parsedAddr.data() + addrBeginPos;
+ const char* addrEnd = parsedAddr.data() + parsedAddr.size();
+
+ std::string addr = utility::RemoveSurroundingSpaces(addrBegin, addrEnd);
+
+ if (!addr.empty())
+ {
+ EndPoint endPoint;
+
+ bool success = ParseSingleAddress(addr, endPoint, diag);
+
+ if (success)
+ endPoints.push_back(endPoint);
+ }
+
+ if (!addrBeginPos)
+ break;
+
+ parsedAddr.erase(addrBeginPos - 1);
+ }
+ }
+
+ bool ParseSingleAddress(const std::string& value, EndPoint& endPoint,
+ diagnostic::DiagnosticRecordStorage* diag)
+ {
+ int64_t colonNum = std::count(value.begin(), value.end(), ':');
+
+ if (colonNum == 0)
+ {
+ endPoint.host = value;
+ endPoint.port = Configuration::DefaultValue::port;
+
+ return true;
+ }
+
+ if (colonNum != 1)
+ {
+ std::stringstream stream;
+
+ stream << "Unexpected number of ':' characters in the following address: '"
+ << value << "'. Ignoring address.";
+
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+
+ return false;
+ }
+
+ size_t colonPos = value.find(':');
+
+ endPoint.host = value.substr(0, colonPos);
+
+ if (colonPos == value.size() - 1)
+ {
+ std::stringstream stream;
+
+ stream << "Port is missing in the following address: '" << value << "'. Ignoring address.";
+
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+
+ return false;
+ }
+
+ std::string portRange = value.substr(colonPos + 1);
+
+ if (!ParsePortRange(portRange, endPoint.port, endPoint.range, diag))
+ return false;
+
+ return true;
+ }
+
+ bool ParsePortRange(const std::string& value, uint16_t& port, uint16_t& range,
+ diagnostic::DiagnosticRecordStorage* diag)
+ {
+ size_t sepPos = value.find('.');
+
+ if (sepPos == value.npos)
+ {
+ range = 0;
+ port = ParsePort(value, diag);
+
+ if (!port)
+ return false;
+
+ return true;
+ }
+
+ if (sepPos + 2 > value.size() || value[sepPos + 1] != '.')
+ {
+ std::stringstream stream;
+
+ stream << "Unexpected number of '.' characters in the following address: '"
+ << value << "'. Ignoring address.";
+
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+
+ return false;
+ }
+
+ uint16_t rangeBegin = ParsePort(value.substr(0, sepPos), diag);
+
+ if (!rangeBegin)
+ return false;
+
+ uint16_t rangeEnd = ParsePort(value.substr(sepPos + 2), diag);
+
+ if (!rangeEnd)
+ return false;
+
+ if (rangeEnd < rangeBegin)
+ {
+ std::stringstream stream;
+
+ stream << "Port range end is less than port range begin in the following address: '"
+ << value << "'. Ignoring address.";
+
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+
+ return false;
+ }
+
+ port = rangeBegin;
+ range = rangeEnd - rangeBegin;
+
+ return true;
+ }
+
+ uint16_t ParsePort(const std::string& value, diagnostic::DiagnosticRecordStorage* diag)
+ {
+ std::string port = utility::RemoveSurroundingSpaces(value.begin(), value.end());
+
+ if (!common::AllOf(port.begin(), port.end(), &isdigit))
+ {
+ std::stringstream stream;
+
+ stream << "Unexpected port characters: '" << port << "'. Ignoring address.";
+
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+
+ return 0;
+ }
+
+ if (port.size() >= sizeof("65535"))
+ {
+ std::stringstream stream;
+
+ stream << "Port value is too large: '" << port << "'. Ignoring address.";
+
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+
+ return 0;
+ }
+
+ int32_t intPort = 0;
+ std::stringstream conv;
+
+ conv << port;
+ conv >> intPort;
+
+ if (intPort <= 0 || intPort > 0xFFFF)
+ {
+ std::stringstream stream;
+
+ stream << "Port value is out of range: '" << port << "'. Ignoring address.";
+
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+
+ return 0;
+ }
+
+ return static_cast<uint16_t>(intPort);
+ }
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/config/configuration.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/config/configuration.cpp b/modules/platforms/cpp/odbc/src/config/configuration.cpp
index 769e167..8f6bf18 100644
--- a/modules/platforms/cpp/odbc/src/config/configuration.cpp
+++ b/modules/platforms/cpp/odbc/src/config/configuration.cpp
@@ -17,14 +17,12 @@
#include <string>
#include <sstream>
-#include <algorithm>
#include <iterator>
-#include "ignite/common/common.h"
-#include "ignite/common/utils.h"
-
#include "ignite/odbc/utility.h"
#include "ignite/odbc/config/configuration.h"
+#include "ignite/odbc/config/connection_string_parser.h"
+#include "ignite/odbc/config/config_tools.h"
namespace ignite
{
@@ -32,51 +30,50 @@ namespace ignite
{
namespace config
{
- const std::string Configuration::Key::dsn = "dsn";
- const std::string Configuration::Key::driver = "driver";
- const std::string Configuration::Key::schema = "schema";
- const std::string Configuration::Key::address = "address";
- const std::string Configuration::Key::server = "server";
- const std::string Configuration::Key::port = "port";
- const std::string Configuration::Key::distributedJoins = "distributed_joins";
- const std::string Configuration::Key::enforceJoinOrder = "enforce_join_order";
- const std::string Configuration::Key::protocolVersion = "protocol_version";
- const std::string Configuration::Key::pageSize = "page_size";
- const std::string Configuration::Key::replicatedOnly = "replicated_only";
- const std::string Configuration::Key::collocated = "collocated";
- const std::string Configuration::Key::lazy = "lazy";
- const std::string Configuration::Key::skipReducerOnUpdate = "skip_reducer_on_update";
- const std::string Configuration::Key::sslMode = "ssl_mode";
- const std::string Configuration::Key::sslKeyFile = "ssl_key_file";
- const std::string Configuration::Key::sslCertFile = "ssl_cert_file";
- const std::string Configuration::Key::sslCaFile = "ssl_ca_file";
-
- const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN";
- const std::string Configuration::DefaultValue::driver = "Apache Ignite";
- const std::string Configuration::DefaultValue::schema = "PUBLIC";
- const std::string Configuration::DefaultValue::address = "";
- const std::string Configuration::DefaultValue::server = "";
- const std::string Configuration::DefaultValue::sslMode = "disable";
- const std::string Configuration::DefaultValue::sslKeyFile = "";
- const std::string Configuration::DefaultValue::sslCertFile = "";
- const std::string Configuration::DefaultValue::sslCaFile = "";
-
- const uint16_t Configuration::DefaultValue::port = 10800;
+ const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN";
+ const std::string Configuration::DefaultValue::driver = "Apache Ignite";
+ const std::string Configuration::DefaultValue::schema = "PUBLIC";
+ const std::string Configuration::DefaultValue::address = "";
+ const std::string Configuration::DefaultValue::server = "";
+
+ const uint16_t Configuration::DefaultValue::port = 10800;
const int32_t Configuration::DefaultValue::pageSize = 1024;
- const bool Configuration::DefaultValue::distributedJoins = false;
- const bool Configuration::DefaultValue::enforceJoinOrder = false;
- const bool Configuration::DefaultValue::replicatedOnly = false;
- const bool Configuration::DefaultValue::collocated = false;
- const bool Configuration::DefaultValue::lazy = false;
- const bool Configuration::DefaultValue::skipReducerOnUpdate = false;
+ const bool Configuration::DefaultValue::distributedJoins = false;
+ const bool Configuration::DefaultValue::enforceJoinOrder = false;
+ const bool Configuration::DefaultValue::replicatedOnly = false;
+ const bool Configuration::DefaultValue::collocated = false;
+ const bool Configuration::DefaultValue::lazy = false;
+ const bool Configuration::DefaultValue::skipReducerOnUpdate = false;
const ProtocolVersion& Configuration::DefaultValue::protocolVersion = ProtocolVersion::GetCurrent();
+ const ssl::SslMode::Type Configuration::DefaultValue::sslMode = ssl::SslMode::DISABLE;
+ const std::string Configuration::DefaultValue::sslKeyFile = "";
+ const std::string Configuration::DefaultValue::sslCertFile = "";
+ const std::string Configuration::DefaultValue::sslCaFile = "";
+
Configuration::Configuration() :
- arguments()
+ dsn(DefaultValue::dsn),
+ driver(DefaultValue::driver),
+ schema(DefaultValue::schema),
+ server(DefaultValue::server),
+ port(DefaultValue::port),
+ pageSize(DefaultValue::pageSize),
+ distributedJoins(DefaultValue::distributedJoins),
+ enforceJoinOrder(DefaultValue::enforceJoinOrder),
+ replicatedOnly(DefaultValue::replicatedOnly),
+ collocated(DefaultValue::collocated),
+ lazy(DefaultValue::lazy),
+ skipReducerOnUpdate(DefaultValue::skipReducerOnUpdate),
+ protocolVersion(DefaultValue::protocolVersion),
+ endPoints(std::vector<EndPoint>()),
+ sslMode(DefaultValue::sslMode),
+ sslKeyFile(DefaultValue::sslKeyFile),
+ sslCertFile(DefaultValue::sslCertFile),
+ sslCaFile(DefaultValue::sslCaFile)
{
- ParseAddress(DefaultValue::address, endPoint);
+ // No-op.
}
Configuration::~Configuration()
@@ -84,37 +81,12 @@ namespace ignite
// No-op.
}
- void Configuration::FillFromConnectString(const char* str, size_t len)
+ std::string Configuration::ToConnectString() const
{
- // Initializing map.
- arguments.clear();
+ ArgumentMap arguments;
- // Initializing DSN to empty string.
- arguments[Key::dsn].clear();
-
- // Ignoring terminating zero byte if present.
- // Some Driver Managers pass zero-terminated connection string
- // while others don't.
- if (len && !str[len - 1])
- --len;
-
- ParseAttributeList(str, len, ';', arguments);
-
- ArgumentMap::const_iterator it = arguments.find(Key::address);
- if (it != arguments.end())
- {
- // Parsing address.
- ParseAddress(it->second, endPoint);
- }
- else
- {
- endPoint.host = GetStringValue(Key::server, DefaultValue::server);
- endPoint.port = static_cast<uint16_t>(GetIntValue(Key::port, DefaultValue::port));
- }
- }
+ ToMap(arguments);
- std::string Configuration::ToConnectString() const
- {
std::stringstream connect_string_buffer;
for (ArgumentMap::const_iterator it = arguments.begin(); it != arguments.end(); ++it)
@@ -134,209 +106,348 @@ namespace ignite
return connect_string_buffer.str();
}
- void Configuration::FillFromConfigAttributes(const char* attributes)
+ uint16_t Configuration::GetTcpPort() const
+ {
+ return port.GetValue();
+ }
+
+ void Configuration::SetTcpPort(uint16_t port)
{
- // Initializing map.
- arguments.clear();
+ this->port.SetValue(port);
+ }
- size_t len = 0;
+ bool Configuration::IsTcpPortSet() const
+ {
+ return port.IsSet();
+ }
- // Getting list length. List is terminated by two '\0'.
- while (attributes[len] || attributes[len + 1])
- ++len;
+ const std::string& Configuration::GetDsn(const std::string& dflt) const
+ {
+ if (!dsn.IsSet())
+ return dflt;
- ++len;
+ return dsn.GetValue();
+ }
- ParseAttributeList(attributes, len, '\0', arguments);
+ bool Configuration::IsDsnSet() const
+ {
+ return dsn.IsSet();
+ }
- ArgumentMap::const_iterator it = arguments.find(Key::address);
- if (it != arguments.end())
- {
- // Parsing address.
- ParseAddress(it->second, endPoint);
- }
- else
- {
- endPoint.host = GetStringValue(Key::server, DefaultValue::server);
- endPoint.port = static_cast<uint16_t>(GetIntValue(Key::port, DefaultValue::port));
- }
+ void Configuration::SetDsn(const std::string& dsn)
+ {
+ this->dsn.SetValue(dsn);
}
- void Configuration::SetTcpPort(uint16_t port)
+ const std::string& Configuration::GetDriver() const
{
- arguments[Key::port] = common::LexicalCast<std::string>(port);
+ return driver.GetValue();
+ }
- ArgumentMap::const_iterator it = arguments.find(Key::address);
+ void Configuration::SetDriver(const std::string& driver)
+ {
+ this->driver.SetValue(driver);
+ }
- if (it == arguments.end())
- endPoint.port = port;
+ const std::string& Configuration::GetHost() const
+ {
+ return server.GetValue();
}
void Configuration::SetHost(const std::string& server)
{
- arguments[Key::server] = server;
+ this->server.SetValue(server);
+ }
- ArgumentMap::const_iterator it = arguments.find(Key::address);
+ bool Configuration::IsHostSet() const
+ {
+ return server.IsSet();
+ }
- if (it == arguments.end())
- endPoint.host = server;
+ const std::string& Configuration::GetSchema() const
+ {
+ return schema.GetValue();
}
- void Configuration::SetAddress(const std::string& address)
+ void Configuration::SetSchema(const std::string& schema)
{
- arguments[Key::address] = address;
+ this->schema.SetValue(schema);
+ }
- ParseAddress(address, endPoint);
+ bool Configuration::IsSchemaSet() const
+ {
+ return schema.IsSet();
}
- ProtocolVersion Configuration::GetProtocolVersion() const
+ const std::vector<EndPoint>& Configuration::GetAddresses() const
{
- ArgumentMap::const_iterator it = arguments.find(Key::protocolVersion);
+ return endPoints.GetValue();
+ }
- if (it != arguments.end())
- return ProtocolVersion::FromString(it->second);
+ void Configuration::SetAddresses(const std::vector<EndPoint>& endPoints)
+ {
+ this->endPoints.SetValue(endPoints);
+ }
- return DefaultValue::protocolVersion;
+ bool Configuration::IsAddressesSet() const
+ {
+ return endPoints.IsSet();
}
- const std::string& Configuration::GetStringValue(const std::string& key, const std::string& dflt) const
+ ssl::SslMode::Type Configuration::GetSslMode() const
{
- ArgumentMap::const_iterator it = arguments.find(common::ToLower(key));
+ return sslMode.GetValue();
+ }
- if (it != arguments.end())
- return it->second;
+ void Configuration::SetSslMode(ssl::SslMode::Type sslMode)
+ {
+ this->sslMode.SetValue(sslMode);
+ }
- return dflt;
+ bool Configuration::IsSslModeSet() const
+ {
+ return sslMode.IsSet();
}
- int64_t Configuration::GetIntValue(const std::string& key, int64_t dflt) const
+ const std::string& Configuration::GetSslKeyFile() const
{
- ArgumentMap::const_iterator it = arguments.find(common::ToLower(key));
+ return sslKeyFile.GetValue();
+ }
- if (it != arguments.end())
- {
- const std::string& val = it->second;
+ void Configuration::SetSslKeyFile(const std::string& sslKeyFile)
+ {
+ this->sslKeyFile.SetValue(sslKeyFile);
+ }
- if (!common::AllOf(val.begin(), val.end(), isdigit))
- IGNITE_ERROR_FORMATTED_1(IgniteError::IGNITE_ERR_GENERIC,
- "Invalid argument value: Integer value is expected.", "key", key);
+ bool Configuration::IsSslKeyFileSet() const
+ {
+ return sslKeyFile.IsSet();
+ }
- return common::LexicalCast<int64_t>(val);
- }
+ const std::string& Configuration::GetSslCertFile() const
+ {
+ return sslCertFile.GetValue();
+ }
- return dflt;
+ void Configuration::SetSslCertFile(const std::string& sslCertFile)
+ {
+ this->sslCertFile.SetValue(sslCertFile);
}
- bool Configuration::GetBoolValue(const std::string& key, bool dflt) const
+ bool Configuration::IsSslCertFileSet() const
{
- ArgumentMap::const_iterator it = arguments.find(common::ToLower(key));
+ return sslCertFile.IsSet();
+ }
- if (it != arguments.end())
- {
- std::string lowercaseVal = common::ToLower(it->second);
+ const std::string& Configuration::GetSslCaFile() const
+ {
+ return sslCaFile.GetValue();
+ }
+
+ void Configuration::SetSslCaFile(const std::string& sslCaFile)
+ {
+ this->sslCaFile.SetValue(sslCaFile);
+ }
- if (lowercaseVal != "true" && lowercaseVal != "false")
- IGNITE_ERROR_FORMATTED_1(IgniteError::IGNITE_ERR_GENERIC,
- "Invalid argument value: Boolean value is expected (true or false).", "key", key);
+ bool Configuration::IsSslCaFileSet() const
+ {
+ return sslCaFile.IsSet();
+ }
- return lowercaseVal == "true";
- }
+ bool Configuration::IsDistributedJoins() const
+ {
+ return distributedJoins.GetValue();
+ }
- return dflt;
+ void Configuration::SetDistributedJoins(bool val)
+ {
+ this->distributedJoins.SetValue(val);
}
- void Configuration::SetBoolValue(const std::string& key, bool val)
+ bool Configuration::IsDistributedJoinsSet() const
{
- arguments[key] = val ? "true" : "false";
+ return distributedJoins.IsSet();
}
- void Configuration::ParseAttributeList(const char * str, size_t len, char delimeter, ArgumentMap & args)
+ bool Configuration::IsEnforceJoinOrder() const
{
- std::string connect_str(str, len);
+ return enforceJoinOrder.GetValue();
+ }
- while (!connect_str.empty())
- {
- size_t attr_begin = connect_str.rfind(delimeter);
+ void Configuration::SetEnforceJoinOrder(bool val)
+ {
+ this->enforceJoinOrder.SetValue(val);
+ }
- if (attr_begin == std::string::npos)
- attr_begin = 0;
- else
- ++attr_begin;
+ bool Configuration::IsEnforceJoinOrderSet() const
+ {
+ return enforceJoinOrder.IsSet();
+ }
- size_t attr_eq_pos = connect_str.rfind('=');
+ bool Configuration::IsReplicatedOnly() const
+ {
+ return replicatedOnly.GetValue();
+ }
- if (attr_eq_pos == std::string::npos)
- attr_eq_pos = 0;
+ void Configuration::SetReplicatedOnly(bool val)
+ {
+ this->replicatedOnly.SetValue(val);
+ }
- if (attr_begin < attr_eq_pos)
- {
- const char* key_begin = connect_str.data() + attr_begin;
- const char* key_end = connect_str.data() + attr_eq_pos;
+ bool Configuration::IsReplicatedOnlySet() const
+ {
+ return replicatedOnly.IsSet();
+ }
- const char* value_begin = connect_str.data() + attr_eq_pos + 1;
- const char* value_end = connect_str.data() + connect_str.size();
+ bool Configuration::IsCollocated() const
+ {
+ return collocated.GetValue();
+ }
- std::string key = utility::RemoveSurroundingSpaces(key_begin, key_end);
- std::string value = utility::RemoveSurroundingSpaces(value_begin, value_end);
+ void Configuration::SetCollocated(bool val)
+ {
+ this->collocated.SetValue(val);
+ }
- utility::IntoLower(key);
+ bool Configuration::IsCollocatedSet() const
+ {
+ return collocated.IsSet();
+ }
- if (value[0] == '{' && value[value.size() - 1] == '}')
- value = value.substr(1, value.size() - 2);
+ bool Configuration::IsLazy() const
+ {
+ return lazy.GetValue();
+ }
- args[key] = value;
- }
+ void Configuration::SetLazy(bool val)
+ {
+ this->lazy.SetValue(val);
+ }
- if (!attr_begin)
- break;
+ bool Configuration::IsLazySet() const
+ {
+ return lazy.IsSet();
+ }
- connect_str.erase(attr_begin - 1);
- }
+ bool Configuration::IsSkipReducerOnUpdate() const
+ {
+ return skipReducerOnUpdate.GetValue();
}
- void Configuration::ParseAddress(const std::string& address, EndPoint& res)
+ void Configuration::SetSkipReducerOnUpdate(bool val)
{
- int64_t colonNum = std::count(address.begin(), address.end(), ':');
+ this->skipReducerOnUpdate.SetValue(val);
+ }
- if (colonNum == 0)
- {
- res.host = address;
- res.port = DefaultValue::port;
- }
- else if (colonNum == 1)
- {
- size_t pos = address.find(':');
+ bool Configuration::IsSkipReducerOnUpdateSet() const
+ {
+ return skipReducerOnUpdate.IsSet();
+ }
- if (pos == address.size() - 1)
- throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
- "Invalid address format: no port after colon");
+ ProtocolVersion Configuration::GetProtocolVersion() const
+ {
+ return protocolVersion.GetValue();
+ }
- res.host = address.substr(0, pos);
+ void Configuration::SetProtocolVersion(const ProtocolVersion& version)
+ {
+ this->protocolVersion.SetValue(version);
+ }
- std::string port = address.substr(pos + 1);
+ bool Configuration::IsProtocolVersionSet() const
+ {
+ return protocolVersion.IsSet();
+ }
- if (!common::AllOf(port.begin(), port.end(), isdigit))
- throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
- "Invalid address format: port can only contain digits");
+ void Configuration::SetPageSize(int32_t size)
+ {
+ this->pageSize.SetValue(size);
+ }
- int32_t intPort = common::LexicalCast<int32_t>(port);
+ bool Configuration::IsPageSizeSet() const
+ {
+ return pageSize.IsSet();
+ }
- if (port.size() > sizeof("65535") - 1 || intPort > UINT16_MAX)
- {
- throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
- "Invalid address format: Port value is too large,"
- " valid value should be in range from 1 to 65535");
- }
+ int32_t Configuration::GetPageSize() const
+ {
+ return pageSize.GetValue();
+ }
- if (intPort == 0)
- throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
- "Invalid address format: Port value can not be zero");
+ void Configuration::ToMap(ArgumentMap& res) const
+ {
+ AddToMap(res, ConnectionStringParser::Key::dsn, dsn);
+ AddToMap(res, ConnectionStringParser::Key::driver, driver);
+ AddToMap(res, ConnectionStringParser::Key::schema, schema);
+ AddToMap(res, ConnectionStringParser::Key::address, endPoints);
+ AddToMap(res, ConnectionStringParser::Key::server, server);
+ AddToMap(res, ConnectionStringParser::Key::port, port);
+ AddToMap(res, ConnectionStringParser::Key::distributedJoins, distributedJoins);
+ AddToMap(res, ConnectionStringParser::Key::enforceJoinOrder, enforceJoinOrder);
+ AddToMap(res, ConnectionStringParser::Key::protocolVersion, protocolVersion);
+ AddToMap(res, ConnectionStringParser::Key::pageSize, pageSize);
+ AddToMap(res, ConnectionStringParser::Key::replicatedOnly, replicatedOnly);
+ AddToMap(res, ConnectionStringParser::Key::collocated, collocated);
+ AddToMap(res, ConnectionStringParser::Key::lazy, lazy);
+ AddToMap(res, ConnectionStringParser::Key::skipReducerOnUpdate, skipReducerOnUpdate);
+ AddToMap(res, ConnectionStringParser::Key::sslMode, sslMode);
+ AddToMap(res, ConnectionStringParser::Key::sslKeyFile, sslKeyFile);
+ AddToMap(res, ConnectionStringParser::Key::sslCertFile, sslCertFile);
+ AddToMap(res, ConnectionStringParser::Key::sslCaFile, sslCaFile);
+ }
- res.port = static_cast<uint16_t>(intPort);
- }
- else
- throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
- "Invalid address format: too many colons");
+ template<>
+ void Configuration::AddToMap(ArgumentMap& map, const std::string& key, const SettableValue<uint16_t>& value)
+ {
+ if (value.IsSet())
+ map[key] = common::LexicalCast<std::string>(value.GetValue());
+ }
+
+ template<>
+ void Configuration::AddToMap(ArgumentMap& map, const std::string& key, const SettableValue<int32_t>& value)
+ {
+ if (value.IsSet())
+ map[key] = common::LexicalCast<std::string>(value.GetValue());
+ }
+
+ template<>
+ void Configuration::AddToMap(ArgumentMap& map, const std::string& key,
+ const SettableValue<std::string>& value)
+ {
+ if (value.IsSet())
+ map[key] = value.GetValue();
+ }
+
+ template<>
+ void Configuration::AddToMap(ArgumentMap& map, const std::string& key,
+ const SettableValue<bool>& value)
+ {
+ if (value.IsSet())
+ map[key] = value.GetValue() ? "true" : "false";
+ }
+
+ template<>
+ void Configuration::AddToMap(ArgumentMap& map, const std::string& key,
+ const SettableValue<ProtocolVersion>& value)
+ {
+ if (value.IsSet())
+ map[key] = value.GetValue().ToString();
+ }
+
+ template<>
+ void Configuration::AddToMap(ArgumentMap& map, const std::string& key,
+ const SettableValue< std::vector<EndPoint> >& value)
+ {
+ if (value.IsSet())
+ map[key] = AddressesToString(value.GetValue());
+ }
+
+ template<>
+ void Configuration::AddToMap(ArgumentMap& map, const std::string& key,
+ const SettableValue<ssl::SslMode::Type>& value)
+ {
+ if (value.IsSet())
+ map[key] = ssl::SslMode::ToString(value.GetValue());
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/6ddc6d70/modules/platforms/cpp/odbc/src/config/connection_string_parser.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/config/connection_string_parser.cpp b/modules/platforms/cpp/odbc/src/config/connection_string_parser.cpp
new file mode 100644
index 0000000..cda23c8
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/config/connection_string_parser.cpp
@@ -0,0 +1,452 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include "ignite/common/utils.h"
+
+#include "ignite/odbc/utility.h"
+#include "ignite/odbc/odbc_error.h"
+#include "ignite/odbc/ssl/ssl_mode.h"
+#include "ignite/odbc/config/connection_string_parser.h"
+#include "ignite/odbc/config/config_tools.h"
+
+namespace ignite
+{
+ namespace odbc
+ {
+ namespace config
+ {
+ const std::string ConnectionStringParser::Key::dsn = "dsn";
+ const std::string ConnectionStringParser::Key::driver = "driver";
+ const std::string ConnectionStringParser::Key::schema = "schema";
+ const std::string ConnectionStringParser::Key::address = "address";
+ const std::string ConnectionStringParser::Key::server = "server";
+ const std::string ConnectionStringParser::Key::port = "port";
+ const std::string ConnectionStringParser::Key::distributedJoins = "distributed_joins";
+ const std::string ConnectionStringParser::Key::enforceJoinOrder = "enforce_join_order";
+ const std::string ConnectionStringParser::Key::protocolVersion = "protocol_version";
+ const std::string ConnectionStringParser::Key::pageSize = "page_size";
+ const std::string ConnectionStringParser::Key::replicatedOnly = "replicated_only";
+ const std::string ConnectionStringParser::Key::collocated = "collocated";
+ const std::string ConnectionStringParser::Key::lazy = "lazy";
+ const std::string ConnectionStringParser::Key::skipReducerOnUpdate = "skip_reducer_on_update";
+ const std::string ConnectionStringParser::Key::sslMode = "ssl_mode";
+ const std::string ConnectionStringParser::Key::sslKeyFile = "ssl_key_file";
+ const std::string ConnectionStringParser::Key::sslCertFile = "ssl_cert_file";
+ const std::string ConnectionStringParser::Key::sslCaFile = "ssl_ca_file";
+
+ ConnectionStringParser::ConnectionStringParser(Configuration& cfg):
+ cfg(cfg)
+ {
+ // No-op.
+ }
+
+ ConnectionStringParser::~ConnectionStringParser()
+ {
+ // No-op.
+ }
+
+ void ConnectionStringParser::ParseConnectionString(const char* str, size_t len, char delimeter,
+ diagnostic::DiagnosticRecordStorage* diag)
+ {
+ std::string connect_str(str, len);
+
+ while (connect_str.rbegin() != connect_str.rend() && *connect_str.rbegin() == 0)
+ connect_str.erase(connect_str.size() - 1);
+
+ while (!connect_str.empty())
+ {
+ size_t attr_begin = connect_str.rfind(delimeter);
+
+ if (attr_begin == std::string::npos)
+ attr_begin = 0;
+ else
+ ++attr_begin;
+
+ size_t attr_eq_pos = connect_str.rfind('=');
+
+ if (attr_eq_pos == std::string::npos)
+ attr_eq_pos = 0;
+
+ if (attr_begin < attr_eq_pos)
+ {
+ const char* key_begin = connect_str.data() + attr_begin;
+ const char* key_end = connect_str.data() + attr_eq_pos;
+
+ const char* value_begin = connect_str.data() + attr_eq_pos + 1;
+ const char* value_end = connect_str.data() + connect_str.size();
+
+ std::string key = utility::RemoveSurroundingSpaces(key_begin, key_end);
+ std::string value = utility::RemoveSurroundingSpaces(value_begin, value_end);
+
+ if (value[0] == '{' && value[value.size() - 1] == '}')
+ value = value.substr(1, value.size() - 2);
+
+ HandleAttributePair(key, value, diag);
+ }
+
+ if (!attr_begin)
+ break;
+
+ connect_str.erase(attr_begin - 1);
+ }
+ }
+
+ void ConnectionStringParser::ParseConnectionString(const std::string& str,
+ diagnostic::DiagnosticRecordStorage* diag)
+ {
+ ParseConnectionString(str.data(), str.size(), ';', diag);
+ }
+
+ void ConnectionStringParser::ParseConfigAttributes(const char* str,
+ diagnostic::DiagnosticRecordStorage* diag)
+ {
+ size_t len = 0;
+
+ // Getting list length. List is terminated by two '\0'.
+ while (str[len] || str[len + 1])
+ ++len;
+
+ ++len;
+
+ ParseConnectionString(str, len, '\0', diag);
+ }
+
+ void ConnectionStringParser::HandleAttributePair(const std::string &key, const std::string &value,
+ diagnostic::DiagnosticRecordStorage* diag)
+ {
+ std::string lKey = common::ToLower(key);
+
+ if (lKey == Key::dsn)
+ {
+ cfg.SetDsn(value);
+ }
+ else if (lKey == Key::schema)
+ {
+ cfg.SetSchema(value);
+ }
+ else if (lKey == Key::address)
+ {
+ std::vector<EndPoint> endPoints;
+
+ ParseAddress(value, endPoints, diag);
+
+ cfg.SetAddresses(endPoints);
+ }
+ else if (lKey == Key::server)
+ {
+ cfg.SetHost(value);
+ }
+ else if (lKey == Key::port)
+ {
+ if (value.empty())
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Port attribute value is empty. Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ if (!common::AllOf(value.begin(), value.end(), isdigit))
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Port attribute value contains unexpected characters."
+ " Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ if (value.size() >= sizeof("65535"))
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Port attribute value is too large. Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ int32_t numValue = 0;
+ std::stringstream conv;
+
+ conv << value;
+ conv >> numValue;
+
+ if (numValue <= 0 || numValue > 0xFFFF)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Port attribute value is out of range. "
+ "Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetTcpPort(static_cast<uint16_t>(numValue));
+ }
+ else if (lKey == Key::distributedJoins)
+ {
+ BoolParseResult::Type res = StringToBool(value);
+
+ if (res == BoolParseResult::AI_UNRECOGNIZED)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Unrecognized bool value. Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetDistributedJoins(res == BoolParseResult::AI_TRUE);
+ }
+ else if (lKey == Key::enforceJoinOrder)
+ {
+ BoolParseResult::Type res = StringToBool(value);
+
+ if (res == BoolParseResult::AI_UNRECOGNIZED)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Unrecognized bool value. Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetEnforceJoinOrder(res == BoolParseResult::AI_TRUE);
+ }
+ else if (lKey == Key::protocolVersion)
+ {
+ try
+ {
+ ProtocolVersion version = ProtocolVersion::FromString(value);
+
+ if (!version.IsSupported())
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ "Specified version is not supported. Default value used.");
+ }
+
+ return;
+ }
+
+ cfg.SetProtocolVersion(version);
+ }
+ catch (IgniteError& err)
+ {
+ if (diag)
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, err.GetText());
+ }
+ }
+ else if (lKey == Key::pageSize)
+ {
+ if (!common::AllOf(value.begin(), value.end(), isdigit))
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Page size attribute value contains unexpected characters."
+ " Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ if (value.size() >= sizeof("4294967295"))
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Page size attribute value is too large."
+ " Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ int64_t numValue = 0;
+ std::stringstream conv;
+
+ conv << value;
+ conv >> numValue;
+
+ if (numValue <= 0 || numValue > 0xFFFFFFFFLL)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Page size attribute value is out of range."
+ " Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetPageSize(static_cast<int32_t>(numValue));
+ }
+ else if (lKey == Key::replicatedOnly)
+ {
+ BoolParseResult::Type res = StringToBool(value);
+
+ if (res == BoolParseResult::AI_UNRECOGNIZED)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Unrecognized bool value. Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetReplicatedOnly(res == BoolParseResult::AI_TRUE);
+ }
+ else if (lKey == Key::collocated)
+ {
+ BoolParseResult::Type res = StringToBool(value);
+
+ if (res == BoolParseResult::AI_UNRECOGNIZED)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Unrecognized bool value. Using default value.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetCollocated(res == BoolParseResult::AI_TRUE);
+ }
+ else if (lKey == Key::lazy)
+ {
+ BoolParseResult::Type res = StringToBool(value);
+
+ if (res == BoolParseResult::AI_UNRECOGNIZED)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Unrecognized bool value. Defaulting to 'false'.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetLazy(res == BoolParseResult::AI_TRUE);
+ }
+ else if (lKey == Key::skipReducerOnUpdate)
+ {
+ BoolParseResult::Type res = StringToBool(value);
+
+ if (res == BoolParseResult::AI_UNRECOGNIZED)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ MakeErrorMessage("Unrecognized bool value. Defaulting to 'false'.", key, value));
+ }
+
+ return;
+ }
+
+ cfg.SetSkipReducerOnUpdate(res == BoolParseResult::AI_TRUE);
+ }
+ else if (lKey == Key::sslMode)
+ {
+ ssl::SslMode::Type mode = ssl::SslMode::FromString(value);
+
+ if (mode == ssl::SslMode::UNKNOWN)
+ {
+ if (diag)
+ {
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+ "Specified SSL mode is not supported. Default value used ('disable').");
+ }
+
+ return;
+ }
+
+ cfg.SetSslMode(mode);
+ }
+ else if (lKey == Key::sslKeyFile)
+ {
+ cfg.SetSslKeyFile(value);
+ }
+ else if (lKey == Key::sslCertFile)
+ {
+ cfg.SetSslCertFile(value);
+ }
+ else if (lKey == Key::sslCaFile)
+ {
+ cfg.SetSslCaFile(value);
+ }
+ else if (lKey == Key::driver)
+ {
+ cfg.SetDriver(value);
+ }
+ else if (diag)
+ {
+ std::stringstream stream;
+
+ stream << "Unknown attribute: '" << key << "'. Ignoring.";
+
+ diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, stream.str());
+ }
+ }
+
+ ConnectionStringParser::BoolParseResult::Type ConnectionStringParser::StringToBool(const std::string& value)
+ {
+ std::string lower = common::ToLower(value);
+
+ if (lower == "true")
+ return BoolParseResult::AI_TRUE;
+
+ if (lower == "false")
+ return BoolParseResult::AI_FALSE;
+
+ return BoolParseResult::AI_UNRECOGNIZED;
+ }
+
+ std::string ConnectionStringParser::MakeErrorMessage(const std::string& msg, const std::string& key,
+ const std::string& value)
+ {
+ std::stringstream stream;
+
+ stream << msg << " [key='" << key << "', value='" << value << "']";
+
+ return stream.str();
+ }
+ }
+ }
+}
+