IGNITE-4421: Added BinaryObject handling in ODBC. Added test.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/bf1770bc Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/bf1770bc Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/bf1770bc Branch: refs/heads/master Commit: bf1770bcebfb17d36ac90e157373901b5a181c05 Parents: 83710a9 Author: Igor Sapego <[email protected]> Authored: Wed Dec 14 12:26:27 2016 +0300 Committer: Igor Sapego <[email protected]> Committed: Wed Dec 14 12:26:27 2016 +0300 ---------------------------------------------------------------------- .../cpp/odbc-test/config/queries-test.xml | 37 ++++++ .../platforms/cpp/odbc-test/include/Makefile.am | 1 + .../cpp/odbc-test/include/complex_type.h | 122 +++++++++++++++++++ .../cpp/odbc-test/project/vs/odbc-test.vcxproj | 1 + .../project/vs/odbc-test.vcxproj.filters | 3 + .../cpp/odbc-test/src/queries_test.cpp | 101 ++++++++++++--- modules/platforms/cpp/odbc/src/column.cpp | 41 ++++--- modules/platforms/cpp/odbc/src/type_traits.cpp | 3 + 8 files changed, 277 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/bf1770bc/modules/platforms/cpp/odbc-test/config/queries-test.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/config/queries-test.xml b/modules/platforms/cpp/odbc-test/config/queries-test.xml index f511c7d..906fadf 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-test.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-test.xml @@ -85,6 +85,43 @@ </list> </property> </bean> + + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache2"/> + <property name="cacheMode" value="PARTITIONED"/> + <property name="atomicityMode" value="TRANSACTIONAL"/> + <property name="writeSynchronizationMode" value="FULL_SYNC"/> + + <!-- Configure type metadata to enable queries. --> + <property name="queryEntities"> + <list> + <bean class="org.apache.ignite.cache.QueryEntity"> + <property name="keyType" value="java.lang.Long"/> + <property name="valueType" value="ComplexType"/> + + <property name="fields"> + <map> + <entry key="i32Field" value="java.lang.Integer"/> + <entry key="objField" value="TestObject"/> + <entry key="strField" value="java.lang.String"/> + </map> + </property> + + <property name="keyFields"> + <list></list> + </property> + + <property name="indexes"> + <list> + <bean class="org.apache.ignite.cache.QueryIndex"> + <constructor-arg value="i32Field"/> + </bean> + </list> + </property> + </bean> + </list> + </property> + </bean> </list> </property> http://git-wip-us.apache.org/repos/asf/ignite/blob/bf1770bc/modules/platforms/cpp/odbc-test/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/include/Makefile.am b/modules/platforms/cpp/odbc-test/include/Makefile.am index 832103c..d13e7b6 100644 --- a/modules/platforms/cpp/odbc-test/include/Makefile.am +++ b/modules/platforms/cpp/odbc-test/include/Makefile.am @@ -19,6 +19,7 @@ ACLOCAL_AMFLAGS =-I m4 noinst_HEADERS = \ teamcity/teamcity_messages.h \ + complex_type.h \ test_type.h \ test_utils.h \ sql_test_suite_fixture.h http://git-wip-us.apache.org/repos/asf/ignite/blob/bf1770bc/modules/platforms/cpp/odbc-test/include/complex_type.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/include/complex_type.h b/modules/platforms/cpp/odbc-test/include/complex_type.h new file mode 100644 index 0000000..a84b033 --- /dev/null +++ b/modules/platforms/cpp/odbc-test/include/complex_type.h @@ -0,0 +1,122 @@ +/* + * 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_TEST_COMPLEX_TYPE +#define _IGNITE_ODBC_TEST_COMPLEX_TYPE + +#include <string> + +#include "ignite/ignite.h" +#include "ignite/ignition.h" + +namespace ignite +{ + struct TestObject + { + TestObject() : + f1(412), + f2("Lorem ipsum") + { + // No-op. + } + + int32_t f1; + std::string f2; + }; + + struct ComplexType + { + ComplexType() : + i32Field(0) + { + // No-op. + } + + int32_t i32Field; + TestObject objField; + std::string strField; + }; +} + +namespace ignite +{ + namespace binary + { + + IGNITE_BINARY_TYPE_START(ignite::TestObject) + + typedef ignite::TestObject TestObject; + + IGNITE_BINARY_GET_TYPE_ID_AS_HASH(TestObject) + IGNITE_BINARY_GET_TYPE_NAME_AS_IS(TestObject) + IGNITE_BINARY_GET_FIELD_ID_AS_HASH + IGNITE_BINARY_GET_HASH_CODE_ZERO(TestObject) + IGNITE_BINARY_IS_NULL_FALSE(TestObject) + IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(TestObject) + + void Write(BinaryWriter& writer, TestObject obj) + { + writer.WriteInt32("f1", obj.f1); + writer.WriteString("f2", obj.f2); + } + + TestObject Read(BinaryReader& reader) + { + TestObject obj; + + obj.f1 = reader.ReadInt32("f1"); + obj.f2 = reader.ReadString("f2"); + + return obj; + } + + IGNITE_BINARY_TYPE_END + + IGNITE_BINARY_TYPE_START(ignite::ComplexType) + + typedef ignite::ComplexType ComplexType; + + IGNITE_BINARY_GET_TYPE_ID_AS_HASH(ComplexType) + IGNITE_BINARY_GET_TYPE_NAME_AS_IS(ComplexType) + IGNITE_BINARY_GET_FIELD_ID_AS_HASH + IGNITE_BINARY_GET_HASH_CODE_ZERO(ComplexType) + IGNITE_BINARY_IS_NULL_FALSE(ComplexType) + IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(ComplexType) + + void Write(BinaryWriter& writer, ComplexType obj) + { + writer.WriteInt32("i32Field", obj.i32Field); + writer.WriteObject("objField", obj.objField); + writer.WriteString("strField", obj.strField); + } + + ComplexType Read(BinaryReader& reader) + { + ComplexType obj; + + obj.i32Field = reader.ReadInt32("i32Field"); + obj.objField = reader.ReadObject<TestObject>("objField"); + obj.strField = reader.ReadString("strField"); + + return obj; + } + + IGNITE_BINARY_TYPE_END + } +}; + +#endif // _IGNITE_ODBC_TEST_COMPLEX_TYPE http://git-wip-us.apache.org/repos/asf/ignite/blob/bf1770bc/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 91603dc..753ae4c 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj @@ -186,6 +186,7 @@ <ClCompile Include="..\..\src\utility_test.cpp" /> </ItemGroup> <ItemGroup> + <ClInclude Include="..\..\include\complex_type.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/bf1770bc/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 eef6abb..bedceaa 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 @@ -129,6 +129,9 @@ <ClInclude Include="..\..\include\sql_test_suite_fixture.h"> <Filter>Code</Filter> </ClInclude> + <ClInclude Include="..\..\include\complex_type.h"> + <Filter>Code\CacheTypes</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="..\..\config\queries-test.xml"> http://git-wip-us.apache.org/repos/asf/ignite/blob/bf1770bc/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 554cee2..52b885d 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -37,6 +37,7 @@ #include "ignite/impl/binary/binary_utils.h" #include "test_type.h" +#include "complex_type.h" #include "test_utils.h" using namespace ignite; @@ -150,11 +151,17 @@ struct QueriesTestSuiteFixture /** * Constructor. */ - QueriesTestSuiteFixture() : testCache(0), env(NULL), dbc(NULL), stmt(NULL) + QueriesTestSuiteFixture() : + cache1(0), + cache2(0), + env(NULL), + dbc(NULL), + stmt(NULL) { grid = StartNode("NodeMain", "queries-test.xml"); - testCache = grid.GetCache<int64_t, TestType>("cache"); + cache1 = grid.GetCache<int64_t, TestType>("cache"); + cache2 = grid.GetCache<int64_t, ComplexType>("cache2"); } /** @@ -180,8 +187,8 @@ struct QueriesTestSuiteFixture TestType in2(8, 7, 6, 5, "4", 3.0f, 2.0, false, Guid(1, 0), BinaryUtils::MakeDateGmt(1976, 1, 12), BinaryUtils::MakeTimestampGmt(1978, 8, 21, 23, 13, 45, 456)); - testCache.Put(1, in1); - testCache.Put(2, in2); + cache1.Put(1, in1); + cache1.Put(2, in2); const size_t columnsCnt = 11; @@ -362,8 +369,11 @@ struct QueriesTestSuiteFixture /** Node started during the test. */ Ignite grid; - /** Test cache instance. */ - Cache<int64_t, TestType> testCache; + /** Frist cache instance. */ + Cache<int64_t, TestType> cache1; + + /** Second cache instance. */ + Cache<int64_t, ComplexType> cache2; /** ODBC Environment. */ SQLHENV env; @@ -444,8 +454,8 @@ BOOST_AUTO_TEST_CASE(TestTwoRowsString) TestType in2(8, 7, 6, 5, "4", 3.0f, 2.0, false, Guid(1, 0), BinaryUtils::MakeDateGmt(1976, 1, 12), BinaryUtils::MakeTimestampGmt(1978, 8, 21, 23, 13, 45, 999999999)); - testCache.Put(1, in1); - testCache.Put(2, in2); + cache1.Put(1, in1); + cache1.Put(2, in2); const size_t columnsCnt = 11; @@ -541,7 +551,7 @@ BOOST_AUTO_TEST_CASE(TestOneRowString) TestType in(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456)); - testCache.Put(1, in); + cache1.Put(1, in); const size_t columnsCnt = 11; @@ -607,7 +617,7 @@ BOOST_AUTO_TEST_CASE(TestOneRowStringLen) TestType in(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456)); - testCache.Put(1, in); + cache1.Put(1, in); const size_t columnsCnt = 11; @@ -649,6 +659,63 @@ BOOST_AUTO_TEST_CASE(TestOneRowStringLen) BOOST_CHECK(ret == SQL_NO_DATA); } +BOOST_AUTO_TEST_CASE(TestOneRowObject) +{ + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache2"); + + SQLRETURN ret; + + ComplexType obj; + + obj.i32Field = 123; + obj.strField = "Some string"; + + obj.objField.f1 = 54321; + obj.objField.f2 = "Hello Ignite"; + + cache2.Put(1, obj); + + int64_t column1 = 0; + int8_t column2[ODBC_BUFFER_SIZE] = { 0 }; + char column3[ODBC_BUFFER_SIZE] = { 0 }; + + SQLLEN column1Len = sizeof(column1); + SQLLEN column2Len = sizeof(column2); + SQLLEN column3Len = sizeof(column3); + + // Binding columns. + ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &column1, column1Len, &column1Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 2, SQL_C_BINARY, &column2, column2Len, &column2Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLBindCol(stmt, 3, SQL_C_CHAR, &column3, column3Len, &column3Len); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + SQLCHAR request[] = "SELECT i32Field, objField, strField FROM ComplexType"; + + ret = SQLExecDirect(stmt, request, 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(column1, obj.i32Field); + BOOST_CHECK_EQUAL(column3, obj.strField); + + ret = SQLFetch(stmt); + BOOST_CHECK(ret == SQL_NO_DATA); +} + BOOST_AUTO_TEST_CASE(TestDataAtExecution) { Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache"); @@ -661,8 +728,8 @@ BOOST_AUTO_TEST_CASE(TestDataAtExecution) TestType in2(8, 7, 6, 5, "4", 3.0f, 2.0, false, Guid(1, 0), BinaryUtils::MakeDateGmt(1976, 1, 12), BinaryUtils::MakeTimestampGmt(1978, 8, 21, 23, 13, 45, 999999999)); - testCache.Put(1, in1); - testCache.Put(2, in2); + cache1.Put(1, in1); + cache1.Put(2, in2); const size_t columnsCnt = 11; @@ -785,9 +852,9 @@ BOOST_AUTO_TEST_CASE(TestNullFields) inNull.allNulls = true; - testCache.Put(1, in); - testCache.Put(2, inNull); - testCache.Put(3, in); + cache1.Put(1, in); + cache1.Put(2, inNull); + cache1.Put(3, in); const size_t columnsCnt = 10; @@ -900,7 +967,7 @@ BOOST_AUTO_TEST_CASE(TestDistributedJoins) entry.i32Field = i; entry.i64Field = entriesNum - i - 1; - testCache.Put(i, entry); + cache1.Put(i, entry); } Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache"); @@ -974,7 +1041,7 @@ BOOST_AUTO_TEST_CASE(TestDistributedJoinsWithOldVersion) entry.i32Field = i; entry.i64Field = entriesNum - i - 1; - testCache.Put(i, entry); + cache1.Put(i, entry); } Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache;DISTRIBUTED_JOINS=true;PROTOCOL_VERSION=1.6.0"); http://git-wip-us.apache.org/repos/asf/ignite/blob/bf1770bc/modules/platforms/cpp/odbc/src/column.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/column.cpp b/modules/platforms/cpp/odbc/src/column.cpp index b076a12..3e6bbca 100644 --- a/modules/platforms/cpp/odbc/src/column.cpp +++ b/modules/platforms/cpp/odbc/src/column.cpp @@ -31,24 +31,32 @@ namespace int8_t hdr = stream.ReadInt8(); - if (hdr != IGNITE_HDR_FULL) - return false; - - int8_t protoVer = stream.ReadInt8(); + switch (hdr) + { + case IGNITE_TYPE_BINARY: + { + // Header field + Length field + Object itself + Offset field + len = 1 + 4 + stream.ReadInt32() + 4; - if (protoVer != IGNITE_PROTO_VER) - return false; + break; + } + + case IGNITE_TYPE_OBJECT: + { + int8_t protoVer = stream.ReadInt8(); - // Skipping flags - stream.ReadInt16(); + if (protoVer != IGNITE_PROTO_VER) + return false; - // Skipping typeId - stream.ReadInt32(); + // Skipping flags, typeId and hash code + len = stream.ReadInt32(stream.Position() + 2 + 4 + 4); - // Skipping hash code - stream.ReadInt32(); + break; + } - len = stream.ReadInt32(); + default: + return false; + } return true; } @@ -238,7 +246,8 @@ namespace ignite break; } - case IGNITE_HDR_FULL: + case IGNITE_TYPE_BINARY: + case IGNITE_TYPE_OBJECT: { int32_t len; @@ -284,6 +293,7 @@ namespace ignite default: { // This is a fail case. + assert(false); return; } } @@ -413,7 +423,8 @@ namespace ignite break; } - case IGNITE_HDR_FULL: + case IGNITE_TYPE_BINARY: + case IGNITE_TYPE_OBJECT: { int32_t len; http://git-wip-us.apache.org/repos/asf/ignite/blob/bf1770bc/modules/platforms/cpp/odbc/src/type_traits.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/type_traits.cpp b/modules/platforms/cpp/odbc/src/type_traits.cpp index fced2e1..643e1b4 100644 --- a/modules/platforms/cpp/odbc/src/type_traits.cpp +++ b/modules/platforms/cpp/odbc/src/type_traits.cpp @@ -299,12 +299,14 @@ namespace ignite return IGNITE_ODBC_C_TYPE_WCHAR; case SQL_C_SSHORT: + case SQL_C_SHORT: return IGNITE_ODBC_C_TYPE_SIGNED_SHORT; case SQL_C_USHORT: return IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT; case SQL_C_SLONG: + case SQL_C_LONG: return IGNITE_ODBC_C_TYPE_SIGNED_LONG; case SQL_C_ULONG: @@ -320,6 +322,7 @@ namespace ignite return IGNITE_ODBC_C_TYPE_BIT; case SQL_C_STINYINT: + case SQL_C_TINYINT: return IGNITE_ODBC_C_TYPE_SIGNED_TINYINT; case SQL_C_UTINYINT:
