You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/12/05 12:38:14 UTC

[10/52] ignite git commit: IGNITE-4096: Added ODBC-DML tests. Fixed issues. This closes #1178.

IGNITE-4096: Added ODBC-DML tests. Fixed issues. This closes #1178.


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

Branch: refs/heads/master
Commit: f4524a6a7b86df9cd008dcd22fa5cfa400c3af27
Parents: 4ba1386
Author: isapego <ig...@gmail.com>
Authored: Wed Nov 23 17:58:41 2016 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Nov 23 17:58:41 2016 +0300

----------------------------------------------------------------------
 .../processors/odbc/OdbcRequestHandler.java     |   2 +-
 .../cpp/core-test/config/cache-query.xml        |  10 +
 .../src/application_data_buffer_test.cpp        |   2 +-
 .../cpp/odbc-test/src/queries_test.cpp          | 336 +++++++++++++++++++
 .../ignite/odbc/app/application_data_buffer.h   |   4 +-
 .../odbc/include/ignite/odbc/app/parameter.h    |   2 +-
 .../cpp/odbc/include/ignite/odbc/statement.h    |  48 ++-
 .../odbc/src/app/application_data_buffer.cpp    |  57 ++--
 modules/platforms/cpp/odbc/src/odbc.cpp         |   4 +-
 .../platforms/cpp/odbc/src/query/data_query.cpp |   4 +
 modules/platforms/cpp/odbc/src/statement.cpp    |  45 ++-
 modules/platforms/cpp/odbc/src/utility.cpp      |   2 +-
 12 files changed, 433 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java
index eef9945..cf2615d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java
@@ -184,7 +184,7 @@ public class OdbcRequestHandler {
             qry.setDistributedJoins(distributedJoins);
             qry.setEnforceJoinOrder(enforceJoinOrder);
 
-            IgniteCache<Object, Object> cache = ctx.grid().cache(req.cacheName());
+            IgniteCache<Object, Object> cache = ctx.grid().cache(req.cacheName()).withKeepBinary();
 
             if (cache == null)
                 return new OdbcResponse(OdbcResponse.STATUS_FAILED,

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/platforms/cpp/core-test/config/cache-query.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/config/cache-query.xml b/modules/platforms/cpp/core-test/config/cache-query.xml
index bb18f7c..dead2b1 100644
--- a/modules/platforms/cpp/core-test/config/cache-query.xml
+++ b/modules/platforms/cpp/core-test/config/cache-query.xml
@@ -69,6 +69,16 @@
                                     </list>
                                 </property>
                             </bean>
+
+                            <bean class="org.apache.ignite.cache.CacheTypeMetadata">
+                                <property name="valueType" value="QueryRelation"/>
+                                <property name="queryFields">
+                                    <map>
+                                        <entry key="personId" value="java.lang.Integer"/>
+                                        <entry key="someVal" value="java.lang.Integer"/>
+                                    </map>
+                                </property>
+                            </bean>
                         </list>
                     </property>
                 </bean>

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/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 f62bcd6..fe50295 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
@@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(TestPutGuidToString)
 BOOST_AUTO_TEST_CASE(TestGetGuidFromString)
 {
     char buffer[] = "1da1ef8f-39ff-4d62-8b72-e8e9f3371801";
-    SqlLen reslen = 0;
+    SqlLen reslen = sizeof(buffer) - 1;
 
     ApplicationDataBuffer appBuf(IGNITE_ODBC_C_TYPE_CHAR, buffer, sizeof(buffer) - 1, &reslen, 0);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/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 db9dafb..554cee2 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -288,6 +288,77 @@ struct QueriesTestSuiteFixture
         return res;
     }
 
+    static std::string getTestString(int64_t ind)
+    {
+        std::stringstream builder;
+
+        builder << "String#" << ind;
+
+        return builder.str();
+    }
+
+    /**
+     * Insert requested number of TestType vlaues with all defaults except
+     * for the strFields, which are generated using getTestString().
+     *
+     * @param num Number of records to insert.
+     * @param merge Set to true to use merge instead.
+     */
+    void InsertTestStrings(int recordsNum, bool merge = false)
+    {
+        SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)";
+        SQLCHAR mergeReq[] = "MERGE INTO TestType(_key, strField) VALUES(?, ?)";
+
+        SQLRETURN ret;
+
+        ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        int64_t key = 0;
+        char strField[1024] = { 0 };
+        SQLLEN strFieldLen = 0;
+
+        // Binding parameters.
+        ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(strField),
+            sizeof(strField), &strField, sizeof(strField), &strFieldLen);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        // Inserting values.
+        for (SQLSMALLINT i = 0; i < recordsNum; ++i)
+        {
+            key = i + 1;
+            std::string val = getTestString(i);
+
+            strncpy(strField, val.c_str(), sizeof(strField));
+            strFieldLen = SQL_NTS;
+
+            ret = SQLExecute(stmt);
+
+            if (!SQL_SUCCEEDED(ret))
+                BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+            ret = SQLMoreResults(stmt);
+
+            if (ret != SQL_NO_DATA)
+                BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+        }
+
+        // Resetting parameters.
+        ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+    }
+
     /** Node started during the test. */
     Ignite grid;
 
