ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akuznet...@apache.org
Subject [09/60] [abbrv] ignite git commit: IGNITE-1786: Implemented ODBC driver.
Date Thu, 12 May 2016 06:42:03 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc-test/src/cursor_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/cursor_test.cpp b/modules/platforms/cpp/odbc-test/src/cursor_test.cpp
new file mode 100644
index 0000000..2be2e23
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/cursor_test.cpp
@@ -0,0 +1,205 @@
+/*
+ * 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 _MSC_VER
+#   define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include <ignite/impl/binary/binary_writer_impl.h>
+
+#include "ignite/odbc/system/odbc_constants.h"
+#include "ignite/odbc/cursor.h"
+
+using namespace ignite::odbc;
+
+const int64_t testQueryId = 42;
+
+std::auto_ptr<ResultPage> CreateTestPage(bool last, int32_t size)
+{
+    using namespace ignite::impl::binary;
+    using namespace ignite::impl::interop;
+
+    ignite::impl::interop::InteropUnpooledMemory mem(1024);
+    InteropOutputStream outStream(&mem);
+    BinaryWriterImpl writer(&outStream, 0);
+
+    // Last page flag.
+    writer.WriteBool(last);
+
+    //Page size.
+    writer.WriteInt32(size);
+
+    for (int32_t i = 0; i < size; ++i)
+    {
+        // Writing row size = 1 column.
+        writer.WriteInt32(1);
+
+        // Writing column type.
+        writer.WriteInt8(IGNITE_TYPE_INT);
+
+        // Column value.
+        writer.WriteInt32(i);
+    }
+
+    outStream.Synchronize();
+
+    std::auto_ptr<ResultPage> res(new ResultPage());
+
+    InteropInputStream inStream(&mem);
+    BinaryReaderImpl reader(&inStream);
+
+    res->Read(reader);
+
+    BOOST_REQUIRE(res->GetSize() == size);
+    BOOST_REQUIRE(res->IsLast() == last);
+
+    return res;
+}
+
+void CheckCursorNeedUpdate(Cursor& cursor)
+{
+    BOOST_REQUIRE(cursor.NeedDataUpdate());
+
+    BOOST_REQUIRE(cursor.HasData());
+
+    BOOST_REQUIRE(!cursor.Increment());
+
+    BOOST_REQUIRE(!cursor.GetRow());
+}
+
+void CheckCursorReady(Cursor& cursor)
+{
+    BOOST_REQUIRE(!cursor.NeedDataUpdate());
+
+    BOOST_REQUIRE(cursor.HasData());
+
+    BOOST_REQUIRE(cursor.GetRow());
+}
+
+void CheckCursorEnd(Cursor& cursor)
+{
+    BOOST_REQUIRE(!cursor.NeedDataUpdate());
+
+    BOOST_REQUIRE(!cursor.HasData());
+
+    BOOST_REQUIRE(!cursor.Increment());
+
+    BOOST_REQUIRE(!cursor.GetRow());
+}
+
+BOOST_AUTO_TEST_SUITE(CursorTestSuite)
+
+BOOST_AUTO_TEST_CASE(TestCursorEmpty)
+{
+    Cursor cursor(testQueryId);
+
+    BOOST_REQUIRE(cursor.GetQueryId() == testQueryId);
+
+    CheckCursorNeedUpdate(cursor);
+}
+
+BOOST_AUTO_TEST_CASE(TestCursorLast)
+{
+    const int32_t pageSize = 16;
+
+    Cursor cursor(testQueryId);
+
+    std::auto_ptr<ResultPage> resultPage = CreateTestPage(true, pageSize);
+
+    cursor.UpdateData(resultPage);
+
+    BOOST_REQUIRE(cursor.GetQueryId() == testQueryId);
+
+    CheckCursorReady(cursor);
+
+    for (int32_t i = 0; i < pageSize; ++i)
+        BOOST_REQUIRE(cursor.Increment());
+
+    CheckCursorEnd(cursor);
+}
+
+BOOST_AUTO_TEST_CASE(TestCursorUpdate)
+{
+    const int32_t pageSize = 16;
+
+    Cursor cursor(testQueryId);
+
+    std::auto_ptr<ResultPage> resultPage = CreateTestPage(false, pageSize);
+
+    cursor.UpdateData(resultPage);
+
+    BOOST_REQUIRE(cursor.GetQueryId() == testQueryId);
+
+    for (int32_t i = 0; i < pageSize; ++i)
+    {
+        CheckCursorReady(cursor);
+
+        BOOST_REQUIRE(cursor.Increment());
+    }
+
+    CheckCursorNeedUpdate(cursor);
+
+    resultPage = CreateTestPage(true, pageSize);
+
+    cursor.UpdateData(resultPage);
+
+    CheckCursorReady(cursor);
+
+    for (int32_t i = 0; i < pageSize; ++i)
+    {
+        CheckCursorReady(cursor);
+
+        BOOST_REQUIRE(cursor.Increment());
+    }
+
+    CheckCursorEnd(cursor);
+}
+
+BOOST_AUTO_TEST_CASE(TestCursorUpdateOneRow)
+{
+    Cursor cursor(testQueryId);
+
+    std::auto_ptr<ResultPage> resultPage = CreateTestPage(false, 1);
+
+    cursor.UpdateData(resultPage);
+
+    BOOST_REQUIRE(cursor.GetQueryId() == testQueryId);
+
+    CheckCursorReady(cursor);
+
+    BOOST_REQUIRE(cursor.Increment());
+
+    CheckCursorNeedUpdate(cursor);
+
+    BOOST_REQUIRE(!cursor.Increment());
+
+    resultPage = CreateTestPage(true, 1);
+
+    cursor.UpdateData(resultPage);
+
+    CheckCursorReady(cursor);
+
+    BOOST_REQUIRE(cursor.Increment());
+
+    CheckCursorEnd(cursor);
+
+    BOOST_REQUIRE(!cursor.Increment());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc-test/src/parser_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/parser_test.cpp b/modules/platforms/cpp/odbc-test/src/parser_test.cpp
new file mode 100644
index 0000000..7c8a73d
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/parser_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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 _MSC_VER
+#   define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include <ignite/odbc/parser.h>
+
+using namespace ignite::odbc;
+
+struct TestMessage
+{
+    TestMessage()
+    {
+        // No-op.
+    }
+
+    TestMessage(int32_t a, const std::string& b) : a(a), b(b)
+    {
+        // No-op.
+    }
+
+    ~TestMessage()
+    {
+        // No-op.
+    }
+
+    void Write(ignite::impl::binary::BinaryWriterImpl& writer) const
+    {
+        writer.WriteInt32(a);
+        writer.WriteString(b.data(), static_cast<int32_t>(b.size()));
+    }
+
+    void Read(ignite::impl::binary::BinaryReaderImpl& reader)
+    {
+        a = reader.ReadInt32();
+
+        b.resize(reader.ReadString(0, 0));
+        reader.ReadString(&b[0], static_cast<int32_t>(b.size()));
+    }
+
+    int32_t a;
+    std::string b;
+};
+
+bool operator==(const TestMessage& lhs, const TestMessage& rhs)
+{
+    return lhs.a == rhs.a &&
+           lhs.b == rhs.b;
+}
+
+BOOST_AUTO_TEST_SUITE(ParserTestSuite)
+
+BOOST_AUTO_TEST_CASE(TestParserEncodeDecode)
+{
+    Parser parser;
+
+    std::vector<int8_t> buffer;
+
+    TestMessage outMsg(42, "Test message");
+    TestMessage inMsg;
+
+    parser.Encode(outMsg, buffer);
+
+    parser.Decode(inMsg, buffer);
+
+    BOOST_REQUIRE(outMsg == inMsg);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/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
new file mode 100644
index 0000000..cc3fa8e
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -0,0 +1,516 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+#   include <windows.h>
+#endif
+
+#include <sql.h>
+#include <sqlext.h>
+
+#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"
+
+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;
+
+/** 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.
+ */
+struct QueriesTestSuiteFixture 
+{
+    /**
+     * Constructor.
+     */
+    QueriesTestSuiteFixture() : 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");
+
+        cfg.springCfgPath = std::string(cfgPath).append("/").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.
+     */
+    ~QueriesTestSuiteFixture()
+    {
+        // 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);
+    }
+
+    template<typename T>
+    void CheckTwoRowsInt(SQLSMALLINT type)
+    {
+        SQLRETURN ret;
+
+        TestType in1(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
+        TestType in2(8, 7, 6, 5, "4", 3.0f, 2.0, false, Guid(1, 0), BinaryUtils::MakeDateGmt(1976, 1, 12), BinaryUtils::MakeTimestampGmt(1978, 8, 21, 23, 13, 45, 456));
+
+        testCache.Put(1, in1);
+        testCache.Put(2, in2);
+
+        const size_t columnsCnt = 11;
+
+        T columns[columnsCnt] = { 0 };
+
+        // Binding colums.
+        for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
+        {
+            ret = SQLBindCol(stmt, i + 1, type, &columns[i], sizeof(columns[i]), 0);
+
+            if (!SQL_SUCCEEDED(ret))
+                BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+        }
+
+        SQLCHAR request[] = "SELECT i8Field, i16Field, i32Field, i64Field, strField, "
+            "floatField, doubleField, boolField, guidField, dateField, timestampField FROM TestType";
+
+        ret = SQLExecDirect(stmt, 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));
+
+        BOOST_CHECK_EQUAL(columns[0], 1);
+        BOOST_CHECK_EQUAL(columns[1], 2);
+        BOOST_CHECK_EQUAL(columns[2], 3);
+        BOOST_CHECK_EQUAL(columns[3], 4);
+        BOOST_CHECK_EQUAL(columns[4], 5);
+        BOOST_CHECK_EQUAL(columns[5], 6);
+        BOOST_CHECK_EQUAL(columns[6], 7);
+        BOOST_CHECK_EQUAL(columns[7], 1);
+        BOOST_CHECK_EQUAL(columns[8], 0);
+        BOOST_CHECK_EQUAL(columns[9], 0);
+        BOOST_CHECK_EQUAL(columns[10], 0);
+
+        SQLLEN columnLens[columnsCnt] = { 0 };
+
+        // Binding colums.
+        for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
+        {
+            ret = SQLBindCol(stmt, i + 1, type, &columns[i], sizeof(columns[i]), &columnLens[i]);
+
+            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));
+
+        BOOST_CHECK_EQUAL(columns[0], 8);
+        BOOST_CHECK_EQUAL(columns[1], 7);
+        BOOST_CHECK_EQUAL(columns[2], 6);
+        BOOST_CHECK_EQUAL(columns[3], 5);
+        BOOST_CHECK_EQUAL(columns[4], 4);
+        BOOST_CHECK_EQUAL(columns[5], 3);
+        BOOST_CHECK_EQUAL(columns[6], 2);
+        BOOST_CHECK_EQUAL(columns[7], 0);
+        BOOST_CHECK_EQUAL(columns[8], 0);
+        BOOST_CHECK_EQUAL(columns[9], 0);
+        BOOST_CHECK_EQUAL(columns[10], 0);
+
+        BOOST_CHECK_EQUAL(columnLens[0], 0);
+        BOOST_CHECK_EQUAL(columnLens[1], 0);
+        BOOST_CHECK_EQUAL(columnLens[2], 0);
+        BOOST_CHECK_EQUAL(columnLens[3], 0);
+        BOOST_CHECK_EQUAL(columnLens[4], 0);
+        BOOST_CHECK_EQUAL(columnLens[5], 0);
+        BOOST_CHECK_EQUAL(columnLens[6], 0);
+        BOOST_CHECK_EQUAL(columnLens[7], 0);
+        BOOST_CHECK_EQUAL(columnLens[8], SQL_NO_TOTAL);
+        BOOST_CHECK_EQUAL(columnLens[9], SQL_NO_TOTAL);
+        BOOST_CHECK_EQUAL(columnLens[10], SQL_NO_TOTAL);
+
+        ret = SQLFetch(stmt);
+        BOOST_CHECK(ret == SQL_NO_DATA);
+    }
+
+    /** 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;
+};
+
+BOOST_FIXTURE_TEST_SUITE(QueriesTestSuite, QueriesTestSuiteFixture)
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsInt8)
+{
+    CheckTwoRowsInt<int8_t>(SQL_C_STINYINT);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsUint8)
+{
+    CheckTwoRowsInt<uint8_t>(SQL_C_UTINYINT);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsInt16)
+{
+    CheckTwoRowsInt<int16_t>(SQL_C_SSHORT);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsUint16)
+{
+    CheckTwoRowsInt<uint16_t>(SQL_C_USHORT);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsInt32)
+{
+    CheckTwoRowsInt<int32_t>(SQL_C_SLONG);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsUint32)
+{
+    CheckTwoRowsInt<uint32_t>(SQL_C_ULONG);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsInt64)
+{
+    CheckTwoRowsInt<int64_t>(SQL_C_SBIGINT);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsUint64)
+{
+    CheckTwoRowsInt<uint64_t>(SQL_C_UBIGINT);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRowsString)
+{
+    SQLRETURN ret;
+
+    TestType in1(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
+    TestType in2(8, 7, 6, 5, "4", 3.0f, 2.0, false, Guid(1, 0), BinaryUtils::MakeDateGmt(1976, 1, 12), BinaryUtils::MakeTimestampGmt(1978, 8, 21, 23, 13, 45, 999999999));
+
+    testCache.Put(1, in1);
+    testCache.Put(2, in2);
+
+    const size_t columnsCnt = 11;
+
+    SQLCHAR columns[columnsCnt][ODBC_BUFFER_SIZE] = { 0 };
+
+    // Binding colums.
+    for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
+    {
+        ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, &columns[i], ODBC_BUFFER_SIZE, 0);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+    }
+
+    SQLCHAR request[] = "SELECT i8Field, i16Field, i32Field, i64Field, strField, "
+        "floatField, doubleField, boolField, guidField, dateField, timestampField FROM TestType";
+
+    ret = SQLExecDirect(stmt, 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));
+
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[0])), "1");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[1])), "2");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[2])), "3");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[3])), "4");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[4])), "5");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[5])), "6");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[6])), "7");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[7])), "1");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[8])), "00000000-0000-0008-0000-000000000009");
+    // Such format is used because Date returned as Timestamp.
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[9])), "1987-06-05 00:00:00");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[10])), "1998-12-27 01:02:03");
+
+    SQLLEN columnLens[columnsCnt] = { 0 };
+
+    // Binding colums.
+    for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
+    {
+        ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, &columns[i], ODBC_BUFFER_SIZE, &columnLens[i]);
+
+        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));
+
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[0])), "8");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[1])), "7");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[2])), "6");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[3])), "5");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[4])), "4");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[5])), "3");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[6])), "2");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[7])), "0");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[8])), "00000000-0000-0001-0000-000000000000");
+    // Such format is used because Date returned as Timestamp.
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[9])), "1976-01-12 00:00:00");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[10])), "1978-08-21 23:13:45");
+
+    BOOST_CHECK_EQUAL(columnLens[0], 1);
+    BOOST_CHECK_EQUAL(columnLens[1], 1);
+    BOOST_CHECK_EQUAL(columnLens[2], 1);
+    BOOST_CHECK_EQUAL(columnLens[3], 1);
+    BOOST_CHECK_EQUAL(columnLens[4], 1);
+    BOOST_CHECK_EQUAL(columnLens[5], 1);
+    BOOST_CHECK_EQUAL(columnLens[6], 1);
+    BOOST_CHECK_EQUAL(columnLens[7], 1);
+    BOOST_CHECK_EQUAL(columnLens[8], 36);
+    BOOST_CHECK_EQUAL(columnLens[9], 19);
+    BOOST_CHECK_EQUAL(columnLens[10], 19);
+
+    ret = SQLFetch(stmt);
+    BOOST_CHECK(ret == SQL_NO_DATA);
+}
+
+BOOST_AUTO_TEST_CASE(TestOneRowString)
+{
+    SQLRETURN ret;
+
+    TestType in(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
+
+    testCache.Put(1, in);
+
+    const size_t columnsCnt = 11;
+
+    SQLCHAR columns[columnsCnt][ODBC_BUFFER_SIZE] = { 0 };
+
+    SQLLEN columnLens[columnsCnt] = { 0 };
+
+    // Binding colums.
+    for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
+    {
+        ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, &columns[i], ODBC_BUFFER_SIZE, &columnLens[i]);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+    }
+
+    SQLCHAR request[] = "SELECT i8Field, i16Field, i32Field, i64Field, strField, "
+        "floatField, doubleField, boolField, guidField, dateField, timestampField FROM TestType";
+
+    ret = SQLExecDirect(stmt, request, SQL_NTS);
+
+    ret = SQLFetch(stmt);
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[0])), "1");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[1])), "2");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[2])), "3");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[3])), "4");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[4])), "5");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[5])), "6");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[6])), "7");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[7])), "1");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[8])), "00000000-0000-0008-0000-000000000009");
+    // Such format is used because Date returned as Timestamp.
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[9])), "1987-06-05 00:00:00");
+    BOOST_CHECK_EQUAL(std::string(reinterpret_cast<char*>(columns[10])), "1998-12-27 01:02:03");
+
+    BOOST_CHECK_EQUAL(columnLens[0], 1);
+    BOOST_CHECK_EQUAL(columnLens[1], 1);
+    BOOST_CHECK_EQUAL(columnLens[2], 1);
+    BOOST_CHECK_EQUAL(columnLens[3], 1);
+    BOOST_CHECK_EQUAL(columnLens[4], 1);
+    BOOST_CHECK_EQUAL(columnLens[5], 1);
+    BOOST_CHECK_EQUAL(columnLens[6], 1);
+    BOOST_CHECK_EQUAL(columnLens[7], 1);
+    BOOST_CHECK_EQUAL(columnLens[8], 36);
+    BOOST_CHECK_EQUAL(columnLens[9], 19);
+    BOOST_CHECK_EQUAL(columnLens[10], 19);
+
+    ret = SQLFetch(stmt);
+    BOOST_CHECK(ret == SQL_NO_DATA);
+}
+
+BOOST_AUTO_TEST_CASE(TestOneRowStringLen)
+{
+    SQLRETURN ret;
+
+    TestType in(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
+
+    testCache.Put(1, in);
+
+    const size_t columnsCnt = 11;
+
+    SQLLEN columnLens[columnsCnt] = { 0 };
+
+    // Binding colums.
+    for (SQLSMALLINT i = 0; i < columnsCnt; ++i)
+    {
+        ret = SQLBindCol(stmt, i + 1, SQL_C_CHAR, 0, 0, &columnLens[i]);
+
+        if (!SQL_SUCCEEDED(ret))
+            BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+    }
+
+    SQLCHAR request[] = "SELECT i8Field, i16Field, i32Field, i64Field, strField, "
+        "floatField, doubleField, boolField, guidField, dateField, timestampField FROM TestType";
+
+    ret = SQLExecDirect(stmt, request, SQL_NTS);
+
+    ret = SQLFetch(stmt);
+    if (!SQL_SUCCEEDED(ret))
+        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+
+    BOOST_CHECK_EQUAL(columnLens[0], 1);
+    BOOST_CHECK_EQUAL(columnLens[1], 1);
+    BOOST_CHECK_EQUAL(columnLens[2], 1);
+    BOOST_CHECK_EQUAL(columnLens[3], 1);
+    BOOST_CHECK_EQUAL(columnLens[4], 1);
+    BOOST_CHECK_EQUAL(columnLens[5], 1);
+    BOOST_CHECK_EQUAL(columnLens[6], 1);
+    BOOST_CHECK_EQUAL(columnLens[7], 1);
+    BOOST_CHECK_EQUAL(columnLens[8], 36);
+    BOOST_CHECK_EQUAL(columnLens[9], 19);
+    BOOST_CHECK_EQUAL(columnLens[10], 19);
+
+    ret = SQLFetch(stmt);
+    BOOST_CHECK(ret == SQL_NO_DATA);
+}
+
+BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/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
new file mode 100644
index 0000000..bbf0e3d
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/row_test.cpp
@@ -0,0 +1,208 @@
+/*
+ * 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 _MSC_VER
+#   define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include <ignite/impl/binary/binary_writer_impl.h>
+
+#include "ignite/odbc/system/odbc_constants.h"
+#include "ignite/odbc/row.h"
+
+using namespace ignite::odbc::app;
+using namespace ignite::odbc;
+
+
+std::string GetStrColumnValue(size_t rowIdx)
+{
+    std::stringstream generator("Column 2 test string, row num: ");
+    generator << rowIdx << ". Some trailing bytes";
+
+    return generator.str();
+}
+
+void FillMemWithData(ignite::impl::interop::InteropUnpooledMemory& mem, size_t rowNum)
+{
+    using namespace ignite::impl::binary;
+    using namespace ignite::impl::interop;
+    
+    InteropOutputStream stream(&mem);
+    BinaryWriterImpl writer(&stream, 0);
+
+    for (size_t i = 0; i < rowNum; ++i)
+    {
+        // Number of columns in page.
+        writer.WriteInt32(4);
+
+        // First column is int.
+        writer.WriteInt8(IGNITE_TYPE_LONG);
+        writer.WriteInt64(static_cast<int64_t>(i * 10));
+
+        // Second column is string.
+        const std::string& str(GetStrColumnValue(i));
+
+        writer.WriteString(str.data(), static_cast<int32_t>(str.size()));
+
+        // Third column is GUID.
+        ignite::Guid guid(0x2b218f63642a4a64ULL, 0x9674098f388ac298ULL + i);
+        
+        writer.WriteGuid(guid);
+
+        // The last column is bool.
+        writer.WriteInt8(IGNITE_TYPE_BOOL);
+        writer.WriteBool(i % 2 == 1);
+    }
+
+    stream.Synchronize();
+}
+
+void CheckRowData(Row& row, size_t rowIdx)
+{
+    SqlLen reslen;
+
+    long longBuf;
+    char strBuf[1024];
+    SQLGUID guidBuf;
+    char bitBuf;
+    size_t* offset = 0;
+
+    ApplicationDataBuffer appLongBuf(type_traits::IGNITE_ODBC_C_TYPE_SIGNED_LONG, &longBuf, sizeof(longBuf), &reslen, &offset);
+    ApplicationDataBuffer appStrBuf(type_traits::IGNITE_ODBC_C_TYPE_CHAR, &strBuf, sizeof(strBuf), &reslen, &offset);
+    ApplicationDataBuffer appGuidBuf(type_traits::IGNITE_ODBC_C_TYPE_GUID, &guidBuf, sizeof(guidBuf), &reslen, &offset);
+    ApplicationDataBuffer appBitBuf(type_traits::IGNITE_ODBC_C_TYPE_BIT, &bitBuf, sizeof(bitBuf), &reslen, &offset);
+
+    // Checking size.
+    BOOST_REQUIRE(row.GetSize() == 4);
+
+    // Checking 1st column.
+    BOOST_REQUIRE(row.ReadColumnToBuffer(1, appLongBuf) == SQL_RESULT_SUCCESS);
+    BOOST_REQUIRE(longBuf == rowIdx * 10);
+
+    // Checking 2nd column.
+    BOOST_REQUIRE(row.ReadColumnToBuffer(2, appStrBuf) == SQL_RESULT_SUCCESS);
+
+    std::string strReal(strBuf, static_cast<size_t>(reslen));
+    std::string strExpected(GetStrColumnValue(rowIdx));
+
+    BOOST_REQUIRE(strReal == strExpected);
+
+    // Checking 3rd column.
+    BOOST_REQUIRE(row.ReadColumnToBuffer(3, appGuidBuf) == SQL_RESULT_SUCCESS);
+
+    BOOST_REQUIRE(guidBuf.Data1 == 0x2b218f63UL);
+    BOOST_REQUIRE(guidBuf.Data2 == 0x642aU);
+    BOOST_REQUIRE(guidBuf.Data3 == 0x4a64U);
+
+    BOOST_REQUIRE(guidBuf.Data4[0] == 0x96);
+    BOOST_REQUIRE(guidBuf.Data4[1] == 0x74);
+    BOOST_REQUIRE(guidBuf.Data4[2] == 0x09);
+    BOOST_REQUIRE(guidBuf.Data4[3] == 0x8f);
+    BOOST_REQUIRE(guidBuf.Data4[4] == 0x38);
+    BOOST_REQUIRE(guidBuf.Data4[5] == 0x8a);
+    BOOST_REQUIRE(guidBuf.Data4[6] == 0xc2);
+    BOOST_REQUIRE(guidBuf.Data4[7] == 0x98 + rowIdx);
+
+    // Checking 4th column.
+    BOOST_REQUIRE(row.ReadColumnToBuffer(4, appBitBuf) == SQL_RESULT_SUCCESS);
+    BOOST_REQUIRE(bitBuf == rowIdx % 2);
+}
+
+
+BOOST_AUTO_TEST_SUITE(RowTestSuite)
+
+BOOST_AUTO_TEST_CASE(TestRowMoveToNext)
+{
+    ignite::impl::interop::InteropUnpooledMemory mem(4096);
+
+    const size_t rowNum = 32;
+
+    FillMemWithData(mem, rowNum);
+
+    Row row(mem);
+
+    for (size_t i = 0; i < rowNum - 1; ++i)
+    {
+        BOOST_REQUIRE(row.GetSize() == 4);
+
+        BOOST_REQUIRE(row.MoveToNext());
+    }
+
+    BOOST_REQUIRE(row.GetSize() == 4);
+}
+
+BOOST_AUTO_TEST_CASE(TestRowRead)
+{
+    ignite::impl::interop::InteropUnpooledMemory mem(4096);
+
+    const size_t rowNum = 8;
+
+    FillMemWithData(mem, rowNum);
+
+    Row row(mem);
+
+    BOOST_REQUIRE(row.GetSize() == 4);
+
+    for (size_t i = 0; i < rowNum - 1; ++i)
+    {
+        CheckRowData(row, i);
+
+        BOOST_REQUIRE(row.MoveToNext());
+    }
+
+    CheckRowData(row, rowNum - 1);
+}
+
+BOOST_AUTO_TEST_CASE(TestSingleRow)
+{
+    ignite::impl::interop::InteropUnpooledMemory mem(4096);
+
+    const size_t rowNum = 1;
+
+    FillMemWithData(mem, 1);
+
+    Row row(mem);
+
+    BOOST_REQUIRE(row.GetSize() == 4);
+
+    CheckRowData(row, 0);
+}
+
+BOOST_AUTO_TEST_CASE(TestTwoRows)
+{
+    ignite::impl::interop::InteropUnpooledMemory mem(4096);
+
+    const size_t rowNum = 2;
+
+    FillMemWithData(mem, 2);
+
+    Row row(mem);
+
+    BOOST_REQUIRE(row.GetSize() == 4);
+
+    CheckRowData(row, 0);
+
+    BOOST_REQUIRE(row.MoveToNext());
+
+    BOOST_REQUIRE(row.GetSize() == 4);
+
+    CheckRowData(row, 1);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_boost.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_boost.cpp b/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_boost.cpp
new file mode 100644
index 0000000..9a14fe9
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_boost.cpp
@@ -0,0 +1,159 @@
+/* Copyright 2011 JetBrains s.r.o.
+ * 
+ * Licensed 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.
+ * 
+ * $Revision: 88625 $
+*/
+
+#define BOOST_TEST_MODULE IgniteOdbcTest
+
+#include <sstream>
+
+#include <boost/test/unit_test_suite_impl.hpp>
+#include <boost/test/results_collector.hpp>
+#include <boost/test/utils/basic_cstring/io.hpp>
+#include <boost/test/unit_test_log.hpp>
+#include <boost/test/included/unit_test.hpp>
+
+#include "teamcity/teamcity_messages.h"
+
+using namespace boost::unit_test;
+using namespace std;
+
+namespace JetBrains {
+
+// Custom formatter for TeamCity messages
+class TeamcityBoostLogFormatter: public boost::unit_test::unit_test_log_formatter {
+    TeamcityMessages messages;
+    std::string currentDetails;
+    std::string flowId;
+    
+public:
+    TeamcityBoostLogFormatter(const std::string &_flowId);
+    TeamcityBoostLogFormatter();
+
+    void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount);
+    void log_finish(std::ostream&);
+    void log_build_info(std::ostream&);
+
+    void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu);
+    void test_unit_finish(std::ostream&,
+        boost::unit_test::test_unit const& tu,
+        unsigned long elapsed);
+    void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu);
+
+    void log_exception(std::ostream&,
+        boost::unit_test::log_checkpoint_data const&,
+        boost::unit_test::const_string explanation);
+
+    void log_entry_start(std::ostream&,
+        boost::unit_test::log_entry_data const&,
+        log_entry_types let);
+    void log_entry_value(std::ostream&, boost::unit_test::const_string value);
+    void log_entry_finish(std::ostream&);
+};
+
+// Fake fixture to register formatter
+struct TeamcityFormatterRegistrar {
+    TeamcityFormatterRegistrar() {
+        if (JetBrains::underTeamcity()) {
+            boost::unit_test::unit_test_log.set_formatter(new JetBrains::TeamcityBoostLogFormatter());
+            boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::log_successful_tests);
+        }
+    }
+};
+BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar);
+
+// Formatter implementation
+string toString(const_string bstr) {
+    stringstream ss;
+
+    ss << bstr;
+
+    return ss.str();
+}
+
+TeamcityBoostLogFormatter::TeamcityBoostLogFormatter(const std::string &_flowId)
+: flowId(_flowId)
+{}
+
+TeamcityBoostLogFormatter::TeamcityBoostLogFormatter()
+: flowId(getFlowIdFromEnvironment())
+{}
+
+void TeamcityBoostLogFormatter::log_start(ostream &out, counter_t test_cases_amount)
+{}
+
+void TeamcityBoostLogFormatter::log_finish(ostream &out)
+{}
+
+void TeamcityBoostLogFormatter::log_build_info(ostream &out)
+{}
+
+void TeamcityBoostLogFormatter::test_unit_start(ostream &out, test_unit const& tu) {
+    messages.setOutput(out);
+
+    if (tu.p_type == tut_case) {
+        messages.testStarted(tu.p_name, flowId);
+    } else {
+        messages.suiteStarted(tu.p_name, flowId);
+    }
+
+    currentDetails.clear();
+}
+
+void TeamcityBoostLogFormatter::test_unit_finish(ostream &out, test_unit const& tu, unsigned long elapsed) {
+    messages.setOutput(out);
+
+    test_results const& tr = results_collector.results(tu.p_id);
+    if (tu.p_type == tut_case) {
+        if(!tr.passed()) {
+            if(tr.p_skipped) {
+                messages.testIgnored(tu.p_name, "ignored", flowId);
+            } else if (tr.p_aborted) {
+                messages.testFailed(tu.p_name, "aborted", currentDetails, flowId);
+            } else {
+                messages.testFailed(tu.p_name, "failed", currentDetails, flowId);
+            }
+        }
+
+        messages.testFinished(tu.p_name, elapsed / 1000, flowId);
+    } else {
+        messages.suiteFinished(tu.p_name, flowId);
+    }
+}
+
+void TeamcityBoostLogFormatter::test_unit_skipped(ostream &out, test_unit const& tu)
+{}
+
+void TeamcityBoostLogFormatter::log_exception(ostream &out, log_checkpoint_data const&, const_string explanation) {
+    string what = toString(explanation);
+
+    out << what << endl;
+    currentDetails += what + "\n";
+}
+
+void TeamcityBoostLogFormatter::log_entry_start(ostream&, log_entry_data const&, log_entry_types let)
+{}
+
+void TeamcityBoostLogFormatter::log_entry_value(ostream &out, const_string value) {
+    out << value;
+    currentDetails += toString(value);
+}
+
+void TeamcityBoostLogFormatter::log_entry_finish(ostream &out) {
+    out << endl;
+    currentDetails += "\n";
+}
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_messages.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_messages.cpp b/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_messages.cpp
new file mode 100644
index 0000000..1f224af
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/teamcity/teamcity_messages.cpp
@@ -0,0 +1,150 @@
+/* Copyright 2011 JetBrains s.r.o.
+ * 
+ * Licensed 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.
+ *
+ * $Revision: 88625 $
+*/
+
+#include <stdlib.h>
+#include <sstream>
+
+#include "teamcity/teamcity_messages.h"
+
+using namespace std;
+
+namespace JetBrains {
+
+std::string getFlowIdFromEnvironment() {
+    const char *flowId = getenv("TEAMCITY_PROCESS_FLOW_ID");
+    return flowId == NULL ? "" : flowId;
+}
+
+bool underTeamcity() {
+    return getenv("TEAMCITY_PROJECT_NAME") != NULL;
+}
+
+TeamcityMessages::TeamcityMessages()
+: m_out(&cout)
+{}
+
+void TeamcityMessages::setOutput(ostream &out) {
+    m_out = &out;
+}
+
+string TeamcityMessages::escape(string s) {
+    string result;
+
+    for (size_t i = 0; i < s.length(); i++) {
+        char c = s[i];
+        
+        switch (c) {
+        case '\n': result.append("|n"); break;
+        case '\r': result.append("|r"); break;
+        case '\'': result.append("|'"); break;
+        case '|':  result.append("||"); break;
+        case ']':  result.append("|]"); break;
+        default:   result.append(1, c);
+        }
+    }
+
+    return result;
+}
+
+void TeamcityMessages::openMsg(const string &name) {
+    // endl for http://jetbrains.net/tracker/issue/TW-4412
+    *m_out << endl << "##teamcity[" << name;
+}
+
+void TeamcityMessages::closeMsg() {
+    *m_out << "]";
+    // endl for http://jetbrains.net/tracker/issue/TW-4412
+    *m_out << endl;
+    m_out->flush();
+}
+
+void TeamcityMessages::writeProperty(string name, string value) {
+    *m_out << " " << name << "='" << escape(value) << "'";
+}
+
+void TeamcityMessages::suiteStarted(string name, string flowid) {
+    openMsg("testSuiteStarted");
+    writeProperty("name", name);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    closeMsg();
+}
+
+void TeamcityMessages::suiteFinished(string name, string flowid) {
+    openMsg("testSuiteFinished");
+    writeProperty("name", name);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    closeMsg();
+}
+
+void TeamcityMessages::testStarted(string name, string flowid) {
+    openMsg("testStarted");
+    writeProperty("name", name);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    closeMsg();
+}
+
+void TeamcityMessages::testFinished(string name, int durationMs, string flowid) {
+    openMsg("testFinished");
+
+    writeProperty("name", name);
+
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    if(durationMs >= 0) {
+        stringstream out;
+        out << durationMs;
+        writeProperty("duration", out.str());
+    }
+
+    closeMsg();
+}
+
+void TeamcityMessages::testFailed(string name, string message, string details, string flowid) {
+    openMsg("testFailed");
+    writeProperty("name", name);
+    writeProperty("message", message);
+    writeProperty("details", details);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    closeMsg();
+}
+
+void TeamcityMessages::testIgnored(std::string name, std::string message, string flowid) {
+    openMsg("testIgnored");
+    writeProperty("name", name);
+    writeProperty("message", message);
+    if(flowid.length() > 0) {
+        writeProperty("flowId", flowid);
+    }
+
+    closeMsg();
+}
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc-test/src/utility_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/utility_test.cpp b/modules/platforms/cpp/odbc-test/src/utility_test.cpp
new file mode 100644
index 0000000..6c4d104
--- /dev/null
+++ b/modules/platforms/cpp/odbc-test/src/utility_test.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 _MSC_VER
+#   define BOOST_TEST_DYN_LINK
+#endif
+
+#include <boost/test/unit_test.hpp>
+
+#include <ignite/impl/binary/binary_writer_impl.h>
+
+#include <ignite/odbc/utility.h>
+
+using namespace ignite::utility;
+
+BOOST_AUTO_TEST_SUITE(UtilityTestSuite)
+
+BOOST_AUTO_TEST_CASE(TestUtilityRemoveSurroundingSpaces)
+{
+    std::string inStr("   \r \n    \t  some meaningfull data   \n\n   \t  \r  ");
+    std::string expectedOutStr("some meaningfull data");
+
+    std::string realOutStr(RemoveSurroundingSpaces(inStr.begin(), inStr.end()));
+
+    BOOST_REQUIRE(expectedOutStr == realOutStr);
+}
+
+BOOST_AUTO_TEST_CASE(TestUtilityCopyStringToBuffer)
+{
+    char buffer[1024];
+
+    std::string str("Some data. And some more data here.");
+
+    CopyStringToBuffer(str, buffer, sizeof(buffer));
+
+    BOOST_REQUIRE(!strcmp(buffer, str.c_str()));
+
+    CopyStringToBuffer(str, buffer, 11);
+
+    BOOST_REQUIRE(!strcmp(buffer, str.substr(0, 10).c_str()));
+}
+
+BOOST_AUTO_TEST_CASE(TestUtilityReadString)
+{
+    using namespace ignite::impl::binary;
+    using namespace ignite::impl::interop;
+
+    std::string inputStr("Hello World!");
+    std::string outputStr;
+
+    ignite::impl::interop::InteropUnpooledMemory mem(1024);
+    InteropOutputStream outStream(&mem);
+    BinaryWriterImpl writer(&outStream, 0);
+
+    writer.WriteString(inputStr.data(), static_cast<int32_t>(inputStr.size()));
+
+    outStream.Synchronize();
+
+    InteropInputStream inStream(&mem);
+    BinaryReaderImpl reader(&inStream);
+
+    ReadString(reader, outputStr);
+
+    BOOST_REQUIRE(inputStr == outputStr);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/Makefile.am
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/Makefile.am b/modules/platforms/cpp/odbc/Makefile.am
new file mode 100644
index 0000000..cb9a2aa
--- /dev/null
+++ b/modules/platforms/cpp/odbc/Makefile.am
@@ -0,0 +1,84 @@
+##
+## 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.
+##
+
+ACLOCAL_AMFLAGS =-I m4
+
+lib_LTLIBRARIES = libignite-odbc.la
+
+SUBDIRS = \
+    include
+
+AM_CPPFLAGS = \
+    -I$(srcdir)/include \
+    -I@top_srcdir@/common/include \
+    -I@top_srcdir@/common/os/linux/include \
+    -I@top_srcdir@/binary/include \
+    -DIGNITE_IMPL
+
+AM_CXXFLAGS = \
+    -Wall \
+    -std=c++0x
+
+libignite_odbc_la_LIBADD = \
+    @top_srcdir@/binary/libignite-binary.la
+
+libignite_odbc_la_LDFLAGS = \
+    -no-undefined \
+    -ldl \
+    -version-info 0:0:0 \
+    -release $(PACKAGE_VERSION)
+
+libignite_odbc_la_DEPENDENCIES = \
+    @top_srcdir@/binary/libignite-binary.la
+
+libignite_odbc_la_SOURCES = \
+    os/linux/src/system/socket_client.cpp \
+    src/app/application_data_buffer.cpp \
+    src/app/parameter.cpp \
+    src/common_types.cpp \
+    src/config/configuration.cpp \
+    src/config/connection_info.cpp \
+    src/connection.cpp \
+    src/cursor.cpp \
+    src/decimal.cpp \
+    src/diagnostic/diagnosable_adapter.cpp \
+    src/diagnostic/diagnostic_record.cpp \
+    src/diagnostic/diagnostic_record_storage.cpp \
+    src/environment.cpp \
+    src/meta/column_meta.cpp \
+    src/meta/table_meta.cpp \
+    src/odbc.cpp \
+    src/entry_points.cpp \
+    src/query/column_metadata_query.cpp \
+    src/query/data_query.cpp \
+    src/query/foreign_keys_query.cpp \
+    src/query/primary_keys_query.cpp \
+    src/query/table_metadata_query.cpp \
+    src/query/type_info_query.cpp \
+    src/query/special_columns_query.cpp \
+    src/result_page.cpp \
+    src/row.cpp \
+    src/column.cpp \
+    src/statement.cpp \
+    src/type_traits.cpp \
+    src/utility.cpp
+
+clean-local:
+	$(RM) *.gcno *.gcda
+
+clean-docs:
+	$(RM) $(DX_CLEANFILES)

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/README.txt
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/README.txt b/modules/platforms/cpp/odbc/README.txt
new file mode 100644
index 0000000..e9d423f
--- /dev/null
+++ b/modules/platforms/cpp/odbc/README.txt
@@ -0,0 +1,88 @@
+Apache Ignite ODBC driver
+=======================================
+
+Apache Ignite provides ODBC driver that can be used to retrieve distributed 
+data from cache using standard SQL queries and native ODBC API.
+
+For more info on ODBC please refer to ODBC Programmer's Reference at
+https://msdn.microsoft.com/en-us/library/ms714177.aspx
+
+To use Apache Ignite ODBC driver you first need to build and install it for
+your system. You can find driver installation instructions below. For build
+instruction please refer to $IGNITE_HOME/platforms/cpp/DEVNOTES.txt.
+
+Connection string and DSN arguments
+=======================================
+
+Apache Ignite ODBC driver supports and uses following connection string/DSN
+arguments:
+
+1. Address of the node to connect to:
+   SERVER=<host_name_or_IP_address>;
+   
+2. Port on which OdbcProcessor of the node is listening:
+   PORT=<TCP_port>;
+   
+3. Datagrid cache to connect to:
+   CACHE=<cache_name>;
+   
+All arguments are case-insensitive so "SERVER", "Server" and "server" all are
+valid server address arguments.
+
+Installing ODBC driver on Linux
+=======================================
+
+To be able to build and install ODBC driver on Linux you first need to install
+ODBC Driver Manager. Apache Ignite ODBC driver has been tested with UnixODBC
+(http://www.unixodbc.org). 
+
+Once you have built and installed Ignite ODBC Driver i.e. libignite-odbc.so it
+is most likely placed to /usr/local/lib. To install and be able to use Ignite
+ODBC driver you should perfrom the following steps:
+
+1. Ensure linker is able to locate all dependencies of the ODBC driver. You
+   can check it using "ldd" command like this (assuming ODBC driver is located
+   under /usr/local/lib):
+   $ ldd /usr/local/lib/libignite-odbc.so.
+   
+2. Edit file $IGNITE_HOME/platforms/cpp/odbc/install/ignite-odbc-install.ini
+   and ensure that "Driver" parameter of the "Apache Ignite" section points
+   to the right location where libignite-odbc.so is located.
+   
+3. To install Apache Ignite ODBC driver use the following command:
+   $ odbcinst -i -d -f $IGNITE_HOME/platforms/cpp/odbc/install/ignite-odbc-install.ini
+   To perform this command you most likely will need root privileges.
+
+Installing ODBC driver on Windows
+=======================================
+
+For 32-bit Windows you should use 32-bit version of the driver while for the
+64-bit Windows you can use 64-bit driver as well as 32-bit.
+
+To install driver on Windows you should first choose a directory on your
+filesystem where your driver or drivers will be located. Once you have
+choosen the place you should put your driver there and ensure that all driver
+dependencies can be resolved i.e. they can be found either in the %PATH% or
+in the same directory as the driver.
+
+After that you should use one of the install scripts from the directory 
+%IGNITE_HOME%/platforms/cpp/odbc/install:
+
+For the 32-bit Windows you should use file install_x86.cmd like that:
+$ install_x86 <absolute_path_to_32_bit_driver>
+
+For the 64-bit Windows you should use file install_amd64.cmd like that:
+$ install_amd64 <absolute_path_to_64_bit_driver> [<absolute_path_to_32_bit_driver>]
+
+Most likely you will need OS administrator privileges to execute these scripts.
+
+Thats it. Your driver/drivers are installed.
+
+After the installation
+=======================================
+   
+Now Apache Ignite ODBC driver is installed and ready for use. You can connect
+to it and use it like to any other ODBC driver.
+
+For further instruction on the usage of the ODBC driver please refer to the
+official ODBC documentation.

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/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
new file mode 100644
index 0000000..db4ffe0
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/Makefile.am
@@ -0,0 +1,58 @@
+##
+## 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.
+##
+
+ACLOCAL_AMFLAGS =-I m4
+
+noinst_HEADERS = \
+    ignite/odbc.h \
+    ignite/odbc/query/table_metadata_query.h \
+    ignite/odbc/query/special_columns_query.h \
+    ignite/odbc/query/type_info_query.h \
+    ignite/odbc/query/data_query.h \
+    ignite/odbc/query/foreign_keys_query.h \
+    ignite/odbc/query/column_metadata_query.h \
+    ignite/odbc/query/query.h \
+    ignite/odbc/query/primary_keys_query.h \
+    ignite/odbc/statement.h \
+    ignite/odbc/config/configuration.h \
+    ignite/odbc/config/connection_info.h \
+    ignite/odbc/column.h \
+    ignite/odbc/parser.h \
+    ignite/odbc/app/application_data_buffer.h \
+    ignite/odbc/app/parameter.h \
+    ignite/odbc/row.h \
+    ignite/odbc/utility.h \
+    ignite/odbc/environment.h \
+    ignite/odbc/system/odbc_constants.h \
+    ignite/odbc/system/socket_client.h \
+    ignite/odbc/meta/primary_key_meta.h \
+    ignite/odbc/meta/column_meta.h \
+    ignite/odbc/meta/table_meta.h \
+    ignite/odbc/diagnostic/diagnostic_record.h \
+    ignite/odbc/diagnostic/diagnostic_record_storage.h \
+    ignite/odbc/diagnostic/diagnosable.h \
+    ignite/odbc/diagnostic/diagnosable_adapter.h \
+    ignite/odbc/connection.h \
+    ignite/odbc/message.h \
+    ignite/odbc/cursor.h \
+    ignite/odbc/common_types.h \
+    ignite/odbc/result_page.h \
+    ignite/odbc/decimal.h \
+    ignite/odbc/type_traits.h
+
+uninstall-hook:
+	if [ -d ${includedir}/ignite ]; then find ${includedir}/ignite -type d -empty -delete; fi

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/include/ignite/odbc.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc.h b/modules/platforms/cpp/odbc/include/ignite/odbc.h
new file mode 100644
index 0000000..40158dd
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc.h
@@ -0,0 +1,257 @@
+/*
+ * 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_ODBC
+#define _IGNITE_ODBC_ODBC
+
+#include "ignite/odbc/system/odbc_constants.h"
+
+/**
+ * @file odbc.h
+ *
+ * Functions here are placed to the ignite namespace so there are no
+ * collisions with standard ODBC functions when we call driver API
+ * functions from other API functions. I.e, when we call SQLAllocEnv
+ * from SQLAllocHandle linker can place Driver Manager call here,
+ * instead of internal driver call. On other hand if we call
+ * ignite::SQLAllocEnv from ignite::SQLAllocHandle we can be sure 
+ * there are no collisions.
+ */
+
+namespace ignite
+{
+    BOOL ConfigDSN(HWND     hwndParent,
+                   WORD     req,
+                   LPCSTR   driver,
+                   LPCSTR   attributes);
+
+    SQLRETURN SQLGetInfo(SQLHDBC        conn,
+                         SQLUSMALLINT   infoType,
+                         SQLPOINTER     infoValue,
+                         SQLSMALLINT    infoValueMax,
+                         SQLSMALLINT*   length);
+
+    SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result);
+
+    SQLRETURN SQLAllocEnv(SQLHENV* env);
+
+    SQLRETURN SQLAllocConnect(SQLHENV env, SQLHDBC* conn);
+
+    SQLRETURN SQLAllocStmt(SQLHDBC conn, SQLHSTMT* stmt);
+
+    SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle);
+
+    SQLRETURN SQLFreeEnv(SQLHENV env);
+
+    SQLRETURN SQLFreeConnect(SQLHDBC conn);
+
+    SQLRETURN SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT option);
+
+    SQLRETURN SQLCloseCursor(SQLHSTMT stmt);
+
+    SQLRETURN SQLDriverConnect(SQLHDBC      conn,
+                               SQLHWND      windowHandle,
+                               SQLCHAR*     inConnectionString,
+                               SQLSMALLINT  inConnectionStringLen,
+                               SQLCHAR*     outConnectionString,
+                               SQLSMALLINT  outConnectionStringBufferLen,
+                               SQLSMALLINT* outConnectionStringLen,
+                               SQLUSMALLINT driverCompletion);
+
+    SQLRETURN SQLConnect(SQLHDBC        conn,
+                         SQLCHAR*       serverName,
+                         SQLSMALLINT    serverNameLen,
+                         SQLCHAR*       userName,
+                         SQLSMALLINT    userNameLen,
+                         SQLCHAR*       auth,
+                         SQLSMALLINT    authLen);
+
+    SQLRETURN SQLDisconnect(SQLHDBC conn);
+
+    SQLRETURN SQLPrepare(SQLHSTMT stmt, SQLCHAR* query, SQLINTEGER queryLen);
+
+    SQLRETURN SQLExecute(SQLHSTMT stmt);
+
+    SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLCHAR* query, SQLINTEGER queryLen);
+
+    SQLRETURN SQLBindCol(SQLHSTMT       stmt,
+                         SQLUSMALLINT   colNum,
+                         SQLSMALLINT    targetType,
+                         SQLPOINTER     targetValue,
+                         SQLLEN         bufferLength,
+                         SQLLEN*        strLengthOrIndicator);
+
+    SQLRETURN SQLFetch(SQLHSTMT stmt);
+
+    SQLRETURN SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orientation, SQLLEN offset);
+
+    SQLRETURN SQLExtendedFetch(SQLHSTMT         stmt,
+                               SQLUSMALLINT     orientation,
+                               SQLLEN           offset,
+                               SQLULEN*         rowCount,
+                               SQLUSMALLINT*    rowStatusArray);
+
+    SQLRETURN SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *columnNum);
+
+    SQLRETURN SQLTables(SQLHSTMT    stmt,
+                        SQLCHAR*    catalogName,
+                        SQLSMALLINT catalogNameLen,
+                        SQLCHAR*    schemaName,
+                        SQLSMALLINT schemaNameLen,
+                        SQLCHAR*    tableName,
+                        SQLSMALLINT tableNameLen,
+                        SQLCHAR*    tableType,
+                        SQLSMALLINT tableTypeLen);
+
+    SQLRETURN SQLColumns(SQLHSTMT       stmt,
+                         SQLCHAR*       catalogName,
+                         SQLSMALLINT    catalogNameLen,
+                         SQLCHAR*       schemaName,
+                         SQLSMALLINT    schemaNameLen,
+                         SQLCHAR*       tableName,
+                         SQLSMALLINT    tableNameLen,
+                         SQLCHAR*       columnName,
+                         SQLSMALLINT    columnNameLen);
+
+    SQLRETURN SQLMoreResults(SQLHSTMT stmt);
+
+    SQLRETURN SQLBindParameter(SQLHSTMT     stmt,
+                               SQLUSMALLINT paramIdx,
+                               SQLSMALLINT  ioType,
+                               SQLSMALLINT  bufferType,
+                               SQLSMALLINT  paramSqlType,
+                               SQLULEN      columnSize,
+                               SQLSMALLINT  decDigits,
+                               SQLPOINTER   buffer,
+                               SQLLEN       bufferLen,
+                               SQLLEN*      resLen);
+
+    SQLRETURN SQLNativeSql(SQLHDBC      conn,
+                           SQLCHAR*     inQuery,
+                           SQLINTEGER   inQueryLen,
+                           SQLCHAR*     outQueryBuffer,
+                           SQLINTEGER   outQueryBufferLen,
+                           SQLINTEGER*  outQueryLen);
+
+    SQLRETURN SQLColAttribute(SQLHSTMT        stmt,
+                              SQLUSMALLINT    columnNum,
+                              SQLUSMALLINT    fieldId,
+                              SQLPOINTER      strAttr,
+                              SQLSMALLINT     bufferLen,
+                              SQLSMALLINT*    strAttrLen,
+                              SQLLEN*         numericAttr);
+
+    SQLRETURN SQLDescribeCol(SQLHSTMT       stmt,
+                             SQLUSMALLINT   columnNum, 
+                             SQLCHAR*       columnNameBuf,
+                             SQLSMALLINT    columnNameBufLen,
+                             SQLSMALLINT*   columnNameLen,
+                             SQLSMALLINT*   dataType, 
+                             SQLULEN*       columnSize,
+                             SQLSMALLINT*   decimalDigits, 
+                             SQLSMALLINT*   nullable);
+
+    SQLRETURN SQLRowCount(SQLHSTMT stmt, SQLLEN* rowCnt);
+
+    SQLRETURN SQLForeignKeys(SQLHSTMT       stmt,
+                             SQLCHAR*       primaryCatalogName,
+                             SQLSMALLINT    primaryCatalogNameLen,
+                             SQLCHAR*       primarySchemaName,
+                             SQLSMALLINT    primarySchemaNameLen,
+                             SQLCHAR*       primaryTableName,
+                             SQLSMALLINT    primaryTableNameLen,
+                             SQLCHAR*       foreignCatalogName,
+                             SQLSMALLINT    foreignCatalogNameLen,
+                             SQLCHAR*       foreignSchemaName,
+                             SQLSMALLINT    foreignSchemaNameLen,
+                             SQLCHAR*       foreignTableName,
+                             SQLSMALLINT    foreignTableNameLen);
+
+    SQLRETURN SQLGetStmtAttr(SQLHSTMT       stmt,
+                             SQLINTEGER     attr,
+                             SQLPOINTER     valueBuf,
+                             SQLINTEGER     valueBufLen,
+                             SQLINTEGER*    valueResLen);
+
+    SQLRETURN SQLSetStmtAttr(SQLHSTMT    stmt,
+                             SQLINTEGER  attr,
+                             SQLPOINTER  value,
+                             SQLINTEGER  valueLen);
+
+    SQLRETURN SQLPrimaryKeys(SQLHSTMT       stmt,
+                             SQLCHAR*       catalogName,
+                             SQLSMALLINT    catalogNameLen,
+                             SQLCHAR*       schemaName,
+                             SQLSMALLINT    schemaNameLen,
+                             SQLCHAR*       tableName,
+                             SQLSMALLINT    tableNameLen);
+
+    SQLRETURN SQLNumParams(SQLHSTMT stmt, SQLSMALLINT* paramCnt);
+
+    SQLRETURN SQLGetDiagField(SQLSMALLINT   handleType,
+                              SQLHANDLE     handle,
+                              SQLSMALLINT   recNum,
+                              SQLSMALLINT   diagId,
+                              SQLPOINTER    buffer,
+                              SQLSMALLINT   bufferLen,
+                              SQLSMALLINT*  resLen);
+
+    SQLRETURN SQLGetDiagRec(SQLSMALLINT     handleType,
+                            SQLHANDLE       handle,
+                            SQLSMALLINT     recNum,
+                            SQLCHAR*        sqlState,
+                            SQLINTEGER*     nativeError,
+                            SQLCHAR*        msgBuffer,
+                            SQLSMALLINT     msgBufferLen,
+                            SQLSMALLINT*    msgLen);
+
+    SQLRETURN SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT type);
+
+    SQLRETURN SQLEndTran(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT completionType);
+
+    SQLRETURN SQLGetData(SQLHSTMT       stmt,
+                         SQLUSMALLINT   colNum,
+                         SQLSMALLINT    targetType,
+                         SQLPOINTER     targetValue,
+                         SQLLEN         bufferLength,
+                         SQLLEN*        strLengthOrIndicator);
+
+    SQLRETURN SQLSetEnvAttr(SQLHENV     env,
+                            SQLINTEGER  attr,
+                            SQLPOINTER  value,
+                            SQLINTEGER  valueLen);
+
+    SQLRETURN SQLGetEnvAttr(SQLHENV     env,
+                            SQLINTEGER  attr,
+                            SQLPOINTER  valueBuf,
+                            SQLINTEGER  valueBufLen,
+                            SQLINTEGER* valueResLen);
+
+    SQLRETURN SQLSpecialColumns(SQLHSTMT    stmt,
+                                SQLSMALLINT idType,
+                                SQLCHAR*    catalogName,
+                                SQLSMALLINT catalogNameLen,
+                                SQLCHAR*    schemaName,
+                                SQLSMALLINT schemaNameLen,
+                                SQLCHAR*    tableName,
+                                SQLSMALLINT tableNameLen,
+                                SQLSMALLINT scope,
+                                SQLSMALLINT nullable);
+
+} // namespace ignite
+
+#endif //_IGNITE_ODBC
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/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
new file mode 100644
index 0000000..4d7460b
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h
@@ -0,0 +1,379 @@
+/*
+ * 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_APPLICATION_DATA_BUFFER
+#define _IGNITE_ODBC_APP_APPLICATION_DATA_BUFFER
+
+#include <stdint.h>
+
+#include <map>
+
+#include <ignite/guid.h>
+#include <ignite/date.h>
+#include <ignite/timestamp.h>
+
+#include "ignite/odbc/decimal.h"
+#include "ignite/odbc/common_types.h"
+#include "ignite/odbc/type_traits.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace app
+        {
+            /**
+             * User application data buffer.
+             */
+            class ApplicationDataBuffer
+            {
+            public:
+                /**
+                 * Default constructor.
+                 */
+                ApplicationDataBuffer();
+
+                /**
+                 * Constructor.
+                 *
+                 * @param type Underlying data type.
+                 * @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::IgniteSqlType type, void* buffer, SqlLen buflen, SqlLen* reslen, size_t** offset = 0);
+
+                /**
+                 * Copy constructor.
+                 *
+                 * @param other Other instance.
+                 */
+                ApplicationDataBuffer(const ApplicationDataBuffer& other);
+
+                /**
+                 * Destructor.
+                 */
+                ~ApplicationDataBuffer();
+
+                /**
+                 * Copy assigment operator.
+                 *
+                 * @param other Other instance.
+                 * @return This.
+                 */
+                ApplicationDataBuffer& operator=(const ApplicationDataBuffer& other);
+
+                /**
+                 * Set pointer to offset pointer.
+                 *
+                 * @param offset Pointer to offset pointer.
+                 */
+                void SetPtrToOffsetPtr(size_t** offset)
+                {
+                    this->offset = offset;
+                }
+
+                /**
+                 * Put in buffer value of type int8_t.
+                 *
+                 * @param value Value.
+                 */
+                void PutInt8(int8_t value);
+
+                /**
+                 * Put in buffer value of type int16_t.
+                 *
+                 * @param value Value.
+                 */
+                void PutInt16(int16_t value);
+
+                /**
+                 * Put in buffer value of type int32_t.
+                 *
+                 * @param value Value.
+                 */
+                void PutInt32(int32_t value);
+
+                /**
+                 * Put in buffer value of type int64_t.
+                 *
+                 * @param value Value.
+                 */
+                void PutInt64(int64_t value);
+
+                /**
+                 * Put in buffer value of type float.
+                 *
+                 * @param value Value.
+                 */
+                void PutFloat(float value);
+
+                /**
+                 * Put in buffer value of type double.
+                 *
+                 * @param value Value.
+                 */
+                void PutDouble(double value);
+
+                /**
+                 * Put in buffer value of type string.
+                 *
+                 * @param value Value.
+                 * @return Number of bytes that have been put in buffer.
+                 */
+                int32_t PutString(const std::string& value);
+
+                /**
+                 * Put in buffer value of type GUID.
+                 *
+                 * @param value Value.
+                 */
+                void PutGuid(const Guid& value);
+
+                /**
+                 * Put binary data in buffer.
+                 *
+                 * @param data Data pointer.
+                 * @param len Data length.
+                 * @return Number of bytes that have been put in buffer.
+                 */
+                int32_t PutBinaryData(void* data, size_t len);
+
+                /**
+                 * Put NULL.
+                 */
+                void PutNull();
+
+                /**
+                 * Put decimal value to buffer.
+                 *
+                 * @param value Value to put.
+                 */
+                void PutDecimal(const Decimal& value);
+
+                /**
+                 * Put date to buffer.
+                 *
+                 * @param value Value to put.
+                 */
+                void PutDate(const Date& value);
+
+                /**
+                 * Put timestamp to buffer.
+                 *
+                 * @param value Value to put.
+                 */
+                void PutTimestamp(const Timestamp& value);
+
+                /**
+                 * Get string.
+                 *
+                 * @return String value of buffer.
+                 */
+                std::string GetString(size_t maxLen) const;
+
+                /**
+                 * Get value of type int8_t.
+                 *
+                 * @return Integer value of type int8_t.
+                 */
+                int8_t GetInt8() const;
+
+                /**
+                 * Get value of type int16_t.
+                 *
+                 * @return Integer value of type int16_t.
+                 */
+                int16_t GetInt16() const;
+
+                /**
+                 * Get value of type int32_t.
+                 *
+                 * @return Integer value of type int32_t.
+                 */
+                int32_t GetInt32() const;
+
+                /**
+                 * Get value of type int64_t.
+                 *
+                 * @return Integer value of type int64_t.
+                 */
+                int64_t GetInt64() const;
+
+                /**
+                 * Get value of type float.
+                 *
+                 * @return Integer value of type float.
+                 */
+                float GetFloat() const;
+
+                /**
+                 * Get value of type double.
+                 *
+                 * @return Value of type double.
+                 */
+                double GetDouble() const;
+
+                /**
+                 * Get value of type GUID.
+                 *
+                 * @return Value of type Guid.
+                 */
+                Guid GetGuid() const;
+
+                /**
+                 * Get value of type Date.
+                 *
+                 * @return Value of type Date.
+                 */
+                Date GetDate() const;
+
+                /**
+                 * Get value of type Timestamp.
+                 *
+                 * @return Value of type Timestamp.
+                 */
+                Timestamp GetTimestamp() const;
+
+                /**
+                 * Get raw data.
+                 *
+                 * @return Buffer data.
+                 */
+                const void* GetData() const;
+
+                /**
+                 * Get result data length.
+                 *
+                 * @return Data length pointer.
+                 */
+                const SqlLen* GetResLen() const;
+
+                /**
+                 * Get buffer size in bytes.
+                 *
+                 * @return Buffer size.
+                 */
+                SqlLen GetSize() const
+                {
+                    return buflen;
+                }
+
+            private:
+                /**
+                 * Get raw data.
+                 *
+                 * @return Buffer data.
+                 */
+                void* GetData();
+
+                /**
+                 * Get result data length.
+                 *
+                 * @return Data length pointer.
+                 */
+                SqlLen* GetResLen();
+
+                /**
+                 * Put value of numeric type in the buffer.
+                 *
+                 * @param value Numeric value to put.
+                 */
+                template<typename T>
+                void PutNum(T value);
+
+                /**
+                 * Put numeric value to numeric buffer.
+                 *
+                 * @param value Numeric value.
+                 */
+                template<typename Tbuf, typename Tin>
+                void PutNumToNumBuffer(Tin value);
+
+                /**
+                 * Put value to string buffer.
+                 *
+                 * @param value Value that can be converted to string.
+                 */
+                template<typename CharT, typename Tin>
+                void PutValToStrBuffer(const Tin& value);
+
+                /**
+                 * Put value to string buffer.
+                 * Specialisation for int8_t.
+                 * @param value Value that can be converted to string.
+                 */
+                template<typename CharT>
+                void PutValToStrBuffer(const int8_t & value);
+
+                /**
+                 * Put string to string buffer.
+                 *
+                 * @param value String value.
+                 */
+                template<typename OutCharT, typename InCharT>
+                void PutStrToStrBuffer(const std::basic_string<InCharT>& value);
+
+                /**
+                 * Put raw data to any buffer.
+                 *
+                 * @param data Data pointer.
+                 * @param len Data length.
+                 */
+                void PutRawDataToBuffer(void *data, size_t len);
+
+                /**
+                 * Get int of type T.
+                 *
+                 * @return Integer value of specified type.
+                 */
+                template<typename T>
+                T GetNum() const;
+
+                /**
+                 * Apply buffer offset to pointer.
+                 * Adds offset to pointer if offset pointer is not null.
+                 * @param ptr Pointer.
+                 * @return Pointer with applied offset.
+                 */
+                template<typename T>
+                T* ApplyOffset(T* ptr) const;
+
+                /** Underlying data type. */
+                type_traits::IgniteSqlType type;
+
+                /** Buffer pointer. */
+                void* buffer;
+
+                /** Buffer length. */
+                SqlLen buflen;
+
+                /** Result length. */
+                SqlLen* reslen;
+
+                /** Pointer to implementation pointer to application offset */
+                size_t** offset;
+            };
+
+            /** Column binging map type alias. */
+            typedef std::map<uint16_t, ApplicationDataBuffer> ColumnBindingMap;
+        }
+    }
+}
+
+#endif //_IGNITE_ODBC_APP_APPLICATION_DATA_BUFFER
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/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
new file mode 100644
index 0000000..d1ea697
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h
@@ -0,0 +1,113 @@
+/*
+ * 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
+#define _IGNITE_ODBC_APP_PARAMETER
+
+#include <stdint.h>
+
+#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
+{
+    namespace odbc
+    {
+        namespace app
+        {
+            /**
+             * Statement parameter.
+             */
+            class Parameter
+            {
+            public:
+                /**
+                 * Default constructor.
+                 */
+                Parameter();
+
+                /**
+                 * Constructor.
+                 *
+                 * @param buffer Underlying data buffer.
+                 * @param sqlType IPD type.
+                 * @param columnSize IPD column size.
+                 * @param decDigits IPD decimal digits.
+                 */
+                Parameter(const ApplicationDataBuffer& buffer, int16_t sqlType,
+                    size_t columnSize, int16_t decDigits);
+
+                /**
+                 * Copy constructor.
+                 *
+                 * @param other Other instance.
+                 */
+                Parameter(const Parameter& other);
+
+                /**
+                 * Destructor.
+                 */
+                ~Parameter();
+
+                /**
+                 * Copy assigment operator.
+                 *
+                 * @param other Other instance.
+                 * @return This.
+                 */
+                Parameter& operator=(const Parameter& other);
+
+                /**
+                 * Write request using provided writer.
+                 * @param writer Writer.
+                 */
+                void Write(ignite::impl::binary::BinaryWriterImpl& writer) const;
+
+                /**
+                 * Get data buffer.
+                 *
+                 * @return underlying ApplicationDataBuffer instance.
+                 */
+                ApplicationDataBuffer& GetBuffer();
+
+            private:
+                /** Underlying data buffer. */
+                ApplicationDataBuffer buffer;
+
+                /** IPD type. */
+                int16_t sqlType;
+
+                /** IPD column size. */
+                size_t columnSize;
+
+                /** IPD decimal digits. */
+                int16_t decDigits;
+            };
+
+            /** Parameter binging map type alias. */
+            typedef std::map<uint16_t, Parameter> ParameterBindingMap;
+        }
+    }
+}
+
+#endif //_IGNITE_ODBC_APP_PARAMETER
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/include/ignite/odbc/column.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/column.h b/modules/platforms/cpp/odbc/include/ignite/odbc/column.h
new file mode 100644
index 0000000..cd48a40
--- /dev/null
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/column.h
@@ -0,0 +1,149 @@
+/*
+ * 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_COLUMN
+#define _IGNITE_ODBC_COLUMN
+
+#include <stdint.h>
+
+#include <ignite/impl/binary/binary_reader_impl.h>
+
+#include "ignite/odbc/app/application_data_buffer.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        /**
+         * Result set column.
+         */
+        class Column
+        {
+        public:
+            /**
+             * Default constructor.
+             */
+            Column();
+
+            /**
+             * Copy constructor.
+             *
+             * @param other Another instance.
+             */
+            Column(const Column& other);
+
+            /**
+             * Copy operator.
+             *
+             * @param other Another instance.
+             * @return This.
+             */
+            Column& operator=(const Column& other);
+
+            /**
+             * Destructor.
+             */
+            ~Column();
+
+            /**
+             * Constructor.
+             *
+             * @param reader Reader to be used to retrieve column data.
+             */
+            Column(ignite::impl::binary::BinaryReaderImpl& reader);
+
+            /**
+             * Get column size in bytes.
+             *
+             * @return Column size.
+             */
+            int32_t GetSize() const
+            {
+                return size;
+            }
+
+            /**
+             * Read column data and store it in application data buffer.
+             *
+             * @param dataBuf Application data buffer.
+             * @return Operation result.
+             */
+            SqlResult ReadToBuffer(ignite::impl::binary::BinaryReaderImpl& reader,
+                app::ApplicationDataBuffer& dataBuf);
+
+            /**
+             * Check if the column is in valid state.
+             *
+             * @return True if valid.
+             */
+            bool IsValid() const
+            {
+                return startPos >= 0;
+            }
+
+            /**
+             * Get unread data length.
+             * Find out how many bytes of data are left unread.
+             *
+             * @return Lengh of unread data in bytes.
+             */
+            int32_t GetUnreadDataLength() const
+            {
+                return size - offset;
+            }
+
+            /**
+             * Get unread data length.
+             * Find out how many bytes of data are left unread.
+             *
+             * @return Lengh of unread data in bytes.
+             */
+            int32_t GetEndPosition() const
+            {
+                return endPos;
+            }
+
+        private:
+            /**
+             * Increase offset.
+             *
+             * Increases offset on specified value and makes sure resulting
+             * offset does not exceed column size.
+             *
+             * @param value Offset is incremented on this value.
+             */
+            void IncreaseOffset(int32_t value);
+
+            /** Column type */
+            int8_t type;
+
+            /** Column position in current row. */
+            int32_t startPos;
+
+            /** Column end position in current row. */
+            int32_t endPos;
+
+            /** Current offset in column. */
+            int32_t offset;
+
+            /** Column data size in bytes. */
+            int32_t size;
+        };
+    }
+}
+
+#endif //_IGNITE_ODBC_COLUMN
\ No newline at end of file


Mime
View raw message