IGNITE-7855: ODBC: implemented streaming mode. This closes #4669.

Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/9f8d331d
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/9f8d331d
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/9f8d331d

Branch: refs/heads/ignite-2.7
Commit: 9f8d331dca3255621c31f4c8eac861107c089fee
Parents: ba7833c
Author: Igor Sapego <igors...@gmail.com>
Authored: Thu Sep 27 11:25:48 2018 +0300
Committer: devozerov <voze...@gridgain.com>
Committed: Thu Sep 27 11:28:36 2018 +0300

----------------------------------------------------------------------
 .../odbc/ClientListenerNioListener.java         |   2 +-
 .../odbc/ClientListenerResponseSender.java      |  29 +
 .../odbc/jdbc/JdbcConnectionContext.java        |   3 +-
 .../odbc/jdbc/JdbcRequestHandler.java           |   5 +-
 .../odbc/jdbc/JdbcResponseSender.java           |  31 -
 .../odbc/odbc/OdbcConnectionContext.java        |  33 +-
 .../processors/odbc/odbc/OdbcMessageParser.java |  32 +
 .../processors/odbc/odbc/OdbcQuery.java         |  94 +++
 .../processors/odbc/odbc/OdbcRequest.java       |  25 +-
 .../odbc/odbc/OdbcRequestHandler.java           | 321 +++++++---
 .../odbc/odbc/OdbcStreamingBatchRequest.java    | 102 ++++
 .../odbc/odbc/OdbcStreamingBatchResult.java     |  74 +++
 .../processors/query/SqlClientContext.java      |   2 +-
 .../ignite/impl/interop/interop_memory.h        |   7 +
 .../binary/src/impl/interop/interop_memory.cpp  |   5 +
 modules/platforms/cpp/common/Makefile.am        |   2 +-
 .../platforms/cpp/common/include/Makefile.am    |   1 +
 .../include/ignite/common/default_allocator.h   |   6 -
 .../cpp/common/include/ignite/common/expected.h | 300 ++++++++++
 .../cpp/common/include/ignite/common/utils.h    |   9 +
 .../cpp/common/project/vs/common.vcxproj        |   1 +
 .../common/project/vs/common.vcxproj.filters    |   3 +
 .../cpp/core-test/src/teamcity_boost.cpp        |   2 +-
 modules/platforms/cpp/odbc-test/Makefile.am     |  10 +-
 .../cpp/odbc-test/include/odbc_test_suite.h     |   2 +-
 .../cpp/odbc-test/include/test_utils.h          |  10 +-
 .../cpp/odbc-test/project/vs/odbc-test.vcxproj  |  14 +-
 .../project/vs/odbc-test.vcxproj.filters        |  18 +
 .../cpp/odbc-test/src/api_robustness_test.cpp   |  22 +-
 .../cpp/odbc-test/src/attributes_test.cpp       |  13 +-
 .../cpp/odbc-test/src/authentication_test.cpp   |   2 +-
 .../cpp/odbc-test/src/connection_test.cpp       |   4 +-
 .../platforms/cpp/odbc-test/src/errors_test.cpp |   2 +-
 .../cpp/odbc-test/src/meta_queries_test.cpp     |   4 +-
 .../cpp/odbc-test/src/queries_ssl_test.cpp      |   2 +-
 .../cpp/odbc-test/src/queries_test.cpp          |   4 +-
 .../cpp/odbc-test/src/sql_get_info_test.cpp     |   2 +-
 .../cpp/odbc-test/src/sql_parsing_test.cpp      | 372 ++++++++++++
 .../odbc-test/src/sql_test_suite_fixture.cpp    |   6 +-
 .../cpp/odbc-test/src/streaming_test.cpp        | 589 +++++++++++++++++++
 .../odbc-test/src/teamcity/teamcity_boost.cpp   |   2 +-
 .../platforms/cpp/odbc-test/src/test_utils.cpp  |  13 +
 .../platforms/cpp/odbc-test/src/types_test.cpp  |   2 +-
 modules/platforms/cpp/odbc/Makefile.am          |   7 +
 modules/platforms/cpp/odbc/include/Makefile.am  |  10 +
 .../odbc/config/connection_string_parser.h      |   4 +-
 .../cpp/odbc/include/ignite/odbc/connection.h   |  52 +-
 .../cpp/odbc/include/ignite/odbc/message.h      | 124 +++-
 .../cpp/odbc/include/ignite/odbc/odbc_error.h   |  36 +-
 .../ignite/odbc/query/column_metadata_query.h   |   2 +-
 .../ignite/odbc/query/foreign_keys_query.h      |   2 +-
 .../include/ignite/odbc/query/internal_query.h  | 189 ++++++
 .../ignite/odbc/query/primary_keys_query.h      |   2 +-
 .../cpp/odbc/include/ignite/odbc/query/query.h  |  10 +-
 .../ignite/odbc/query/special_columns_query.h   |   2 +-
 .../include/ignite/odbc/query/streaming_query.h | 151 +++++
 .../ignite/odbc/query/table_metadata_query.h    |   2 +-
 .../include/ignite/odbc/query/type_info_query.h |   2 +-
 .../odbc/include/ignite/odbc/sql/sql_command.h  |  87 +++
 .../odbc/include/ignite/odbc/sql/sql_lexer.h    | 117 ++++
 .../odbc/include/ignite/odbc/sql/sql_parser.h   |  68 +++
 .../ignite/odbc/sql/sql_set_streaming_command.h | 198 +++++++
 .../odbc/include/ignite/odbc/sql/sql_token.h    | 159 +++++
 .../odbc/include/ignite/odbc/sql/sql_utils.h    |  62 ++
 .../cpp/odbc/include/ignite/odbc/statement.h    |  30 +
 .../ignite/odbc/streaming/streaming_batch.h     | 115 ++++
 .../ignite/odbc/streaming/streaming_context.h   | 136 +++++
 .../src/system/ui/dsn_configuration_window.cpp  |  19 +-
 .../platforms/cpp/odbc/project/vs/odbc.vcxproj  |  17 +
 .../cpp/odbc/project/vs/odbc.vcxproj.filters    |  57 ++
 .../src/config/connection_string_parser.cpp     |   4 +-
 modules/platforms/cpp/odbc/src/connection.cpp   |   7 +-
 modules/platforms/cpp/odbc/src/message.cpp      |  62 +-
 .../cpp/odbc/src/query/batch_query.cpp          |   3 +-
 .../cpp/odbc/src/query/streaming_query.cpp      |  93 +++
 .../platforms/cpp/odbc/src/sql/sql_lexer.cpp    | 236 ++++++++
 .../platforms/cpp/odbc/src/sql/sql_parser.cpp   |  97 +++
 .../odbc/src/sql/sql_set_streaming_command.cpp  | 200 +++++++
 .../platforms/cpp/odbc/src/sql/sql_utils.cpp    |  55 ++
 modules/platforms/cpp/odbc/src/statement.cpp    | 134 ++++-
 .../cpp/odbc/src/streaming/streaming_batch.cpp  |  76 +++
 .../odbc/src/streaming/streaming_context.cpp    | 158 +++++
 82 files changed, 4749 insertions(+), 218 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
