You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2016/08/31 06:32:53 UTC

[03/38] ignite git commit: IGNITE-3736: ODBC: Added support for string scalar functions. This closes #979.

IGNITE-3736: ODBC: Added support for string scalar functions. This closes #979.


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

Branch: refs/heads/ignite-3443
Commit: c02ad87f863bd730e60fb7052547fa0848e7eb77
Parents: 118db2f
Author: isapego <is...@gridgain.com>
Authored: Wed Aug 24 17:21:48 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Aug 24 17:21:48 2016 +0300

----------------------------------------------------------------------
 modules/platforms/cpp/odbc-test/Makefile.am     |   2 +
 .../cpp/odbc-test/config/queries-test.xml       |   7 +-
 .../platforms/cpp/odbc-test/include/Makefile.am |   3 +-
 .../cpp/odbc-test/include/test_utils.h          |  45 ++
 .../cpp/odbc-test/project/vs/odbc-test.vcxproj  |   3 +
 .../project/vs/odbc-test.vcxproj.filters        |   9 +
 .../cpp/odbc-test/src/queries_test.cpp          |  41 +-
 .../odbc-test/src/sql_string_functions_test.cpp | 515 +++++++++++++++++++
 .../platforms/cpp/odbc-test/src/test_utils.cpp  |  36 ++
 .../cpp/odbc/src/config/connection_info.cpp     |  64 +--
 .../platforms/cpp/odbc/src/query/data_query.cpp |   6 +-
 11 files changed, 653 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/modules/platforms/cpp/odbc-test/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/Makefile.am b/modules/platforms/cpp/odbc-test/Makefile.am
index 48b193a..cc84a7f 100644
--- a/modules/platforms/cpp/odbc-test/Makefile.am
+++ b/modules/platforms/cpp/odbc-test/Makefile.am
@@ -61,6 +61,8 @@ ignite_odbc_tests_SOURCES = \
     src/row_test.cpp \
     src/utility_test.cpp \
     src/queries_test.cpp \
+    src/test_utils.cpp \
+    src/sql_string_functions_test.cpp \
     ../odbc/src/cursor.cpp \
     ../odbc/src/config/connection_info.cpp \
     ../odbc/src/app/application_data_buffer.cpp \

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/modules/platforms/cpp/odbc-test/config/queries-test.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/config/queries-test.xml b/modules/platforms/cpp/odbc-test/config/queries-test.xml
index f08f86d..67415fb 100644
--- a/modules/platforms/cpp/odbc-test/config/queries-test.xml
+++ b/modules/platforms/cpp/odbc-test/config/queries-test.xml
@@ -26,8 +26,8 @@
         http://www.springframework.org/schema/util
         http://www.springframework.org/schema/util/spring-util.xsd">
     <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
-        <!-- Set to true to enable distributed class loading for examples, default is false. -->
-        <property name="peerClassLoadingEnabled" value="true"/>
+        <property name="localHost" value="127.0.0.1"/>
+        <property name="connectorConfiguration"><null/></property>
 
         <!-- Enabling ODBC. -->
         <property name="odbcConfiguration">
@@ -84,11 +84,12 @@
                         <property name="addresses">
                             <list>
                                 <!-- In distributed environment, replace with actual host IP address. -->
-                                <value>127.0.0.1:47500..47501</value>
+                                <value>127.0.0.1:47500</value>
                             </list>
                         </property>
                     </bean>
                 </property>
+                <property name="socketTimeout" value="300" />
             </bean>
         </property>
     </bean>

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/modules/platforms/cpp/odbc-test/include/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/Makefile.am b/modules/platforms/cpp/odbc-test/include/Makefile.am
index 6b2d8b6..7b17102 100644
--- a/modules/platforms/cpp/odbc-test/include/Makefile.am
+++ b/modules/platforms/cpp/odbc-test/include/Makefile.am
@@ -19,5 +19,6 @@ ACLOCAL_AMFLAGS =-I m4
 
 noinst_HEADERS = \
     teamcity/teamcity_messages.h \
-    test_type.h
+    test_type.h \
+    test_utils.h
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/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
new file mode 100644
index 0000000..e8cd089
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/include/test_utils.h
@@ -0,0 +1,45 @@
+/*
+ * 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_TEST_TEST_UTILS
+#define _IGNITE_ODBC_TEST_TEST_UTILS
+
+#ifdef _WIN32
+#   include <windows.h>
+#endif
+
+#include <sql.h>
+#include <sqlext.h>
+
+#include <string>
+
+namespace ignite
+{
+    /** Read buffer size. */
+    enum { ODBC_BUFFER_SIZE = 1024 };
+
+    /**
+     * Extract error message.
+     *
+     * @param handleType Type of the handle.
+     * @param handle Handle.
+     * @return Error message.
+     */
+    std::string GetOdbcErrorMessage(SQLSMALLINT handleType, SQLHANDLE handle);
+}
+
+#endif // _IGNITE_ODBC_TEST_TEST_UTILS
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
index fbc0929..619b4b2 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj
@@ -168,13 +168,16 @@
     <ClCompile Include="..\..\src\queries_test.cpp" />
     <ClCompile Include="..\..\src\parser_test.cpp" />
     <ClCompile Include="..\..\src\row_test.cpp" />
+    <ClCompile Include="..\..\src\sql_string_functions_test.cpp" />
     <ClCompile Include="..\..\src\teamcity\teamcity_boost.cpp" />
     <ClCompile Include="..\..\src\teamcity\teamcity_messages.cpp" />
+    <ClCompile Include="..\..\src\test_utils.cpp" />
     <ClCompile Include="..\..\src\utility_test.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\teamcity\teamcity_messages.h" />
     <ClInclude Include="..\..\include\test_type.h" />
+    <ClInclude Include="..\..\include\test_utils.h" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\..\binary\project\vs\binary.vcxproj">

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
index 2e38c24..1871149 100644
--- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
+++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters
@@ -76,6 +76,12 @@
     <ClCompile Include="..\..\src\queries_test.cpp">
       <Filter>Code</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\sql_string_functions_test.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\test_utils.cpp">
+      <Filter>Code</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\test_type.h">
@@ -84,6 +90,9 @@
     <ClInclude Include="..\..\include\teamcity\teamcity_messages.h">
       <Filter>Code\TeamCity</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\test_utils.h">
+      <Filter>Code</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="..\..\config\queries-test.xml">

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/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 cc3fa8e..2d9bd58 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -36,6 +36,7 @@
 #include "ignite/impl/binary/binary_utils.h"
 
 #include "test_type.h"
+#include "test_utils.h"
 
 using namespace ignite;
 using namespace ignite::cache;
@@ -46,30 +47,6 @@ using namespace boost::unit_test;
 
 using ignite::impl::binary::BinaryUtils;
 
-/** Read buffer size. */
-enum { ODBC_BUFFER_SIZE = 1024 };
-
-/**
- * Extract error message.
- *
- * @param handleType Type of the handle.
- * @param handle Handle.
- * @return Error message.
- */
-std::string GetOdbcErrorMessage(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(reinterpret_cast<char*>(message), reallen);
-}
-
 /**
  * Test setup fixture.
  */
@@ -98,7 +75,9 @@ struct QueriesTestSuiteFixture
 
         char* cfgPath = getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH");
 
-        cfg.springCfgPath = std::string(cfgPath).append("/").append("queries-test.xml");
+        BOOST_REQUIRE(cfgPath != 0);
+
+        cfg.springCfgPath.assign(cfgPath).append("/queries-test.xml");
 
         IgniteError err;
 
@@ -178,7 +157,7 @@ struct QueriesTestSuiteFixture
 
         T columns[columnsCnt] = { 0 };
 
-        // Binding colums.
+        // Binding columns.
         for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
         {
             ret = SQLBindCol(stmt, i + 1, type, &columns[i], sizeof(columns[i]), 0);
@@ -214,7 +193,7 @@ struct QueriesTestSuiteFixture
 
         SQLLEN columnLens[columnsCnt] = { 0 };
 
-        // Binding colums.
+        // Binding columns.
         for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
         {
             ret = SQLBindCol(stmt, i + 1, type, &columns[i], sizeof(columns[i]), &columnLens[i]);
@@ -327,7 +306,7 @@ BOOST_AUTO_TEST_CASE(TestTwoRowsString)
 
     SQLCHAR columns[columnsCnt][ODBC_BUFFER_SIZE] = { 0 };
 
-    // Binding colums.
+    // Binding columns.
     for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
     {
         ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, &columns[i], ODBC_BUFFER_SIZE, 0);
@@ -364,7 +343,7 @@ BOOST_AUTO_TEST_CASE(TestTwoRowsString)
 
     SQLLEN columnLens[columnsCnt] = { 0 };
 
-    // Binding colums.
+    // Binding columns.
     for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
     {
         ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, &columns[i], ODBC_BUFFER_SIZE, &columnLens[i]);
@@ -420,7 +399,7 @@ BOOST_AUTO_TEST_CASE(TestOneRowString)
 
     SQLLEN columnLens[columnsCnt] = { 0 };
 
-    // Binding colums.
+    // Binding columns.
     for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
     {
         ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, &columns[i], ODBC_BUFFER_SIZE, &columnLens[i]);
@@ -479,7 +458,7 @@ BOOST_AUTO_TEST_CASE(TestOneRowStringLen)
 
     SQLLEN columnLens[columnsCnt] = { 0 };
 
-    // Binding colums.
+    // Binding columns.
     for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
     {
         ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, 0, 0, &columnLens[i]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp b/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp
new file mode 100644
index 0000000..e84aba6
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/sql_string_functions_test.cpp
@@ -0,0 +1,515 @@
+/*
+ * 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.
+ */
+
+#define _USE_MATH_DEFINES
+
+#ifdef _WIN32
+#   include <windows.h>
+#endif
+
+#include <sql.h>
+#include <sqlext.h>
+
+#include <cmath>
+
+#include <vector>
+#include <string>
+
+#ifndef _MSC_VER
+#   define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include "ignite/ignite.h"
+#include "ignite/ignition.h"
+#include "ignite/impl/binary/binary_utils.h"
+
+#include "test_type.h"
+#include "test_utils.h"
+
+using namespace ignite;
+using namespace ignite::cache;
+using namespace ignite::cache::query;
+using namespace ignite::common;
+
+using namespace boost::unit_test;
+
+using ignite::impl::binary::BinaryUtils;
+
+/**
+ * Test setup fixture.
+ */
+struct SqlStringFunctionTestSuiteFixture
+{
+    /**
+     * Constructor.
+     */
+    SqlStringFunctionTestSuiteFixture() :
+        testCache(0),
+        env(NULL),
+        dbc(NULL),
+        stmt(NULL)
+    {
+        IgniteConfiguration cfg;
+
+        cfg.jvmOpts.push_back("-Xdebug");
+        cfg.jvmOpts.push_back("-Xnoagent");
+        cfg.jvmOpts.push_back("-Djava.compiler=NONE");
+        cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005");
+        cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError");
+
+#ifdef IGNITE_TESTS_32
+        cfg.jvmInitMem = 256;
+        cfg.jvmMaxMem = 768;
+#else
+        cfg.jvmInitMem = 1024;
+        cfg.jvmMaxMem = 4096;
+#endif
+
+        char* cfgPath = getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH");
+
+        BOOST_REQUIRE(cfgPath != 0);
+
+        cfg.springCfgPath.assign(cfgPath).append("/queries-test.xml");
+
+        IgniteError err;
+
+        grid = Ignition::Start(cfg, &err);
+
+        if (err.GetCode() != IgniteError::IGNITE_SUCCESS)
+            BOOST_FAIL(err.GetText());
+
+        testCache = grid.GetCache<int64_t, TestType>("cache");
+
+        // Allocate an environment handle
+        SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
+
+        BOOST_REQUIRE(env != NULL);
+
+        // We want ODBC 3 support
+        SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0);
+
+        // Allocate a connection handle
+        SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
+
+        BOOST_REQUIRE(dbc != NULL);
+
+        // Connect string
+        SQLCHAR connectStr[] = "DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;CACHE=cache";
+
+        SQLCHAR outstr[ODBC_BUFFER_SIZE];
+        SQLSMALLINT outstrlen;
+
+        // Connecting to ODBC server.
+        SQLRETURN ret = SQLDriverConnect(dbc, NULL, connectStr, static_cast<SQLSMALLINT>(sizeof(connectStr)),
+            outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
+
+        if (!SQL_SUCCEEDED(ret))
+        {
+            Ignition::Stop(grid.GetName(), true);
+
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc));
+        }
+
+        // Allocate a statement handle
+        SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
+
+        BOOST_REQUIRE(stmt != NULL);
+    }
+
+    /**
+     * Destructor.
+     */
+    ~SqlStringFunctionTestSuiteFixture()
+    {
+        // Releasing statement handle.
+        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+
+        // Disconneting from the server.
+        SQLDisconnect(dbc);
+
+        // Releasing allocated handles.
+        SQLFreeHandle(SQL_HANDLE_DBC, dbc);
+        SQLFreeHandle(SQL_HANDLE_ENV, env);
+
+        Ignition::Stop(grid.GetName(), true);
+    }
+
+    void CheckSingleResult0(const char* request, SQLSMALLINT type, void* column, SQLLEN bufSize, SQLLEN* resSize)
+    {
+        SQLRETURN ret;
+
+        ret = SQLBindCol(stmt, 1, type, column, bufSize, resSize);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        ret = SQLExecDirect(stmt, reinterpret_cast<SQLCHAR*>(const_cast<char*>(request)), SQL_NTS);
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        ret = SQLFetch(stmt);
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+        ret = SQLFetch(stmt);
+        BOOST_CHECK(ret == SQL_NO_DATA);
+    }
+
+    /**
+     * Run query returning single result and check it to be equal to expected.
+     *
+     * @param request SQL request.
+     * @param expected Expected result.
+     */
+    template<typename T>
+    void CheckSingleResult(const char* request, const T& expected)
+    {
+        BOOST_FAIL("Function is not defined for the type.");
+    }
+    
+    /**
+     * Run query returning single result and check it to be equal to expected.
+     *
+     * @param request SQL request.
+     * @param expected Expected result.
+     * @param type Result type.
+     */
+    template<typename T>
+    void CheckSingleResultNum0(const char* request, const T& expected, SQLSMALLINT type)
+    {
+        T res = 0;
+
+        CheckSingleResult0(request, type, &res, 0, 0);
+
+        BOOST_CHECK_EQUAL(res, expected);
+    }
+
+
+    /** Node started during the test. */
+    Ignite grid;
+
+    /** Test cache instance. */
+    Cache<int64_t, TestType> testCache;
+
+    /** ODBC Environment. */
+    SQLHENV env;
+
+    /** ODBC Connect. */
+    SQLHDBC dbc;
+
+    /** ODBC Statement. */
+    SQLHSTMT stmt;
+};
+
+template<>
+void SqlStringFunctionTestSuiteFixture::CheckSingleResult<std::string>(const char* request, const std::string& expected)
+{
+    SQLCHAR res[ODBC_BUFFER_SIZE] = { 0 };
+    SQLLEN resLen = 0;
+
+    CheckSingleResult0(request, SQL_C_CHAR, res, ODBC_BUFFER_SIZE, &resLen);
+
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(res), static_cast<size_t>(resLen)), expected);
+}
+
+template<>
+void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int64_t>(const char* request, const int64_t& expected)
+{
+    CheckSingleResultNum0<int64_t>(request, expected, SQL_C_SBIGINT);
+}
+
+template<>
+void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int32_t>(const char* request, const int32_t& expected)
+{
+    CheckSingleResultNum0<int32_t>(request, expected, SQL_C_SLONG);
+}
+
+template<>
+void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int16_t>(const char* request, const int16_t& expected)
+{
+    CheckSingleResultNum0<int16_t>(request, expected, SQL_C_SSHORT);
+}
+
+template<>
+void SqlStringFunctionTestSuiteFixture::CheckSingleResult<int8_t>(const char* request, const int8_t& expected)
+{
+    CheckSingleResultNum0<int8_t>(request, expected, SQL_C_STINYINT);
+}
+
+template<>
+void SqlStringFunctionTestSuiteFixture::CheckSingleResult<float>(const char* request, const float& expected)
+{
+    SQLFLOAT res = 0;
+
+    CheckSingleResult0(request, SQL_C_FLOAT, &res, 0, 0);
+
+    BOOST_CHECK_CLOSE(static_cast<float>(res), expected, 1E-6f);
+}
+
+template<>
+void SqlStringFunctionTestSuiteFixture::CheckSingleResult<double>(const char* request, const double& expected)
+{
+    SQLDOUBLE res = 0;
+
+    CheckSingleResult0(request, SQL_C_DOUBLE, &res, 0, 0);
+
+    BOOST_CHECK_CLOSE(static_cast<double>(res), expected, 1E-6);
+}
+
+BOOST_FIXTURE_TEST_SUITE(SqlStringFunctionTestSuite, SqlStringFunctionTestSuiteFixture)
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionAscii)
+{
+    TestType in;
+
+    in.strField = "Hi";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int32_t>("SELECT {fn ASCII(strField)} FROM TestType", static_cast<int32_t>('H'));
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionBitLength)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn BIT_LENGTH(strField)} FROM TestType", in.strField.size() * 16);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionChar)
+{
+    TestType in;
+
+    in.i32Field = static_cast<int32_t>('H');
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn CHAR(i32Field)} FROM TestType", "H");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionCharLength)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn CHAR_LENGTH(strField)} FROM TestType", in.strField.size());
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionCharacterLength)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn CHARACTER_LENGTH(strField)} FROM TestType", in.strField.size());
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionConcat)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor sit amet,";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn CONCAT(strField, \' consectetur adipiscing elit\')} FROM TestType",
+        in.strField + " consectetur adipiscing elit");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionDifference)
+{
+    TestType in;
+    in.strField = "Hello";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int32_t>("SELECT {fn DIFFERENCE(strField, \'Hola!\')} FROM TestType", 4);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionInsert)
+{
+    TestType in;
+    in.strField = "Hello World!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn INSERT(strField, 7, 5, \'Ignite\')} FROM TestType", "Hello Ignite!");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionLcase)
+{
+    TestType in;
+    in.strField = "Hello World!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn LCASE(strField)} FROM TestType", "hello world!");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionLeft)
+{
+    TestType in;
+    in.strField = "Hello World!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn LEFT(strField, 5)} FROM TestType", "Hello");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionLength)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn LENGTH(strField)} FROM TestType", in.strField.size());
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionLocate)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn LOCATE(\'ip\', strField)} FROM TestType", 7);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionLocate2)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn LOCATE(\'ip\', strField, 10)} FROM TestType", 43);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionLtrim)
+{
+    TestType in;
+    in.strField = "    Lorem ipsum  ";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn LTRIM(strField)} FROM TestType", "Lorem ipsum  ");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionOctetLength)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn OCTET_LENGTH(strField)} FROM TestType", in.strField.size() * 2);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionPosition)
+{
+    TestType in;
+    in.strField = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<int64_t>("SELECT {fn POSITION(\'sit\', strField)} FROM TestType", 19);
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionRepeat)
+{
+    TestType in;
+    in.strField = "Test";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn REPEAT(strField,4)} FROM TestType", "TestTestTestTest");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionReplace)
+{
+    TestType in;
+    in.strField = "Hello Ignite!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn REPLACE(strField, \'Ignite\', \'World\')} FROM TestType", "Hello World!");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionRight)
+{
+    TestType in;
+    in.strField = "Hello World!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn RIGHT(strField, 6)} FROM TestType", "World!");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionRtrim)
+{
+    TestType in;
+    in.strField = "    Lorem ipsum  ";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn RTRIM(strField)} FROM TestType", "    Lorem ipsum");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionSoundex)
+{
+    TestType in;
+    in.strField = "Hello Ignite!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn SOUNDEX(strField)} FROM TestType", "H425");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionSpace)
+{
+    CheckSingleResult<std::string>("SELECT {fn SPACE(10)}", "          ");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionSubstring)
+{
+    TestType in;
+    in.strField = "Hello Ignite!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn SUBSTRING(strField, 7, 6)} FROM TestType", "Ignite");
+}
+
+BOOST_AUTO_TEST_CASE(TestStringFunctionUcase)
+{
+    TestType in;
+    in.strField = "Hello World!";
+
+    testCache.Put(1, in);
+
+    CheckSingleResult<std::string>("SELECT {fn UCASE(strField)} FROM TestType", "HELLO WORLD!");
+}
+
+BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/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
new file mode 100644
index 0000000..48f409b
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/test_utils.cpp
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test_utils.h"
+
+namespace ignite
+{
+
+    std::string GetOdbcErrorMessage(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(reinterpret_cast<char*>(message), reallen);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/modules/platforms/cpp/odbc/src/config/connection_info.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/config/connection_info.cpp b/modules/platforms/cpp/odbc/src/config/connection_info.cpp
index 7f0e3bd..f35b790 100644
--- a/modules/platforms/cpp/odbc/src/config/connection_info.cpp
+++ b/modules/platforms/cpp/odbc/src/config/connection_info.cpp
@@ -124,7 +124,7 @@ namespace ignite
 #ifdef SQL_COLUMN_ALIAS
                 // A character string: "Y" if the data source supports column 
                 // aliases; otherwise, "N".
-                strParams[SQL_COLUMN_ALIAS] = "N";
+                strParams[SQL_COLUMN_ALIAS] = "Y";
 #endif // SQL_COLUMN_ALIAS
 
 #ifdef SQL_IDENTIFIER_QUOTE_CHAR
@@ -192,7 +192,7 @@ namespace ignite
 
 #ifdef SQL_GETDATA_EXTENSIONS
                 // Bitmask enumerating extensions to SQLGetData.
-                intParams[SQL_GETDATA_EXTENSIONS] = SQL_GD_ANY_COLUMN;
+                intParams[SQL_GETDATA_EXTENSIONS] = SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER | SQL_GD_BOUND;
 #endif // SQL_GETDATA_EXTENSIONS
 
 #ifdef SQL_ODBC_INTERFACE_CONFORMANCE
@@ -203,7 +203,7 @@ namespace ignite
 
 #ifdef SQL_SQL_CONFORMANCE
                 // Indicates the level of SQL-92 supported by the driver.
-                intParams[SQL_SQL_CONFORMANCE] = 0; // SQL_SC_SQL92_ENTRY;
+                intParams[SQL_SQL_CONFORMANCE] = SQL_SC_SQL92_ENTRY;
 #endif // SQL_SQL_CONFORMANCE
 
 #ifdef SQL_CATALOG_USAGE
@@ -213,7 +213,8 @@ namespace ignite
 
 #ifdef SQL_SCHEMA_USAGE
                 // Bitmask enumerating the statements in which schemas can be used.
-                intParams[SQL_SCHEMA_USAGE] = 0;
+                intParams[SQL_SCHEMA_USAGE] = SQL_SU_DML_STATEMENTS |
+                    SQL_SU_TABLE_DEFINITION | SQL_SU_PRIVILEGE_DEFINITION;
 #endif // SQL_SCHEMA_USAGE
 
 #ifdef SQL_MAX_IDENTIFIER_LEN
@@ -224,21 +225,24 @@ namespace ignite
 
 #ifdef SQL_AGGREGATE_FUNCTIONS
                 // Bitmask enumerating support for aggregation functions.
-                intParams[SQL_AGGREGATE_FUNCTIONS] = SQL_AF_ALL | SQL_AF_AVG | 
-                    SQL_AF_COUNT | SQL_AF_DISTINCT | SQL_AF_MAX | SQL_AF_MIN |
-                    SQL_AF_SUM;
+                intParams[SQL_AGGREGATE_FUNCTIONS] = 0;
 #endif // SQL_AGGREGATE_FUNCTIONS
 
 #ifdef SQL_NUMERIC_FUNCTIONS
                 // Bitmask enumerating the scalar numeric functions supported by
                 // the driver and associated data source.
-                intParams[SQL_NUMERIC_FUNCTIONS] = SQL_FN_NUM_ABS;
+                intParams[SQL_NUMERIC_FUNCTIONS] = 0;
 #endif // SQL_NUMERIC_FUNCTIONS
 
 #ifdef SQL_STRING_FUNCTIONS
                 // Bitmask enumerating the scalar string functions supported by the
                 // driver and associated data source.
-                intParams[SQL_STRING_FUNCTIONS] = 0;
+                intParams[SQL_STRING_FUNCTIONS] = SQL_FN_STR_ASCII | SQL_FN_STR_BIT_LENGTH | SQL_FN_STR_CHAR |
+                    SQL_FN_STR_CONCAT | SQL_FN_STR_DIFFERENCE | SQL_FN_STR_INSERT | SQL_FN_STR_LEFT |
+                    SQL_FN_STR_LENGTH | SQL_FN_STR_LOCATE | SQL_FN_STR_LTRIM | SQL_FN_STR_OCTET_LENGTH |
+                    SQL_FN_STR_POSITION | SQL_FN_STR_REPEAT | SQL_FN_STR_REPLACE | SQL_FN_STR_RIGHT | SQL_FN_STR_RTRIM |
+                    SQL_FN_STR_SOUNDEX | SQL_FN_STR_SPACE | SQL_FN_STR_SUBSTRING | SQL_FN_STR_LCASE | SQL_FN_STR_UCASE |
+                    SQL_FN_STR_LOCATE_2 | SQL_FN_STR_CHAR_LENGTH | SQL_FN_STR_CHARACTER_LENGTH;
 #endif // SQL_STRING_FUNCTIONS
 
 #ifdef SQL_TIMEDATE_FUNCTIONS
@@ -262,15 +266,7 @@ namespace ignite
 #ifdef SQL_DATETIME_LITERALS
                 // Bitmask enumerating the SQL-92 datetime literals supported by
                 // the data source.
-                intParams[SQL_DATETIME_LITERALS] = SQL_DL_SQL92_INTERVAL_HOUR |
-                    SQL_DL_SQL92_DATE | SQL_DL_SQL92_INTERVAL_MINUTE_TO_SECOND |
-                    SQL_DL_SQL92_TIME | SQL_DL_SQL92_INTERVAL_HOUR_TO_SECOND |
-                    SQL_DL_SQL92_TIMESTAMP | SQL_DL_SQL92_INTERVAL_HOUR_TO_MINUTE |
-                    SQL_DL_SQL92_INTERVAL_YEAR | SQL_DL_SQL92_INTERVAL_DAY_TO_SECOND |
-                    SQL_DL_SQL92_INTERVAL_MONTH | SQL_DL_SQL92_INTERVAL_DAY_TO_HOUR |
-                    SQL_DL_SQL92_INTERVAL_DAY | SQL_DL_SQL92_INTERVAL_DAY_TO_MINUTE |
-                    SQL_DL_SQL92_INTERVAL_MINUTE | SQL_DL_SQL92_INTERVAL_SECOND |
-                    SQL_DL_SQL92_INTERVAL_YEAR_TO_MONTH;
+                intParams[SQL_DATETIME_LITERALS] = 0;
 #endif // SQL_DATETIME_LITERALS
 
 #ifdef SQL_SYSTEM_FUNCTIONS
@@ -288,9 +284,7 @@ namespace ignite
 #ifdef SQL_OJ_CAPABILITIES
                 // Bitmask enumerating the types of outer joins supported by the 
                 // driver and data source.
-                intParams[SQL_OJ_CAPABILITIES] = SQL_OJ_LEFT | SQL_OJ_RIGHT |
-                    SQL_OJ_FULL | SQL_OJ_NESTED | SQL_OJ_INNER | 
-                    SQL_OJ_ALL_COMPARISON_OPS;
+                intParams[SQL_OJ_CAPABILITIES] = 0;
 #endif // SQL_OJ_CAPABILITIES
 
 #ifdef SQL_POS_OPERATIONS
@@ -305,42 +299,36 @@ namespace ignite
 
 #ifdef SQL_SQL92_STRING_FUNCTIONS
                 // Bitmask enumerating the string scalar functions.
-                intParams[SQL_SQL92_STRING_FUNCTIONS] = 0;
+                intParams[SQL_SQL92_STRING_FUNCTIONS] = SQL_SSF_CONVERT | SQL_SSF_LOWER | SQL_SSF_UPPER |
+                    SQL_SSF_SUBSTRING | SQL_SSF_TRANSLATE;
 #endif // SQL_SQL92_STRING_FUNCTIONS
 
 #ifdef SQL_SQL92_DATETIME_FUNCTIONS
                 // Bitmask enumerating the datetime scalar functions.
-                intParams[SQL_SQL92_DATETIME_FUNCTIONS] = SQL_SDF_CURRENT_DATE |
-                    SQL_SDF_CURRENT_TIMESTAMP;
+                intParams[SQL_SQL92_DATETIME_FUNCTIONS] = 0;
 #endif // SQL_SQL92_DATETIME_FUNCTIONS
 
 #ifdef SQL_SQL92_VALUE_EXPRESSIONS
                 // Bitmask enumerating the value expressions supported,
                 // as defined in SQL-92.
                 intParams[SQL_SQL92_VALUE_EXPRESSIONS] = SQL_SVE_CASE | 
-                    SQL_SVE_COALESCE | SQL_SVE_NULLIF;
+                    SQL_SVE_CAST | SQL_SVE_COALESCE | SQL_SVE_NULLIF;
 #endif // SQL_SQL92_VALUE_EXPRESSIONS
 
 #ifdef SQL_SQL92_PREDICATES
                 // Bitmask enumerating the datetime scalar functions.
-                intParams[SQL_SQL92_PREDICATES] = SQL_SP_BETWEEN |
-                    SQL_SP_COMPARISON | SQL_SP_EXISTS | SQL_SP_IN |
-                    SQL_SP_ISNOTNULL | SQL_SP_ISNULL | SQL_SP_LIKE |
-                    SQL_SP_MATCH_FULL | SQL_SP_MATCH_PARTIAL |
-                    SQL_SP_MATCH_UNIQUE_FULL | SQL_SP_MATCH_UNIQUE_PARTIAL |
-                    SQL_SP_OVERLAPS | SQL_SP_QUANTIFIED_COMPARISON |
-                    SQL_SP_UNIQUE;
+                intParams[SQL_SQL92_PREDICATES] = SQL_SP_BETWEEN | SQL_SP_COMPARISON | SQL_SP_EXISTS | SQL_SP_IN |
+                    SQL_SP_ISNOTNULL | SQL_SP_ISNULL | SQL_SP_LIKE | SQL_SP_MATCH_FULL | SQL_SP_MATCH_PARTIAL |
+                    SQL_SP_MATCH_UNIQUE_FULL | SQL_SP_MATCH_UNIQUE_PARTIAL | SQL_SP_OVERLAPS | SQL_SP_UNIQUE |
+                    SQL_SP_QUANTIFIED_COMPARISON;
 #endif // SQL_SQL92_PREDICATES
 
 #ifdef SQL_SQL92_RELATIONAL_JOIN_OPERATORS
                 // Bitmask enumerating the relational join operators supported
                 // in a SELECT statement, as defined in SQL-92.
-                intParams[SQL_SQL92_RELATIONAL_JOIN_OPERATORS] =
-                    SQL_SRJO_CORRESPONDING_CLAUSE | SQL_SRJO_CROSS_JOIN |
-                    SQL_SRJO_EXCEPT_JOIN | SQL_SRJO_EXCEPT_JOIN |
-                    SQL_SRJO_INNER_JOIN | SQL_SRJO_INTERSECT_JOIN |
-                    SQL_SRJO_LEFT_OUTER_JOIN | SQL_SRJO_NATURAL_JOIN |
-                    SQL_SRJO_RIGHT_OUTER_JOIN | SQL_SRJO_UNION_JOIN;
+                intParams[SQL_SQL92_RELATIONAL_JOIN_OPERATORS] = SQL_SRJO_CORRESPONDING_CLAUSE | SQL_SRJO_CROSS_JOIN |
+                    SQL_SRJO_EXCEPT_JOIN | SQL_SRJO_INNER_JOIN | SQL_SRJO_LEFT_OUTER_JOIN| SQL_SRJO_RIGHT_OUTER_JOIN |
+                    SQL_SRJO_NATURAL_JOIN | SQL_SRJO_INTERSECT_JOIN | SQL_SRJO_UNION_JOIN;
 #endif // SQL_SQL92_RELATIONAL_JOIN_OPERATORS
 
                 //========================= Short Params ==========================

http://git-wip-us.apache.org/repos/asf/ignite/blob/c02ad87f/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 e96f1da..183bbb5 100644
--- a/modules/platforms/cpp/odbc/src/query/data_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -141,11 +141,7 @@ namespace ignite
             SqlResult DataQuery::Close()
             {
                 if (!cursor.get())
-                {
-                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query cursor is not in open state.");
-
-                    return SQL_RESULT_ERROR;
-                }
+                    return SQL_RESULT_SUCCESS;
 
                 SqlResult result = MakeRequestClose();