Repository: ignite Updated Branches: refs/heads/master 82504a0e5 -> 00902afbb
IGNITE-3587: ODBC: Added distributed joins support. This closes #908. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/311428ee Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/311428ee Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/311428ee Branch: refs/heads/master Commit: 311428eee8d52640a6efdac721335f63a4244d38 Parents: a596e67 Author: isapego <isap...@gridgain.com> Authored: Fri Aug 5 10:38:50 2016 +0300 Committer: vozerov-gridgain <voze...@gridgain.com> Committed: Fri Aug 5 10:38:50 2016 +0300 ---------------------------------------------------------------------- .../processors/odbc/OdbcHandshakeRequest.java | 42 +++- .../processors/odbc/OdbcHandshakeResult.java | 17 +- .../processors/odbc/OdbcMessageParser.java | 34 ++- .../processors/odbc/OdbcProtocolVersion.java | 125 +++++++++++ .../processors/odbc/OdbcRequestHandler.java | 26 ++- modules/platforms/cpp/odbc-test/Makefile.am | 1 + .../odbc-test/config/queries-test-noodbc.xml | 103 +++++++++ .../cpp/odbc-test/config/queries-test.xml | 45 ++-- .../cpp/odbc-test/project/vs/odbc-test.vcxproj | 1 + .../project/vs/odbc-test.vcxproj.filters | 3 + .../cpp/odbc-test/src/configuration_test.cpp | 148 +++++++++++-- .../cpp/odbc-test/src/queries_test.cpp | 218 +++++++++++++++++-- modules/platforms/cpp/odbc/Makefile.am | 1 + modules/platforms/cpp/odbc/include/Makefile.am | 1 + .../cpp/odbc/include/ignite/odbc/common_types.h | 3 + .../include/ignite/odbc/config/configuration.h | 67 +++++- .../cpp/odbc/include/ignite/odbc/connection.h | 16 +- .../cpp/odbc/include/ignite/odbc/message.h | 35 ++- .../cpp/odbc/include/ignite/odbc/parser.h | 3 - .../odbc/include/ignite/odbc/protocol_version.h | 172 +++++++++++++++ .../platforms/cpp/odbc/project/vs/odbc.vcxproj | 2 + .../cpp/odbc/project/vs/odbc.vcxproj.filters | 6 + .../cpp/odbc/src/config/configuration.cpp | 92 ++++++-- modules/platforms/cpp/odbc/src/connection.cpp | 23 +- .../odbc/src/diagnostic/diagnostic_record.cpp | 6 + .../platforms/cpp/odbc/src/protocol_version.cpp | 134 ++++++++++++ 26 files changed, 1204 insertions(+), 120 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java index 5e09041..55ff21f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java @@ -24,24 +24,58 @@ import org.apache.ignite.internal.util.typedef.internal.S; */ public class OdbcHandshakeRequest extends OdbcRequest { /** Protocol version. */ - private final long ver; + private final OdbcProtocolVersion ver; + + /** Distributed joins flag. */ + private boolean distributedJoins = false; + + /** Enforce join order flag. */ + private boolean enforceJoinOrder = false; /** - * @param ver Protocol version. + * @param ver Long value for protocol version. */ public OdbcHandshakeRequest(long ver) { super(HANDSHAKE); - this.ver = ver; + this.ver = OdbcProtocolVersion.fromLong(ver); } /** * @return Protocol version. */ - public long version() { + public OdbcProtocolVersion version() { return ver; } + /** + * @return Distributed joins flag. + */ + public boolean distributedJoins() { + return distributedJoins; + } + + /** + * @param distributedJoins Distributed joins flag. + */ + public void distributedJoins(boolean distributedJoins) { + this.distributedJoins = distributedJoins; + } + + /** + * @return Enforce join order flag. + */ + public boolean enforceJoinOrder() { + return enforceJoinOrder; + } + + /** + * @param enforceJoinOrder Enforce join order flag. + */ + public void enforceJoinOrder(boolean enforceJoinOrder) { + this.enforceJoinOrder = enforceJoinOrder; + } + /** {@inheritDoc} */ @Override public String toString() { return S.toString(OdbcHandshakeRequest.class, this); http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java index bf1c61e..74c5bd4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java @@ -17,7 +17,7 @@ package org.apache.ignite.internal.processors.odbc; -import org.jetbrains.annotations.Nullable; +import org.apache.ignite.internal.util.typedef.internal.S; /** * ODBC handshake result. @@ -33,11 +33,13 @@ public class OdbcHandshakeResult { private final String curVer; /** - * @param accepted Handshake accepted. + * Constructor. + * + * @param accepted Indicates whether handshake accepted or not. * @param protoVerSince Apache Ignite version when protocol version has been introduced. * @param curVer Current Apache Ignite version. */ - public OdbcHandshakeResult(boolean accepted, @Nullable String protoVerSince, @Nullable String curVer) { + public OdbcHandshakeResult(boolean accepted, String protoVerSince, String curVer) { this.accepted = accepted; this.protoVerSince = protoVerSince; this.curVer = curVer; @@ -53,14 +55,19 @@ public class OdbcHandshakeResult { /** * @return Apache Ignite version when protocol version has been introduced. */ - @Nullable public String protoVerSince() { + public String protocolVersionSince() { return protoVerSince; } /** * @return Current Apache Ignite version. */ - @Nullable public String currentVer() { + public String currentVersion() { return curVer; } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(OdbcHandshakeResult.class, this); + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java index fce8b1b..e8b594e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java @@ -34,12 +34,6 @@ import java.util.Collection; * ODBC message parser. */ public class OdbcMessageParser { - /** Current ODBC communication protocol version. */ - public static final long PROTO_VER = 1; - - /** Apache Ignite version when ODBC communication protocol version has been introduced. */ - public static final String PROTO_VER_SINCE = "1.6.0"; - /** Initial output stream capacity. */ private static final int INIT_CAP = 1024; @@ -82,10 +76,26 @@ public class OdbcMessageParser { // we has not confirmed that the remote client uses the same protocol version. if (!verConfirmed) { if (cmd == OdbcRequest.HANDSHAKE) - return new OdbcHandshakeRequest(reader.readLong()); + { + long longVersion = reader.readLong(); + + OdbcHandshakeRequest res = new OdbcHandshakeRequest(longVersion); + + OdbcProtocolVersion version = res.version(); + + if (version.isUnknown()) + return res; + + if (version.isDistributedJoinsSupported()) { + res.distributedJoins(reader.readBoolean()); + res.enforceJoinOrder(reader.readBoolean()); + } + + return res; + } else - throw new IgniteException("Unexpected ODBC command (first message is not a handshake request): [cmd=" + - cmd + ']'); + throw new IgniteException("Unexpected ODBC command " + + "(first message is not a handshake request): [cmd=" + cmd + ']'); } OdbcRequest res; @@ -174,6 +184,8 @@ public class OdbcMessageParser { Object res0 = msg.response(); + if (res0 == null) + return writer.array(); if (res0 instanceof OdbcHandshakeResult) { OdbcHandshakeResult res = (OdbcHandshakeResult) res0; @@ -189,8 +201,8 @@ public class OdbcMessageParser { } else { writer.writeBoolean(false); - writer.writeString(res.protoVerSince()); - writer.writeString(res.currentVer()); + writer.writeString(res.protocolVersionSince()); + writer.writeString(res.currentVersion()); } } else if (res0 instanceof OdbcQueryExecuteResult) { http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProtocolVersion.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProtocolVersion.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProtocolVersion.java new file mode 100644 index 0000000..57efa02 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProtocolVersion.java @@ -0,0 +1,125 @@ +/* + * 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. + */ +package org.apache.ignite.internal.processors.odbc; + +import java.util.HashMap; +import java.util.Map; + +/** + * ODBC protocol version. + */ +public enum OdbcProtocolVersion { + /** First version of the ODBC. Released with Ignite 1.6 */ + VERSION_1_6_0(1), + + /** Second version of the ODBC. Released with Ignite 1.8 */ + VERSION_1_8_0(makeVersion(1,8,0)), + + /** Unknown version. */ + VERSION_UNKNOWN(Long.MIN_VALUE); + + /** Mask to get 2 lowest bytes of the value and cast to long. */ + private static final long LONG_MASK = 0x000000000000FFFFL; + + /** Long value to enum map. */ + private static final Map<Long, OdbcProtocolVersion> versions = new HashMap<>(); + + /** Enum value to Ignite version map */ + private static final Map<OdbcProtocolVersion, String> since = new HashMap<>(); + + /** + * Map long values to version. + */ + static { + for (OdbcProtocolVersion version : values()) + versions.put(version.longValue(), version); + + since.put(VERSION_1_6_0, "1.6.0"); + since.put(VERSION_1_8_0, "1.8.0"); + } + + /** Long value for version. */ + private final long longVal; + + /** + * @param longVal Long value. + */ + OdbcProtocolVersion(long longVal) { + this.longVal = longVal; + } + + /** + * Make long value for the version. + * + * @param major Major version. + * @param minor Minor version. + * @param maintenance Maintenance version. + * @return Long value for the version. + */ + private static long makeVersion(int major, int minor, int maintenance) { + return ((major & LONG_MASK) << 48) | ((minor & LONG_MASK) << 32) | ((maintenance & LONG_MASK) << 16); + } + + /** + * @param longVal Long value. + * @return Protocol version. + */ + public static OdbcProtocolVersion fromLong(long longVal) { + OdbcProtocolVersion res = versions.get(longVal); + + return res == null ? VERSION_UNKNOWN : res; + } + + /** + * @return Current version. + */ + public static OdbcProtocolVersion current() { + return VERSION_1_8_0; + } + + /** + * @return Long value. + */ + public long longValue() { + return longVal; + } + + /** + * @return {@code true} if this version is unknown. + */ + public boolean isUnknown() { + return longVal == VERSION_UNKNOWN.longVal; + } + + /** + * @return {@code true} if this version supports distributed joins. + */ + public boolean isDistributedJoinsSupported() { + assert !isUnknown(); + + return longVal >= VERSION_1_8_0.longVal; + } + + /** + * @return Ignite version when introduced. + */ + public String since() { + assert !isUnknown(); + + return since.get(this); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java index 43a1fa4..8f2d092 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java @@ -54,6 +54,12 @@ public class OdbcRequestHandler { /** Current queries cursors. */ private final ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCursors = new ConcurrentHashMap<>(); + /** Distributed joins flag. */ + private boolean distributedJoins = false; + + /** Enforce join order flag. */ + private boolean enforceJoinOrder = false; + /** * Constructor. * @@ -115,16 +121,23 @@ public class OdbcRequestHandler { * @return Response. */ private OdbcResponse performHandshake(OdbcHandshakeRequest req) { - OdbcHandshakeResult res; + OdbcProtocolVersion version = req.version(); - if (req.version() == OdbcMessageParser.PROTO_VER) - res = new OdbcHandshakeResult(true, null, null); - else { + if (version.isUnknown()) { IgniteProductVersion ver = ctx.grid().version(); String verStr = Byte.toString(ver.major()) + '.' + ver.minor() + '.' + ver.maintenance(); - res = new OdbcHandshakeResult(false, OdbcMessageParser.PROTO_VER_SINCE, verStr); + OdbcHandshakeResult res = new OdbcHandshakeResult(false, OdbcProtocolVersion.current().since(), verStr); + + return new OdbcResponse(res); + } + + OdbcHandshakeResult res = new OdbcHandshakeResult(true, null, null); + + if (version.isDistributedJoinsSupported()) { + distributedJoins = req.distributedJoins(); + enforceJoinOrder = req.enforceJoinOrder(); } return new OdbcResponse(res); @@ -151,6 +164,9 @@ public class OdbcRequestHandler { qry.setArgs(req.arguments()); + qry.setDistributedJoins(distributedJoins); + qry.setEnforceJoinOrder(enforceJoinOrder); + IgniteCache<Object, Object> cache = ctx.grid().cache(req.cacheName()); if (cache == null) http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 48b193a..a878d02 100644 --- a/modules/platforms/cpp/odbc-test/Makefile.am +++ b/modules/platforms/cpp/odbc-test/Makefile.am @@ -66,6 +66,7 @@ ignite_odbc_tests_SOURCES = \ ../odbc/src/app/application_data_buffer.cpp \ ../odbc/src/config/configuration.cpp \ ../odbc/src/row.cpp \ + ../odbc/src/protocol_version.cpp \ ../odbc/src/column.cpp \ ../odbc/src/utility.cpp \ ../odbc/src/result_page.cpp http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml b/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml new file mode 100644 index 0000000..18447c2 --- /dev/null +++ b/modules/platforms/cpp/odbc-test/config/queries-test-noodbc.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + 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. +--> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:util="http://www.springframework.org/schema/util" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util + http://www.springframework.org/schema/util/spring-util.xsd"> + <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> + <property name="localHost" value="127.0.0.1"/> + <property name="connectorConfiguration"><null/></property> + + <property name="cacheConfiguration"> + <list> + <bean class="org.apache.ignite.configuration.CacheConfiguration"> + <property name="name" value="cache"/> + <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="TestType"/> + + <property name="fields"> + <map> + <entry key="i8Field" value="java.lang.Byte"/> + <entry key="i16Field" value="java.lang.Short"/> + <entry key="i32Field" value="java.lang.Integer"/> + <entry key="i64Field" value="java.lang.Long"/> + <entry key="strField" value="java.lang.String"/> + <entry key="floatField" value="java.lang.Float"/> + <entry key="doubleField" value="java.lang.Double"/> + <entry key="boolField" value="java.lang.Boolean"/> + <entry key="guidField" value="java.util.UUID"/> + <entry key="dateField" value="java.util.Date"/> + <entry key="timestampField" value="java.sql.Timestamp"/> + </map> + </property> + + <property name="indexes"> + <list> + <bean class="org.apache.ignite.cache.QueryIndex"> + <constructor-arg value="i32Field"/> + </bean> + <bean class="org.apache.ignite.cache.QueryIndex"> + <constructor-arg value="i64Field"/> + </bean> + </list> + </property> + </bean> + </list> + </property> + </bean> + </list> + </property> + + <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. --> + <property name="discoverySpi"> + <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi"> + <property name="ipFinder"> + <!-- + Ignite provides several options for automatic discovery that can be used + instead os static IP based discovery. + --> + <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. --> + <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">--> + <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"> + <property name="addresses"> + <list> + <!-- In distributed environment, replace with actual host IP address. --> + <value>127.0.0.1:47500</value> + </list> + </property> + </bean> + </property> + <property name="socketTimeout" value="300" /> + </bean> + </property> + </bean> +</beans> http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 054da42..54cb9be 100644 --- a/modules/platforms/cpp/odbc-test/config/queries-test.xml +++ b/modules/platforms/cpp/odbc-test/config/queries-test.xml @@ -41,17 +41,18 @@ <bean class="org.apache.ignite.configuration.CacheConfiguration"> <property name="name" value="cache"/> <property name="cacheMode" value="PARTITIONED"/> - <property name="atomicityMode" value="ATOMIC"/> - <property name="writeSynchronizationMode" value="PRIMARY_SYNC"/> + <property name="atomicityMode" value="TRANSACTIONAL"/> + <property name="writeSynchronizationMode" value="FULL_SYNC"/> <!-- Configure type metadata to enable queries. --> - <property name="typeMetadata"> - <list> - <bean class="org.apache.ignite.cache.CacheTypeMetadata"> - <property name="keyType" value="java.lang.Long"/> - <property name="valueType" value="TestType"/> - <property name="queryFields"> - <map> + <property name="queryEntities"> + <list> + <bean class="org.apache.ignite.cache.QueryEntity"> + <property name="keyType" value="java.lang.Long"/> + <property name="valueType" value="TestType"/> + + <property name="fields"> + <map> <entry key="i8Field" value="java.lang.Byte"/> <entry key="i16Field" value="java.lang.Short"/> <entry key="i32Field" value="java.lang.Integer"/> @@ -63,11 +64,22 @@ <entry key="guidField" value="java.util.UUID"/> <entry key="dateField" value="java.util.Date"/> <entry key="timestampField" value="java.sql.Timestamp"/> - </map> - </property> - </bean> - </list> - </property> + </map> + </property> + + <property name="indexes"> + <list> + <bean class="org.apache.ignite.cache.QueryIndex"> + <constructor-arg value="i32Field"/> + </bean> + <bean class="org.apache.ignite.cache.QueryIndex"> + <constructor-arg value="i64Field"/> + </bean> + </list> + </property> + </bean> + </list> + </property> </bean> </list> </property> @@ -81,12 +93,11 @@ instead os static IP based discovery. --> <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. --> - <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">--> - <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"> + <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder"> <property name="addresses"> <list> <!-- In distributed environment, replace with actual host IP address. --> - <value>127.0.0.1:47500..47501</value> + <value>127.0.0.1:47500</value> </list> </property> </bean> http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 fbc0929..833904e 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj @@ -157,6 +157,7 @@ <ClCompile Include="..\..\..\odbc\src\config\configuration.cpp" /> <ClCompile Include="..\..\..\odbc\src\config\connection_info.cpp" /> <ClCompile Include="..\..\..\odbc\src\cursor.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\utility.cpp" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 2e38c24..aead2af 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 @@ -76,6 +76,9 @@ <ClCompile Include="..\..\src\queries_test.cpp"> <Filter>Code</Filter> </ClCompile> + <ClCompile Include="..\..\..\odbc\src\protocol_version.cpp"> + <Filter>Externals</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\test_type.h"> http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 10fd137..c0bb439 100644 --- a/modules/platforms/cpp/odbc-test/src/configuration_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/configuration_test.cpp @@ -20,6 +20,7 @@ #endif #include <iostream> +#include <set> #include <boost/test/unit_test.hpp> @@ -36,6 +37,8 @@ namespace const uint16_t testServerPort = 4242; const std::string testCacheName = "TestCache"; const std::string testDsn = "Ignite DSN"; + const bool testDistributedJoins = true; + const bool testEnforceJoinOrder = true; const std::string testAddress = testServerHost + ':' + ignite::common::LexicalCast<std::string>(testServerPort); } @@ -49,6 +52,42 @@ void CheckValidAddress(const char* connectStr, uint16_t port) BOOST_CHECK_EQUAL(cfg.GetPort(), port); } +void CheckValidProtocolVersion(const char* connectStr, ignite::odbc::ProtocolVersion version) +{ + Configuration cfg; + + BOOST_CHECK_NO_THROW(cfg.FillFromConnectString(connectStr)); + + BOOST_CHECK(cfg.GetProtocolVersion() == version); +} + +void CheckInvalidProtocolVersion(const char* connectStr) +{ + Configuration cfg; + + cfg.FillFromConnectString(connectStr); + + BOOST_CHECK_THROW(cfg.GetProtocolVersion(), ignite::IgniteError); +} + +void CheckValidBoolValue(const std::string& connectStr, const std::string& key, bool val) +{ + Configuration cfg; + + BOOST_CHECK_NO_THROW(cfg.FillFromConnectString(connectStr)); + + BOOST_CHECK_EQUAL(cfg.GetBoolValue(key, val), val); +} + +void CheckInvalidBoolValue(const std::string& connectStr, const std::string& key) +{ + Configuration cfg; + + cfg.FillFromConnectString(connectStr); + + BOOST_CHECK_THROW(cfg.GetBoolValue(key, false), ignite::IgniteError); +} + void CheckConnectionConfig(const Configuration& cfg) { BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName); @@ -57,16 +96,20 @@ void CheckConnectionConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetAddress(), testAddress); BOOST_CHECK_EQUAL(cfg.GetCache(), testCacheName); BOOST_CHECK_EQUAL(cfg.GetDsn(), std::string()); + BOOST_CHECK_EQUAL(cfg.IsDistributedJoins(), testDistributedJoins); + BOOST_CHECK_EQUAL(cfg.IsEnforceJoinOrder(), testEnforceJoinOrder); std::stringstream constructor; constructor << "address=" << testAddress << ';' << "cache=" << testCacheName << ';' - << "driver={" << testDriverName << "};"; + << "distributed_joins=" << (testDistributedJoins ? "true" : "false") << ';' + << "driver={" << testDriverName << "};" + << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false") << ';'; const std::string& expectedStr = constructor.str(); - BOOST_CHECK_EQUAL(cfg.ToConnectString(), expectedStr); + BOOST_CHECK_EQUAL(ignite::common::ToLower(cfg.ToConnectString()), ignite::common::ToLower(expectedStr)); } void CheckDsnConfig(const Configuration& cfg) @@ -76,7 +119,9 @@ void CheckDsnConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetCache(), Configuration::DefaultValue::cache); BOOST_CHECK_EQUAL(cfg.GetAddress(), Configuration::DefaultValue::address); BOOST_CHECK_EQUAL(cfg.GetHost(), std::string()); - BOOST_CHECK_EQUAL(cfg.GetPort(), Configuration::DefaultValue::uintPort); + BOOST_CHECK_EQUAL(cfg.GetPort(), Configuration::DefaultValue::port); + BOOST_CHECK_EQUAL(cfg.IsDistributedJoins(), false); + BOOST_CHECK_EQUAL(cfg.IsEnforceJoinOrder(), false); } BOOST_AUTO_TEST_SUITE(ConfigurationTestSuite) @@ -85,9 +130,11 @@ BOOST_AUTO_TEST_CASE(CheckTestValuesNotEquealDefault) { BOOST_CHECK_NE(testDriverName, Configuration::DefaultValue::driver); BOOST_CHECK_NE(testAddress, Configuration::DefaultValue::address); - BOOST_CHECK_NE(testServerPort, Configuration::DefaultValue::uintPort); + BOOST_CHECK_NE(testServerPort, Configuration::DefaultValue::port); BOOST_CHECK_NE(testCacheName, Configuration::DefaultValue::cache); BOOST_CHECK_NE(testDsn, Configuration::DefaultValue::dsn); + BOOST_CHECK_NE(testDistributedJoins, Configuration::DefaultValue::distributedJoins); + BOOST_CHECK_NE(testEnforceJoinOrder, Configuration::DefaultValue::enforceJoinOrder); } BOOST_AUTO_TEST_CASE(TestConnectStringUppercase) @@ -98,7 +145,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase) constructor << "DRIVER={" << testDriverName << "};" << "ADDRESS=" << testAddress << ';' - << "CACHE=" << testCacheName; + << "CACHE=" << testCacheName << ';' + << "DISTRIBUTED_JOINS=" << (testDistributedJoins ? "TRUE" : "FALSE") << ';' + << "ENFORCE_JOIN_ORDER=" << (testEnforceJoinOrder ? "TRUE" : "FALSE"); const std::string& connectStr = constructor.str(); @@ -115,7 +164,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase) constructor << "driver={" << testDriverName << "};" << "address=" << testAddress << ';' - << "cache=" << testCacheName; + << "cache=" << testCacheName << ';' + << "distributed_joins=" << (testDistributedJoins ? "true" : "false") << ';' + << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false"); const std::string& connectStr = constructor.str(); @@ -132,7 +183,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated) constructor << "driver={" << testDriverName << "};" << "address=" << testAddress << ';' - << "cache=" << testCacheName; + << "cache=" << testCacheName << ';' + << "distributed_joins=" << (testDistributedJoins ? "true" : "false") << ';' + << "enforce_join_order=" << (testEnforceJoinOrder ? "true" : "false"); const std::string& connectStr = constructor.str(); @@ -149,7 +202,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed) constructor << "Driver={" << testDriverName << "};" << "Address=" << testAddress << ';' - << "Cache=" << testCacheName; + << "Cache=" << testCacheName << ';' + << "Distributed_Joins=" << (testDistributedJoins ? "True" : "False") << ';' + << "Enforce_Join_Order=" << (testEnforceJoinOrder ? "True" : "False"); const std::string& connectStr = constructor.str(); @@ -166,7 +221,9 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces) constructor << "DRIVER = {" << testDriverName << "} ;\n" << " ADDRESS =" << testAddress << "; " - << "CACHE = \n\r" << testCacheName; + << "CACHE = \n\r" << testCacheName << ';' + << " DISTRIBUTED_JOINS=" << (testDistributedJoins ? "TRUE" : "FALSE") << ';' + << "ENFORCE_JOIN_ORDER= " << (testEnforceJoinOrder ? "TRUE " : "FALSE "); const std::string& connectStr = constructor.str(); @@ -190,13 +247,74 @@ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidAddress) BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress) { - Configuration cfg; - 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::uintPort); + CheckValidAddress("Address=example.com;", Configuration::DefaultValue::port); +} + +BOOST_AUTO_TEST_CASE(TestConnectStringInvalidVersion) +{ + CheckInvalidProtocolVersion("Protocol_Version=0;"); + CheckInvalidProtocolVersion("Protocol_Version=1;"); + CheckInvalidProtocolVersion("Protocol_Version=2;"); + CheckInvalidProtocolVersion("Protocol_Version=1.6.1;"); + CheckInvalidProtocolVersion("Protocol_Version=1.7.0;"); + CheckInvalidProtocolVersion("Protocol_Version=1.8.1;"); +} + +BOOST_AUTO_TEST_CASE(TestConnectStringValidVersion) +{ + CheckValidProtocolVersion("Protocol_Version=1.6.0;", ignite::odbc::ProtocolVersion::VERSION_1_6_0); + CheckValidProtocolVersion("Protocol_Version=1.8.0;", ignite::odbc::ProtocolVersion::VERSION_1_8_0); +} + +BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) +{ + typedef std::set<std::string> Set; + + Set keys; + + keys.insert("distributed_joins"); + keys.insert("enforce_join_order"); + + for (Set::const_iterator it = keys.begin(); it != keys.end(); ++it) + { + const std::string& key = *it; + + CheckInvalidBoolValue(key + "=1;", key); + CheckInvalidBoolValue(key + "=0;", key); + CheckInvalidBoolValue(key + "=42;", key); + CheckInvalidBoolValue(key + "=truee;", key); + CheckInvalidBoolValue(key + "=flase;", key); + CheckInvalidBoolValue(key + "=falsee;", key); + CheckInvalidBoolValue(key + "=yes;", key); + CheckInvalidBoolValue(key + "=no;", key); + } +} + +BOOST_AUTO_TEST_CASE(TestConnectStringValidBoolKeys) +{ + typedef std::set<std::string> Set; + + Set keys; + + keys.insert("distributed_joins"); + keys.insert("enforce_join_order"); + + for (Set::const_iterator it = keys.begin(); it != keys.end(); ++it) + { + const std::string& key = *it; + + CheckValidBoolValue(key + "=true;", key, true); + CheckValidBoolValue(key + "=True;", key, true); + CheckValidBoolValue(key + "=TRUE;", key, true); + + CheckValidBoolValue(key + "=false;", key, false); + CheckValidBoolValue(key + "=False;", key, false); + CheckValidBoolValue(key + "=FALSE;", key, false); + } } BOOST_AUTO_TEST_CASE(TestDsnStringUppercase) @@ -215,7 +333,7 @@ BOOST_AUTO_TEST_CASE(TestDsnStringUppercase) CheckDsnConfig(cfg); } -BOOST_AUTO_TEST_CASE(TestDsnStrinLowercase) +BOOST_AUTO_TEST_CASE(TestDsnStringLowercase) { Configuration cfg; @@ -231,7 +349,7 @@ BOOST_AUTO_TEST_CASE(TestDsnStrinLowercase) CheckDsnConfig(cfg); } -BOOST_AUTO_TEST_CASE(TestDsnStrinMixed) +BOOST_AUTO_TEST_CASE(TestDsnStringMixed) { Configuration cfg; @@ -247,7 +365,7 @@ BOOST_AUTO_TEST_CASE(TestDsnStrinMixed) CheckDsnConfig(cfg); } -BOOST_AUTO_TEST_CASE(TestDsnStrinWhitespaces) +BOOST_AUTO_TEST_CASE(TestDsnStringWhitespaces) { Configuration cfg; http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 ccb3a4d..58b5f64 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -122,6 +122,44 @@ struct QueriesTestSuiteFixture 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) + { + IgniteConfiguration cfg; + + cfg.jvmOpts.push_back("-Xdebug"); + cfg.jvmOpts.push_back("-Xnoagent"); + cfg.jvmOpts.push_back("-Djava.compiler=NONE"); + cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); + cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); + +#ifdef IGNITE_TESTS_32 + cfg.jvmInitMem = 256; + cfg.jvmMaxMem = 768; +#else + cfg.jvmInitMem = 1024; + cfg.jvmMaxMem = 4096; +#endif + + cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH")).append("/queries-test-noodbc.xml"); + + IgniteError err; + + return Ignition::Start(cfg, name); + } + /** * Constructor. */ @@ -143,16 +181,11 @@ struct QueriesTestSuiteFixture cfg.jvmMaxMem = 4096; #endif - char* cfgPath = getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH"); - - cfg.springCfgPath = std::string(cfgPath).append("/").append("queries-test.xml"); + cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH")).append("/queries-test.xml"); IgniteError err; - grid = Ignition::Start(cfg, &err); - - if (err.GetCode() != IgniteError::IGNITE_SUCCESS) - BOOST_FAIL(err.GetText()); + grid = Ignition::Start(cfg, "NodeMain"); testCache = grid.GetCache<int64_t, TestType>("cache"); } @@ -162,17 +195,9 @@ struct QueriesTestSuiteFixture */ ~QueriesTestSuiteFixture() { - // 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); + Disconnect(); - Ignition::Stop(grid.GetName(), true); + Ignition::StopAll(true); } template<typename T> @@ -269,6 +294,28 @@ struct QueriesTestSuiteFixture BOOST_CHECK(ret == SQL_NO_DATA); } + int CountRows(SQLHSTMT stmt) + { + int res = 0; + + SQLRETURN 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)); + + ++res; + } + + return res; + } + /** Node started during the test. */ Ignite grid; @@ -292,6 +339,16 @@ BOOST_AUTO_TEST_CASE(TestLegacyConnection) Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;CACHE=cache"); } +BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_1_6_0) +{ + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache;PROTOCOL_VERSION=1.6.0"); +} + +BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_1_8_0) +{ + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache;PROTOCOL_VERSION=1.8.0"); +} + BOOST_AUTO_TEST_CASE(TestTwoRowsInt8) { CheckTwoRowsInt<int8_t>(SQL_C_STINYINT); @@ -538,4 +595,131 @@ BOOST_AUTO_TEST_CASE(TestOneRowStringLen) BOOST_CHECK(ret == SQL_NO_DATA); } +BOOST_AUTO_TEST_CASE(TestDistributedJoins) +{ + // Starting additional node. + Ignite node1 = StartAdditionalNode("Node1"); + Ignite node2 = StartAdditionalNode("Node2"); + + const int entriesNum = 1000; + + // Filling cache with data. + for (int i = 0; i < entriesNum; ++i) + { + TestType entry; + + entry.i32Field = i; + entry.i64Field = entriesNum - i - 1; + + testCache.Put(i, entry); + } + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache"); + + SQLRETURN ret; + + const size_t columnsCnt = 2; + + SQLBIGINT columns[columnsCnt] = { 0 }; + + // Binding colums. + for (SQLSMALLINT i = 0; i < columnsCnt; ++i) + { + ret = SQLBindCol(stmt, i + 1, SQL_C_SLONG, &columns[i], 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + } + + SQLCHAR request[] = + "SELECT T0.i32Field, T1.i64Field FROM TestType AS T0 " + "INNER JOIN TestType AS T1 " + "ON (T0.i32Field = T1.i64Field)"; + + ret = SQLExecDirect(stmt, request, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + int rowsNum = CountRows(stmt); + + BOOST_CHECK_GT(rowsNum, 0); + BOOST_CHECK_LT(rowsNum, entriesNum); + + Disconnect(); + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache;DISTRIBUTED_JOINS=true;"); + + // Binding colums. + for (SQLSMALLINT i = 0; i < columnsCnt; ++i) + { + ret = SQLBindCol(stmt, i + 1, SQL_C_SLONG, &columns[i], 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + } + + ret = SQLExecDirect(stmt, request, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + rowsNum = CountRows(stmt); + + BOOST_CHECK_EQUAL(rowsNum, entriesNum); +} + +BOOST_AUTO_TEST_CASE(TestDistributedJoinsWithOldVersion) +{ + // Starting additional node. + Ignite node1 = StartAdditionalNode("Node1"); + Ignite node2 = StartAdditionalNode("Node2"); + + const int entriesNum = 1000; + + // Filling cache with data. + for (int i = 0; i < entriesNum; ++i) + { + TestType entry; + + entry.i32Field = i; + entry.i64Field = entriesNum - i - 1; + + testCache.Put(i, entry); + } + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache;DISTRIBUTED_JOINS=true;PROTOCOL_VERSION=1.6.0"); + + SQLRETURN ret; + + const size_t columnsCnt = 2; + + SQLBIGINT columns[columnsCnt] = { 0 }; + + // Binding colums. + for (SQLSMALLINT i = 0; i < columnsCnt; ++i) + { + ret = SQLBindCol(stmt, i + 1, SQL_C_SLONG, &columns[i], 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + } + + SQLCHAR request[] = + "SELECT T0.i32Field, T1.i64Field FROM TestType AS T0 " + "INNER JOIN TestType AS T1 " + "ON (T0.i32Field = T1.i64Field)"; + + ret = SQLExecDirect(stmt, request, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + int rowsNum = CountRows(stmt); + + BOOST_CHECK_GT(rowsNum, 0); + BOOST_CHECK_LT(rowsNum, entriesNum); +} + + BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/Makefile.am b/modules/platforms/cpp/odbc/Makefile.am index 29f0ef4..9faa999 100644 --- a/modules/platforms/cpp/odbc/Makefile.am +++ b/modules/platforms/cpp/odbc/Makefile.am @@ -69,6 +69,7 @@ libignite_odbc_la_SOURCES = \ src/query/table_metadata_query.cpp \ src/query/type_info_query.cpp \ src/query/special_columns_query.cpp \ + src/protocol_version.cpp \ src/result_page.cpp \ src/row.cpp \ src/column.cpp \ http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/Makefile.am b/modules/platforms/cpp/odbc/include/Makefile.am index 192021d..0776548 100644 --- a/modules/platforms/cpp/odbc/include/Makefile.am +++ b/modules/platforms/cpp/odbc/include/Makefile.am @@ -27,6 +27,7 @@ noinst_HEADERS = \ ignite/odbc/query/column_metadata_query.h \ ignite/odbc/query/query.h \ ignite/odbc/query/primary_keys_query.h \ + ignite/odbc/protocol_version.h \ ignite/odbc/statement.h \ ignite/odbc/config/configuration.h \ ignite/odbc/config/connection_info.h \ http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h b/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h index 6636ca4..250eaf2 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h @@ -60,6 +60,9 @@ namespace ignite /** Output data has been truncated. */ SQL_STATE_01004_DATA_TRUNCATED, + /** Invalid connection string attribute. */ + SQL_STATE_01S00_INVALID_CONNECTION_STRING_ATTRIBUTE, + /** Error in row. */ SQL_STATE_01S01_ERROR_IN_ROW, http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 05fe8bf..30f9ad6 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h @@ -24,6 +24,7 @@ #include <ignite/common/common.h> #include <ignite/common/utils.h> +#include "ignite/odbc/protocol_version.h" namespace ignite { @@ -60,6 +61,15 @@ namespace ignite /** 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; }; /** Default values for configuration. */ @@ -80,11 +90,17 @@ namespace ignite /** Default value for server attribute. */ static const std::string server; + /** Default value for protocol version. */ + static const ProtocolVersion& protocolVersion; + /** Default value for port attribute. */ - static const std::string port; + static const uint16_t port; - /** Default value for port attribute. Uint16 value. */ - static const uint16_t uintPort; + /** Default value for distributed joins attribute. */ + static const bool distributedJoins; + + /** Default value for enforce join order attribute. */ + static const bool enforceJoinOrder; }; /** @@ -200,6 +216,33 @@ namespace ignite } /** + * Check distributed joins flag. + * + * @return True if distributed joins are enabled. + */ + bool IsDistributedJoins() const + { + return GetBoolValue(Key::distributedJoins, DefaultValue::distributedJoins); + } + + /** + * Check enforce join order flag. + * + * @return True if enforcing of join order is enabled. + */ + bool IsEnforceJoinOrder() const + { + return GetBoolValue(Key::enforceJoinOrder, DefaultValue::enforceJoinOrder); + } + + /** + * Get protocol version. + * + * @return Protocol version. + */ + ProtocolVersion GetProtocolVersion() const; + + /** * Get string value from the config. * * @param key Configuration key. @@ -208,6 +251,24 @@ namespace ignite */ const std::string& GetStringValue(const std::string& key, const std::string& dflt) const; + /** + * Get int 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. + */ + int64_t GetIntValue(const std::string& key, int64_t dflt) const; + + /** + * Get bool 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. + */ + bool GetBoolValue(const std::string& key, bool dflt) const; + private: /** * Parse connect string into key-value storage. http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 00bdfc8..9fe46df 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h @@ -41,15 +41,6 @@ namespace ignite { friend class Environment; public: - /** ODBC communication protocol version. */ - enum { PROTOCOL_VERSION = 1 }; - - /** - * Apache Ignite version when the current ODBC communication - * protocol version has been introduced. - */ - static const std::string PROTOCOL_VERSION_SINCE; - /** * Destructor. */ @@ -263,6 +254,13 @@ namespace ignite SqlResult MakeRequestHandshake(); /** + * Perform configure request. + * + * @return Operation result. + */ + SqlResult MakeRequestConfigure(); + + /** * Constructor. */ Connection(); http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/include/ignite/odbc/message.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h index f0b40e2..03fa627 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h @@ -66,8 +66,13 @@ namespace ignite * Constructor. * * @param version Protocol version. + * @param distributedJoins Distributed joins flag. + * @param enforceJoinOrder Enforce join order flag. */ - HandshakeRequest(int64_t version) : version(version) + HandshakeRequest(int64_t version, bool distributedJoins, bool enforceJoinOrder) : + version(version), + distributedJoins(distributedJoins), + enforceJoinOrder(enforceJoinOrder) { // No-op. } @@ -89,11 +94,20 @@ namespace ignite writer.WriteInt8(REQUEST_TYPE_HANDSHAKE); writer.WriteInt64(version); + + writer.WriteBool(distributedJoins); + writer.WriteBool(enforceJoinOrder); } private: /** Protocol version. */ int64_t version; + + /** Distributed joins flag. */ + bool distributedJoins; + + /** Enforce join order flag. */ + bool enforceJoinOrder; }; /** @@ -153,6 +167,7 @@ namespace ignite const app::ParameterBindingMap& params; }; + /** * Query close request. */ @@ -348,13 +363,13 @@ namespace ignite /** * Query close response. */ - class QueryResponse + class Response { public: /** * Constructor. */ - QueryResponse() : status(RESPONSE_STATUS_FAILED), error() + Response() : status(RESPONSE_STATUS_FAILED), error() { // No-op. } @@ -362,7 +377,7 @@ namespace ignite /** * Destructor. */ - ~QueryResponse() + virtual ~Response() { // No-op. } @@ -426,7 +441,7 @@ namespace ignite /** * Handshake response. */ - class HandshakeResponse : public QueryResponse + class HandshakeResponse : public Response { public: /** @@ -504,7 +519,7 @@ namespace ignite /** * Query close response. */ - class QueryCloseResponse : public QueryResponse + class QueryCloseResponse : public Response { public: /** @@ -549,7 +564,7 @@ namespace ignite /** * Query execute response. */ - class QueryExecuteResponse : public QueryResponse + class QueryExecuteResponse : public Response { public: /** @@ -608,7 +623,7 @@ namespace ignite /** * Query fetch response. */ - class QueryFetchResponse : public QueryResponse + class QueryFetchResponse : public Response { public: /** @@ -659,7 +674,7 @@ namespace ignite /** * Query get column metadata response. */ - class QueryGetColumnsMetaResponse : public QueryResponse + class QueryGetColumnsMetaResponse : public Response { public: /** @@ -704,7 +719,7 @@ namespace ignite /** * Query get table metadata response. */ - class QueryGetTablesMetaResponse : public QueryResponse + class QueryGetTablesMetaResponse : public Response { public: /** http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h b/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h index c19e08c..a91af22 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h @@ -42,9 +42,6 @@ namespace ignite /** Default initial size of operational memory. */ enum { DEFAULT_MEM_ALLOCATION = 4096 }; - /** ODBC communication protocol version. */ - enum { PROTOCOL_VERSION = 1 }; - /** * Constructor. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/include/ignite/odbc/protocol_version.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/protocol_version.h b/modules/platforms/cpp/odbc/include/ignite/odbc/protocol_version.h new file mode 100644 index 0000000..747d78d --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/protocol_version.h @@ -0,0 +1,172 @@ +/* + * 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_PROTOCOL_VERSION +#define _IGNITE_ODBC_PROTOCOL_VERSION + +#include <stdint.h> + +#include <string> +#include <map> + +namespace ignite +{ + namespace odbc + { + /** Protocol version. */ + class ProtocolVersion + { + public: + /** String to version map type alias. */ + typedef std::map<std::string, ProtocolVersion> StringToVersionMap; + + /** Version to string map type alias. */ + typedef std::map<ProtocolVersion, std::string> VersionToStringMap; + + /** First version of the protocol that was introduced in Ignite 1.6.0. */ + static const ProtocolVersion VERSION_1_6_0; + + /** First version of the protocol that was introduced in Ignite 1.8.0. */ + static const ProtocolVersion VERSION_1_8_0; + + /** Unknown version of the protocol. */ + static const ProtocolVersion VERSION_UNKNOWN; + + /** + * Get current version. + * + * @return Current version. + */ + static const ProtocolVersion& GetCurrent(); + + /** + * Parse string and extract protocol version. + * + * @throw IgniteException if version can not be parsed. + * @param version Version string to parse. + * @return Protocol version. + */ + static ProtocolVersion FromString(const std::string& version); + + /** + * Convert to string value. + * + * @throw IgniteException if version is unknow parsed. + * @param version Version string to parse. + * @return Protocol version. + */ + const std::string& ToString() const; + + /** + * Get int value. + * + * @return Integer value. + */ + int64_t GetIntValue() const; + + /** + * Check if the version is unknown. + * + * @return True if the version is unknown. + */ + bool IsUnknown() const; + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if equal. + */ + friend bool operator==(const ProtocolVersion& val1, const ProtocolVersion& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if not equal. + */ + friend bool operator!=(const ProtocolVersion& val1, const ProtocolVersion& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if less. + */ + friend bool operator<(const ProtocolVersion& val1, const ProtocolVersion& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if less or equal. + */ + friend bool operator<=(const ProtocolVersion& val1, const ProtocolVersion& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if gretter. + */ + friend bool operator>(const ProtocolVersion& val1, const ProtocolVersion& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if gretter or equal. + */ + friend bool operator>=(const ProtocolVersion& val1, const ProtocolVersion& val2); + + private: + /** + * Constructor. + * + * @param val Underlying value. + */ + explicit ProtocolVersion(int64_t val); + + /** + * Make int value for the version. + * + * @param major Major version. + * @param minor Minor version. + * @param maintenance Maintenance version. + * @return Int value for the version. + */ + static int64_t MakeVersion(uint16_t major, uint16_t minor, uint16_t maintenance); + + /** String to version map. */ + static const StringToVersionMap stringToVersionMap; + + /** Version to string map. */ + static const VersionToStringMap versionToStringMap; + + /** Underlying int value. */ + int64_t val; + }; + } +} + +#endif //_IGNITE_ODBC_PROTOCOL_VERSION \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 5820030..0e0f0d3 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj @@ -170,6 +170,7 @@ <ClCompile Include="..\..\src\meta\column_meta.cpp" /> <ClCompile Include="..\..\src\meta\table_meta.cpp" /> <ClCompile Include="..\..\src\odbc.cpp" /> + <ClCompile Include="..\..\src\protocol_version.cpp" /> <ClCompile Include="..\..\src\query\data_query.cpp" /> <ClCompile Include="..\..\src\query\column_metadata_query.cpp" /> <ClCompile Include="..\..\src\query\foreign_keys_query.cpp" /> @@ -206,6 +207,7 @@ <ClInclude Include="..\..\include\ignite\odbc\meta\primary_key_meta.h" /> <ClInclude Include="..\..\include\ignite\odbc\meta\table_meta.h" /> <ClInclude Include="..\..\include\ignite\odbc\parser.h" /> + <ClInclude Include="..\..\include\ignite\odbc\protocol_version.h" /> <ClInclude Include="..\..\include\ignite\odbc\query\data_query.h" /> <ClInclude Include="..\..\include\ignite\odbc\query\column_metadata_query.h" /> <ClInclude Include="..\..\include\ignite\odbc\query\foreign_keys_query.h" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 6ca58e2..9caf483 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters @@ -115,6 +115,9 @@ <ClCompile Include="..\..\src\entry_points.cpp"> <Filter>Code</Filter> </ClCompile> + <ClCompile Include="..\..\src\protocol_version.cpp"> + <Filter>Code</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <None Include="module.def"> @@ -224,5 +227,8 @@ <ClInclude Include="..\..\include\ignite\odbc.h"> <Filter>Code</Filter> </ClInclude> + <ClInclude Include="..\..\include\ignite\odbc\protocol_version.h"> + <Filter>Code</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 45b0507..24c2bdf 100644 --- a/modules/platforms/cpp/odbc/src/config/configuration.cpp +++ b/modules/platforms/cpp/odbc/src/config/configuration.cpp @@ -20,6 +20,9 @@ #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" @@ -29,20 +32,29 @@ namespace ignite { namespace config { - const std::string Configuration::Key::dsn = "dsn"; - const std::string Configuration::Key::driver = "driver"; - const std::string Configuration::Key::cache = "cache"; - 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::DefaultValue::dsn = "Apache Ignite DSN"; - const std::string Configuration::DefaultValue::driver = "Apache Ignite"; - const std::string Configuration::DefaultValue::cache = ""; - const std::string Configuration::DefaultValue::address = ""; - const std::string Configuration::DefaultValue::server = ""; - const std::string Configuration::DefaultValue::port = "10800"; - const uint16_t Configuration::DefaultValue::uintPort = common::LexicalCast<uint16_t>(port); + const std::string Configuration::Key::dsn = "dsn"; + const std::string Configuration::Key::driver = "driver"; + const std::string Configuration::Key::cache = "cache"; + 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::DefaultValue::dsn = "Apache Ignite DSN"; + const std::string Configuration::DefaultValue::driver = "Apache Ignite"; + const std::string Configuration::DefaultValue::cache = ""; + const std::string Configuration::DefaultValue::address = ""; + const std::string Configuration::DefaultValue::server = ""; + + const uint16_t Configuration::DefaultValue::port = 10800; + + const bool Configuration::DefaultValue::distributedJoins = false; + const bool Configuration::DefaultValue::enforceJoinOrder = false; + + const ProtocolVersion& Configuration::DefaultValue::protocolVersion = ProtocolVersion::GetCurrent(); + Configuration::Configuration() : arguments() @@ -80,7 +92,7 @@ namespace ignite else { endPoint.host = GetStringValue(Key::server, DefaultValue::server); - endPoint.port = common::LexicalCast<uint16_t>(GetStringValue(Key::port, DefaultValue::port)); + endPoint.port = static_cast<uint16_t>(GetIntValue(Key::port, DefaultValue::port)); } } @@ -134,10 +146,20 @@ namespace ignite else { endPoint.host = GetStringValue(Key::server, DefaultValue::server); - endPoint.port = common::LexicalCast<uint16_t>(GetStringValue(Key::port, DefaultValue::port)); + endPoint.port = static_cast<uint16_t>(GetIntValue(Key::port, DefaultValue::port)); } } + ProtocolVersion Configuration::GetProtocolVersion() const + { + ArgumentMap::const_iterator it = arguments.find(Key::protocolVersion); + + if (it != arguments.end()) + return ProtocolVersion::FromString(it->second); + + return DefaultValue::protocolVersion; + } + const std::string& Configuration::GetStringValue(const std::string& key, const std::string& dflt) const { ArgumentMap::const_iterator it = arguments.find(common::ToLower(key)); @@ -148,6 +170,42 @@ namespace ignite return dflt; } + int64_t Configuration::GetIntValue(const std::string& key, int64_t dflt) const + { + ArgumentMap::const_iterator it = arguments.find(common::ToLower(key)); + + if (it != arguments.end()) + { + const std::string& val = it->second; + + 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); + + return common::LexicalCast<int64_t>(val); + } + + return dflt; + } + + bool Configuration::GetBoolValue(const std::string& key, bool dflt) const + { + ArgumentMap::const_iterator it = arguments.find(common::ToLower(key)); + + if (it != arguments.end()) + { + std::string lowercaseVal = common::ToLower(it->second); + + 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); + + return lowercaseVal == "true"; + } + + return dflt; + } + void Configuration::ParseAttributeList(const char * str, size_t len, char delimeter, ArgumentMap & args) { std::string connect_str(str, len); @@ -199,7 +257,7 @@ namespace ignite if (colonNum == 0) { res.host = address; - res.port = DefaultValue::uintPort; + res.port = DefaultValue::port; } else if (colonNum == 1) { http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/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 844ad70..4315698 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -39,8 +39,6 @@ namespace ignite { namespace odbc { - const std::string Connection::PROTOCOL_VERSION_SINCE = "1.6.0"; - Connection::Connection() : socket(), connected(false), @@ -309,7 +307,24 @@ namespace ignite SqlResult Connection::MakeRequestHandshake() { - HandshakeRequest req(PROTOCOL_VERSION); + bool distributedJoins = false; + bool enforceJoinOrder = false; + int64_t protocolVersion = 0; + + try + { + distributedJoins = config.IsDistributedJoins(); + enforceJoinOrder = config.IsEnforceJoinOrder(); + protocolVersion = config.GetProtocolVersion().GetIntValue(); + } + catch (const IgniteError& err) + { + AddStatusRecord(SQL_STATE_01S00_INVALID_CONNECTION_STRING_ATTRIBUTE, err.GetText()); + + return SQL_RESULT_ERROR; + } + + HandshakeRequest req(protocolVersion, distributedJoins, enforceJoinOrder); HandshakeResponse rsp; try @@ -343,7 +358,7 @@ namespace ignite constructor << "Node rejected handshake message. " << "Current node Apache Ignite version: " << rsp.CurrentVer() << ", " << "node protocol version introduced in version: " << rsp.ProtoVerSince() << ", " - << "driver protocol version introduced in version: " << PROTOCOL_VERSION_SINCE << "."; + << "driver protocol version introduced in version: " << config.GetProtocolVersion().ToString() << "."; AddStatusRecord(SQL_STATE_08001_CANNOT_CONNECT, constructor.str()); http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp index 568c125..0fdfbc8 100644 --- a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp +++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp @@ -34,6 +34,9 @@ namespace /** SQL state 01004 constant. */ const std::string STATE_01004 = "01004"; + /** SQL state 01S00 constant. */ + const std::string STATE_01S00 = "01S00"; + /** SQL state 01S01 constant. */ const std::string STATE_01S01 = "01S01"; @@ -190,6 +193,9 @@ namespace ignite case SQL_STATE_01004_DATA_TRUNCATED: return STATE_01004; + case SQL_STATE_01S00_INVALID_CONNECTION_STRING_ATTRIBUTE: + return STATE_01S00; + case SQL_STATE_01S01_ERROR_IN_ROW: return STATE_01S01; http://git-wip-us.apache.org/repos/asf/ignite/blob/311428ee/modules/platforms/cpp/odbc/src/protocol_version.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/protocol_version.cpp b/modules/platforms/cpp/odbc/src/protocol_version.cpp new file mode 100644 index 0000000..c65099d --- /dev/null +++ b/modules/platforms/cpp/odbc/src/protocol_version.cpp @@ -0,0 +1,134 @@ +/* + * 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 "ignite/odbc/protocol_version.h" +#include <ignite/common/concurrent.h> +#include <ignite/common/utils.h> +#include <ignite/ignite_error.h> + +namespace ignite +{ + namespace odbc + { + const ProtocolVersion ProtocolVersion::VERSION_1_6_0(1); + const ProtocolVersion ProtocolVersion::VERSION_1_8_0(MakeVersion(1,8,0)); + const ProtocolVersion ProtocolVersion::VERSION_UNKNOWN(INT64_MIN); + + ProtocolVersion::StringToVersionMap::value_type s2vInitVals[] = { + std::make_pair("1.6.0", ProtocolVersion::VERSION_1_6_0), + std::make_pair("1.8.0", ProtocolVersion::VERSION_1_8_0) + }; + + const ProtocolVersion::StringToVersionMap ProtocolVersion::stringToVersionMap(s2vInitVals, + s2vInitVals + (sizeof(s2vInitVals) / sizeof(s2vInitVals[0]))); + + ProtocolVersion::VersionToStringMap::value_type v2sInitVals[] = { + std::make_pair(ProtocolVersion::VERSION_1_6_0, "1.6.0"), + std::make_pair(ProtocolVersion::VERSION_1_8_0, "1.8.0") + }; + + const ProtocolVersion::VersionToStringMap ProtocolVersion::versionToStringMap(v2sInitVals, + v2sInitVals + (sizeof(v2sInitVals) / sizeof(v2sInitVals[0]))); + + ProtocolVersion::ProtocolVersion(int64_t val) : + val(val) + { + // No-op. + } + + int64_t ProtocolVersion::MakeVersion(uint16_t major, uint16_t minor, uint16_t maintenance) + { + const static int64_t MASK = 0x000000000000FFFFLL; + return ((major & MASK) << 48) | ((minor & MASK) << 32) | ((maintenance & MASK) << 16); + } + + const ProtocolVersion& ProtocolVersion::GetCurrent() + { + return VERSION_1_8_0; + } + + ProtocolVersion ProtocolVersion::FromString(const std::string& version) + { + StringToVersionMap::const_iterator it = stringToVersionMap.find(common::ToLower(version)); + + if (it == stringToVersionMap.end()) + { + throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, + "Invalid version format. Valid format is X.Y.Z, where X, Y and Z are major, " + "minor and maintenance versions of Ignite since which protocol is introduced."); + } + + return it->second; + } + + const std::string& ProtocolVersion::ToString() const + { + VersionToStringMap::const_iterator it = versionToStringMap.find(*this); + + if (it == versionToStringMap.end()) + { + throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, + "Unknown protocol version can not be converted to string."); + } + + return it->second; + } + + int64_t ProtocolVersion::GetIntValue() const + { + assert(!IsUnknown()); + + return val; + } + + bool ProtocolVersion::IsUnknown() const + { + return *this == VERSION_UNKNOWN; + } + + bool operator==(const ProtocolVersion& val1, const ProtocolVersion& val2) + { + return val1.val == val2.val; + } + + bool operator!=(const ProtocolVersion& val1, const ProtocolVersion& val2) + { + return val1.val != val2.val; + } + + bool operator<(const ProtocolVersion& val1, const ProtocolVersion& val2) + { + return val1.val < val2.val; + } + + bool operator<=(const ProtocolVersion& val1, const ProtocolVersion& val2) + { + return val1.val <= val2.val; + } + + bool operator>(const ProtocolVersion& val1, const ProtocolVersion& val2) + { + return val1.val > val2.val; + } + + bool operator>=(const ProtocolVersion& val1, const ProtocolVersion& val2) + { + return val1.val >= val2.val; + } + } +} +