You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/12/22 11:11:11 UTC
[02/13] ignite git commit: IGNITE-7143: Fixed Decimal serialization
issue.
IGNITE-7143: Fixed Decimal serialization issue.
This closes #3207
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e9702a52
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e9702a52
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e9702a52
Branch: refs/heads/ignite-zk
Commit: e9702a520cde61c6479ab843f356f1b2bd4b531c
Parents: b0f6d19
Author: Igor Sapego <is...@gridgain.com>
Authored: Tue Dec 19 18:53:56 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Wed Dec 20 14:30:41 2017 +0300
----------------------------------------------------------------------
.../cpp/common/src/common/big_integer.cpp | 24 +-
modules/platforms/cpp/odbc-test/Makefile.am | 2 +
.../cpp/odbc-test/include/odbc_test_suite.h | 123 +++++
.../odbc-test/include/sql_test_suite_fixture.h | 1 -
.../cpp/odbc-test/project/vs/odbc-test.vcxproj | 3 +
.../project/vs/odbc-test.vcxproj.filters | 11 +-
.../cpp/odbc-test/src/odbc_test_suite.cpp | 526 +++++++++++++++++++
.../cpp/odbc-test/src/queries_test.cpp | 512 +-----------------
.../platforms/cpp/odbc-test/src/types_test.cpp | 165 ++++++
9 files changed, 860 insertions(+), 507 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/modules/platforms/cpp/common/src/common/big_integer.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/src/common/big_integer.cpp b/modules/platforms/cpp/common/src/common/big_integer.cpp
index 6aa6614..2ff3478 100644
--- a/modules/platforms/cpp/common/src/common/big_integer.cpp
+++ b/modules/platforms/cpp/common/src/common/big_integer.cpp
@@ -56,7 +56,7 @@ namespace ignite
mag()
{
assert(val != 0);
- assert(len > 0);
+ assert(len >= 0);
assert(sign == 1 || sign == 0 || sign == -1);
if (bigEndian)
@@ -65,6 +65,13 @@ namespace ignite
while (firstNonZero < len && val[firstNonZero] == 0)
++firstNonZero;
+ if (firstNonZero == len)
+ {
+ AssignInt64(0);
+
+ return;
+ }
+
int32_t intLength = (len - firstNonZero + 3) / 4;
mag.Resize(intLength);
@@ -106,9 +113,17 @@ namespace ignite
else
{
int32_t firstNonZero = len - 1;
+
while (firstNonZero >= 0 && val[firstNonZero] == 0)
--firstNonZero;
+ if (firstNonZero == -1)
+ {
+ AssignInt64(0);
+
+ return;
+ }
+
int32_t intLength = (firstNonZero + 4) / 4;
mag.Resize(intLength);
@@ -269,6 +284,13 @@ namespace ignite
{
int32_t bytesNum = static_cast<int32_t>((GetBitLength() + 7) / 8);
+ if (bytesNum == 0)
+ {
+ buffer.Reset(1);
+
+ return;
+ }
+
buffer.Reset(bytesNum);
int32_t i;
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/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 7cccf4c..b025e2c 100644
--- a/modules/platforms/cpp/odbc-test/Makefile.am
+++ b/modules/platforms/cpp/odbc-test/Makefile.am
@@ -81,6 +81,8 @@ ignite_odbc_tests_SOURCES = \
src/api_robustness_test.cpp \
src/attributes_test.cpp \
src/errors_test.cpp \
+ src/odbc_test_suite.cpp \
+ src/types_test.cpp \
../odbc/src/cursor.cpp \
../odbc/src/config/connection_info.cpp \
../odbc/src/app/application_data_buffer.cpp \
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/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
new file mode 100644
index 0000000..f79d65f
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
@@ -0,0 +1,123 @@
+/*
+ * 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 ODBC_TEST_ODBC_TEST_SUITE
+#define ODBC_TEST_ODBC_TEST_SUITE
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+#include <sql.h>
+#include <sqlext.h>
+
+#include <string>
+
+#include "ignite/ignite.h"
+
+#include "test_type.h"
+#include "complex_type.h"
+
+namespace ignite
+{
+ namespace odbc
+ {
+ /**
+ * Test setup fixture.
+ */
+ struct OdbcTestSuite
+ {
+ /**
+ * Establish connection to node.
+ *
+ * @param connectStr Connection string.
+ */
+ void Connect(const std::string& connectStr);
+
+ /**
+ * Disconnect.
+ */
+ void Disconnect();
+
+ /**
+ * Start additional with the specified name and config.
+ *
+ * @param cfg Config path.
+ * @param name Instance name.
+ */
+ static Ignite StartTestNode(const char* cfg, const char* name);
+
+ /**
+ * Constructor.
+ */
+ OdbcTestSuite();
+
+ /**
+ * Destructor.
+ */
+ virtual ~OdbcTestSuite();
+
+ /**
+ * Insert requested number of TestType values with all defaults except
+ * for the strFields, which are generated using getTestString().
+ *
+ * @param recordsNum Number of records to insert.
+ * @param merge Set to true to use merge instead.
+ */
+ void InsertTestStrings(int recordsNum, bool merge = false);
+
+ /**
+ * Insert requested number of TestType values in a batch.
+ *
+ * @param from Index to start from.
+ * @param to Index to stop.
+ * @param expectedToAffect Expected number of affected records.
+ * @param merge Set to true to use merge instead of insert.
+ * @return Records inserted.
+ */
+ int InsertTestBatch(int from, int to, int expectedToAffect, bool merge = false);
+
+ /**
+ * Insert requested number of TestType values in a batch,
+ * select them and check all the values.
+ *
+ * @param recordsNum Number of records.
+ */
+ void InsertBatchSelect(int recordsNum);
+
+ /**
+ * Insert values in two batches, select them and check all the values.
+ * @param recordsNum Number of records.
+ * @param splitAt Point where two batches are separated.
+ */
+ void InsertNonFullBatchSelect(int recordsNum, int splitAt);
+
+ static std::string getTestString(int64_t ind);
+
+ /** ODBC Environment. */
+ SQLHENV env;
+
+ /** ODBC Connect. */
+ SQLHDBC dbc;
+
+ /** ODBC Statement. */
+ SQLHSTMT stmt;
+ };
+ }
+}
+
+#endif //ODBC_TEST_ODBC_TEST_SUITE
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/modules/platforms/cpp/odbc-test/include/sql_test_suite_fixture.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/sql_test_suite_fixture.h b/modules/platforms/cpp/odbc-test/include/sql_test_suite_fixture.h
index bbcc0ad..8a76a67 100644
--- a/modules/platforms/cpp/odbc-test/include/sql_test_suite_fixture.h
+++ b/modules/platforms/cpp/odbc-test/include/sql_test_suite_fixture.h
@@ -112,7 +112,6 @@ namespace ignite
* Run query returning single result and check it to be equal to expected.
*
* @param request SQL request.
- * @param expected Expected result.
* @param type Result type.
*/
template<typename T>
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/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 e11a3ba..d565306 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
@@ -171,6 +171,7 @@
<ClCompile Include="..\..\src\cursor_test.cpp" />
<ClCompile Include="..\..\src\errors_test.cpp" />
<ClCompile Include="..\..\src\meta_queries_test.cpp" />
+ <ClCompile Include="..\..\src\odbc_test_suite.cpp" />
<ClCompile Include="..\..\src\queries_test.cpp" />
<ClCompile Include="..\..\src\parser_test.cpp" />
<ClCompile Include="..\..\src\row_test.cpp" />
@@ -189,10 +190,12 @@
<ClCompile Include="..\..\src\teamcity\teamcity_boost.cpp" />
<ClCompile Include="..\..\src\teamcity\teamcity_messages.cpp" />
<ClCompile Include="..\..\src\test_utils.cpp" />
+ <ClCompile Include="..\..\src\types_test.cpp" />
<ClCompile Include="..\..\src\utility_test.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\complex_type.h" />
+ <ClInclude Include="..\..\include\odbc_test_suite.h" />
<ClInclude Include="..\..\include\sql_test_suite_fixture.h" />
<ClInclude Include="..\..\include\teamcity\teamcity_messages.h" />
<ClInclude Include="..\..\include\test_type.h" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/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 ebdf7d3..58cf045 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
@@ -133,6 +133,12 @@
<ClCompile Include="..\..\src\sql_get_info_test.cpp">
<Filter>Code</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\types_test.cpp">
+ <Filter>Code</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\src\odbc_test_suite.cpp">
+ <Filter>Code</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\test_type.h">
@@ -150,6 +156,9 @@
<ClInclude Include="..\..\include\complex_type.h">
<Filter>Code\CacheTypes</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\odbc_test_suite.h">
+ <Filter>Code</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\config\queries-test-32.xml">
@@ -171,4 +180,4 @@
<Filter>Configs</Filter>
</None>
</ItemGroup>
-</Project>
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/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
new file mode 100644
index 0000000..a967b4f
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
@@ -0,0 +1,526 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+#include <sql.h>
+#include <sqlext.h>
+
+#ifndef _MSC_VER
+# define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include "ignite/ignition.h"
+
+#include "test_utils.h"
+#include "odbc_test_suite.h"
+
+using namespace ignite_test;
+using namespace boost::unit_test;
+
+namespace ignite
+{
+ namespace odbc
+ {
+ void OdbcTestSuite::Connect(const std::string& connectStr)
+ {
+ // 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);
+
+ // 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);
+
+ if (!SQL_SUCCEEDED(ret))
+ {
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc));
+ }
+
+ // Allocate a statement handle
+ SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
+
+ BOOST_REQUIRE(stmt != NULL);
+ }
+
+ void OdbcTestSuite::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);
+ }
+
+ Ignite OdbcTestSuite::StartTestNode(const char* cfg, const char* name)
+ {
+ std::string config(cfg);
+
+#ifdef IGNITE_TESTS_32
+ // Cutting off the ".xml" part.
+ config.resize(config.size() - 4);
+ config += "-32.xml";
+#endif //IGNITE_TESTS_32
+
+ return StartNode(config.c_str(), name);
+ }
+
+ OdbcTestSuite::OdbcTestSuite():
+ env(NULL),
+ dbc(NULL),
+ stmt(NULL)
+ {
+ // No-op.
+ }
+
+ OdbcTestSuite::~OdbcTestSuite()
+ {
+ Disconnect();
+
+ Ignition::StopAll(true);
+ }
+
+ std::string OdbcTestSuite::getTestString(int64_t ind)
+ {
+ std::stringstream builder;
+
+ builder << "String#" << ind;
+
+ return builder.str();
+ }
+
+ void OdbcTestSuite::InsertTestStrings(int recordsNum, bool merge)
+ {
+ SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)";
+ SQLCHAR mergeReq[] = "MERGE INTO TestType(_key, strField) VALUES(?, ?)";
+
+ SQLRETURN ret;
+
+ ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ int64_t key = 0;
+ char strField[1024] = {0};
+ SQLLEN strFieldLen = 0;
+
+ // Binding parameters.
+ ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(strField),
+ sizeof(strField), &strField, sizeof(strField), &strFieldLen);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ // Inserting values.
+ for (SQLSMALLINT i = 0; i < recordsNum; ++i)
+ {
+ key = i + 1;
+ std::string val = getTestString(i);
+
+ strncpy(strField, val.c_str(), sizeof(strField));
+ strFieldLen = SQL_NTS;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ SQLLEN affected = 0;
+ ret = SQLRowCount(stmt, &affected);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECK_EQUAL(affected, 1);
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ }
+
+ // Resetting parameters.
+ ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ }
+
+ int OdbcTestSuite::InsertTestBatch(int from, int to, int expectedToAffect, bool merge)
+ {
+ using common::FixedSizeArray;
+
+ SQLCHAR insertReq[] = "INSERT "
+ "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, "
+ "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+ SQLCHAR mergeReq[] = "MERGE "
+ "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, "
+ "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+ SQLRETURN ret;
+
+ int recordsNum = to - from;
+
+ ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ FixedSizeArray<int64_t> keys(recordsNum);
+ FixedSizeArray<int8_t> i8Fields(recordsNum);
+ FixedSizeArray<int16_t> i16Fields(recordsNum);
+ FixedSizeArray<int32_t> i32Fields(recordsNum);
+ FixedSizeArray<char> strFields(recordsNum * 1024);
+ FixedSizeArray<float> floatFields(recordsNum);
+ FixedSizeArray<double> doubleFields(recordsNum);
+ FixedSizeArray<bool> boolFields(recordsNum);
+ FixedSizeArray<SQL_DATE_STRUCT> dateFields(recordsNum);
+ FixedSizeArray<SQL_TIME_STRUCT> timeFields(recordsNum);
+ FixedSizeArray<SQL_TIMESTAMP_STRUCT> timestampFields(recordsNum);
+ FixedSizeArray<int8_t> i8ArrayFields(recordsNum * 42);
+
+ FixedSizeArray<SQLLEN> strFieldsLen(recordsNum);
+ FixedSizeArray<SQLLEN> i8ArrayFieldsLen(recordsNum);
+
+ BOOST_CHECKPOINT("Filling param data");
+
+ for (int i = 0; i < recordsNum; ++i)
+ {
+ int seed = from + i;
+
+ keys[i] = seed;
+ i8Fields[i] = seed * 8;
+ i16Fields[i] = seed * 16;
+ i32Fields[i] = seed * 32;
+
+ std::string val = getTestString(seed);
+ strncpy(strFields.GetData() + 1024 * i, val.c_str(), 1023);
+ strFieldsLen[i] = val.size();
+
+ floatFields[i] = seed * 0.5f;
+ doubleFields[i] = seed * 0.25f;
+ boolFields[i] = seed % 2 == 0;
+
+ dateFields[i].year = 2017 + seed / 365;
+ dateFields[i].month = ((seed / 28) % 12) + 1;
+ dateFields[i].day = (seed % 28) + 1;
+
+ timeFields[i].hour = (seed / 3600) % 24;
+ timeFields[i].minute = (seed / 60) % 60;
+ timeFields[i].second = seed % 60;
+
+ timestampFields[i].year = dateFields[i].year;
+ timestampFields[i].month = dateFields[i].month;
+ timestampFields[i].day = dateFields[i].day;
+ timestampFields[i].hour = timeFields[i].hour;
+ timestampFields[i].minute = timeFields[i].minute;
+ timestampFields[i].second = timeFields[i].second;
+ timestampFields[i].fraction = std::abs(seed * 914873) % 1000000000;
+
+ for (int j = 0; j < 42; ++j)
+ i8ArrayFields[i * 42 + j] = seed * 42 + j;
+ i8ArrayFieldsLen[i] = 42;
+ }
+
+ SQLULEN setsProcessed = 0;
+
+ BOOST_CHECKPOINT("Setting processed pointer");
+ ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &setsProcessed, SQL_IS_POINTER);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding keys");
+ ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, keys.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding i8Fields");
+ ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_STINYINT, SQL_TINYINT, 0, 0, i8Fields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding i16Fields");
+ ret = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_SMALLINT, 0, 0, i16Fields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding i32Fields");
+ ret = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, i32Fields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding strFields");
+ ret = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 1024, 0, strFields.GetData(), 1024, strFieldsLen.GetData());
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding floatFields");
+ ret = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, floatFields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding doubleFields");
+ ret = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, doubleFields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding boolFields");
+ ret = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, 0, 0, boolFields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding dateFields");
+ ret = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE, 0, 0, dateFields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding timeFields");
+ ret = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_TIME, SQL_TIME, 0, 0, timeFields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding timestampFields");
+ ret = SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 0, 0, timestampFields.GetData(), 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Binding i8ArrayFields");
+ ret = SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY, 42, 0, i8ArrayFields.GetData(), 42, i8ArrayFieldsLen.GetData());
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Setting paramset size");
+ ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(recordsNum), 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Executing query");
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ SQLLEN totallyAffected = 0;
+
+ do
+ {
+ SQLLEN affected = 0;
+ ret = SQLRowCount(stmt, &affected);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ totallyAffected += affected;
+
+ BOOST_CHECKPOINT("Getting next result set");
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_SUCCESS && ret != SQL_NO_DATA)
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ }
+ while (ret != SQL_NO_DATA);
+
+ BOOST_CHECK_EQUAL(totallyAffected, expectedToAffect);
+
+ BOOST_CHECKPOINT("Resetting parameters.");
+ ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECKPOINT("Setting paramset size");
+ ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(1), 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ return static_cast<int>(setsProcessed);
+ }
+
+ void OdbcTestSuite::InsertBatchSelect(int recordsNum)
+ {
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+ // Inserting values.
+ int inserted = InsertTestBatch(0, recordsNum, recordsNum);
+
+ BOOST_REQUIRE_EQUAL(inserted, recordsNum);
+
+ int64_t key = 0;
+ char strField[1024] = {0};
+ SQLLEN strFieldLen = 0;
+
+ // Binding columns.
+ SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ // Binding columns.
+ ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ // Just selecting everything to make sure everything is OK
+ SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY _key";
+
+ ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ int selectedRecordsNum = 0;
+
+ ret = SQL_SUCCESS;
+
+ while (ret == SQL_SUCCESS)
+ {
+ ret = SQLFetch(stmt);
+
+ if (ret == SQL_NO_DATA)
+ break;
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ std::string expectedStr = getTestString(selectedRecordsNum);
+ int64_t expectedKey = selectedRecordsNum;
+
+ BOOST_CHECK_EQUAL(key, expectedKey);
+
+ BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+ ++selectedRecordsNum;
+ }
+
+ BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+ }
+
+ void OdbcTestSuite::InsertNonFullBatchSelect(int recordsNum, int splitAt)
+ {
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+ // Inserting values.
+ int inserted = InsertTestBatch(splitAt, recordsNum, recordsNum - splitAt);
+
+ BOOST_REQUIRE_EQUAL(inserted, recordsNum - splitAt);
+
+ inserted = InsertTestBatch(0, recordsNum, splitAt);
+
+ BOOST_REQUIRE_EQUAL(inserted, splitAt);
+
+ int64_t key = 0;
+ char strField[1024] = {0};
+ SQLLEN strFieldLen = 0;
+
+ // Binding columns.
+ SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ // Binding columns.
+ ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ // Just selecting everything to make sure everything is OK
+ SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY _key";
+
+ ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ int selectedRecordsNum = 0;
+
+ ret = SQL_SUCCESS;
+
+ while (ret == SQL_SUCCESS)
+ {
+ ret = SQLFetch(stmt);
+
+ if (ret == SQL_NO_DATA)
+ break;
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ std::string expectedStr = getTestString(selectedRecordsNum);
+ int64_t expectedKey = selectedRecordsNum;
+
+ BOOST_CHECK_EQUAL(key, expectedKey);
+
+ BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+ ++selectedRecordsNum;
+ }
+
+ BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/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 dafab1a..b11c8b1 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -42,6 +42,7 @@
#include "test_type.h"
#include "complex_type.h"
#include "test_utils.h"
+#include "odbc_test_suite.h"
using namespace ignite;
using namespace ignite::cache;
@@ -59,91 +60,16 @@ using ignite::impl::binary::BinaryUtils;
/**
* Test setup fixture.
*/
-struct QueriesTestSuiteFixture
+struct QueriesTestSuiteFixture : odbc::OdbcTestSuite
{
/**
- * Establish connection to node.
- *
- * @param connectStr Connection string.
- */
- void Connect(const std::string& connectStr)
- {
- // 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);
-
- // 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);
-
- if (!SQL_SUCCEEDED(ret))
- {
- Ignition::Stop(grid.GetName(), true);
-
- BOOST_FAIL(GetOdbcErrorMessage(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);
- }
-
- static Ignite StartAdditionalNode(const char* name)
- {
-#ifdef IGNITE_TESTS_32
- return StartNode("queries-test-noodbc-32.xml", name);
-#else
- return StartNode("queries-test-noodbc.xml", name);
-#endif
- }
-
- /**
* Constructor.
*/
QueriesTestSuiteFixture() :
cache1(0),
- cache2(0),
- env(NULL),
- dbc(NULL),
- stmt(NULL)
+ cache2(0)
{
-#ifdef IGNITE_TESTS_32
- grid = StartNode("queries-test-32.xml", "NodeMain");
-#else
- grid = StartNode("queries-test.xml", "NodeMain");
-#endif
+ grid = StartTestNode("queries-test.xml", "NodeMain");
cache1 = grid.GetCache<int64_t, TestType>("cache");
cache2 = grid.GetCache<int64_t, ComplexType>("cache2");
@@ -152,11 +78,9 @@ struct QueriesTestSuiteFixture
/**
* Destructor.
*/
- ~QueriesTestSuiteFixture()
+ virtual ~QueriesTestSuiteFixture()
{
- Disconnect();
-
- Ignition::StopAll(true);
+ // No-op.
}
template<typename T>
@@ -302,420 +226,9 @@ struct QueriesTestSuiteFixture
return res;
}
- static std::string getTestString(int64_t ind)
- {
- std::stringstream builder;
-
- builder << "String#" << ind;
-
- return builder.str();
- }
-
- /**
- * Insert requested number of TestType values with all defaults except
- * for the strFields, which are generated using getTestString().
- *
- * @param recordsNum Number of records to insert.
- * @param merge Set to true to use merge instead.
- */
- void InsertTestStrings(int recordsNum, bool merge = false)
- {
- SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)";
- SQLCHAR mergeReq[] = "MERGE INTO TestType(_key, strField) VALUES(?, ?)";
-
- SQLRETURN ret;
-
- ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- int64_t key = 0;
- char strField[1024] = { 0 };
- SQLLEN strFieldLen = 0;
-
- // Binding parameters.
- ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(strField),
- sizeof(strField), &strField, sizeof(strField), &strFieldLen);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- // Inserting values.
- for (SQLSMALLINT i = 0; i < recordsNum; ++i)
- {
- key = i + 1;
- std::string val = getTestString(i);
-
- strncpy(strField, val.c_str(), sizeof(strField));
- strFieldLen = SQL_NTS;
-
- ret = SQLExecute(stmt);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- SQLLEN affected = 0;
- ret = SQLRowCount(stmt, &affected);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECK_EQUAL(affected, 1);
-
- ret = SQLMoreResults(stmt);
-
- if (ret != SQL_NO_DATA)
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
- }
-
- // Resetting parameters.
- ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
- }
-
- /**
- * Insert requested number of TestType values in a batch.
- *
- * @param from Index to start from.
- * @param to Index to stop.
- * @param expectedToAffect Expected number of affected records.
- * @param merge Set to true to use merge instead of insert.
- * @return Records inserted.
- */
- int InsertTestBatch(int from, int to, int expectedToAffect, bool merge = false)
- {
- SQLCHAR insertReq[] = "INSERT "
- "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, "
- "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
-
- SQLCHAR mergeReq[] = "MERGE "
- "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, "
- "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
-
- SQLRETURN ret;
-
- int recordsNum = to - from;
-
- ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- FixedSizeArray<int64_t> keys(recordsNum);
- FixedSizeArray<int8_t> i8Fields(recordsNum);
- FixedSizeArray<int16_t> i16Fields(recordsNum);
- FixedSizeArray<int32_t> i32Fields(recordsNum);
- FixedSizeArray<char> strFields(recordsNum * 1024);
- FixedSizeArray<float> floatFields(recordsNum);
- FixedSizeArray<double> doubleFields(recordsNum);
- FixedSizeArray<bool> boolFields(recordsNum);
- FixedSizeArray<SQL_DATE_STRUCT> dateFields(recordsNum);
- FixedSizeArray<SQL_TIME_STRUCT> timeFields(recordsNum);
- FixedSizeArray<SQL_TIMESTAMP_STRUCT> timestampFields(recordsNum);
- FixedSizeArray<int8_t> i8ArrayFields(recordsNum * 42);
-
- FixedSizeArray<SQLLEN> strFieldsLen(recordsNum);
- FixedSizeArray<SQLLEN> i8ArrayFieldsLen(recordsNum);
-
- BOOST_CHECKPOINT("Filling param data");
-
- for (int i = 0; i < recordsNum; ++i)
- {
- int seed = from + i;
-
- keys[i] = seed;
- i8Fields[i] = seed * 8;
- i16Fields[i] = seed * 16;
- i32Fields[i] = seed * 32;
-
- std::string val = getTestString(seed);
- strncpy(strFields.GetData() + 1024 * i, val.c_str(), 1023);
- strFieldsLen[i] = val.size();
-
- floatFields[i] = seed * 0.5f;
- doubleFields[i] = seed * 0.25f;
- boolFields[i] = seed % 2 == 0;
-
- dateFields[i].year = 2017 + seed / 365;
- dateFields[i].month = ((seed / 28) % 12) + 1;
- dateFields[i].day = (seed % 28) + 1;
-
- timeFields[i].hour = (seed / 3600) % 24;
- timeFields[i].minute = (seed / 60) % 60;
- timeFields[i].second = seed % 60;
-
- timestampFields[i].year = dateFields[i].year;
- timestampFields[i].month = dateFields[i].month;
- timestampFields[i].day = dateFields[i].day;
- timestampFields[i].hour = timeFields[i].hour;
- timestampFields[i].minute = timeFields[i].minute;
- timestampFields[i].second = timeFields[i].second;
- timestampFields[i].fraction = std::abs(seed * 914873) % 1000000000;
-
- for (int j = 0; j < 42; ++j)
- i8ArrayFields[i * 42 + j] = seed * 42 + j;
- i8ArrayFieldsLen[i] = 42;
- }
-
- SQLULEN setsProcessed = 0;
-
- BOOST_CHECKPOINT("Setting processed pointer");
- ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &setsProcessed, SQL_IS_POINTER);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding keys");
- ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, keys.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding i8Fields");
- ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_STINYINT, SQL_TINYINT, 0, 0, i8Fields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding i16Fields");
- ret = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_SMALLINT, 0, 0, i16Fields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding i32Fields");
- ret = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, i32Fields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding strFields");
- ret = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 1024, 0, strFields.GetData(), 1024, strFieldsLen.GetData());
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding floatFields");
- ret = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, floatFields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding doubleFields");
- ret = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, doubleFields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding boolFields");
- ret = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, 0, 0, boolFields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding dateFields");
- ret = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE, 0, 0, dateFields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding timeFields");
- ret = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_TIME, SQL_TIME, 0, 0, timeFields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding timestampFields");
- ret = SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 0, 0, timestampFields.GetData(), 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Binding i8ArrayFields");
- ret = SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY, 42, 0, i8ArrayFields.GetData(), 42, i8ArrayFieldsLen.GetData());
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Setting paramset size");
- ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(recordsNum), 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Executing query");
- ret = SQLExecute(stmt);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- SQLLEN totallyAffected = 0;
-
- do
- {
- SQLLEN affected = 0;
- ret = SQLRowCount(stmt, &affected);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- totallyAffected += affected;
-
- BOOST_CHECKPOINT("Getting next result set");
-
- ret = SQLMoreResults(stmt);
-
- if (ret != SQL_SUCCESS && ret != SQL_NO_DATA)
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
- } while (ret != SQL_NO_DATA);
-
- BOOST_CHECK_EQUAL(totallyAffected, expectedToAffect);
-
- BOOST_CHECKPOINT("Resetting parameters.");
- ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- BOOST_CHECKPOINT("Setting paramset size");
- ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(1), 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- return static_cast<int>(setsProcessed);
- }
-
- void InsertBatchSelect(int recordsNum)
- {
- Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
-
- // Inserting values.
- int inserted = InsertTestBatch(0, recordsNum, recordsNum);
-
- BOOST_REQUIRE_EQUAL(inserted, recordsNum);
-
- int64_t key = 0;
- char strField[1024] = { 0 };
- SQLLEN strFieldLen = 0;
-
- // Binding columns.
- SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- // Binding columns.
- ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- // Just selecting everything to make sure everything is OK
- SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY _key";
-
- ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- int selectedRecordsNum = 0;
-
- ret = SQL_SUCCESS;
-
- while (ret == SQL_SUCCESS)
- {
- ret = SQLFetch(stmt);
-
- if (ret == SQL_NO_DATA)
- break;
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- std::string expectedStr = getTestString(selectedRecordsNum);
- int64_t expectedKey = selectedRecordsNum;
-
- BOOST_CHECK_EQUAL(key, expectedKey);
-
- BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
-
- ++selectedRecordsNum;
- }
-
- BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
- }
-
- void InsertNonFullBatchSelect(int recordsNum, int splitAt)
+ static Ignite StartAdditionalNode(const char* name)
{
- Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
-
- // Inserting values.
- int inserted = InsertTestBatch(splitAt, recordsNum, recordsNum - splitAt);
-
- BOOST_REQUIRE_EQUAL(inserted, recordsNum - splitAt);
-
- inserted = InsertTestBatch(0, recordsNum, splitAt);
-
- BOOST_REQUIRE_EQUAL(inserted, splitAt);
-
- int64_t key = 0;
- char strField[1024] = { 0 };
- SQLLEN strFieldLen = 0;
-
- // Binding columns.
- SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- // Binding columns.
- ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen);
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- // Just selecting everything to make sure everything is OK
- SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY _key";
-
- ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- int selectedRecordsNum = 0;
-
- ret = SQL_SUCCESS;
-
- while (ret == SQL_SUCCESS)
- {
- ret = SQLFetch(stmt);
-
- if (ret == SQL_NO_DATA)
- break;
-
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
-
- std::string expectedStr = getTestString(selectedRecordsNum);
- int64_t expectedKey = selectedRecordsNum;
-
- BOOST_CHECK_EQUAL(key, expectedKey);
-
- BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
-
- ++selectedRecordsNum;
- }
-
- BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+ return StartTestNode("queries-test-noodbc.xml", name);
}
/** Node started during the test. */
@@ -726,15 +239,6 @@ struct QueriesTestSuiteFixture
/** Second cache instance. */
Cache<int64_t, ComplexType> cache2;
-
- /** ODBC Environment. */
- SQLHENV env;
-
- /** ODBC Connect. */
- SQLHDBC dbc;
-
- /** ODBC Statement. */
- SQLHSTMT stmt;
};
BOOST_FIXTURE_TEST_SUITE(QueriesTestSuite, QueriesTestSuiteFixture)
http://git-wip-us.apache.org/repos/asf/ignite/blob/e9702a52/modules/platforms/cpp/odbc-test/src/types_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/types_test.cpp b/modules/platforms/cpp/odbc-test/src/types_test.cpp
new file mode 100644
index 0000000..d5c7834
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/types_test.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+#include <sql.h>
+#include <sqlext.h>
+
+#include <vector>
+#include <string>
+#include <algorithm>
+
+#ifndef _MSC_VER
+# define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include "ignite/ignite.h"
+#include "test_type.h"
+#include "test_utils.h"
+#include "odbc_test_suite.h"
+
+using namespace ignite;
+using namespace ignite_test;
+
+using namespace boost::unit_test;
+
+/**
+ * Test setup fixture.
+ */
+struct TypesTestSuiteFixture : odbc::OdbcTestSuite
+{
+ /**
+ * Constructor.
+ */
+ TypesTestSuiteFixture() :
+ cache1(0)
+ {
+ node = StartTestNode("queries-test.xml", "NodeMain");
+
+ cache1 = node.GetCache<int64_t, TestType>("cache");
+ }
+
+ /**
+ * Destructor.
+ */
+ virtual ~TypesTestSuiteFixture()
+ {
+ // No-op.
+ }
+
+ /** Node started during the test. */
+ Ignite node;
+
+ /** Cache instance. */
+ cache::Cache<int64_t, TestType> cache1;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TypesTestSuite, TypesTestSuiteFixture)
+
+BOOST_AUTO_TEST_CASE(TestZeroDecimal)
+{
+ Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;SCHEMA=PUBLIC");
+
+ SQLCHAR ddl[] = "CREATE TABLE IF NOT EXISTS TestTable "
+ "(RecId varchar PRIMARY KEY, RecValue DECIMAL(4,2))"
+ "WITH \"template=replicated, cache_name=TestTable_Cache\";";
+
+ SQLRETURN ret = SQLExecDirect(stmt, ddl, SQL_NTS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ SQLCHAR dml[] = "INSERT INTO TestTable (RecId, RecValue) VALUES ('1', ?)";
+
+ ret = SQLPrepare(stmt, dml, SQL_NTS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ SQL_NUMERIC_STRUCT num;
+
+ memset(&num, 0, sizeof(num));
+
+ num.sign = 1;
+ num.precision = 1;
+
+ ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_DECIMAL, 0, 0, &num, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ SQL_NUMERIC_STRUCT num0;
+ SQLLEN num0Len = static_cast<SQLLEN>(sizeof(num0));
+
+ // Filling data to avoid acidental equality
+ memset(&num0, 0xFF, sizeof(num0));
+
+ ret = SQLBindCol(stmt, 1, SQL_C_NUMERIC, &num0, sizeof(num0), &num0Len);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ SQLCHAR qry[] = "SELECT RecValue FROM TestTable WHERE RecId = '1'";
+
+ ret = SQLExecDirect(stmt, qry, SQL_NTS);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ ret = SQLFetch(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+ BOOST_CHECK_EQUAL(num.precision, num0.precision);
+ BOOST_CHECK_EQUAL(num.scale, num0.scale);
+ BOOST_CHECK_EQUAL(num.sign, num0.sign);
+
+ BOOST_CHECK_EQUAL(num.val[0], num0.val[0]);
+ BOOST_CHECK_EQUAL(num.val[1], num0.val[1]);
+ BOOST_CHECK_EQUAL(num.val[2], num0.val[2]);
+ BOOST_CHECK_EQUAL(num.val[3], num0.val[3]);
+ BOOST_CHECK_EQUAL(num.val[4], num0.val[4]);
+ BOOST_CHECK_EQUAL(num.val[5], num0.val[5]);
+ BOOST_CHECK_EQUAL(num.val[6], num0.val[6]);
+ BOOST_CHECK_EQUAL(num.val[7], num0.val[7]);
+ BOOST_CHECK_EQUAL(num.val[8], num0.val[8]);
+ BOOST_CHECK_EQUAL(num.val[9], num0.val[9]);
+ BOOST_CHECK_EQUAL(num.val[10], num0.val[10]);
+ BOOST_CHECK_EQUAL(num.val[11], num0.val[11]);
+ BOOST_CHECK_EQUAL(num.val[12], num0.val[12]);
+ BOOST_CHECK_EQUAL(num.val[13], num0.val[13]);
+ BOOST_CHECK_EQUAL(num.val[14], num0.val[14]);
+ BOOST_CHECK_EQUAL(num.val[15], num0.val[15]);
+}
+
+BOOST_AUTO_TEST_SUITE_END()