You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by nt...@apache.org on 2017/08/15 18:00:28 UTC

[27/29] ignite git commit: IGNITE-5995: ODBC fix for SQLGetData.

IGNITE-5995: ODBC fix for SQLGetData.

(cherry picked from commit 0d8d166)


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

Branch: refs/heads/ignite-5947
Commit: 276e84a91bcea9c6b076ff674cdd16d93fbbde4d
Parents: 621380d
Author: Igor Sapego <is...@gridgain.com>
Authored: Thu Aug 10 15:31:44 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Tue Aug 15 16:53:57 2017 +0300

----------------------------------------------------------------------
 .../impl/cache/query/query_fields_row_impl.h    |   2 +-
 .../cpp/odbc-test/include/test_utils.h          |   9 ++
 .../cpp/odbc-test/src/meta_queries_test.cpp     | 100 +++++++++++++++++++
 .../platforms/cpp/odbc-test/src/test_utils.cpp  |  13 +++
 .../ignite/odbc/query/column_metadata_query.h   |   3 +
 .../ignite/odbc/query/table_metadata_query.h    |   3 +
 .../include/ignite/odbc/query/type_info_query.h |   3 +
 .../cpp/odbc/src/query/batch_query.cpp          |   7 +-
 .../odbc/src/query/column_metadata_query.cpp    |  16 ++-
 .../platforms/cpp/odbc/src/query/data_query.cpp |   7 +-
 .../cpp/odbc/src/query/table_metadata_query.cpp |  16 ++-
 .../cpp/odbc/src/query/type_info_query.cpp      |  16 ++-
 12 files changed, 183 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h b/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h
index 63e0523..2943625 100644
--- a/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h
+++ b/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h
@@ -143,7 +143,7 @@ namespace ignite
 
                             int32_t actualLen = reader.ReadInt8Array(dst, len);
 
-                            if (actualLen == 0 || dst && len >= actualLen)
+                            if (actualLen == 0 || (dst && len >= actualLen))
                                 ++processed;
 
                             return actualLen;

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc-test/include/test_utils.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/test_utils.h b/modules/platforms/cpp/odbc-test/include/test_utils.h
index 6a58e54..5dc6d6e 100644
--- a/modules/platforms/cpp/odbc-test/include/test_utils.h
+++ b/modules/platforms/cpp/odbc-test/include/test_utils.h
@@ -43,6 +43,15 @@ namespace ignite_test
     enum { ODBC_BUFFER_SIZE = 1024 };
 
     /**
+     * Extract error state.
+     *
+     * @param handleType Type of the handle.
+     * @param handle Handle.
+     * @return Error state.
+     */
+    std::string GetOdbcErrorState(SQLSMALLINT handleType, SQLHANDLE handle);
+
+    /**
      * Extract error message.
      *
      * @param handleType Type of the handle.

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
index 454a989..ff3695d 100644
--- a/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/meta_queries_test.cpp
@@ -103,6 +103,9 @@ struct MetaQueriesTestSuiteFixture
         BOOST_REQUIRE(stmt != NULL);
     }
 
+    /**
+     * Disconnect.
+     */
     void Disconnect()
     {
         // Releasing statement handle.
@@ -116,6 +119,11 @@ struct MetaQueriesTestSuiteFixture
         SQLFreeHandle(SQL_HANDLE_ENV, env);
     }
 
+    /**
+     * Start additional node with the specified name.
+     *
+     * @param name Node name.
+     */
     static Ignite StartAdditionalNode(const char* name)
     {
 #ifdef IGNITE_TESTS_32
@@ -126,6 +134,36 @@ struct MetaQueriesTestSuiteFixture
     }
 
     /**
+     * Checks single row result set for correct work with SQLGetData.
+     *
+     * @param stmt Statement.
+     */
+    void CheckSingleRowResultSetWithGetData(SQLHSTMT stmt)
+    {
+        SQLRETURN ret = SQLFetch(stmt);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        char buf[1024];
+        SQLLEN bufLen = sizeof(buf);
+
+        ret = SQLGetData(stmt, 1, SQL_C_CHAR, buf, sizeof(buf), &bufLen);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        ret = SQLFetch(stmt);
+
+        BOOST_REQUIRE_EQUAL(ret, SQL_NO_DATA);
+
+        ret = SQLGetData(stmt, 1, SQL_C_CHAR, buf, sizeof(buf), &bufLen);
+
+        BOOST_REQUIRE_EQUAL(ret, SQL_ERROR);
+        BOOST_CHECK_EQUAL(GetOdbcErrorState(SQL_HANDLE_STMT, stmt), "24000");
+    }
+
+    /**
      * Constructor.
      */
     MetaQueriesTestSuiteFixture() :
@@ -237,4 +275,66 @@ BOOST_AUTO_TEST_CASE(TestColAttributesColumnScale)
         BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
 }
 
+BOOST_AUTO_TEST_CASE(TestGetDataWithGetTypeInfo)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLGetTypeInfo(stmt, SQL_VARCHAR);
+
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    CheckSingleRowResultSetWithGetData(stmt);
+}
+
+BOOST_AUTO_TEST_CASE(TestGetDataWithTables)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLCHAR empty[] = "";
+    SQLCHAR table[] = "TestType";
+
+    SQLRETURN ret = SQLTables(stmt, empty, SQL_NTS, empty, SQL_NTS, table, SQL_NTS, empty, SQL_NTS);
+
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    CheckSingleRowResultSetWithGetData(stmt);
+}
+
+BOOST_AUTO_TEST_CASE(TestGetDataWithColumns)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLCHAR empty[] = "";
+    SQLCHAR table[] = "TestType";
+    SQLCHAR column[] = "strField";
+
+    SQLRETURN ret = SQLColumns(stmt, empty, SQL_NTS, empty, SQL_NTS, table, SQL_NTS, column, SQL_NTS);
+
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    CheckSingleRowResultSetWithGetData(stmt);
+}
+
+BOOST_AUTO_TEST_CASE(TestGetDataWithSelectQuery)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLCHAR insertReq[] = "insert into TestType(_key, strField) VALUES(1, 'Lorem ipsum')";
+    SQLRETURN ret = SQLExecDirect(stmt, insertReq, SQL_NTS);
+
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    SQLCHAR selectReq[] = "select strField from TestType";
+    ret = SQLExecDirect(stmt, selectReq, SQL_NTS);
+
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    CheckSingleRowResultSetWithGetData(stmt);
+}
+
 BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/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 c7aa70a..6e8fe6a 100644
--- a/modules/platforms/cpp/odbc-test/src/test_utils.cpp
+++ b/modules/platforms/cpp/odbc-test/src/test_utils.cpp
@@ -21,6 +21,19 @@
 
 namespace ignite_test
 {
+    std::string GetOdbcErrorState(SQLSMALLINT handleType, SQLHANDLE handle)
+    {
+        SQLCHAR sqlstate[7] = {};
+        SQLINTEGER nativeCode;
+
+        SQLCHAR message[ODBC_BUFFER_SIZE];
+        SQLSMALLINT reallen = 0;
+
+        SQLGetDiagRec(handleType, handle, 1, sqlstate, &nativeCode, message, ODBC_BUFFER_SIZE, &reallen);
+
+        return std::string(reinterpret_cast<char*>(sqlstate));
+    }
+
     std::string GetOdbcErrorMessage(SQLSMALLINT handleType, SQLHANDLE handle)
     {
         SQLCHAR sqlstate[7] = {};

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc/include/ignite/odbc/query/column_metadata_query.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/query/column_metadata_query.h b/modules/platforms/cpp/odbc/include/ignite/odbc/query/column_metadata_query.h
index 878a4be..875b1ce 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/query/column_metadata_query.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/query/column_metadata_query.h
@@ -130,6 +130,9 @@ namespace ignite
                 /** Query executed. */
                 bool executed;
 
+                /** Fetched flag. */
+                bool fetched;
+
                 /** Fetched metadata. */
                 meta::ColumnMetaVector meta;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc/include/ignite/odbc/query/table_metadata_query.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/query/table_metadata_query.h b/modules/platforms/cpp/odbc/include/ignite/odbc/query/table_metadata_query.h
index cef963c..acd3f49 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/query/table_metadata_query.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/query/table_metadata_query.h
@@ -134,6 +134,9 @@ namespace ignite
                 /** Query executed. */
                 bool executed;
 
+                /** Fetched flag. */
+                bool fetched;
+
                 /** Fetched metadata. */
                 meta::TableMetaVector meta;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc/include/ignite/odbc/query/type_info_query.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/query/type_info_query.h b/modules/platforms/cpp/odbc/include/ignite/odbc/query/type_info_query.h
index a7cee92..00cca08 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/query/type_info_query.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/query/type_info_query.h
@@ -105,6 +105,9 @@ namespace ignite
                 /** Executed flag. */
                 bool executed;
 
+                /** Fetched flag. */
+                bool fetched;
+
                 /** Requested types. */
                 std::vector<int8_t> types;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc/src/query/batch_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/batch_query.cpp b/modules/platforms/cpp/odbc/src/query/batch_query.cpp
index df9fb05..46447c0 100644
--- a/modules/platforms/cpp/odbc/src/query/batch_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/batch_query.cpp
@@ -112,7 +112,12 @@ namespace ignite
                 }
 
                 if (dataRetrieved)
-                    return SqlResult::AI_NO_DATA;
+                {
+                    diag.AddStatusRecord(SqlState::S24000_INVALID_CURSOR_STATE,
+                        "Cursor has reached end of the result set.");
+
+                    return SqlResult::AI_ERROR;
+                }
 
                 if (columnIdx != 1)
                 {

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
index 8ba9323..b9c08f5 100644
--- a/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
@@ -83,6 +83,7 @@ namespace ignite
                 table(table),
                 column(column),
                 executed(false),
+                fetched(false),
                 meta(),
                 columnsMeta()
             {
@@ -125,6 +126,7 @@ namespace ignite
                 if (result == SqlResult::AI_SUCCESS)
                 {
                     executed = true;
+                    fetched = false;
 
                     cursor = meta.begin();
                 }
@@ -146,6 +148,11 @@ namespace ignite
                     return SqlResult::AI_ERROR;
                 }
 
+                if (!fetched)
+                    fetched = true;
+                else
+                    ++cursor;
+
                 if (cursor == meta.end())
                     return SqlResult::AI_NO_DATA;
 
@@ -154,8 +161,6 @@ namespace ignite
                 for (it = columnBindings.begin(); it != columnBindings.end(); ++it)
                     GetColumn(it->first, it->second);
 
-                ++cursor;
-
                 return SqlResult::AI_SUCCESS;
             }
 
@@ -169,7 +174,12 @@ namespace ignite
                 }
 
                 if (cursor == meta.end())