index c9670c6..0eb6ac4 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
@@ -286,7 +286,7 @@ public class ClientListenerNioListener extends 
GridNioServerListenerAdapter<byte
 
         switch (clientType) {
             case ODBC_CLIENT:
-                return new OdbcConnectionContext(ctx, busyLock, connId, 
maxCursors);
+                return new OdbcConnectionContext(ctx, ses, busyLock, connId, 
maxCursors);
 
             case JDBC_CLIENT:
                 return new JdbcConnectionContext(ctx, ses, busyLock, connId, 
maxCursors);

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerResponseSender.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerResponseSender.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerResponseSender.java
new file mode 100644
index 0000000..dcb2d3f
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerResponseSender.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+/**
+ * Client listener response result sender.
+ */
+public interface ClientListenerResponseSender {
+    /**
+     * Send response to the client. Used for asynchronous result send.
+     * @param resp Client listener response.
+     */
+    public void send(ClientListenerResponse resp);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
index 5e9a1b3..c80136d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java
@@ -29,6 +29,7 @@ import 
org.apache.ignite.internal.processors.odbc.ClientListenerMessageParser;
 import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler;
 import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
+import org.apache.ignite.internal.processors.odbc.ClientListenerResponseSender;
 import org.apache.ignite.internal.processors.query.NestedTxMode;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
 import org.apache.ignite.internal.util.nio.GridNioSession;
@@ -174,7 +175,7 @@ public class JdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
 
         parser = new JdbcMessageParser(ctx, ver);
 
-        JdbcResponseSender sender = new JdbcResponseSender() {
+        ClientListenerResponseSender sender = new 
ClientListenerResponseSender() {
             @Override public void send(ClientListenerResponse resp) {
                 if (resp != null) {
                     if (log.isDebugEnabled())

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
index 97ce20a..d59788c 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java
@@ -52,6 +52,7 @@ import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequest;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler;
 import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
+import org.apache.ignite.internal.processors.odbc.ClientListenerResponseSender;
 import 
org.apache.ignite.internal.processors.odbc.odbc.OdbcQueryGetColumnsMetaRequest;
 import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
 import org.apache.ignite.internal.processors.query.GridQueryProperty;
@@ -127,7 +128,7 @@ public class JdbcRequestHandler implements 
ClientListenerRequestHandler {
     private final Object orderedBatchesMux = new Object();
 
     /** Response sender. */
-    private final JdbcResponseSender sender;
+    private final ClientListenerResponseSender sender;
 
     /** Automatic close of cursors. */
     private final boolean autoCloseCursors;
@@ -158,7 +159,7 @@ public class JdbcRequestHandler implements 
ClientListenerRequestHandler {
      * @param protocolVer Protocol version.
      */
     public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock,
-        JdbcResponseSender sender, int maxCursors,
+        ClientListenerResponseSender sender, int maxCursors,
         boolean distributedJoins, boolean enforceJoinOrder, boolean 
collocated, boolean replicatedOnly,
         boolean autoCloseCursors, boolean lazy, boolean skipReducerOnUpdate, 
NestedTxMode nestedTxMode,
         AuthorizationContext actx, ClientListenerProtocolVersion protocolVer) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponseSender.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponseSender.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponseSender.java
deleted file mode 100644
index 128bcee..0000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponseSender.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.jdbc;
-
-import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
-
-/**
- * JDBC response result sender.
- */
-public interface JdbcResponseSender {
-    /**
-     * Send response to the client. Used for asynchronous result send.
-     * @param resp JDBC response.
-     */
-    public void send(ClientListenerResponse resp);
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
index d82dcc6..5592aab 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.processors.odbc.odbc;
 
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import 
org.apache.ignite.internal.processors.authentication.AuthorizationContext;
@@ -26,7 +27,10 @@ import 
org.apache.ignite.internal.processors.odbc.ClientListenerMessageParser;
 import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler;
 import org.apache.ignite.internal.processors.query.NestedTxMode;
+import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
+import org.apache.ignite.internal.processors.odbc.ClientListenerResponseSender;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.nio.GridNioSession;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -59,6 +63,9 @@ public class OdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
     /** Supported versions. */
     private static final Set<ClientListenerProtocolVersion> SUPPORTED_VERS = 
new HashSet<>();
 
+    /** Session. */
+    private final GridNioSession ses;
+
     /** Shutdown busy lock. */
     private final GridSpinBusyLock busyLock;
 
@@ -71,6 +78,9 @@ public class OdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
     /** Request handler. */
     private OdbcRequestHandler handler = null;
 
+    /** Logger. */
+    private final IgniteLogger log;
+
     static {
         SUPPORTED_VERS.add(CURRENT_VER);
         SUPPORTED_VERS.add(VER_2_5_0);
@@ -83,15 +93,19 @@ public class OdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
     /**
      * Constructor.
      * @param ctx Kernal Context.
+     * @param ses Session.
      * @param busyLock Shutdown busy lock.
-     * @param connId
+     * @param connId Connection ID.
      * @param maxCursors Maximum allowed cursors.
      */
-    public OdbcConnectionContext(GridKernalContext ctx, GridSpinBusyLock 
busyLock, long connId, int maxCursors) {
+    public OdbcConnectionContext(GridKernalContext ctx, GridNioSession ses, 
GridSpinBusyLock busyLock, long connId, int maxCursors) {
         super(ctx, connId);
 
+        this.ses = ses;
         this.busyLock = busyLock;
         this.maxCursors = maxCursors;
+
+        log = ctx.log(getClass());
     }
 
     /** {@inheritDoc} */
@@ -140,7 +154,20 @@ public class OdbcConnectionContext extends 
ClientListenerAbstractConnectionConte
 
         AuthorizationContext actx = authenticate(user, passwd);
 
-        handler = new OdbcRequestHandler(ctx, busyLock, maxCursors, 
distributedJoins, enforceJoinOrder,
+        ClientListenerResponseSender sender = new 
ClientListenerResponseSender() {
+            @Override public void send(ClientListenerResponse resp) {
+                if (resp != null) {
+                    if (log.isDebugEnabled())
+                        log.debug("Async response: [resp=" + resp.status() + 
']');
+
+                    byte[] outMsg = parser.encode(resp);
+
+                    ses.send(outMsg);
+                }
+            }
+        };
+
+        handler = new OdbcRequestHandler(ctx, busyLock, sender, maxCursors, 
distributedJoins, enforceJoinOrder,
             replicatedOnly, collocated, lazy, skipReducerOnUpdate, actx, 
nestedTxMode, ver);
 
         parser = new OdbcMessageParser(ctx, ver);

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
index 5b4cebb..0e9b48a 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.odbc.odbc;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
@@ -138,6 +139,30 @@ public class OdbcMessageParser implements 
ClientListenerMessageParser {
                 break;
             }
 
+            case OdbcRequest.STREAMING_BATCH:
+            {
+                String schema = reader.readString();
+
+                int num = reader.readInt();
+
+                ArrayList<OdbcQuery> queries = new ArrayList<>(num);
+
+                for (int i = 0; i < num; ++i)
+                {
+                    OdbcQuery qry = new OdbcQuery();
+                    qry.readBinary(reader);
+
+                    queries.add(qry);
+                }
+
+                boolean last = reader.readBoolean();
+                long order = reader.readLong();
+
+                res = new OdbcStreamingBatchRequest(schema, queries, last, 
order);
+
+                break;
+            }
+
             case OdbcRequest.QRY_FETCH: {
                 long queryId = reader.readLong();
                 int pageSize = reader.readInt();
@@ -278,6 +303,13 @@ public class OdbcMessageParser implements 
ClientListenerMessageParser {
                     writer.writeInt(res.errorCode());
             }
         }
+        else if (res0 instanceof OdbcStreamingBatchResult) {
+            OdbcStreamingBatchResult res = (OdbcStreamingBatchResult) res0;
+
+            writer.writeString(res.error());
+            writer.writeInt(res.status());
+            writer.writeLong(res.order());
+        }
         else if (res0 instanceof OdbcQueryFetchResult) {
             OdbcQueryFetchResult res = (OdbcQueryFetchResult) res0;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQuery.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQuery.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQuery.java
new file mode 100644
index 0000000..d89cc0d
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQuery.java
@@ -0,0 +1,94 @@
+/*
+ * 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.odbc;
+
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * ODBC SQL query with parameters.
+ */
+public class OdbcQuery {
+    /** Query SQL. */
+    private String sql;
+
+    /** Arguments. */
+    private Object[] args;
+
+    /**
+     * Default constructor is used for serialization.
+     */
+    public OdbcQuery() {
+        // No-op.
+    }
+
+    /**
+     * @return Query SQL string.
+     */
+    public String sql() {
+        return sql;
+    }
+
+    /**
+     * @return Query arguments.
+     */
+    public Object[] args() {
+        return args;
+    }
+
+    /**
+     * Writes fields to provided writer.
+     *
+     * @param writer Binary object writer.
+     */
+    public void writeBinary(BinaryWriterExImpl writer) {
+        writer.writeString(sql);
+
+        if (args == null || args.length == 0)
+            writer.writeInt(0);
+        else {
+            writer.writeInt(args.length);
+
+            for (Object arg : args)
+                SqlListenerUtils.writeObject(writer, arg, false);
+        }
+    }
+
+    /**
+     * Reads fields from provided reader.
+     *
+     * @param reader Binary object reader.
+     */
+    public void readBinary(BinaryReaderExImpl reader) {
+        sql = reader.readString();
+
+        int argsNum = reader.readInt();
+
+        args = new Object[argsNum];
+
+        for (int i = 0; i < argsNum; ++i)
+            args[i] = SqlListenerUtils.readObject(reader, false);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQuery.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
index 9b9aa01..5b02cfe 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java
@@ -24,43 +24,46 @@ import 
org.apache.ignite.internal.processors.odbc.ClientListenerRequestNoId;
  */
 public class OdbcRequest extends ClientListenerRequestNoId {
     /** Execute sql query. */
-    public static final int QRY_EXEC = 2;
+    public static final byte QRY_EXEC = 2;
 
     /** Fetch query results. */
-    public static final int QRY_FETCH = 3;
+    public static final byte QRY_FETCH = 3;
 
     /** Close query. */
-    public static final int QRY_CLOSE = 4;
+    public static final byte QRY_CLOSE = 4;
 
     /** Get columns meta query. */
-    public static final int META_COLS = 5;
+    public static final byte META_COLS = 5;
 
     /** Get columns meta query. */
-    public static final int META_TBLS = 6;
+    public static final byte META_TBLS = 6;
 
     /** Get parameters meta. */
-    public static final int META_PARAMS = 7;
+    public static final byte META_PARAMS = 7;
 
     /** Execute sql query with the batch of parameters. */
-    public static final int QRY_EXEC_BATCH = 8;
+    public static final byte QRY_EXEC_BATCH = 8;
 
     /** Get next result set. */
-    public static final int MORE_RESULTS = 9;
+    public static final byte MORE_RESULTS = 9;
+
+    /** Process ordered streaming batch. */
+    public static final byte STREAMING_BATCH = 10;
 
     /** Command. */
-    private final int cmd;
+    private final byte cmd;
 
     /**
      * @param cmd Command type.
      */
-    public OdbcRequest(int cmd) {
+    public OdbcRequest(byte cmd) {
         this.cmd = cmd;
     }
 
     /**
      * @return Command.
      */
-    public int command() {
+    public byte command() {
         return cmd;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
index 16baeb9..6f3324d 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
@@ -25,15 +25,18 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.PriorityQueue;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
+import javax.cache.configuration.Factory;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 import org.apache.ignite.internal.binary.GridBinaryMarshaller;
 import 
org.apache.ignite.internal.processors.authentication.AuthorizationContext;
@@ -44,16 +47,21 @@ import 
org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequest;
 import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler;
 import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
+import org.apache.ignite.internal.processors.odbc.ClientListenerResponseSender;
 import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils;
 import org.apache.ignite.internal.processors.query.GridQueryProperty;
 import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.processors.query.NestedTxMode;
+import org.apache.ignite.internal.processors.query.QueryUtils;
+import org.apache.ignite.internal.processors.query.SqlClientContext;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.util.worker.GridWorker;
+import org.apache.ignite.lang.IgniteBiTuple;
 
 import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_COLS;
 import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_PARAMS;
@@ -63,6 +71,7 @@ import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_CL
 import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_EXEC;
 import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_EXEC_BATCH;
 import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_FETCH;
+import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.STREAMING_BATCH;
 
 /**
  * SQL query handler.
@@ -74,6 +83,9 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
     /** Kernel context. */
     private final GridKernalContext ctx;
 
+    /** Client context. */
+    private final SqlClientContext cliCtx;
+
     /** Logger. */
     private final IgniteLogger log;
 
@@ -89,37 +101,29 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
     /** Current queries cursors. */
     private final ConcurrentHashMap<Long, OdbcQueryResults> qryResults = new 
ConcurrentHashMap<>();
 
-    /** Distributed joins flag. */
-    private final boolean distributedJoins;
-
-    /** Enforce join order flag. */
-    private final boolean enforceJoinOrder;
-
-    /** Replicated only flag. */
-    private final boolean replicatedOnly;
-
     /** Nested transaction behaviour. */
     private final NestedTxMode nestedTxMode;
 
-    /** Collocated flag. */
-    private final boolean collocated;
-
-    /** Lazy flag. */
-    private final boolean lazy;
-
-    /** Update on server flag. */
-    private final boolean skipReducerOnUpdate;
-
     /** Authentication context */
     private final AuthorizationContext actx;
 
     /** Client version. */
     private ClientListenerProtocolVersion ver;
 
+    /** Ordered batches queue. */
+    private final PriorityQueue<OdbcStreamingBatchRequest> orderedBatchesQueue 
= new PriorityQueue<>();
+
+    /** Ordered batches mutex. */
+    private final Object orderedBatchesMux = new Object();
+
+    /** Response sender. */
+    private final ClientListenerResponseSender sender;
+
     /**
      * Constructor.
      * @param ctx Context.
      * @param busyLock Shutdown latch.
+     * @param sender Results sender.
      * @param maxCursors Maximum allowed cursors.
      * @param distributedJoins Distributed joins flag.
      * @param enforceJoinOrder Enforce join order flag.
@@ -131,18 +135,40 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
      * @param actx Authentication context.
      * @param ver Client protocol version.
      */
-    public OdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock 
busyLock, int maxCursors,
-        boolean distributedJoins, boolean enforceJoinOrder, boolean 
replicatedOnly, boolean collocated, boolean lazy,
-        boolean skipReducerOnUpdate, AuthorizationContext actx, NestedTxMode 
nestedTxMode, ClientListenerProtocolVersion ver) {
+    public OdbcRequestHandler(
+        GridKernalContext ctx,
+        GridSpinBusyLock busyLock,
+        ClientListenerResponseSender sender,
+        int maxCursors,
+        boolean distributedJoins,
+        boolean enforceJoinOrder,
+        boolean replicatedOnly,
+        boolean collocated,
+        boolean lazy,
+        boolean skipReducerOnUpdate,
+        AuthorizationContext actx, NestedTxMode nestedTxMode, 
ClientListenerProtocolVersion ver) {
         this.ctx = ctx;
+
+        Factory<GridWorker> orderedFactory = new Factory<GridWorker>() {
+            @Override public GridWorker create() {
+                return new OrderedBatchWorker();
+            }
+        };
+
+        this.cliCtx = new SqlClientContext(
+            ctx,
+            orderedFactory,
+            distributedJoins,
+            enforceJoinOrder,
+            collocated,
+            replicatedOnly,
+            lazy,
+            skipReducerOnUpdate
+        );
+
         this.busyLock = busyLock;
+        this.sender = sender;
         this.maxCursors = maxCursors;
-        this.distributedJoins = distributedJoins;
-        this.enforceJoinOrder = enforceJoinOrder;
-        this.replicatedOnly = replicatedOnly;
-        this.collocated = collocated;
-        this.lazy = lazy;
-        this.skipReducerOnUpdate = skipReducerOnUpdate;
         this.actx = actx;
         this.nestedTxMode = nestedTxMode;
         this.ver = ver;
@@ -204,6 +230,9 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
                 case QRY_EXEC_BATCH:
                     return 
executeBatchQuery((OdbcQueryExecuteBatchRequest)req);
 
+                case STREAMING_BATCH:
+                    return 
dispatchBatchOrdered((OdbcStreamingBatchRequest)req);
+
                 case QRY_FETCH:
                     return fetchQuery((OdbcQueryFetchRequest)req);
 
@@ -247,8 +276,7 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
      * or due to {@code IOException} during network operations.
      */
     public void onDisconnect() {
-        if (busyLock.enterBusy())
-        {
+        if (busyLock.enterBusy()) {
             if (worker != null) {
                 worker.cancel();
 
@@ -260,10 +288,11 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
                 }
             }
 
-            try
-            {
+            try {
                 for (OdbcQueryResults res : qryResults.values())
                     res.closeAll();
+
+                U.close(cliCtx, log);
             }
             finally {
                 busyLock.leaveBusy();
@@ -281,21 +310,32 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
      * @return Query instance.
      */
     private SqlFieldsQueryEx makeQuery(String schema, String sql, Object[] 
args, int timeout, boolean autoCommit) {
-        SqlFieldsQueryEx qry = new SqlFieldsQueryEx(sql, null);
+        SqlFieldsQueryEx qry = makeQuery(schema, sql);
 
         qry.setArgs(args);
-
-        qry.setDistributedJoins(distributedJoins);
-        qry.setEnforceJoinOrder(enforceJoinOrder);
-        qry.setReplicatedOnly(replicatedOnly);
-        qry.setCollocated(collocated);
-        qry.setLazy(lazy);
-        qry.setSchema(schema);
-        qry.setSkipReducerOnUpdate(skipReducerOnUpdate);
-        qry.setNestedTxMode(nestedTxMode);
+        qry.setTimeout(timeout, TimeUnit.SECONDS);
         qry.setAutoCommit(autoCommit);
 
-        qry.setTimeout(timeout, TimeUnit.SECONDS);
+        return qry;
+    }
+
+    /**
+     * Make query considering handler configuration.
+     * @param schema Schema.
+     * @param sql SQL request.
+     * @return Query instance.
+     */
+    private SqlFieldsQueryEx makeQuery(String schema, String sql) {
+        SqlFieldsQueryEx qry = new SqlFieldsQueryEx(sql, null);
+
+        qry.setDistributedJoins(cliCtx.isDistributedJoins());
+        qry.setEnforceJoinOrder(cliCtx.isEnforceJoinOrder());
+        qry.setReplicatedOnly(cliCtx.isReplicatedOnly());
+        qry.setCollocated(cliCtx.isCollocated());
+        qry.setLazy(cliCtx.isLazy());
+        qry.setSchema(F.isEmpty(schema) ? QueryUtils.DFLT_SCHEMA : schema);
+        qry.setSkipReducerOnUpdate(cliCtx.isSkipReducerOnUpdate());
+        qry.setNestedTxMode(nestedTxMode);
 
         return qry;
     }
@@ -317,6 +357,8 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
 
         long qryId = QRY_ID_GEN.getAndIncrement();
 
+        assert !cliCtx.isStream();
+
         try {
             String sql = OdbcEscapeUtils.parse(req.sqlQuery());
 
@@ -326,7 +368,7 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
 
             SqlFieldsQuery qry = makeQuery(req.schema(), sql, req.arguments(), 
req.timeout(), req.autoCommit());
 
-            List<FieldsQueryCursor<List<?>>> cursors = 
ctx.query().querySqlFields(qry, true, false);
+            List<FieldsQueryCursor<List<?>>> cursors = 
ctx.query().querySqlFields(null, qry, cliCtx, true, false);
 
             OdbcQueryResults results = new OdbcQueryResults(cursors, ver);
 
@@ -390,7 +432,7 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
                 qry.addBatchedArgs(set);
 
             List<FieldsQueryCursor<List<?>>> qryCurs =
-                ctx.query().querySqlFields(qry, true, true);
+                ctx.query().querySqlFields(null, qry, cliCtx, true, true);
 
             long[] rowsAffected = new long[req.arguments().length];
 
@@ -409,6 +451,105 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
     }
 
     /**
+     * @param req Ordered batch request.
+     * @return Response.
+     */
+    private ClientListenerResponse 
dispatchBatchOrdered(OdbcStreamingBatchRequest req) {
+        synchronized (orderedBatchesMux) {
+            orderedBatchesQueue.add(req);
+
+            orderedBatchesMux.notify();
+        }
+
+        if (!cliCtx.isStreamOrdered())
+            processStreamingBatchOrdered(req);
+
+        return null;
+    }
+
+    /**
+     * @param req Ordered batch request.
+     */
+    private void processStreamingBatchOrdered(OdbcStreamingBatchRequest req) {
+        try {
+            if (req.last())
+                cliCtx.waitTotalProcessedOrderedRequests(req.order());
+
+            sender.send(processStreamingBatch(req));
+        } catch (Exception e) {
+            U.error(null, "Error processing file batch", e);
+
+            sender.send(new OdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Server 
error: " + e));
+        }
+
+        synchronized (orderedBatchesMux) {
+            orderedBatchesQueue.poll();
+        }
+
+        cliCtx.orderedRequestProcessed();
+    }
+
+    /**
+     * @param req Request.
+     * @return Response.
+     */
+    private ClientListenerResponse 
processStreamingBatch(OdbcStreamingBatchRequest req) {
+        assert cliCtx.isStream();
+
+        // Send back only the first error. Others will be written to the log.
+        IgniteBiTuple<Integer, String> firstErr = new IgniteBiTuple<>();
+
+        SqlFieldsQueryEx qry = null;
+
+        for (OdbcQuery q : req.queries()) {
+            if (q.sql() != null) { // If we have a new query string in the 
batch,
+                if (qry != null) // then execute the previous sub-batch and 
create a new SqlFieldsQueryEx.
+                    processStreamingBatch(qry, firstErr);
+
+                qry = makeQuery(req.schemaName(), q.sql());
+            }
+
+            assert qry != null;
+
+            qry.addBatchedArgs(q.args());
+        }
+
+        if (qry != null)
+            processStreamingBatch(qry, firstErr);
+
+        if (req.last())
+            cliCtx.disableStreaming();
+
+        if (firstErr.isEmpty())
+            return new OdbcResponse(new OdbcStreamingBatchResult(req.order()));
+        else
+        {
+            assert firstErr.getKey() != null;
+
+            return new OdbcResponse(new 
OdbcStreamingBatchResult(firstErr.getKey(), firstErr.getValue(), req.order()));
+        }
+    }
+
+    /**
+     * Executes query and updates result counters.
+     *
+     * @param qry Query.
+     * @param err First error data - code and message.
+     */
+    private void processStreamingBatch(SqlFieldsQueryEx qry, 
IgniteBiTuple<Integer, String> err) {
+        try {
+            assert cliCtx.isStream();
+
+            ctx.query().streamBatchedUpdateQuery(qry.getSchema(), cliCtx, 
qry.getSql(), qry.batchedArguments());
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to execute batch query [qry=" + qry +']', e);
+
+            extractBatchError(e, null, err);
+        }
+    }
+
+    /**
      * {@link OdbcQueryCloseRequest} command handler.
      *
      * @param req Execute query request.
@@ -742,39 +883,41 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
      * @param e Exception to convert.
      * @return resulting {@link OdbcResponse}.
      */
-    private OdbcResponse exceptionToBatchResult(Exception e) {
-        int code;
-        String msg;
-        long[] rowsAffected = null;
+    private static OdbcResponse exceptionToBatchResult(Exception e) {
+        IgniteBiTuple<Integer, String> err = new IgniteBiTuple<>();
+        List<Long> rowsAffected = new ArrayList<>();
+
+        extractBatchError(e, rowsAffected, err);
 
+        OdbcQueryExecuteBatchResult res = new OdbcQueryExecuteBatchResult(
+            U.toLongArray(rowsAffected), -1, err.get1(), err.get2());
+
+        return new OdbcResponse(res);
+    }
+
+    /**
+     * Extract batching error from general exception.
+     * @param e Exception
+     * @param rowsAffected List containing the number of affected rows for 
every query in batch.
+     * @param err Error tuple containing error code and error message.
+     */
+    private static void extractBatchError(Exception e, List<Long> 
rowsAffected, IgniteBiTuple<Integer, String> err) {
         if (e instanceof IgniteSQLException) {
             BatchUpdateException batchCause = X.cause(e, 
BatchUpdateException.class);
 
             if (batchCause != null) {
-                rowsAffected = batchCause.getLargeUpdateCounts();
-
-                msg = batchCause.getMessage();
-
-                code = batchCause.getErrorCode();
-            }
-            else {
-                msg = OdbcUtils.tryRetrieveH2ErrorMessage(e);
+                if (rowsAffected != null) {
+                    for (long cnt : batchCause.getLargeUpdateCounts())
+                        rowsAffected.add(cnt);
+                }
 
-                code = ((IgniteSQLException)e).statusCode();
+                err.set(batchCause.getErrorCode(), batchCause.getMessage());
             }
+            else
+                err.set(((IgniteSQLException)e).statusCode(), 
OdbcUtils.tryRetrieveH2ErrorMessage(e));
         }
-        else {
-            msg = e.getMessage();
-
-            code = IgniteQueryErrorCode.UNKNOWN;
-        }
-
-        if (rowsAffected == null)
-            rowsAffected = new long[0];
-
-        OdbcQueryExecuteBatchResult res = new 
OdbcQueryExecuteBatchResult(rowsAffected, -1, code, msg);
-
-        return new OdbcResponse(res);
+        else
+            err.set(IgniteQueryErrorCode.UNKNOWN, e.getMessage());
     }
 
     /**
@@ -784,7 +927,45 @@ public class OdbcRequestHandler implements 
ClientListenerRequestHandler {
      * @param e Exception to convert.
      * @return resulting {@link OdbcResponse}.
      */
-    private OdbcResponse exceptionToResult(Exception e) {
+    private static OdbcResponse exceptionToResult(Exception e) {
         return new OdbcResponse(OdbcUtils.tryRetrieveSqlErrorCode(e), 
OdbcUtils.tryRetrieveH2ErrorMessage(e));
     }
+
+    /**
+     * Ordered batch worker.
+     */
+    private class OrderedBatchWorker extends GridWorker {
+        /**
+         * Constructor.
+         */
+        OrderedBatchWorker() {
+            super(ctx.igniteInstanceName(), "ordered-batch", 
OdbcRequestHandler.this.log);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected void body() throws InterruptedException, 
IgniteInterruptedCheckedException {
+            long nextBatchOrder = 0;
+
+            while (true) {
+                if (!cliCtx.isStream())
+                    return;
+
+                OdbcStreamingBatchRequest req;
+
+                synchronized (orderedBatchesMux) {
+                    req = orderedBatchesQueue.peek();
+
+                    if (req == null || req.order() != nextBatchOrder) {
+                        orderedBatchesMux.wait();
+
+                        continue;
+                    }
+                }
+
+                processStreamingBatchOrdered(req);
+
+                nextBatchOrder++;
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchRequest.java
new file mode 100644
index 0000000..7f3ee22
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchRequest.java
@@ -0,0 +1,102 @@
+package org.apache.ignite.internal.processors.odbc.odbc;
+
+/*
+ * 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.
+ */
+
+import java.util.List;
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * ODBC query execute request with the batch of parameters.
+ */
+public class OdbcStreamingBatchRequest extends OdbcRequest implements 
java.lang.Comparable<OdbcStreamingBatchRequest> {
+    /** Schema name. */
+    @GridToStringInclude(sensitive = true)
+    private String schemaName;
+
+    /** Sql query. */
+    @GridToStringExclude()
+    private List<OdbcQuery> queries;
+
+    /**
+     * Last stream batch flag - whether open streamers on current connection
+     * must be flushed and closed after this batch.
+     */
+    @GridToStringInclude(sensitive = true)
+    private boolean last;
+
+    /** Order. */
+    @GridToStringInclude(sensitive = true)
+    private long order;
+
+    /**
+     * @param schema Schema.
+     * @param queries SQL queries list.
+     * @param last Last page flag.
+     * @param order Order.
+     */
+    public OdbcStreamingBatchRequest(@Nullable String schema, List<OdbcQuery> 
queries, boolean last, long order) {
+        super(STREAMING_BATCH);
+
+        this.schemaName = schema;
+        this.queries = queries;
+        this.last = last;
+        this.order = order;
+    }
+
+    /**
+     * @return Schema name.
+     */
+    @Nullable public String schemaName() {
+        return schemaName;
+    }
+
+    /**
+     * @return Queries.
+     */
+    public List<OdbcQuery> queries() {
+        return queries;
+    }
+
+    /**
+     * @return Last stream batch flag.
+     */
+    public boolean last() {
+        return last;
+    }
+
+    /**
+     * @return Request order.
+     */
+    public long order() {
+        return order;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcStreamingBatchRequest.class, this);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int compareTo(@NotNull OdbcStreamingBatchRequest o) {
+        return Long.compare(order, o.order);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchResult.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchResult.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchResult.java
new file mode 100644
index 0000000..63831f7
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcStreamingBatchResult.java
@@ -0,0 +1,74 @@
+/*
+ * 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.odbc;
+
+import org.apache.ignite.internal.processors.odbc.ClientListenerResponse;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * ODBC query execute with batch of parameters result.
+ */
+public class OdbcStreamingBatchResult {
+    /** Success status. */
+    private int status;
+
+    /** Error. */
+    private String err;
+
+    /** Order. */
+    private final long order;
+
+    /**
+     * @param order Order.
+     */
+    public OdbcStreamingBatchResult(long order) {
+        this(ClientListenerResponse.STATUS_SUCCESS, null, order);
+    }
+
+    /**
+     * @param status Response status.
+     * @param err Error, {@code null} if success is {@code true}.
+     * @param order Order.
+     */
+    public OdbcStreamingBatchResult(int status, @Nullable String err, long 
order) {
+        this.status = status;
+        this.err = err;
+        this.order = order;
+    }
+
+    /**
+     * @return Success flag.
+     */
+    public int status() {
+        return status;
+    }
+
+    /**
+     * @return Error.
+     */
+    public String error() {
+        return err;
+    }
+
+    /**
+     * @return Order.
+     */
+    public long order() {
+        return order;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/core/src/main/java/org/apache/ignite/internal/processors/query/SqlClientContext.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/SqlClientContext.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/SqlClientContext.java
index 42dbae6..1f2fe43 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/SqlClientContext.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/SqlClientContext.java
@@ -30,7 +30,7 @@ import org.apache.ignite.internal.util.worker.GridWorker;
 import org.apache.ignite.thread.IgniteThread;
 
 /**
- * Container for connection properties passed by various drivers (JDBC 
drivers, possibly ODBC) having notion of an
+ * Container for connection properties passed by various drivers (JDBC, ODBC 
drivers) having notion of an
  * <b>SQL connection</b> - Ignite basically does not have one.<p>
  * Also contains anything that a driver may need to share between threads 
processing queries of logically same client -
  * see JDBC thin driver

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_memory.h
----------------------------------------------------------------------
diff --git 
a/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_memory.h 
b/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_memory.h
index 50b5328..9a1872b 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_memory.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/interop/interop_memory.h
@@ -192,6 +192,13 @@ namespace ignite
                 int8_t* Data();
 
                 /**
+                 * Get raw data pointer.
+                 *
+                 * @return Data pointer.
+                 */
+                const int8_t* Data() const;
+
+                /**
                  * Get capacity.
                  *
                  * @return Capacity.

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/binary/src/impl/interop/interop_memory.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/src/impl/interop/interop_memory.cpp 
b/modules/platforms/cpp/binary/src/impl/interop/interop_memory.cpp
index 04b27ae..645a5bc 100644
--- a/modules/platforms/cpp/binary/src/impl/interop/interop_memory.cpp
+++ b/modules/platforms/cpp/binary/src/impl/interop/interop_memory.cpp
@@ -110,6 +110,11 @@ namespace ignite
                 return Data(memPtr);
             }
 
+            const int8_t* InteropMemory::Data() const
+            {
+                return Data(memPtr);
+            }
+
             int32_t InteropMemory::Capacity() const
             {
                 return Capacity(memPtr);

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/common/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/Makefile.am 
b/modules/platforms/cpp/common/Makefile.am
index 374f417..df9068d 100644
--- a/modules/platforms/cpp/common/Makefile.am
+++ b/modules/platforms/cpp/common/Makefile.am
@@ -46,9 +46,9 @@ libignite_common_la_SOURCES = \
        os/linux/src/common/platform_utils.cpp \
        os/linux/src/common/dynamic_load_os.cpp \
        src/common/big_integer.cpp \
+       src/common/bits.cpp \
        src/common/concurrent.cpp \
        src/common/decimal.cpp \
-       src/common/bits.cpp \
        src/common/utils.cpp \
        src/date.cpp \
        src/ignite_error.cpp \

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/common/include/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/Makefile.am 
b/modules/platforms/cpp/common/include/Makefile.am
index a28d04f..8079579 100644
--- a/modules/platforms/cpp/common/include/Makefile.am
+++ b/modules/platforms/cpp/common/include/Makefile.am
@@ -24,6 +24,7 @@ nobase_include_HEADERS = \
        ignite/common/concurrent.h \
        ignite/common/decimal.h \
        ignite/common/default_allocator.h \
+       ignite/common/expected.h \
        ignite/common/reference_impl.h \
        ignite/common/dynamic_size_array.h \
        ignite/common/fixed_size_array.h \

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/common/include/ignite/common/default_allocator.h
----------------------------------------------------------------------
diff --git 
a/modules/platforms/cpp/common/include/ignite/common/default_allocator.h 
b/modules/platforms/cpp/common/include/ignite/common/default_allocator.h
index 4350987..f7f99b4 100644
--- a/modules/platforms/cpp/common/include/ignite/common/default_allocator.h
+++ b/modules/platforms/cpp/common/include/ignite/common/default_allocator.h
@@ -18,13 +18,9 @@
 #define _IGNITE_COMMON_DEFAULT_ALLOCATOR
 
 #include <stdint.h>
-#include <cstring>
 #include <cassert>
 
-#include <utility>
-
 #include <ignite/common/common.h>
-#include <ignite/common/fixed_size_array.h>
 
 namespace ignite
 {
@@ -86,8 +82,6 @@ namespace ignite
             {
                 p->~ValueType();
             }
-
-        private:
         };
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/common/include/ignite/common/expected.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/common/expected.h 
b/modules/platforms/cpp/common/include/ignite/common/expected.h
new file mode 100644
index 0000000..6322c7a
--- /dev/null
+++ b/modules/platforms/cpp/common/include/ignite/common/expected.h
@@ -0,0 +1,300 @@
+/*
+ * 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_COMMON_EXPECTED
+#define _IGNITE_COMMON_EXPECTED
+
+#include <memory>
+
+#include <ignite/common/utils.h>
+
+namespace ignite
+{
+    namespace common
+    {
+        /**
+         * Helper class to construct Expected class with error value.
+         */
+        template<typename E>
+        struct Unexpected
+        {
+            /** Value type. */
+            typedef E ValueType;
+
+            /**
+             * Constructor.
+             *
+             * @param e Error value reference.
+             */
+            Unexpected(const ValueType& e) : err(e)
+            {
+                // No-op;
+            }
+
+            /** Error. */
+            const ValueType& err;
+        };
+
+        /**
+         * Operation result wrapper.
+         *
+         * Represents a type, which can accept one of two value types - 
expected
+         * result or error.
+         *
+         * @tparam R Result type.
+         * @tparam E Error type.
+         * @tparam AR Allocator type used for the Result type.
+         * @tparam AE Allocator type used for the Error type.
+         */
+        template<
+            typename R,
+            typename E,
+            typename AR = std::allocator<R>,
+            typename AE = std::allocator<E> >
+        class Expected
+        {
+        public:
+            /** Result type. */
+            typedef R ResultType;
+
+            /** Error type. */
+            typedef E ErrorType;
+
+            /** Allocator type used for the ResultType. */
+            typedef AR ResultAllocatorType;
+
+            /** Allocator type used for the ErrorType. */
+            typedef AE ErrorAllocatorType;
+
+            /**
+             * Constructor.
+             *
+             * Creates new instance, containing expected value.
+             * @param res Result.
+             */
+            Expected(const ResultType& res) :
+                ok(true)
+            {
+                ResultAllocatorType ral;
+
+                ral.construct(AsResult(), res);
+            }
+
+            /**
+             * Constructor.
+             *
+             * Creates new instance, containing error.
+             * @param err Result.
+             */
+            explicit Expected(Unexpected<ErrorType> err) :
+                ok(false)
+            {
+                ErrorAllocatorType ral;
+
+                ral.construct(AsError(), err.err);
+            }
+
+            /**
+             * Copy constructor.
+             *
+             * @param other Other.
+             */
+            Expected(const Expected& other) :
+                ok(other.ok)
+            {
+                if (ok)
+                {
+                    ResultAllocatorType ral;
+
+                    ral.construct(AsResult(), *other.AsResult());
+                }
+                else
+                {
+                    ErrorAllocatorType ral;
+
+                    ral.construct(AsError(), *other.AsError());
+                }
+            }
+
+            /**
+             * Destructor.
+             */
+            ~Expected()
+            {
+                if (ok)
+                {
+                    ResultAllocatorType ral;
+
+                    ral.destroy(AsResult());
+                }
+                else
+                {
+                    ErrorAllocatorType ral;
+
+                    ral.destroy(AsError());
+                }
+            }
+
+            /**
+             * Check if the value is OK.
+             *
+             * @return @c false if the value is an error and @c true otherwise.
+             */
+            bool IsOk() const
+            {
+                return ok;
+            }
+
+            /**
+             * Get result. Constant accesser.
+             *
+             * @return Result if it was set before.
+             * @throw ErrorType if there is no result.
+             */
+            const ResultType& GetResult() const
+            {
+                if (!ok)
+                    throw *AsError();
+
+                return *AsResult();
+            }
+
+            /**
+             * Get result.
+             *
+             * @return Result if it was set before.
+             * @throw ErrorType if there is no result.
+             */
+            ResultType& GetResult()
+            {
+                if (!ok)
+                    throw *AsError();
+
+                return *AsResult();
+            }
+
+            /**
+             * Get result. Constant accesser.
+             *
+             * @return Result if it was set before.
+             * @throw ErrorType if there is no result.
+             */
+            const ResultType& operator*() const
+            {
+                return GetResult();
+            }
+
+            /**
+             * Get result.
+             *
+             * @return Result if it was set before.
+             * @throw ErrorType if there is no result.
+             */
+            ResultType& operator*()
+            {
+                return GetResult();
+            }
+
+            /**
+             * Get result. Constant accesser.
+             *
+             * @return Result if it was set before.
+             * @throw ErrorType if there is no result.
+             */
+            const ResultType& operator->() const
+            {
+                return GetResult();
+            }
+
+            /**
+             * Get result.
+             *
+             * @return Result if it was set before.
+             * @throw ErrorType if there is no result.
+             */
+            ResultType& operator->()
+            {
+                return GetResult();
+            }
+
+            /**
+             * Get error.
+             *
+             * @return Error if it was set before. If there is no error, 
default
+             * constructed error is returned (which is expected to be "No 
error").
+             */
+            const ErrorType& GetError() const
+            {
+                static ErrorType noError;
+
+                if (ok)
+                    return noError;
+
+                return *AsError();
+            }
+
+        private:
+            /**
+             * Get storage as an result.
+             *
+             * @return Storage pointer as an result pointer.
+             */
+            ResultType* AsResult()
+            {
+                return reinterpret_cast<ResultType*>(&storage);
+            }
+
+            /**
+             * Get storage as an result.
+             *
+             * @return Storage pointer as an result pointer.
+             */
+            const ResultType* AsResult() const
+            {
+                return reinterpret_cast<const ResultType*>(&storage);
+            }
+
+            /**
+             * Get storage as an error.
+             *
+             * @return Storage pointer as an error pointer.
+             */
+            ErrorType* AsError()
+            {
+                return reinterpret_cast<ErrorType*>(&storage);
+            }
+
+            /**
+             * Get storage as an error.
+             *
+             * @return Storage pointer as an error pointer.
+             */
+            const ErrorType* AsError() const
+            {
+                return reinterpret_cast<const ErrorType*>(&storage);
+            }
+
+            /** Storage. */
+            int8_t storage[sizeof(typename Bigger<ResultType, 
ErrorType>::type)];
+
+            /** Result flag. Set to @c false if the value is an error. */
+            bool ok;
+        };
+    }
+}
+
+#endif // _IGNITE_COMMON_EXPECTED
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/common/include/ignite/common/utils.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/common/utils.h 
b/modules/platforms/cpp/common/include/ignite/common/utils.h
index 4edbf4b..29e36f5 100644
--- a/modules/platforms/cpp/common/include/ignite/common/utils.h
+++ b/modules/platforms/cpp/common/include/ignite/common/utils.h
@@ -489,6 +489,15 @@ namespace ignite
         };
 
         /**
+         * Returns the bigger type.
+         */
+        template<typename T1, typename T2>
+        struct Bigger
+        {
+            typedef typename Conditional<(sizeof(T1) > sizeof(T2)), T1, 
T2>::type type;
+        };
+
+        /**
          * Utility class to bind class instance with member function.
          */
         template<typename R, typename T>

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/common/project/vs/common.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/project/vs/common.vcxproj 
b/modules/platforms/cpp/common/project/vs/common.vcxproj
index bce1c2f..8f3bbe7 100644
--- a/modules/platforms/cpp/common/project/vs/common.vcxproj
+++ b/modules/platforms/cpp/common/project/vs/common.vcxproj
@@ -171,6 +171,7 @@
     <ClInclude Include="..\..\include\ignite\common\decimal.h" />
     <ClInclude Include="..\..\include\ignite\common\default_allocator.h" />
     <ClInclude Include="..\..\include\ignite\common\dynamic_size_array.h" />
+    <ClInclude Include="..\..\include\ignite\common\expected.h" />
     <ClInclude Include="..\..\include\ignite\common\fixed_size_array.h" />
     <ClInclude Include="..\..\include\ignite\common\bits.h" />
     <ClInclude Include="..\..\include\ignite\common\lazy.h" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/project/vs/common.vcxproj.filters 
b/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
index 2d1a8b8..ee10799 100644
--- a/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
+++ b/modules/platforms/cpp/common/project/vs/common.vcxproj.filters
@@ -82,6 +82,9 @@
     <ClInclude Include="..\..\include\ignite\common\lazy.h">
       <Filter>Code\common</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\ignite\common\expected.h">
+      <Filter>Code\common</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\date.cpp">

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/core-test/src/teamcity_boost.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/teamcity_boost.cpp 
b/modules/platforms/cpp/core-test/src/teamcity_boost.cpp
index 45c666d..5f0441c 100644
--- a/modules/platforms/cpp/core-test/src/teamcity_boost.cpp
+++ b/modules/platforms/cpp/core-test/src/teamcity_boost.cpp
@@ -19,7 +19,7 @@
 
 #include <sstream>
 
-#include <boost/test/unit_test_suite_impl.hpp>
+#include <boost/test/unit_test_suite.hpp>
 #include <boost/test/results_collector.hpp>
 #include <boost/test/utils/basic_cstring/io.hpp>
 #include <boost/test/unit_test_log.hpp>

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/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 14dae7c..c5dc54e 100644
--- a/modules/platforms/cpp/odbc-test/Makefile.am
+++ b/modules/platforms/cpp/odbc-test/Makefile.am
@@ -47,7 +47,9 @@ ignite_odbc_tests_LDADD = \
     -ldl \
     -lodbc \
     -lpthread \
-    -lboost_regex
+    -lboost_thread \
+    -lboost_system \
+    -lboost_chrono
 
 ignite_odbc_tests_LDFLAGS = \
     -static-libtool-libs
@@ -87,6 +89,8 @@ ignite_odbc_tests_SOURCES = \
     src/types_test.cpp \
     src/transaction_test.cpp \
     src/authentication_test.cpp \
+    src/sql_parsing_test.cpp \
+    src/streaming_test.cpp \
     ../odbc/src/log.cpp \
     ../odbc/src/cursor.cpp \
     ../odbc/src/diagnostic/diagnostic_record.cpp \
@@ -97,6 +101,10 @@ ignite_odbc_tests_SOURCES = \
     ../odbc/src/config/connection_string_parser.cpp \
     ../odbc/src/app/application_data_buffer.cpp \
     ../odbc/src/ssl/ssl_mode.cpp \
+    ../odbc/src/sql/sql_parser.cpp \
+    ../odbc/src/sql/sql_lexer.cpp \
+    ../odbc/src/sql/sql_set_streaming_command.cpp \
+    ../odbc/src/sql/sql_utils.cpp \
     ../odbc/src/row.cpp \
     ../odbc/src/protocol_version.cpp \
     ../odbc/src/column.cpp \

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h 
b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
index 94733c5..7a33c6a 100644
--- a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
+++ b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
@@ -70,7 +70,7 @@ namespace ignite
 
             /**
              * Start additional with the specified name and config.
-             * 
+             *
              * @param cfg Config path.
              * @param name Instance name.
              */

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/include/test_utils.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/test_utils.h 
b/modules/platforms/cpp/odbc-test/include/test_utils.h
index 9faf89d..a1de23e 100644
--- a/modules/platforms/cpp/odbc-test/include/test_utils.h
+++ b/modules/platforms/cpp/odbc-test/include/test_utils.h
@@ -110,9 +110,17 @@ namespace ignite_test
     ignite::Ignite StartNode(const char* cfgFile, const char* name);
 
     /**
+     * Start node with the config for the current platform.
+     *
+     * @param cfg Basic config path. Changed to platform config if needed.
+     * @param name Instance name.
+     */
+    ignite::Ignite StartPlatformNode(const char* cfg, const char* name);
+
+    /**
      * Remove all the LFS artifacts.
      */
     void ClearLfs();
 }
 
-#endif // _IGNITE_ODBC_TEST_TEST_UTILS
\ No newline at end of file
+#endif // _IGNITE_ODBC_TEST_TEST_UTILS

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/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 3410ec5..0147e8a 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
@@ -98,7 +98,7 @@
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_regex-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_thread-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_system-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_chrono-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -112,7 +112,7 @@
     </ClCompile>
     <Link>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_regex-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_thread-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_system-vc100-mt-gd-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_chrono-vc100-mt-gd-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <SubSystem>Console</SubSystem>
     </Link>
   </ItemDefinitionGroup>
@@ -131,7 +131,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_regex-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_thread-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_system-vc100-mt-1_58.lib;$(BOOST_HOME)\lib32-msvc-10.0\libboost_chrono-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup 
Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -149,7 +149,7 @@
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_regex-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      
<AdditionalDependencies>$(JAVA_HOME)\lib\jvm.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_unit_test_framework-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_thread-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_system-vc100-mt-1_58.lib;$(BOOST_HOME)\lib64-msvc-10.0\libboost_chrono-vc100-mt-1_58.lib;%(AdditionalDependencies)</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -168,6 +168,10 @@
     <ClCompile Include="..\..\..\odbc\src\protocol_version.cpp" />
     <ClCompile Include="..\..\..\odbc\src\result_page.cpp" />
     <ClCompile Include="..\..\..\odbc\src\row.cpp" />
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_lexer.cpp" />
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_parser.cpp" />
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_set_streaming_command.cpp" />
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_utils.cpp" />
     <ClCompile Include="..\..\..\odbc\src\ssl\ssl_mode.cpp" />
     <ClCompile Include="..\..\..\odbc\src\utility.cpp" />
     <ClCompile Include="..\..\src\api_robustness_test.cpp" />
@@ -190,6 +194,7 @@
     <ClCompile Include="..\..\src\sql_get_info_test.cpp" />
     <ClCompile Include="..\..\src\sql_outer_join_test.cpp" />
     <ClCompile Include="..\..\src\sql_date_time_functions_test.cpp" />
+    <ClCompile Include="..\..\src\sql_parsing_test.cpp" />
     <ClCompile Include="..\..\src\sql_test_suite_fixture.cpp" />
     <ClCompile Include="..\..\src\sql_numeric_functions_test.cpp" />
     <ClCompile Include="..\..\src\sql_operators_test.cpp" />
@@ -198,6 +203,7 @@
     <ClCompile Include="..\..\src\sql_esc_convert_function_test.cpp" />
     <ClCompile Include="..\..\src\sql_types_test.cpp" />
     <ClCompile Include="..\..\src\sql_value_expressions_test.cpp" />
+    <ClCompile Include="..\..\src\streaming_test.cpp" />
     <ClCompile Include="..\..\src\teamcity\teamcity_boost.cpp" />
     <ClCompile Include="..\..\src\teamcity\teamcity_messages.cpp" />
     <ClCompile Include="..\..\src\test_utils.cpp" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/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 3065df0..1d54f07 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
@@ -172,6 +172,24 @@
     <ClCompile Include="..\..\..\odbc\src\nested_tx_mode.cpp">
       <Filter>Externals</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\sql_parsing_test.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_lexer.cpp">
+      <Filter>Externals</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_parser.cpp">
+      <Filter>Externals</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_set_streaming_command.cpp">
+      <Filter>Externals</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\odbc\src\sql\sql_utils.cpp">
+      <Filter>Externals</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\streaming_test.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\test_type.h">

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp 
b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
index 5f807c9..4259667 100644
--- a/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/api_robustness_test.cpp
@@ -58,14 +58,13 @@ struct ApiRobustnessTestSuiteFixture : public 
odbc::OdbcTestSuite
 {
     static Ignite StartAdditionalNode(const char* name)
     {
-        return StartTestNode("queries-test.xml", name);
+        return StartPlatformNode("queries-test.xml", name);
     }
 
     /**
      * Constructor.
      */
     ApiRobustnessTestSuiteFixture() :
-        grid(),
         testCache(0)
     {
         grid = StartAdditionalNode("NodeMain");
@@ -82,8 +81,6 @@ struct ApiRobustnessTestSuiteFixture : public 
odbc::OdbcTestSuite
     {
         Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
 
-        SQLRETURN ret;
-
         const int64_t recordsNum = 100;
 
         for (int i = 0; i < recordsNum; ++i)
@@ -98,7 +95,7 @@ struct ApiRobustnessTestSuiteFixture : public 
odbc::OdbcTestSuite
         int32_t i32Field = -1;
 
         // Binding column.
-        ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &i32Field, 0, 0);
+        SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &i32Field, 0, 0);
 
         if (!SQL_SUCCEEDED(ret))
             BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
@@ -126,7 +123,7 @@ struct ApiRobustnessTestSuiteFixture : public 
odbc::OdbcTestSuite
     /**
      * Destructor.
      */
-    ~ApiRobustnessTestSuiteFixture()
+    virtual ~ApiRobustnessTestSuiteFixture()
     {
         // No-op.
     }
@@ -457,7 +454,7 @@ BOOST_AUTO_TEST_CASE(TestSQLBindCol)
     ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
 
     //Unsupported data types
-    for(int i = 0; i < sizeof(unsupportedC)/sizeof(unsupportedC[0]); ++i)
+    for (size_t i = 0; i < sizeof(unsupportedC)/sizeof(unsupportedC[0]); ++i)
     {
         ret = SQLBindCol(stmt, 1, unsupportedC[i], &ind1, sizeof(ind1), &len1);
         BOOST_REQUIRE_EQUAL(ret, SQL_ERROR);
@@ -506,16 +503,16 @@ BOOST_AUTO_TEST_CASE(TestSQLBindParameter)
     SQLBindParameter(stmt, 2, SQL_PARAM_INPUT_OUTPUT, SQL_C_SLONG, 
SQL_INTEGER, 100, 100, &ind1, sizeof(ind1), &len1);
     CheckSQLStatementDiagnosticError("HY105");
 
-
     //Unsupported data types
-    for(int i = 0; i < sizeof(unsupportedSql)/sizeof(unsupportedSql[0]); ++i)
+    for (size_t i = 0; i < sizeof(unsupportedSql)/sizeof(unsupportedSql[0]); 
++i)
     {
-        ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, 
unsupportedSql[i], 100, 100, &ind1, sizeof(ind1), &len1);
+        ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG,
+            unsupportedSql[i], 100, 100, &ind1, sizeof(ind1), &len1);
+
         BOOST_REQUIRE_EQUAL(ret, SQL_ERROR);
         CheckSQLStatementDiagnosticError("HYC00");
     }
 
-
     // Size is null.
     SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 100, 
100, &ind1, 0, &len1);
 
@@ -1092,9 +1089,8 @@ BOOST_AUTO_TEST_CASE(TestSQLDiagnosticRecords)
     Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
 
     SQLHANDLE hnd;
-    SQLRETURN ret;
 
-    ret = SQLAllocHandle(SQL_HANDLE_DESC, dbc, &hnd);
+    SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_DESC, dbc, &hnd);
     BOOST_REQUIRE_EQUAL(ret, SQL_ERROR);
     CheckSQLConnectionDiagnosticError("IM001");
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp 
b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
index 05c1c7f..69bca67 100644
--- a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
@@ -58,18 +58,9 @@ struct AttributesTestSuiteFixture : odbc::OdbcTestSuite
     /**
      * Constructor.
      */
-    AttributesTestSuiteFixture() :
-        grid()
+    AttributesTestSuiteFixture()
     {
-        const char* config = NULL;
-
-#ifdef IGNITE_TESTS_32
-          config = "queries-test-32.xml";
-#else
-          config = "queries-test.xml";
-#endif
-
-        grid = StartNode(config, "NodeMain");
+        grid = StartPlatformNode("queries-test.xml", "NodeMain");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/src/authentication_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/authentication_test.cpp 
b/modules/platforms/cpp/odbc-test/src/authentication_test.cpp
index c746d5e..b93def6 100644
--- a/modules/platforms/cpp/odbc-test/src/authentication_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/authentication_test.cpp
@@ -56,7 +56,7 @@ struct AuthenticationTestSuiteFixture : odbc::OdbcTestSuite
 {
     static Ignite StartAdditionalNode(const char* name)
     {
-        return StartTestNode("queries-auth.xml", name);
+        return StartPlatformNode("queries-auth.xml", name);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/src/connection_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/connection_test.cpp 
b/modules/platforms/cpp/odbc-test/src/connection_test.cpp
index 709ef61..e9d0fb2 100644
--- a/modules/platforms/cpp/odbc-test/src/connection_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/connection_test.cpp
@@ -85,8 +85,8 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite
     /**
      * Extract code from ODBC error message.
      *
-     * @param err Error.
-     * @return Code.
+     * @param err Error message.
+     * @return Error code.
      */
     static std::string ExtractErrorCode(const std::string& err)
     {

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/src/errors_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/errors_test.cpp 
b/modules/platforms/cpp/odbc-test/src/errors_test.cpp
index 9c640ba..7d330b9 100644
--- a/modules/platforms/cpp/odbc-test/src/errors_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/errors_test.cpp
@@ -64,7 +64,7 @@ struct ErrorTestSuiteFixture : odbc::OdbcTestSuite
 {
     static Ignite StartAdditionalNode(const char* name)
     {
-        return StartTestNode("queries-test.xml", name);
+        return StartPlatformNode("queries-test.xml", name);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp 
b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
index 5cacb96..82dbf3a 100644
--- a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
@@ -65,7 +65,7 @@ struct MetaQueriesTestSuiteFixture : public 
odbc::OdbcTestSuite
      */
     static Ignite StartAdditionalNode(const char* name)
     {
-        return StartTestNode("queries-test.xml", name);
+        return StartPlatformNode("queries-test.xml", name);
     }
 
     /**
@@ -129,7 +129,7 @@ struct MetaQueriesTestSuiteFixture : public 
odbc::OdbcTestSuite
         cache1(0),
         cache2(0)
     {
-        grid = StartTestNode("queries-test.xml", "NodeMain");
+        grid = StartPlatformNode("queries-test.xml", "NodeMain");
 
         cache1 = grid.GetCache<int64_t, TestType>("cache");
         cache2 = grid.GetCache<int64_t, ComplexType>("cache2");

http://git-wip-us.apache.org/repos/asf/ignite/blob/9f8d331d/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp 
b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp
index 861bef1..3ff2f56 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_ssl_test.cpp
@@ -47,7 +47,7 @@ struct SslQueriesTestSuiteFixture : odbc::OdbcTestSuite
 {
     static Ignite StartAdditionalNode(const char* name)
     {
-        return StartTestNode("queries-ssl.xml", name);
+        return StartPlatformNode("queries-ssl.xml", name);
     }
 
     /**

Reply via email to