IGNITE-4370: Implemented writing of batch of parameters for ODBC.

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

Branch: refs/heads/master
Commit: c10be5780589cc84e7929e234e4411d515166e0b
Parents: 1288531
Author: Igor Sapego <[email protected]>
Authored: Thu Jun 15 16:54:05 2017 +0300
Committer: Igor Sapego <[email protected]>
Committed: Thu Jun 15 16:54:05 2017 +0300

----------------------------------------------------------------------
 .../processors/odbc/odbc/OdbcMessageParser.java |  55 ++-
 .../odbc/odbc/OdbcQueryExecuteBatchRequest.java |  95 +++++
 .../odbc/odbc/OdbcQueryExecuteBatchResult.java  |  75 ++++
 .../odbc/odbc/OdbcQueryExecuteRequest.java      |   6 +-
 .../odbc/odbc/OdbcQueryExecuteResult.java       |   2 +-
 .../processors/odbc/odbc/OdbcRequest.java       |   4 +-
 .../odbc/odbc/OdbcRequestHandler.java           | 108 ++++-
 .../platforms/cpp/core-test/src/test_utils.cpp  |   1 +
 .../src/application_data_buffer_test.cpp        | 176 +++-----
 .../platforms/cpp/odbc-test/src/column_test.cpp |  21 +-
 .../cpp/odbc-test/src/queries_test.cpp          | 404 +++++++++++++++++-
 .../platforms/cpp/odbc-test/src/row_test.cpp    |   9 +-
 .../platforms/cpp/odbc-test/src/test_utils.cpp  |   1 +
 modules/platforms/cpp/odbc/Makefile.am          |   3 +
 modules/platforms/cpp/odbc/include/Makefile.am  |   2 +
 .../ignite/odbc/app/application_data_buffer.h   |  38 +-
 .../odbc/include/ignite/odbc/app/parameter.h    |  20 +-
 .../include/ignite/odbc/app/parameter_set.h     | 268 ++++++++++++
 .../ignite/odbc/diagnostic/diagnosable.h        |   4 +-
 .../cpp/odbc/include/ignite/odbc/message.h      | 411 +++++++------------
 .../include/ignite/odbc/query/batch_query.h     | 160 ++++++++
 .../odbc/include/ignite/odbc/query/data_query.h |  12 +-
 .../cpp/odbc/include/ignite/odbc/query/query.h  |   3 +
 .../include/ignite/odbc/query/type_info_query.h |   2 +-
 .../cpp/odbc/include/ignite/odbc/statement.h    |  50 +--
 .../platforms/cpp/odbc/project/vs/odbc.vcxproj  |   5 +
 .../cpp/odbc/project/vs/odbc.vcxproj.filters    |  15 +
 .../odbc/src/app/application_data_buffer.cpp    |  90 +++-
 .../platforms/cpp/odbc/src/app/parameter.cpp    |  11 +-
 .../cpp/odbc/src/app/parameter_set.cpp          | 242 +++++++++++
 modules/platforms/cpp/odbc/src/column.cpp       |   1 -
 .../cpp/odbc/src/config/connection_info.cpp     |  36 ++
 modules/platforms/cpp/odbc/src/message.cpp      | 373 +++++++++++++++++
 .../cpp/odbc/src/query/batch_query.cpp          | 198 +++++++++
 .../platforms/cpp/odbc/src/query/data_query.cpp |  13 +-
 modules/platforms/cpp/odbc/src/statement.cpp    | 250 ++++++-----
 36 files changed, 2542 insertions(+), 622 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/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 91ed139..08cce1e 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
@@ -33,6 +33,7 @@ import 
org.apache.ignite.internal.processors.odbc.SqlListenerMessageParser;
 import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
 import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
 import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * JDBC message parser.
@@ -85,18 +86,32 @@ public class OdbcMessageParser implements 
SqlListenerMessageParser {
             case OdbcRequest.QRY_EXEC: {
                 String schema = reader.readString();
                 String sql = reader.readString();
-                int argsNum = reader.readInt();
+                int paramNum = reader.readInt();
 
-                Object[] params = new Object[argsNum];
-
-                for (int i = 0; i < argsNum; ++i)
-                    params[i] = SqlListenerUtils.readObject(reader, true);
+                Object[] params = readParameterRow(reader, paramNum);
 
                 res = new OdbcQueryExecuteRequest(schema, sql, params);
 
                 break;
             }
 
+            case OdbcRequest.QRY_EXEC_BATCH: {
+                String schema = reader.readString();
+                String sql = reader.readString();
+                int paramRowLen = reader.readInt();
+                int rowNum = reader.readInt();
+                boolean last = reader.readBoolean();
+
+                Object[][] params = new Object[rowNum][];
+
+                for (int i = 0; i < rowNum; ++i)
+                    params[i] = readParameterRow(reader, paramRowLen);
+
+                res = new OdbcQueryExecuteBatchRequest(schema, sql, last, 
params);
+
+                break;
+            }
+
             case OdbcRequest.QRY_FETCH: {
                 long queryId = reader.readLong();
                 int pageSize = reader.readInt();
@@ -151,6 +166,21 @@ public class OdbcMessageParser implements 
SqlListenerMessageParser {
         return res;
     }
 
+    /**
+     * Read row of parameters using reader.
+     * @param reader reader
+     * @param paramNum Number of parameters in a row
+     * @return Parameters array.
+     */
+    @NotNull private static Object[] readParameterRow(BinaryReaderExImpl 
reader, int paramNum) {
+        Object[] params = new Object[paramNum];
+
+        for (int i = 0; i < paramNum; ++i)
+            params[i] = SqlListenerUtils.readObject(reader, true);
+
+        return params;
+    }
+
     /** {@inheritDoc} */
     @Override public byte[] encode(SqlListenerResponse msg0) {
         assert msg0 != null;
@@ -180,9 +210,9 @@ public class OdbcMessageParser implements 
SqlListenerMessageParser {
             OdbcQueryExecuteResult res = (OdbcQueryExecuteResult) res0;
 
             if (log.isDebugEnabled())
-                log.debug("Resulting query ID: " + res.getQueryId());
+                log.debug("Resulting query ID: " + res.queryId());
 
-            writer.writeLong(res.getQueryId());
+            writer.writeLong(res.queryId());
 
             Collection<OdbcColumnMeta> metas = res.getColumnsMetadata();
 
@@ -193,6 +223,17 @@ public class OdbcMessageParser implements 
SqlListenerMessageParser {
             for (OdbcColumnMeta meta : metas)
                 meta.write(writer);
         }
+        else if (res0 instanceof OdbcQueryExecuteBatchResult) {
+            OdbcQueryExecuteBatchResult res = (OdbcQueryExecuteBatchResult) 
res0;
+
+            writer.writeBoolean(res.errorMessage() == null);
+            writer.writeLong(res.rowsAffected());
+
+            if (res.errorMessage() != null) {
+                writer.writeLong(res.errorSetIdx());
+                writer.writeString(res.errorMessage());
+            }
+        }
         else if (res0 instanceof OdbcQueryFetchResult) {
             OdbcQueryFetchResult res = (OdbcQueryFetchResult) res0;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
new file mode 100644
index 0000000..50d16e5
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
@@ -0,0 +1,95 @@
+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 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.Nullable;
+
+/**
+ * ODBC query execute request with the batch of parameters.
+ */
+public class OdbcQueryExecuteBatchRequest extends OdbcRequest {
+    /** Schema. */
+    @GridToStringInclude(sensitive = true)
+    private final String schema;
+
+    /** Sql query. */
+    @GridToStringInclude(sensitive = true)
+    private final String sqlQry;
+
+    /** Last param page flag. */
+    private final boolean last;
+
+    /** Sql query arguments. */
+    @GridToStringExclude
+    private final Object[][] args;
+
+    /**
+     * @param schema Schema.
+     * @param sqlQry SQL query.
+     * @param last Last page flag.
+     * @param args Arguments list.
+     */
+    public OdbcQueryExecuteBatchRequest(@Nullable String schema, String 
sqlQry, boolean last, Object[][] args) {
+        super(QRY_EXEC_BATCH);
+
+        assert sqlQry != null : "SQL query should not be null";
+        assert args != null : "Parameters should not be null";
+
+        this.schema = schema;
+        this.sqlQry = sqlQry;
+        this.last = last;
+        this.args = args;
+    }
+
+    /**
+     * @return Sql query.
+     */
+    public String sqlQuery() {
+        return sqlQry;
+    }
+
+    /**
+     * @return Sql query arguments.
+     */
+    public Object[][] arguments() {
+        return args;
+    }
+
+    /**
+     * @return Schema.
+     */
+    @Nullable
+    public String schema() {
+        return schema;
+    }
+
+    /**
+     * @return Last page flag.
+     */
+    public boolean last() {
+        return last;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(OdbcQueryExecuteBatchRequest.class, this, "args", 
args, true);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java
new file mode 100644
index 0000000..ee02fd6
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java
@@ -0,0 +1,75 @@
+/*
+ * 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.jetbrains.annotations.Nullable;
+
+/**
+ * ODBC query execute with batch of parameters result.
+ */
+public class OdbcQueryExecuteBatchResult {
+    /** Rows affected. */
+    private final long rowsAffected;
+
+    /** Index of the set which caused an error. */
+    private final long errorSetIdx;
+
+    /** Error message. */
+    private final String errorMessage;
+
+    /**
+     * @param rowsAffected Number of rows affected by the query.
+     */
+    public OdbcQueryExecuteBatchResult(long rowsAffected) {
+        this.rowsAffected = rowsAffected;
+        this.errorSetIdx = -1;
+        this.errorMessage = null;
+    }
+
+    /**
+     * @param rowsAffected Number of rows affected by the query.
+     * @param errorSetIdx Sets processed.
+     * @param errorMessage Error message.
+     */
+    public OdbcQueryExecuteBatchResult(long rowsAffected, long errorSetIdx, 
String errorMessage) {
+        this.rowsAffected = rowsAffected;
+        this.errorSetIdx = errorSetIdx;
+        this.errorMessage = errorMessage;
+    }
+
+    /**
+     * @return Number of rows affected by the query.
+     */
+    public long rowsAffected() {
+        return rowsAffected;
+    }
+
+    /**
+     * @return Index of the set which caused an error or -1 if no error 
occurred.
+     */
+    public long errorSetIdx() {
+        return errorSetIdx;
+    }
+
+    /**
+     * @return Error message.
+     */
+    @Nullable public String errorMessage() {
+        return errorMessage;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
index 8bb61dc..26d3328 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
@@ -42,10 +42,12 @@ public class OdbcQueryExecuteRequest extends OdbcRequest {
      * @param sqlQry SQL query.
      * @param args Arguments list.
      */
-    public OdbcQueryExecuteRequest(String schema, String sqlQry, Object[] 
args) {
+    public OdbcQueryExecuteRequest(@Nullable String schema, String sqlQry, 
Object[] args) {
         super(QRY_EXEC);
 
-        this.schema = schema.isEmpty() ? null : schema;
+        assert sqlQry != null : "SQL query should not be null";
+
+        this.schema = schema;
         this.sqlQry = sqlQry;
         this.args = args;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
index de5a8fd..4b8ecbe 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java
@@ -41,7 +41,7 @@ public class OdbcQueryExecuteResult {
     /**
      * @return Query ID.
      */
-    public long getQueryId() {
+    public long queryId() {
         return queryId;
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/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 825e770..62c4de3 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
@@ -41,8 +41,8 @@ public class OdbcRequest extends SqlListenerRequest {
     /** Get parameters meta. */
     public static final int META_PARAMS = 7;
 
-    /** Get parameters meta. */
-    public static final int JDBC_REQ = 8;
+    /** Execute sql query with the batch of parameters. */
+    public static final int QRY_EXEC_BATCH = 8;
 
     /** Command. */
     private final int cmd;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/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 dfcd462..0c65edd 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
@@ -27,6 +27,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
@@ -45,12 +47,7 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 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;
-import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_TBLS;
-import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_CLOSE;
-import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_EXEC;
-import static 
org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_FETCH;
+import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.*;
 
 /**
  * SQL query handler.
@@ -59,6 +56,9 @@ public class OdbcRequestHandler implements 
SqlListenerRequestHandler {
     /** Query ID sequence. */
     private static final AtomicLong QRY_ID_GEN = new AtomicLong();
 
+    /** Batch query ID sequence. */
+    private static final AtomicLong BATCH_QRY_ID_GEN = new AtomicLong();
+
     /** Kernel context. */
     private final GridKernalContext ctx;
 
@@ -115,6 +115,9 @@ public class OdbcRequestHandler implements 
SqlListenerRequestHandler {
                 case QRY_EXEC:
                     return executeQuery((OdbcQueryExecuteRequest)req);
 
+                case QRY_EXEC_BATCH:
+                    return 
executeBatchQuery((OdbcQueryExecuteBatchRequest)req);
+
                 case QRY_FETCH:
                     return fetchQuery((OdbcQueryFetchRequest)req);
 
@@ -194,6 +197,99 @@ public class OdbcRequestHandler implements 
SqlListenerRequestHandler {
     }
 
     /**
+     * {@link OdbcQueryExecuteBatchRequest} command handler.
+     *
+     * @param req Execute query request.
+     * @return Response.
+     */
+    private SqlListenerResponse executeBatchQuery(OdbcQueryExecuteBatchRequest 
req) {
+        long rowsAffected = 0;
+        int currentSet = 0;
+
+        try {
+            String sql = OdbcEscapeUtils.parse(req.sqlQuery());
+
+            if (log.isDebugEnabled())
+                log.debug("ODBC query parsed [reqId=" + req.requestId() + ", 
original=" + req.sqlQuery() +
+                        ", parsed=" + sql + ']');
+
+            SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+            qry.setDistributedJoins(distributedJoins);
+            qry.setEnforceJoinOrder(enforceJoinOrder);
+            qry.setSchema(req.schema());
+
+            Object[][] paramSet = req.arguments();
+
+            if (paramSet.length <= 0)
+                throw new IgniteException("Batch execute request with 
non-positive batch length. [len="
+                        + paramSet.length + ']');
+
+            // Getting meta and do the checks for the first execution.
+            qry.setArgs(paramSet[0]);
+
+            QueryCursorImpl<List<?>> qryCur = 
(QueryCursorImpl<List<?>>)ctx.query().querySqlFieldsNoCache(qry, true);
+
+            if (qryCur.isQuery())
+                throw new IgniteException("Batching of parameters only 
supported for DML statements. [query=" +
+                        req.sqlQuery() + ']');
+
+            rowsAffected += getRowsAffected(qryCur);
+
+            for (currentSet = 1; currentSet < paramSet.length; ++currentSet)
+                rowsAffected += executeQuery(qry, paramSet[currentSet]);
+
+            OdbcQueryExecuteBatchResult res = new 
OdbcQueryExecuteBatchResult(rowsAffected);
+
+            return new OdbcResponse(res);
+        }
+        catch (Exception e) {
+            U.error(log, "Failed to execute SQL query [reqId=" + 
req.requestId() + ", req=" + req + ']', e);
+
+            OdbcQueryExecuteBatchResult res = new 
OdbcQueryExecuteBatchResult(rowsAffected, currentSet,
+                    e.getMessage());
+
+            return new OdbcResponse(res);
+        }
+    }
+
+    /**
+     * Execute query.
+     * @param qry Query
+     * @param row Row
+     * @return Affected rows.
+     */
+    private long executeQuery(SqlFieldsQuery qry, Object[] row) {
+        qry.setArgs(row);
+
+        QueryCursor<List<?>> cur = ctx.query().querySqlFieldsNoCache(qry, 
true);
+
+        return getRowsAffected(cur);
+    }
+
+    /**
+     * Get affected rows for DML statement.
+     * @param qryCur Cursor.
+     * @return Number of table rows affected.
+     */
+    private static long getRowsAffected(QueryCursor<List<?>> qryCur) {
+        Iterator<List<?>> iter = qryCur.iterator();
+
+        if (iter.hasNext()) {
+            List<?> res = iter.next();
+
+            if (res.size() > 0) {
+                Long affected = (Long) res.get(0);
+
+                if (affected != null)
+                    return affected;
+            }
+        }
+
+        return 0;
+    }
+
+    /**
      * {@link OdbcQueryCloseRequest} command handler.
      *
      * @param req Execute query request.

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/core-test/src/test_utils.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/test_utils.cpp 
b/modules/platforms/cpp/core-test/src/test_utils.cpp
index c6e4454..ded229e 100644
--- a/modules/platforms/cpp/core-test/src/test_utils.cpp
+++ b/modules/platforms/cpp/core-test/src/test_utils.cpp
@@ -36,6 +36,7 @@ namespace ignite_test
         cfg.jvmOpts.push_back("-DIGNITE_QUIET=false");
         cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false");
         cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false");
+        cfg.jvmOpts.push_back("-Duser.language=en");
 
         std::string home;
         bool homeFound = jni::ResolveIgniteHome("", home);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp
----------------------------------------------------------------------
diff --git 
a/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp 
b/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp
index 4454066..5c9e90a 100644
--- a/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp
@@ -44,9 +44,8 @@ BOOST_AUTO_TEST_CASE(TestPutIntToString)
 {
     char buffer[1024];
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen);
 
     appBuf.PutInt8(12);
     BOOST_CHECK(!strcmp(buffer, "12"));
@@ -77,9 +76,8 @@ BOOST_AUTO_TEST_CASE(TestPutFloatToString)
 {
     char buffer[1024];
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen);
 
     appBuf.PutFloat(12.42f);
     BOOST_CHECK(!strcmp(buffer, "12.42"));
@@ -102,9 +100,8 @@ BOOST_AUTO_TEST_CASE(TestPutGuidToString)
 {
     char buffer[1024];
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen);
 
     ignite::Guid guid(0x1da1ef8f39ff4d62ULL, 0x8b72e8e9f3371801ULL);
 
@@ -118,9 +115,8 @@ BOOST_AUTO_TEST_CASE(TestPutBinaryToString)
 {
     char buffer[1024];
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen);
 
     uint8_t binary[] = { 0x21, 0x84, 0xF4, 0xDC, 0x01, 0x00, 0xFF, 0xF0 };
 
@@ -134,9 +130,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToString)
 {
     char buffer[1024];
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer), &reslen);
 
     std::string testString("Test string");
 
@@ -150,9 +145,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToWstring)
 {
     wchar_t buffer[1024];
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_WCHAR, buffer, 
sizeof(buffer), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_WCHAR, buffer, 
sizeof(buffer), &reslen);
 
     std::string testString("Test string");
 
@@ -164,9 +158,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToLong)
 {
     long numBuf;
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, 
sizeof(numBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, 
sizeof(numBuf), &reslen);
 
     appBuf.PutString("424242424");
     BOOST_CHECK(numBuf == 424242424L);
@@ -179,9 +172,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToTiny)
 {
     int8_t numBuf;
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_TINYINT, &numBuf, 
sizeof(numBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_TINYINT, &numBuf, 
sizeof(numBuf), &reslen);
 
     appBuf.PutString("12");
     BOOST_CHECK(numBuf == 12);
@@ -194,9 +186,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToFloat)
 {
     float numBuf;
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, 
sizeof(numBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, 
sizeof(numBuf), &reslen);
 
     appBuf.PutString("12.21");
     BOOST_CHECK_CLOSE_FRACTION(numBuf, 12.21, FLOAT_PRECISION);
@@ -209,9 +200,8 @@ BOOST_AUTO_TEST_CASE(TestPutIntToFloat)
 {
     float numBuf;
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, 
sizeof(numBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, 
sizeof(numBuf), &reslen);
 
     appBuf.PutInt8(5);
     BOOST_CHECK_CLOSE_FRACTION(numBuf, 5.0, FLOAT_PRECISION);
@@ -236,9 +226,8 @@ BOOST_AUTO_TEST_CASE(TestPutFloatToShort)
 {
     short numBuf;
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_SHORT, &numBuf, 
sizeof(numBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_SHORT, &numBuf, 
sizeof(numBuf), &reslen);
 
     appBuf.PutDouble(5.42);
     BOOST_CHECK(numBuf == 5);
@@ -258,7 +247,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToDouble)
     double numBuf;
     SqlLen reslen = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, 
sizeof(numBuf), &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, 
sizeof(numBuf), &reslen);
 
     common::Decimal decimal;
 
@@ -287,7 +276,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToLong)
     long numBuf;
     SqlLen reslen = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, 
sizeof(numBuf), &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, 
sizeof(numBuf), &reslen);
 
     common::Decimal decimal;
 
@@ -314,7 +303,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToString)
     char strBuf[64];
     SqlLen reslen = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen);
 
     common::Decimal decimal;
 
@@ -341,7 +330,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToNumeric)
     SQL_NUMERIC_STRUCT buf;
     SqlLen reslen = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_NUMERIC, &buf, 
sizeof(buf), &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_NUMERIC, &buf, 
sizeof(buf), &reslen);
 
     common::Decimal decimal;
 
@@ -392,7 +381,7 @@ BOOST_AUTO_TEST_CASE(TestPutDateToString)
     char strBuf[64] = { 0 };
     SqlLen reslen = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen);
 
     Date date = common::MakeDateGmt(1999, 2, 22);
 
@@ -406,10 +395,7 @@ BOOST_AUTO_TEST_CASE(TestPutDateToDate)
     SQL_DATE_STRUCT buf = { 0 };
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen);
 
     Date date = common::MakeDateGmt(1984, 5, 27);
 
@@ -426,10 +412,7 @@ BOOST_AUTO_TEST_CASE(TestPutDateToTimestamp)
 
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen);
 
     Date date = common::MakeDateGmt(1984, 5, 27);
 
@@ -449,7 +432,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimeToString)
     char strBuf[64] = { 0 };
     SqlLen reslen = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen);
 
     Time time = common::MakeTimeGmt(7, 15, 0);
 
@@ -463,10 +446,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimeToTime)
     SQL_TIME_STRUCT buf = { 0 };
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), 
&reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), 
&reslen);
 
     Time time = common::MakeTimeGmt(23, 51, 1);
 
@@ -482,7 +462,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToString)
     char strBuf[64] = { 0 };
     SqlLen reslen = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, 
sizeof(strBuf), &reslen);
 
     Timestamp date = common::MakeTimestampGmt(2018, 11, 1, 17, 45, 59);
 
@@ -496,10 +476,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToDate)
     SQL_DATE_STRUCT buf = { 0 };
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen);
 
     Timestamp ts = common::MakeTimestampGmt(2004, 8, 14, 6, 34, 51, 573948623);
 
@@ -515,10 +492,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToTime)
     SQL_TIME_STRUCT buf = { 0 };
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), 
&reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), 
&reslen);
 
     Timestamp ts = common::MakeTimestampGmt(2004, 8, 14, 6, 34, 51, 573948623);
 
@@ -534,10 +508,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToTimestamp)
     SQL_TIMESTAMP_STRUCT buf = { 0 };
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen);
 
     Timestamp ts = common::MakeTimestampGmt(2004, 8, 14, 6, 34, 51, 573948623);
 
@@ -557,7 +528,7 @@ BOOST_AUTO_TEST_CASE(TestGetGuidFromString)
     char buffer[] = "1da1ef8f-39ff-4d62-8b72-e8e9f3371801";
     SqlLen reslen = sizeof(buffer) - 1;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer) - 1, &reslen, 0);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, 
sizeof(buffer) - 1, &reslen);
 
     ignite::Guid guid = appBuf.GetGuid();
 
@@ -568,9 +539,8 @@ BOOST_AUTO_TEST_CASE(TestGetStringFromLong)
 {
     long numBuf = 42;
     SqlLen reslen = sizeof(numBuf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, 
reslen, &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, 
reslen, &reslen);
 
     std::string res = appBuf.GetString(32);
 
@@ -587,9 +557,8 @@ BOOST_AUTO_TEST_CASE(TestGetStringFromDouble)
 {
     double numBuf = 43.36;
     SqlLen reslen = sizeof(numBuf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, reslen, 
&reslen);
 
     std::string res = appBuf.GetString(32);
 
@@ -606,9 +575,8 @@ BOOST_AUTO_TEST_CASE(TestGetStringFromString)
 {
     char buf[] = "Some data 32d2d5hs";
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, 
&reslen);
 
     std::string res = appBuf.GetString(reslen);
 
@@ -619,9 +587,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromUshort)
 {
     unsigned short numBuf = 7162;
     SqlLen reslen = sizeof(numBuf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_SHORT, &numBuf, 
reslen, &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_SHORT, &numBuf, 
reslen, &reslen);
 
     float resFloat = appBuf.GetFloat();
 
@@ -636,9 +603,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromString)
 {
     char buf[] = "28.562";
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, 
&reslen);
 
     float resFloat = appBuf.GetFloat();
 
@@ -653,9 +619,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromFloat)
 {
     float buf = 207.49f;
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, 
&reslen);
 
     float resFloat = appBuf.GetFloat();
 
@@ -670,9 +635,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromDouble)
 {
     double buf = 893.162;
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, 
&reslen);
 
     float resFloat = appBuf.GetFloat();
 
@@ -687,9 +651,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromString)
 {
     char buf[] = "39";
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, 
&reslen);
 
     int64_t resInt64 = appBuf.GetInt64();
 
@@ -712,9 +675,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromFloat)
 {
     float buf = -107.49f;
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, 
&reslen);
 
     int64_t resInt64 = appBuf.GetInt64();
 
@@ -737,9 +699,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromDouble)
 {
     double buf = 42.97f;
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, 
&reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, 
&reslen);
 
     int64_t resInt64 = appBuf.GetInt64();
 
@@ -762,9 +723,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromBigint)
 {
     uint64_t buf = 19;
     SqlLen reslen = sizeof(buf);
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, &buf, 
reslen, &reslen, &offset);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, &buf, 
reslen, &reslen);
 
     int64_t resInt64 = appBuf.GetInt64();
 
@@ -796,22 +756,19 @@ BOOST_AUTO_TEST_CASE(TestGetIntWithOffset)
         { 42, sizeof(uint64_t) }
     };
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, 
&buf[0].val, sizeof(buf[0].val), &buf[0].reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, 
&buf[0].val, sizeof(buf[0].val), &buf[0].reslen);
 
     int64_t val = appBuf.GetInt64();
 
     BOOST_CHECK(val == 12);
 
-    offset += sizeof(TestStruct);
+    appBuf.SetByteOffset(sizeof(TestStruct));
 
     val = appBuf.GetInt64();
 
     BOOST_CHECK(val == 42);
 
-    offsetPtr = 0;
+    appBuf.SetByteOffset(0);
 
     val = appBuf.GetInt64();
 
@@ -830,11 +787,8 @@ BOOST_AUTO_TEST_CASE(TestSetStringWithOffset)
         { "", 0 },
         { "", 0 }
     };
-
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0].val, 
sizeof(buf[0].val), &buf[0].reslen, &offsetPtr);
+    
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0].val, 
sizeof(buf[0].val), &buf[0].reslen);
 
     appBuf.PutString("Hello Ignite!");
 
@@ -844,7 +798,7 @@ BOOST_AUTO_TEST_CASE(TestSetStringWithOffset)
     BOOST_CHECK(res == "Hello Ignite!");
     BOOST_CHECK(res.size() == strlen("Hello Ignite!"));
 
-    offset += sizeof(TestStruct);
+    appBuf.SetByteOffset(sizeof(TestStruct));
 
     appBuf.PutString("Hello with offset!");
 
@@ -865,11 +819,8 @@ BOOST_AUTO_TEST_CASE(TestGetDateFromString)
 {
     char buf[] = "1999-02-22";
     SqlLen reslen = sizeof(buf);
-
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], 
sizeof(buf), &reslen, &offsetPtr);
+    
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], 
sizeof(buf), &reslen);
 
     Date date = appBuf.GetDate();
 
@@ -892,10 +843,8 @@ BOOST_AUTO_TEST_CASE(TestGetTimeFromString)
     char buf[] = "17:5:59";
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
 
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], 
sizeof(buf), &reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], 
sizeof(buf), &reslen);
 
     Time time = appBuf.GetTime();
 
@@ -918,10 +867,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromString)
     char buf[] = "2018-11-01 17:45:59";
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], 
sizeof(buf), &reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], 
sizeof(buf), &reslen);
 
     Timestamp date = appBuf.GetTimestamp();
 
@@ -949,10 +895,7 @@ BOOST_AUTO_TEST_CASE(TestGetDateFromDate)
 
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen);
 
     Date date = appBuf.GetDate();
 
@@ -980,10 +923,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromDate)
 
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), 
&reslen);
 
     Timestamp ts = appBuf.GetTimestamp();
 
@@ -1011,10 +951,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromTime)
 
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), 
&reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), 
&reslen);
 
     Time time = appBuf.GetTime();
 
@@ -1046,10 +983,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromTimestamp)
 
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen);
 
     Timestamp ts = appBuf.GetTimestamp();
 
@@ -1082,10 +1016,7 @@ BOOST_AUTO_TEST_CASE(TestGetDateFromTimestamp)
 
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen);
 
     Date date = appBuf.GetDate();
 
@@ -1117,10 +1048,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimeFromTimestamp)
 
     SqlLen reslen = sizeof(buf);
 
-    int offset = 0;
-    int* offsetPtr = &offset;
-
-    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen, &offsetPtr);
+    ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, 
sizeof(buf), &reslen);
 
     Time time = appBuf.GetTime();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/column_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/column_test.cpp 
b/modules/platforms/cpp/odbc-test/src/column_test.cpp
index adc40c4..d6e8f57 100644
--- a/modules/platforms/cpp/odbc-test/src/column_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/column_test.cpp
@@ -66,9 +66,8 @@ BOOST_AUTO_TEST_CASE(TestColumnShort)
 
     short shortBuf = 0;
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_SIGNED_SHORT, 
&shortBuf, sizeof(shortBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_SIGNED_SHORT, 
&shortBuf, sizeof(shortBuf), &reslen);
 
     BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == 
SqlResult::AI_SUCCESS);
 
@@ -114,9 +113,8 @@ BOOST_AUTO_TEST_CASE(TestColumnString)
 
     char strBuf[1024] = {};
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf, sizeof(strBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf, sizeof(strBuf), &reslen);
 
     BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == 
SqlResult::AI_SUCCESS);
 
@@ -164,9 +162,8 @@ BOOST_AUTO_TEST_CASE(TestColumnStringSeveral)
 
     std::string strBuf(data.size() / 3 + 2, 0);
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf[0], strBuf.size(), &reslen, &offset);
+    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf[0], strBuf.size(), &reslen);
 
     BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == 
SqlResult::AI_SUCCESS);
 
@@ -246,9 +243,8 @@ BOOST_AUTO_TEST_CASE(TestColumnMultiString)
 
     char strBuf[1024] = {};
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf, sizeof(strBuf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf, sizeof(strBuf), &reslen);
 
     BOOST_REQUIRE(column1.ReadToBuffer(reader, appBuf) == 
SqlResult::AI_SUCCESS);
 
@@ -312,9 +308,8 @@ BOOST_AUTO_TEST_CASE(TestColumnByteArray)
 
     std::vector<int8_t> buf(data.size());
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, 
&buf[0], buf.size(), &reslen, &offset);
+    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, 
&buf[0], buf.size(), &reslen);
 
     BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == 
SqlResult::AI_SUCCESS);
 
@@ -362,9 +357,8 @@ BOOST_AUTO_TEST_CASE(TestColumnByteArrayHalfBuffer)
 
     std::vector<int8_t> buf(data.size()/2);
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, 
&buf[0], buf.size(), &reslen, &offset);
+    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, 
&buf[0], buf.size(), &reslen);
 
     BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == 
SqlResult::AI_SUCCESS);
 
@@ -435,9 +429,8 @@ BOOST_AUTO_TEST_CASE(TestColumnByteArrayTwoColumns)
 
     int8_t buf[1024] = {};
     SqlLen reslen = 0;
-    int* offset = 0;
 
-    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf, 
sizeof(buf), &reslen, &offset);
+    ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf, 
sizeof(buf), &reslen);
 
     BOOST_REQUIRE(column1.ReadToBuffer(reader, appBuf) == 
SqlResult::AI_SUCCESS);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/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 282c6cb..41bc1fc 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -33,6 +33,7 @@
 #include <boost/test/unit_test.hpp>
 
 #include "ignite/ignite.h"
+#include "ignite/common/fixed_size_array.h"
 #include "ignite/ignition.h"
 #include "ignite/impl/binary/binary_utils.h"
 #include "ignite/binary/binary_object.h"
@@ -310,10 +311,10 @@ struct QueriesTestSuiteFixture
     }
 
     /**
-     * Insert requested number of TestType vlaues with all defaults except
+     * Insert requested number of TestType values with all defaults except
      * for the strFields, which are generated using getTestString().
      *
-     * @param num Number of records to insert.
+     * @param recordsNum Number of records to insert.
      * @param merge Set to true to use merge instead.
      */
     void InsertTestStrings(int recordsNum, bool merge = false)
@@ -371,6 +372,335 @@ struct QueriesTestSuiteFixture
             BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
     }
 
+    /**
+     * Insert requested number of TestType values in a batch.
+     *
+     * @param from Index to start from.
+     * @param to Index to stop.
+     * @param expectedToAffect Expected number of affected records.
+     * @param merge Set to true to use merge instead of insert.
+     * @return Records inserted.
+     */
+    int InsertTestBatch(int from, int to, int expectedToAffect, bool merge = 
false)
+    {
+        SQLCHAR insertReq[] = "INSERT "
+            "INTO TestType(_key, i8Field, i16Field, i32Field, strField, 
floatField, doubleField, boolField, dateField, "
+            "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, 
?, ?, ?, ?, ?, ?)";
+
+        SQLCHAR mergeReq[] = "MERGE "
+            "INTO TestType(_key, i8Field, i16Field, i32Field, strField, 
floatField, doubleField, boolField, dateField, "
+            "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, 
?, ?, ?, ?, ?, ?)";
+
+        SQLRETURN ret;
+
+        int recordsNum = to - from;
+
+        ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        FixedSizeArray<int64_t> keys(recordsNum);
+        FixedSizeArray<int8_t> i8Fields(recordsNum);
+        FixedSizeArray<int16_t> i16Fields(recordsNum);
+        FixedSizeArray<int32_t> i32Fields(recordsNum);
+        FixedSizeArray<char> strFields(recordsNum * 1024);
+        FixedSizeArray<float> floatFields(recordsNum);
+        FixedSizeArray<double> doubleFields(recordsNum);
+        FixedSizeArray<bool> boolFields(recordsNum);
+        FixedSizeArray<SQL_DATE_STRUCT> dateFields(recordsNum);
+        FixedSizeArray<SQL_TIME_STRUCT> timeFields(recordsNum);
+        FixedSizeArray<SQL_TIMESTAMP_STRUCT> timestampFields(recordsNum);
+        FixedSizeArray<int8_t> i8ArrayFields(recordsNum * 42);
+
+        FixedSizeArray<SQLLEN> strFieldsLen(recordsNum);
+        FixedSizeArray<SQLLEN> i8ArrayFieldsLen(recordsNum);
+
+        BOOST_CHECKPOINT("Filling param data");
+
+        for (int i = 0; i < recordsNum; ++i)
+        {
+            int seed = from + i;
+
+            keys[i] = seed;
+            i8Fields[i] = seed * 8;
+            i16Fields[i] = seed * 16;
+            i32Fields[i] = seed * 32;
+
+            std::string val = getTestString(seed);
+            strncpy(strFields.GetData() + 1024 * i, val.c_str(), 1023);
+            strFieldsLen[i] = val.size();
+
+            floatFields[i] = seed * 0.5f;
+            doubleFields[i] = seed * 0.25f;
+            boolFields[i] = seed % 2 == 0;
+
+            dateFields[i].year = 2017 + seed / 365;
+            dateFields[i].month = ((seed / 28) % 12) + 1;
+            dateFields[i].day = (seed % 28) + 1;
+
+            timeFields[i].hour = (seed / 3600) % 24;
+            timeFields[i].minute = (seed / 60) % 60;
+            timeFields[i].second = seed % 60;
+
+            timestampFields[i].year = dateFields[i].year;
+            timestampFields[i].month = dateFields[i].month;
+            timestampFields[i].day = dateFields[i].day;
+            timestampFields[i].hour = timeFields[i].hour;
+            timestampFields[i].minute = timeFields[i].minute;
+            timestampFields[i].second = timeFields[i].second;
+            timestampFields[i].fraction = std::abs(seed * 914873) % 1000000000;
+
+            for (int j = 0; j < 42; ++j)
+                i8ArrayFields[i * 42 + j] = seed * 42 + j;
+            i8ArrayFieldsLen[i] = 42;
+        }
+
+        SQLULEN setsProcessed = 0;
+
+        BOOST_CHECKPOINT("Setting processed pointer");
+        ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, 
&setsProcessed, SQL_IS_POINTER);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding keys");
+        ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, 
SQL_BIGINT, 0, 0, keys.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding i8Fields");
+        ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_STINYINT, 
SQL_TINYINT, 0, 0, i8Fields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding i16Fields");
+        ret = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_SSHORT, 
SQL_SMALLINT, 0, 0, i16Fields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding i32Fields");
+        ret = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SLONG, 
SQL_INTEGER, 0, 0, i32Fields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding strFields");
+        ret = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, 
SQL_VARCHAR, 1024, 0, strFields.GetData(), 1024, strFieldsLen.GetData());
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding floatFields");
+        ret = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_FLOAT, 
SQL_FLOAT, 0, 0, floatFields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding doubleFields");
+        ret = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_DOUBLE, 
SQL_DOUBLE, 0, 0, doubleFields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding boolFields");
+        ret = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, 
0, 0, boolFields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding dateFields");
+        ret = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE, 
0, 0, dateFields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding timeFields");
+        ret = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_TIME, 
SQL_TIME, 0, 0, timeFields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding timestampFields");
+        ret = SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, 
SQL_TIMESTAMP, 0, 0, timestampFields.GetData(), 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Binding i8ArrayFields");
+        ret = SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_BINARY, 
SQL_BINARY, 42, 0, i8ArrayFields.GetData(), 42, i8ArrayFieldsLen.GetData());
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Setting paramset size");
+        ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, 
reinterpret_cast<SQLPOINTER>(recordsNum), 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Executing query");
+        ret = SQLExecute(stmt);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        SQLLEN affected = 0;
+        ret = SQLRowCount(stmt, &affected);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECK_EQUAL(affected, expectedToAffect);
+
+        BOOST_CHECKPOINT("Getting next result set");
+        ret = SQLMoreResults(stmt);
+
+        if (ret != SQL_NO_DATA)
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Resetting parameters.");
+        ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        BOOST_CHECKPOINT("Setting paramset size");
+        ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, 
reinterpret_cast<SQLPOINTER>(1), 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        return static_cast<int>(setsProcessed);
+    }
+
+    void InsertBatchSelect(int recordsNum)
+    {
+        Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+        // Inserting values.
+        int inserted = InsertTestBatch(0, recordsNum, recordsNum);
+
+        BOOST_REQUIRE_EQUAL(inserted, recordsNum);
+
+        int64_t key = 0;
+        char strField[1024] = { 0 };
+        SQLLEN strFieldLen = 0;
+
+        // Binding columns.
+        SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        // Binding columns.
+        ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), 
&strFieldLen);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        // Just selecting everything to make sure everything is OK
+        SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY 
_key";
+
+        ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        int selectedRecordsNum = 0;
+
+        ret = SQL_SUCCESS;
+
+        while (ret == SQL_SUCCESS)
+        {
+            ret = SQLFetch(stmt);
+
+            if (ret == SQL_NO_DATA)
+                break;
+
+            if (!SQL_SUCCEEDED(ret))
+                BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+            std::string expectedStr = getTestString(selectedRecordsNum);
+            int64_t expectedKey = selectedRecordsNum;
+
+            BOOST_CHECK_EQUAL(key, expectedKey);
+
+            BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+            ++selectedRecordsNum;
+        }
+
+        BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+    }
+
+    void InsertNonFullBatchSelect(int recordsNum, int splitAt)
+    {
+        Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+        // Inserting values.
+        int inserted = InsertTestBatch(splitAt, recordsNum, recordsNum - 
splitAt);
+
+        BOOST_REQUIRE_EQUAL(inserted, recordsNum - splitAt);
+
+        inserted = InsertTestBatch(0, recordsNum, splitAt);
+
+        BOOST_REQUIRE_EQUAL(inserted, splitAt);
+
+        int64_t key = 0;
+        char strField[1024] = { 0 };
+        SQLLEN strFieldLen = 0;
+
+        // Binding columns.
+        SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        // Binding columns.
+        ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), 
&strFieldLen);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        // Just selecting everything to make sure everything is OK
+        SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY 
_key";
+
+        ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        int selectedRecordsNum = 0;
+
+        ret = SQL_SUCCESS;
+
+        while (ret == SQL_SUCCESS)
+        {
+            ret = SQLFetch(stmt);
+
+            if (ret == SQL_NO_DATA)
+                break;
+
+            if (!SQL_SUCCEEDED(ret))
+                BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+            std::string expectedStr = getTestString(selectedRecordsNum);
+            int64_t expectedKey = selectedRecordsNum;
+
+            BOOST_CHECK_EQUAL(key, expectedKey);
+
+            BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+            ++selectedRecordsNum;
+        }
+
+        BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+    }
+
     /** Node started during the test. */
     Ignite grid;
 
@@ -1303,6 +1633,76 @@ BOOST_AUTO_TEST_CASE(TestInsertMergeSelect)
     BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
 }
 
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2)
+{
+    InsertBatchSelect(2);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect100)
+{
+    InsertBatchSelect(100);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1000)
+{
+    InsertBatchSelect(1000);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1023)
+{
+    InsertBatchSelect(1024);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1024)
+{
+    InsertBatchSelect(1024);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1025)
+{
+    InsertBatchSelect(1025);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2000)
+{
+    InsertBatchSelect(2000);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2047)
+{
+    InsertBatchSelect(2048);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2048)
+{
+    InsertBatchSelect(2048);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2049)
+{
+    InsertBatchSelect(2049);
+}
+
+BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect900)
+{
+    InsertNonFullBatchSelect(900, 42);
+}
+
+BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect1500)
+{
+    InsertNonFullBatchSelect(1500, 100);
+}
+
+BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect4500)
+{
+    InsertNonFullBatchSelect(4500, 1500);
+}
+
+BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect4096)
+{
+    InsertNonFullBatchSelect(4096, 1024);
+}
+
 template<size_t n, size_t k>
 void CheckMeta(char columns[n][k], SQLLEN columnsLen[n])
 {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/row_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/row_test.cpp 
b/modules/platforms/cpp/odbc-test/src/row_test.cpp
index c692291..08fadd1 100644
--- a/modules/platforms/cpp/odbc-test/src/row_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/row_test.cpp
@@ -82,12 +82,11 @@ void CheckRowData(Row& row, size_t rowIdx)
     char strBuf[1024];
     SQLGUID guidBuf;
     char bitBuf;
-    int* offset = 0;
 
-    ApplicationDataBuffer 
appLongBuf(type_traits::OdbcNativeType::AI_SIGNED_LONG, &longBuf, 
sizeof(longBuf), &reslen, &offset);
-    ApplicationDataBuffer appStrBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf, sizeof(strBuf), &reslen, &offset);
-    ApplicationDataBuffer appGuidBuf(type_traits::OdbcNativeType::AI_GUID, 
&guidBuf, sizeof(guidBuf), &reslen, &offset);
-    ApplicationDataBuffer appBitBuf(type_traits::OdbcNativeType::AI_BIT, 
&bitBuf, sizeof(bitBuf), &reslen, &offset);
+    ApplicationDataBuffer 
appLongBuf(type_traits::OdbcNativeType::AI_SIGNED_LONG, &longBuf, 
sizeof(longBuf), &reslen);
+    ApplicationDataBuffer appStrBuf(type_traits::OdbcNativeType::AI_CHAR, 
&strBuf, sizeof(strBuf), &reslen);
+    ApplicationDataBuffer appGuidBuf(type_traits::OdbcNativeType::AI_GUID, 
&guidBuf, sizeof(guidBuf), &reslen);
+    ApplicationDataBuffer appBitBuf(type_traits::OdbcNativeType::AI_BIT, 
&bitBuf, sizeof(bitBuf), &reslen);
 
     // Checking size.
     BOOST_REQUIRE(row.GetSize() == 4);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/test_utils.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/test_utils.cpp 
b/modules/platforms/cpp/odbc-test/src/test_utils.cpp
index 6fceb03..c7aa70a 100644
--- a/modules/platforms/cpp/odbc-test/src/test_utils.cpp
+++ b/modules/platforms/cpp/odbc-test/src/test_utils.cpp
@@ -50,6 +50,7 @@ namespace ignite_test
         cfg.jvmOpts.push_back("-DIGNITE_QUIET=false");
         cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false");
         cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false");
+        cfg.jvmOpts.push_back("-Duser.language=en");
 
         std::string home;
         bool homeFound = jni::ResolveIgniteHome("", home);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/Makefile.am 
b/modules/platforms/cpp/odbc/Makefile.am
index de6f75a..8d7693c 100644
--- a/modules/platforms/cpp/odbc/Makefile.am
+++ b/modules/platforms/cpp/odbc/Makefile.am
@@ -52,6 +52,7 @@ libignite_odbc_la_SOURCES = \
     os/linux/src/system/socket_client.cpp \
     src/app/application_data_buffer.cpp \
     src/app/parameter.cpp \
+    src/app/parameter_set.cpp \
     src/common_types.cpp \
     src/config/configuration.cpp \
     src/config/connection_info.cpp \
@@ -68,6 +69,7 @@ libignite_odbc_la_SOURCES = \
     src/dsn_config.cpp \
     src/query/column_metadata_query.cpp \
     src/query/data_query.cpp \
+    src/query/batch_query.cpp \
     src/query/foreign_keys_query.cpp \
     src/query/primary_keys_query.cpp \
     src/query/table_metadata_query.cpp \
@@ -76,6 +78,7 @@ libignite_odbc_la_SOURCES = \
     src/protocol_version.cpp \
     src/result_page.cpp \
     src/row.cpp \
+    src/message.cpp \
     src/column.cpp \
     src/statement.cpp \
     src/type_traits.cpp \

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/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 36d8e25..92c85c5 100644
--- a/modules/platforms/cpp/odbc/include/Makefile.am
+++ b/modules/platforms/cpp/odbc/include/Makefile.am
@@ -22,6 +22,7 @@ noinst_HEADERS = \
     ignite/odbc/query/table_metadata_query.h \
     ignite/odbc/query/special_columns_query.h \
     ignite/odbc/query/type_info_query.h \
+    ignite/odbc/query/batch_query.h \
     ignite/odbc/query/data_query.h \
     ignite/odbc/query/foreign_keys_query.h \
     ignite/odbc/query/column_metadata_query.h \
@@ -35,6 +36,7 @@ noinst_HEADERS = \
     ignite/odbc/parser.h \
     ignite/odbc/app/application_data_buffer.h \
     ignite/odbc/app/parameter.h \
+    ignite/odbc/app/parameter_set.h \
     ignite/odbc/row.h \
     ignite/odbc/utility.h \
     ignite/odbc/environment.h \

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h
----------------------------------------------------------------------
diff --git 
a/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h 
b/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h
index 24461c2..abce85c 100644
--- 
a/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h
+++ 
b/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h
@@ -55,10 +55,9 @@ namespace ignite
                  * @param buffer Data buffer pointer.
                  * @param buflen Data buffer length.
                  * @param reslen Resulting data length.
-                 * @param offset Pointer to buffer and reslen offset pointer.
                  */
                 ApplicationDataBuffer(type_traits::OdbcNativeType::Type type, 
void* buffer,
-                    SqlLen buflen, SqlLen* reslen, int** offset = 0);
+                    SqlLen buflen, SqlLen* reslen);
 
                 /**
                  * Copy constructor.
@@ -81,13 +80,23 @@ namespace ignite
                 ApplicationDataBuffer& operator=(const ApplicationDataBuffer& 
other);
 
                 /**
-                 * Set pointer to offset pointer.
+                 * Set offset in bytes for all bound pointers.
                  *
-                 * @param offset Pointer to offset pointer.
+                 * @param offset Offset.
                  */
-                void SetPtrToOffsetPtr(int** offset)
+                void SetByteOffset(int offset)
                 {
-                    this->offset = offset;
+                    this->byteOffset = offset;
+                }
+
+                /**
+                 * Set offset in elements for all bound pointers.
+                 *
+                 * @param
+                 */
+                void SetElementOffset(SqlUlen idx)
+                {
+                    this->elementOffset = idx;
                 }
 
                 /**
@@ -329,6 +338,13 @@ namespace ignite
                 SqlLen GetDataAtExecSize() const;
 
                 /**
+                 * Get single element size.
+                 *
+                 * @return Size of the single element.
+                 */
+                SqlLen GetElementSize() const;
+
+                /**
                  * Get size of the input buffer.
                  *
                  * @return Input buffer size, or zero if the data is going
@@ -407,10 +423,11 @@ namespace ignite
                  * Apply buffer offset to pointer.
                  * Adds offset to pointer if offset pointer is not null.
                  * @param ptr Pointer.
+                 * @param elemSize Element size.
                  * @return Pointer with applied offset.
                  */
                 template<typename T>
-                T* ApplyOffset(T* ptr) const;
+                T* ApplyOffset(T* ptr, size_t elemSize) const;
 
                 /** Underlying data type. */
                 type_traits::OdbcNativeType::Type type;
@@ -424,8 +441,11 @@ namespace ignite
                 /** Result length. */
                 SqlLen* reslen;
 
-                /** Pointer to implementation pointer to application offset */
-                int** offset;
+                /** Current byte offset */
+                int byteOffset;
+
+                /** Current element offset. */
+                SqlUlen elementOffset;
             };
 
             /** Column binging map type alias. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h 
b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h
index 1cf85b5..cdaaead 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h
@@ -22,12 +22,10 @@
 
 #include <map>
 
-#include <ignite/guid.h>
 #include <ignite/impl/binary/binary_writer_impl.h>
 #include <ignite/impl/binary/binary_reader_impl.h>
 
 #include "ignite/odbc/app/application_data_buffer.h"
-#include "ignite/odbc/type_traits.h"
 
 namespace ignite
 {
@@ -70,7 +68,7 @@ namespace ignite
                 ~Parameter();
 
                 /**
-                 * Copy assigment operator.
+                 * Assignment operator.
                  *
                  * @param other Other instance.
                  * @return This.
@@ -78,10 +76,12 @@ namespace ignite
                 Parameter& operator=(const Parameter& other);
 
                 /**
-                 * Write request using provided writer.
+                 * Write parameter using provided writer.
                  * @param writer Writer.
+                 * @param offset Offset for the buffer.
+                 * @param idx Index for the array-of-parameters case.
                  */
-                void Write(impl::binary::BinaryWriterImpl& writer) const;
+                void Write(impl::binary::BinaryWriterImpl& writer, int offset 
= 0, SqlUlen idx = 0) const;
 
                 /**
                  * Get data buffer.
@@ -91,6 +91,13 @@ namespace ignite
                 ApplicationDataBuffer& GetBuffer();
 
                 /**
+                 * Get data buffer.
+                 *
+                 * @return underlying ApplicationDataBuffer instance.
+                 */
+                const ApplicationDataBuffer& GetBuffer() const;
+
+                /**
                  * Reset stored at-execution data.
                  */
                 void ResetStoredData();
@@ -128,9 +135,6 @@ namespace ignite
                 /** Stored at-execution data. */
                 std::vector<int8_t> storedData;
             };
-
-            /** Parameter binging map type alias. */
-            typedef std::map<uint16_t, Parameter> ParameterBindingMap;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h 
b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h
new file mode 100644
index 0000000..2ab5580
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h
@@ -0,0 +1,268 @@
+/*
+ * 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_APP_PARAMETER_SET
+#define _IGNITE_ODBC_APP_PARAMETER_SET
+
+#include <stdint.h>
+
+#include <map>
+
+#include <ignite/impl/binary/binary_writer_impl.h>
+#include <ignite/impl/binary/binary_reader_impl.h>
+
+#include "ignite/odbc/app/parameter.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace app
+        {
+            /**
+             * Parameter set.
+             */
+            class ParameterSet
+            {
+                /** Parameter binging map type alias. */
+                typedef std::map<uint16_t, Parameter> ParameterBindingMap;
+
+                /** Parameter meta vector. */
+                typedef std::vector<int8_t> ParameterTypeVector;
+            public:
+                /**
+                 * Default constructor.
+                 */
+                ParameterSet();
+
+                /**
+                 * Destructor.
+                 */
+                ~ParameterSet()
+                {
+                    // No-op.
+                }
+
+                /**
+                 * Set parameters set size.
+                 *
+                 * @param size Size of the parameter set.
+                 */
+                void SetParamSetSize(SqlUlen size);
+
+                /**
+                 * Bind parameter.
+                 * 
+                 * @param paramIdx Parameter index.
+                 * @param param Parameter.
+                 */
+                void BindParameter(uint16_t paramIdx, const Parameter& param);
+
+                /**
+                 * Unbind specified parameter.
+                 *
+                 * @param paramIdx Parameter index.
+                 */
+                void UnbindParameter(uint16_t paramIdx);
+
+                /**
+                 * Unbind all parameters.
+                 */
+                void UnbindAll();
+
+                /**
+                 * Get number of binded parameters.
+                 *
+                 * @return Number of binded parameters.
+                 */
+                uint16_t GetParametersNumber() const;
+
+                /**
+                 * Set parameter binding offset pointer.
+                 *
+                 * @param ptr Parameter binding offset pointer.
+                 */
+                void SetParamBindOffsetPtr(int* ptr);
+
+                /**
+                 * Get parameter binding offset pointer.
+                 *
+                 * @return Parameter binding offset pointer.
+                 */
+                int* GetParamBindOffsetPtr();
+
+                /**
+                 * Prepare parameters set for statement execution.
+                 */
+                void Prepare();
+
+                /**
+                 * Check if the data at-execution is needed.
+                 *
+                 * @return True if the data at execution is needed.
+                 */
+                bool IsDataAtExecNeeded() const;
+
+                /**
+                 * Update parameter types metadata.
+                 *
+                 * @param meta Types metadata.
+                 */
+                void UpdateParamsTypes(const ParameterTypeVector& meta);
+
+                /**
+                 * Get type id of the parameter.
+                 *
+                 * @param idx Parameter index.
+                 * @param dflt Default value to return if the type can not be 
found.
+                 * @return Type ID of the parameter or dflt, if the type can 
not be returned.
+                 */
+                int8_t GetParamType(int16_t idx, int8_t dflt);
+
+                /**
+                 * Get expected parameters number.
+                 * Using metadata. If metadata was not updated returns zero.
+                 *
+                 * @return Expected parameters number.
+                 */
+                uint16_t GetExpectedParamNum();
+
+                /**
+                 * Check if the metadata was set for the parameter set.
+                 * 
+                 * @return True if the metadata was set for the parameter set. 
+                 */
+                bool IsMetadataSet() const;
+
+                /**
+                 * Check if the parameter selected for putting data 
at-execution.
+                 *
+                 * @return True if the parameter selected for putting data 
at-execution.
+                 */
+                bool IsParameterSelected() const;
+
+                /**
+                 * Get parameter by index.
+                 *
+                 * @param idx Index.
+                 * @return Parameter or null, if parameter is not bound.
+                 */
+                Parameter* GetParameter(uint16_t idx);
+
+                /**
+                 * Get selected parameter.
+                 *
+                 * @return Parameter or null, if parameter is not bound.
+                 */
+                Parameter* GetSelectedParameter();
+
+                /**
+                 * Internally selects next parameter for putting data 
at-execution.
+                 *
+                 * @return Parameter if found and null otherwise.
+                 */
+                Parameter* SelectNextParameter();
+
+                /**
+                 * Write only first row of the param set using provided writer.
+                 * @param writer Writer.
+                 */
+                void Write(impl::binary::BinaryWriterImpl& writer) const;
+
+                /**
+                 * Write rows of the param set in interval [begin, end) using 
provided writer.
+                 * @param writer Writer.
+                 * @param begin Beginng of the interval.
+                 * @param end End of the interval.
+                 * @param last Last page flag.
+                 */
+                void Write(impl::binary::BinaryWriterImpl& writer, SqlUlen 
begin, SqlUlen end, bool last) const;
+
+                /**
+                 * Calculate row length.
+                 *
+                 * @return Row length.
+                 */
+                int32_t CalculateRowLen() const;
+
+                /**
+                 * Get parameter set size.
+                 *
+                 * @return Number of rows in set.
+                 */
+                int32_t GetParamSetSize() const;
+
+                /**
+                 * Set number of parameters processed in batch.
+                 *
+                 * @param processed Processed.
+                 */
+                void SetParamsProcessed(SqlUlen processed) const;
+
+                /**
+                 * Number of processed params should be written using provided 
address.
+                 *
+                 * @param ptr Pointer.
+                 */
+                void SetParamsProcessedPtr(SqlUlen* ptr);
+
+                /**
+                 * Get pointer to write number of parameters processed in 
batch.
+                 *
+                 * @return Pointer to write number of parameters processed in 
batch.
+                 */
+                SqlUlen* GetParamsProcessedPtr();
+
+            private:
+                /**
+                 * Write single row of the param set using provided writer.
+                 * @param writer Writer.
+                 * @param idx Row index.
+                 */
+                void WriteRow(impl::binary::BinaryWriterImpl& writer, SqlUlen 
idx) const;
+
+                IGNITE_NO_COPY_ASSIGNMENT(ParameterSet);
+
+                /** Parameters. */
+                ParameterBindingMap parameters;
+
+                /** Parameter types. */
+                ParameterTypeVector paramTypes;
+
+                /** Offset added to pointers to change binding of parameters. 
*/
+                int* paramBindOffset;
+
+                /** Processed parameters. */
+                SqlUlen* processedParamRows;
+
+                /** Parameter set size. */
+                SqlUlen paramSetSize;
+
+                /** Current position in parametor set. */
+                SqlUlen paramSetPos;
+
+                /** Index of the parameter, which is currently being set. */
+                uint16_t currentParamIdx;
+
+                /** Parameter types are set. */
+                bool typesSet;
+            };
+        }
+    }
+}
+
+#endif //_IGNITE_ODBC_APP_PARAMETER_SET

http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h
----------------------------------------------------------------------
diff --git 
a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h 
b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h
index 4eb1a38..2ec1b5b 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h
@@ -45,14 +45,14 @@ namespace ignite
                  *
                  * @return Diagnostic record.
                  */
-                virtual const diagnostic::DiagnosticRecordStorage& 
GetDiagnosticRecords() const = 0;
+                virtual const DiagnosticRecordStorage& GetDiagnosticRecords() 
const = 0;
 
                 /**
                  * Get diagnostic record.
                  *
                  * @return Diagnostic record.
                  */
-                virtual diagnostic::DiagnosticRecordStorage& 
GetDiagnosticRecords() = 0;
+                virtual DiagnosticRecordStorage& GetDiagnosticRecords() = 0;
 
                 /**
                  * Add new status record.

Reply via email to