@@ -939,4 +1010,269 @@ BOOST_AUTO_TEST_CASE(TestDistributedJoinsWithOldVersion)
     BOOST_CHECK_LT(rowsNum, entriesNum);
 }
 
+BOOST_AUTO_TEST_CASE(TestInsertSelect)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
+    const int recordsNum = 100;
+
+    // Inserting values.
+    InsertTestStrings(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 + 1;
+
+        BOOST_CHECK_EQUAL(key, expectedKey);
+
+        BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+        ++selectedRecordsNum;
+    }
+
+    BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertUpdateSelect)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
+    const int recordsNum = 100;
+
+    // Inserting values.
+    InsertTestStrings(recordsNum);
+
+    int64_t key = 0;
+    char strField[1024] = { 0 };
+    SQLLEN strFieldLen = 0;
+
+    SQLCHAR updateReq[] = "UPDATE TestType SET strField = 'Updated value' WHERE _key = 42";
+
+    SQLRETURN ret = SQLExecDirect(stmt, updateReq, SQL_NTS);
+
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    ret = SQLFreeStmt(stmt, SQL_CLOSE);
+
+    // Binding columns.
+    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));
+
+        int64_t expectedKey = selectedRecordsNum + 1;
+        std::string expectedStr;
+
+        BOOST_CHECK_EQUAL(key, expectedKey);
+
+        if (expectedKey == 42)
+            expectedStr = "Updated value";
+        else
+            expectedStr = getTestString(selectedRecordsNum);
+
+        BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+        ++selectedRecordsNum;
+    }
+
+    BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertDeleteSelect)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
+    const int recordsNum = 100;
+
+    // Inserting values.
+    InsertTestStrings(recordsNum);
+
+    int64_t key = 0;
+    char strField[1024] = { 0 };
+    SQLLEN strFieldLen = 0;
+
+    SQLCHAR updateReq[] = "DELETE FROM TestType WHERE (_key % 2) = 1";
+
+    SQLRETURN ret = SQLExecDirect(stmt, updateReq, SQL_NTS);
+
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    ret = SQLFreeStmt(stmt, SQL_CLOSE);
+
+    // Binding columns.
+    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));
+
+        int64_t expectedKey = (selectedRecordsNum + 1) * 2;
+        std::string expectedStr = getTestString(expectedKey - 1);
+
+        BOOST_CHECK_EQUAL(key, expectedKey);
+        BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+        ++selectedRecordsNum;
+    }
+
+    BOOST_CHECK_EQUAL(recordsNum / 2, selectedRecordsNum);
+}
+
+BOOST_AUTO_TEST_CASE(TestInsertMergeSelect)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
+    const int recordsNum = 100;
+
+    // Inserting values.
+    InsertTestStrings(recordsNum / 2);
+
+    // Merging values.
+    InsertTestStrings(recordsNum, true);
+
+    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 + 1;
+
+        BOOST_CHECK_EQUAL(key, expectedKey);
+
+        BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr);
+
+        ++selectedRecordsNum;
+    }
+
+    BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum);
+}
+
 BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/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 0ce7818..18ac36a 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
@@ -311,7 +311,7 @@ namespace ignite
                  * @return Size of the data that is going to be provided
                  *     at execution.
                  */
-                size_t GetDataAtExecSize() const;
+                SqlLen GetDataAtExecSize() const;
 
                 /**
                  * Get size of the input buffer.
@@ -319,7 +319,7 @@ namespace ignite
                  * @return Input buffer size, or zero if the data is going
                  *     to be provided at execution.
                  */
-                size_t GetInputSize() const;
+                SqlLen GetInputSize() const;
 
                 /**
                  * Get buffer type.

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/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 0bd9395..1cf85b5 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h
@@ -81,7 +81,7 @@ namespace ignite
                  * Write request using provided writer.
                  * @param writer Writer.
                  */
-                void Write(ignite::impl::binary::BinaryWriterImpl& writer) const;
+                void Write(impl::binary::BinaryWriterImpl& writer) const;
 
                 /**
                  * Get data buffer.

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h b/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
index db6205e..981ade1 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
@@ -168,41 +168,19 @@ namespace ignite
             /**
              * Prepare SQL query.
              *
-             * @note Only SELECT queries are supported currently.
              * @param query SQL query.
              */
             void PrepareSqlQuery(const std::string& query);
-
-            /**
-             * Prepare SQL query.
-             *
-             * @note Only SELECT queries are supported currently.
-             * @param query SQL query.
-             * @param len Query length.
-             */
-            void PrepareSqlQuery(const char* query, size_t len);
             
             /**
              * Execute SQL query.
              *
-             * @note Only SELECT queries are supported currently.
              * @param query SQL query.
              */
             void ExecuteSqlQuery(const std::string& query);
 
             /**
              * Execute SQL query.
-             *
-             * @note Only SELECT queries are supported currently.
-             * @param query SQL query.
-             * @param len Query length.
-             */
-            void ExecuteSqlQuery(const char* query, size_t len);
-
-            /**
-             * Execute SQL query.
-             *
-             * @note Only SELECT queries are supported currently.
              */
             void ExecuteSqlQuery();
 
@@ -300,6 +278,13 @@ namespace ignite
             bool DataAvailable() const;
 
             /**
+             * Next results.
+             *
+             * Move to next result set or affected rows number.
+             */
+            void NextResults();
+
+            /**
              * Get column attribute.
              *
              * @param colIdx Column index.
@@ -417,27 +402,22 @@ namespace ignite
             /**
              * Prepare SQL query.
              *
-             * @note Only SELECT queries are supported currently.
              * @param query SQL query.
-             * @param len Query length.
              * @return Operation result.
              */
-            SqlResult InternalPrepareSqlQuery(const char* query, size_t len);
+            SqlResult InternalPrepareSqlQuery(const std::string& query);
             
             /**
              * Execute SQL query.
              *
-             * @note Only SELECT queries are supported currently.
              * @param query SQL query.
-             * @param len Query length.
              * @return Operation result.
              */
-            SqlResult InternalExecuteSqlQuery(const char* query, size_t len);
+            SqlResult InternalExecuteSqlQuery(const std::string& query);
 
             /**
              * Execute SQL query.
              *
-             * @note Only SELECT queries are supported currently.
              * @return Operation result.
              */
             SqlResult InternalExecuteSqlQuery();
@@ -528,10 +508,20 @@ namespace ignite
              * Get type info.
              *
              * @param sqlType SQL type for which to return info or SQL_ALL_TYPES.