-                    return SqlResult::AI_NO_DATA;
+                {
+                    diag.AddStatusRecord(SqlState::S24000_INVALID_CURSOR_STATE,
+                        "Cursor has reached end of the result set.");
+
+                    return SqlResult::AI_ERROR;
+                }
 
                 const meta::ColumnMeta& currentColumn = *cursor;
                 uint8_t columnType = currentColumn.GetDataType();

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/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 23d5240..f14d004 100644
--- a/modules/platforms/cpp/odbc/src/query/data_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -125,7 +125,12 @@ namespace ignite
                 Row* row = cursor->GetRow();
 
                 if (!row)
-                    return SqlResult::AI_NO_DATA;
+                {
+                    diag.AddStatusRecord(SqlState::S24000_INVALID_CURSOR_STATE,
+                        "Cursor has reached end of the result set.");
+
+                    return SqlResult::AI_ERROR;
+                }
 
                 SqlResult::Type result = row->ReadColumnToBuffer(columnIdx, buffer);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp b/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp
index 401a1d2..e66b281 100644
--- a/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp
@@ -63,6 +63,7 @@ namespace ignite
                 table(table),
                 tableType(tableType),
                 executed(false),
+                fetched(false),
                 meta(),
                 columnsMeta()
             {
@@ -98,6 +99,7 @@ namespace ignite
                 if (result == SqlResult::AI_SUCCESS)
                 {
                     executed = true;
+                    fetched = false;
 
                     cursor = meta.begin();
                 }
@@ -119,6 +121,11 @@ namespace ignite
                     return SqlResult::AI_ERROR;
                 }
 
+                if (!fetched)
+                    fetched = true;
+                else
+                    ++cursor;
+
                 if (cursor == meta.end())
                     return SqlResult::AI_NO_DATA;
 
@@ -127,8 +134,6 @@ namespace ignite
                 for (it = columnBindings.begin(); it != columnBindings.end(); ++it)
                     GetColumn(it->first, it->second);
 
-                ++cursor;
-
                 return SqlResult::AI_SUCCESS;
             }
 
@@ -142,7 +147,12 @@ namespace ignite
                 }
 
                 if (cursor == meta.end())
-                    return SqlResult::AI_NO_DATA;
+                {
+                    diag.AddStatusRecord(SqlState::S24000_INVALID_CURSOR_STATE,
+                        "Cursor has reached end of the result set.");
+
+                    return SqlResult::AI_ERROR;
+                }
 
                 const meta::TableMeta& currentColumn = *cursor;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/276e84a9/modules/platforms/cpp/odbc/src/query/type_info_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/type_info_query.cpp b/modules/platforms/cpp/odbc/src/query/type_info_query.cpp
index f6b3990..b4efca0 100644
--- a/modules/platforms/cpp/odbc/src/query/type_info_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/type_info_query.cpp
@@ -122,6 +122,7 @@ namespace ignite
                 Query(diag, QueryType::TYPE_INFO),
                 columnsMeta(),
                 executed(false),
+                fetched(false),
                 types(),
                 cursor(types.end())
             {
@@ -185,6 +186,7 @@ namespace ignite
                 cursor = types.begin();
 
                 executed = true;
+                fetched = false;
 
                 return SqlResult::AI_SUCCESS;
             }
@@ -203,6 +205,11 @@ namespace ignite
                     return SqlResult::AI_ERROR;
                 }
 
+                if (!fetched)
+                    fetched = true;
+                else
+                    ++cursor;
+
                 if (cursor == types.end())
                     return SqlResult::AI_NO_DATA;
 
@@ -211,8 +218,6 @@ namespace ignite
                 for (it = columnBindings.begin(); it != columnBindings.end(); ++it)
                     GetColumn(it->first, it->second);
 
-                ++cursor;
-
                 return SqlResult::AI_SUCCESS;
             }
 
@@ -228,7 +233,12 @@ namespace ignite
                 }
 
                 if (cursor == types.end())
-                    return SqlResult::AI_NO_DATA;
+                {
+                    diag.AddStatusRecord(SqlState::S24000_INVALID_CURSOR_STATE,
+                        "Cursor has reached end of the result set.");
+
+                    return SqlResult::AI_ERROR;
+                }
 
                 int8_t currentType = *cursor;