+             * @return Operation result.
              */
             SqlResult InternalExecuteGetTypeInfoQuery(int16_t sqlType);
 
             /**
+             * Next results.
+             *
+             * Move to next result set or affected rows number.
+             *
+             * @return Operation result.
+             */
+            SqlResult InternalNextResults();
+
+            /**
              * Get column attribute.
              *
              * @param colIdx Column index.

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp b/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp
index 078e691..71c5f39 100644
--- a/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp
+++ b/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp
@@ -368,7 +368,7 @@ namespace ignite
                 PutNum(value);
             }
 
-            int32_t ApplicationDataBuffer::PutString(const std::string & value)
+            int32_t ApplicationDataBuffer::PutString(const std::string& value)
             {
                 using namespace type_traits;
 
@@ -920,8 +920,12 @@ namespace ignite
                         if (!paramLen)
                             break;
 
-                        res.assign(reinterpret_cast<const char*>(GetData()),
-                                   std::min(maxLen, paramLen));
+                        res = utility::SqlStringToString(
+                            reinterpret_cast<const unsigned char*>(GetData()), static_cast<int32_t>(paramLen));
+
+                        if (res.size() > maxLen)
+                            res.resize(maxLen);
+
                         break;
                     }
 
@@ -1024,12 +1028,13 @@ namespace ignite
                 {
                     case IGNITE_ODBC_C_TYPE_CHAR:
                     {
-                        size_t paramLen = GetInputSize();
+                        SqlLen paramLen = GetInputSize();
 
                         if (!paramLen)
                             break;
 
-                        std::string str(reinterpret_cast<const char*>(GetData()), paramLen);
+                        std::string str = utility::SqlStringToString(
+                            reinterpret_cast<const unsigned char*>(GetData()), static_cast<int32_t>(paramLen));
 
                         std::stringstream converter;
 
@@ -1096,7 +1101,7 @@ namespace ignite
                 {
                     case IGNITE_ODBC_C_TYPE_CHAR:
                     {
-                        size_t paramLen = GetInputSize();
+                        SqlLen paramLen = GetInputSize();
 
                         if (!paramLen)
                             break;
@@ -1239,7 +1244,7 @@ namespace ignite
 
                     case IGNITE_ODBC_C_TYPE_CHAR:
                     {
-                        size_t paramLen = GetInputSize();
+                        SqlLen paramLen = GetInputSize();
 
                         if (!paramLen)
                             break;
@@ -1302,7 +1307,7 @@ namespace ignite
 
                     case IGNITE_ODBC_C_TYPE_CHAR:
                     {
-                        size_t paramLen = GetInputSize();
+                        SqlLen paramLen = GetInputSize();
 
                         if (!paramLen)
                             break;
@@ -1334,7 +1339,7 @@ namespace ignite
                 {
                     case IGNITE_ODBC_C_TYPE_CHAR:
                     {
-                        size_t paramLen = GetInputSize();
+                        SqlLen paramLen = GetInputSize();
 
                         if (!paramLen)
                             break;
@@ -1422,7 +1427,7 @@ namespace ignite
                 return ilen <= SQL_LEN_DATA_AT_EXEC_OFFSET || ilen == SQL_DATA_AT_EXEC;
             }
 
-            size_t ApplicationDataBuffer::GetDataAtExecSize() const
+            SqlLen ApplicationDataBuffer::GetDataAtExecSize() const
             {
                 using namespace type_traits;
 
@@ -1440,7 +1445,7 @@ namespace ignite
                         int32_t ilen = static_cast<int32_t>(*resLenPtr);
 
                         if (ilen <= SQL_LEN_DATA_AT_EXEC_OFFSET)
-                            ilen = static_cast<size_t>(SQL_LEN_DATA_AT_EXEC(ilen));
+                            ilen = SQL_LEN_DATA_AT_EXEC(ilen);
                         else
                             ilen = 0;
 
@@ -1452,41 +1457,41 @@ namespace ignite
 
                     case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
                     case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
-                        return sizeof(short);
+                        return static_cast<SqlLen>(sizeof(short));
 
                     case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
                     case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
-                        return sizeof(long);
+                        return static_cast<SqlLen>(sizeof(long));
 
                     case IGNITE_ODBC_C_TYPE_FLOAT:
-                        return sizeof(float);
+                        return static_cast<SqlLen>(sizeof(float));
 
                     case IGNITE_ODBC_C_TYPE_DOUBLE:
-                        return sizeof(double);
+                        return static_cast<SqlLen>(sizeof(double));
 
                     case IGNITE_ODBC_C_TYPE_BIT:
                     case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
                     case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
-                        return sizeof(char);
+                        return static_cast<SqlLen>(sizeof(char));
 
                     case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
                     case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
-                        return sizeof(SQLBIGINT);
+                        return static_cast<SqlLen>(sizeof(SQLBIGINT));
 
                     case IGNITE_ODBC_C_TYPE_TDATE:
-                        return sizeof(SQL_DATE_STRUCT);
+                        return static_cast<SqlLen>(sizeof(SQL_DATE_STRUCT));
 
                     case IGNITE_ODBC_C_TYPE_TTIME:
-                        return sizeof(SQL_TIME_STRUCT);
+                        return static_cast<SqlLen>(sizeof(SQL_TIME_STRUCT));
 
                     case IGNITE_ODBC_C_TYPE_TTIMESTAMP:
-                        return sizeof(SQL_TIMESTAMP_STRUCT);
+                        return static_cast<SqlLen>(sizeof(SQL_TIMESTAMP_STRUCT));
 
                     case IGNITE_ODBC_C_TYPE_NUMERIC:
-                        return sizeof(SQL_NUMERIC_STRUCT);
+                        return static_cast<SqlLen>(sizeof(SQL_NUMERIC_STRUCT));
 
                     case IGNITE_ODBC_C_TYPE_GUID:
-                        return sizeof(SQLGUID);
+                        return static_cast<SqlLen>(sizeof(SQLGUID));
 
                     case IGNITE_ODBC_C_TYPE_DEFAULT:
                     case IGNITE_ODBC_C_TYPE_UNSUPPORTED:
@@ -1497,10 +1502,14 @@ namespace ignite
                 return 0;
             }
 
-            size_t ApplicationDataBuffer::GetInputSize() const
+            SqlLen ApplicationDataBuffer::GetInputSize() const
             {
                 if (!IsDataAtExec())
-                    return static_cast<size_t>(GetSize());
+                {
+                    const SqlLen *len = GetResLen();
+
+                    return len ? *len : SQL_DEFAULT_PARAM;
+                }
 
                 return GetDataAtExecSize();
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/platforms/cpp/odbc/src/odbc.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/odbc.cpp b/modules/platforms/cpp/odbc/src/odbc.cpp
index 684ed08..8ecc0f8 100644
--- a/modules/platforms/cpp/odbc/src/odbc.cpp
+++ b/modules/platforms/cpp/odbc/src/odbc.cpp
@@ -600,7 +600,9 @@ namespace ignite
         if (!statement)
             return SQL_INVALID_HANDLE;
 
-        return statement->DataAvailable() ? SQL_SUCCESS : SQL_NO_DATA;
+        statement->NextResults();
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
     }
 
     SQLRETURN SQLBindParameter(SQLHSTMT     stmt,

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/platforms/cpp/odbc/src/query/data_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/data_query.cpp b/modules/platforms/cpp/odbc/src/query/data_query.cpp
index 7a25ccb..8f76153 100644
--- a/modules/platforms/cpp/odbc/src/query/data_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -146,8 +146,12 @@ namespace ignite
                 SqlResult result = MakeRequestClose();
 
                 if (result == SQL_RESULT_SUCCESS)
+                {
                     cursor.reset();
 
+                    resultMeta.clear();
+                }
+
                 return result;
             }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/platforms/cpp/odbc/src/statement.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/statement.cpp b/modules/platforms/cpp/odbc/src/statement.cpp
index f1a577a..49a9acf 100644
--- a/modules/platforms/cpp/odbc/src/statement.cpp
+++ b/modules/platforms/cpp/odbc/src/statement.cpp
@@ -336,39 +336,27 @@ namespace ignite
 
         void Statement::PrepareSqlQuery(const std::string& query)
         {
-            return PrepareSqlQuery(query.data(), query.size());
+            IGNITE_ODBC_API_CALL(InternalPrepareSqlQuery(query));
         }
 
-        void Statement::PrepareSqlQuery(const char* query, size_t len)
-        {
-            IGNITE_ODBC_API_CALL(InternalPrepareSqlQuery(query, len));
-        }
-
-        SqlResult Statement::InternalPrepareSqlQuery(const char* query, size_t len)
+        SqlResult Statement::InternalPrepareSqlQuery(const std::string& query)
         {
             if (currentQuery.get())
                 currentQuery->Close();
 
-            std::string sql(query, len);
-
-            currentQuery.reset(new query::DataQuery(*this, connection, sql, paramBindings));
+            currentQuery.reset(new query::DataQuery(*this, connection, query, paramBindings));
 
             return SQL_RESULT_SUCCESS;
         }
 
         void Statement::ExecuteSqlQuery(const std::string& query)
         {
-            ExecuteSqlQuery(query.data(), query.size());
+            IGNITE_ODBC_API_CALL(InternalExecuteSqlQuery(query));
         }
 
-        void Statement::ExecuteSqlQuery(const char* query, size_t len)
+        SqlResult Statement::InternalExecuteSqlQuery(const std::string& query)
         {
-            IGNITE_ODBC_API_CALL(InternalExecuteSqlQuery(query, len));
-        }
-
-        SqlResult Statement::InternalExecuteSqlQuery(const char* query, size_t len)
-        {
-            SqlResult result = InternalPrepareSqlQuery(query, len);
+            SqlResult result = InternalPrepareSqlQuery(query);
 
             if (result != SQL_RESULT_SUCCESS)
                 return result;
@@ -546,11 +534,7 @@ namespace ignite
         SqlResult Statement::InternalClose()
         {
             if (!currentQuery.get())
-            {
-                AddStatusRecord(SQL_STATE_24000_INVALID_CURSOR_STATE, "Cursor is not in the open state.");
-
-                return SQL_RESULT_ERROR;
-            }
+                return SQL_RESULT_SUCCESS;
 
             SqlResult result = currentQuery->Close();
 
@@ -604,6 +588,21 @@ namespace ignite
             return currentQuery.get() && currentQuery->DataAvailable();
         }
 
+        void Statement::NextResults()
+        {
+            IGNITE_ODBC_API_CALL(InternalNextResults());
+        }
+
+        SqlResult Statement::InternalNextResults()
+        {
+            if (!currentQuery.get())
+                return SQL_RESULT_NO_DATA;
+
+            SqlResult result = currentQuery->Close();
+
+            return result == SQL_RESULT_SUCCESS ? SQL_RESULT_NO_DATA : result;
+        }
+
         void Statement::GetColumnAttribute(uint16_t colIdx, uint16_t attrId,
             char* strbuf, int16_t buflen, int16_t* reslen, SqlLen* numbuf)
         {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f4524a6a/modules/platforms/cpp/odbc/src/utility.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/utility.cpp b/modules/platforms/cpp/odbc/src/utility.cpp
index 19be799..d4a48af 100644
--- a/modules/platforms/cpp/odbc/src/utility.cpp
+++ b/modules/platforms/cpp/odbc/src/utility.cpp
@@ -131,7 +131,7 @@ namespace ignite
 
             if (sqlStrLen == SQL_NTS)
                 res.assign(sqlStrC);
-            else
+            else if (sqlStrLen > 0)
                 res.assign(sqlStrC, sqlStrLen);
 
             return res;