ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [05/31] ignite git commit: IGNITE-1786: Implemented ODBC driver.
Date Thu, 05 May 2016 13:46:42 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp b/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp
new file mode 100644
index 0000000..600dc86
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/app/application_data_buffer.cpp
@@ -0,0 +1,1216 @@
+/*
+ * 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 <algorithm>
+#include <string>
+#include <sstream>
+
+#include "ignite/impl/binary/binary_utils.h"
+
+#include "ignite/odbc/system/odbc_constants.h"
+#include "ignite/odbc/app/application_data_buffer.h"
+#include "ignite/odbc/utility.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace app
+        {
+            using ignite::impl::binary::BinaryUtils;
+
+            ApplicationDataBuffer::ApplicationDataBuffer() :
+                type(type_traits::IGNITE_ODBC_C_TYPE_UNSUPPORTED), buffer(0), buflen(0), reslen(0), offset(0)
+            {
+                // No-op.
+            }
+
+            ApplicationDataBuffer::ApplicationDataBuffer(type_traits::IgniteSqlType type, 
+                void* buffer, SqlLen buflen, SqlLen* reslen, size_t** offset) :
+                type(type), buffer(buffer), buflen(buflen), reslen(reslen), offset(offset)
+            {
+                // No-op.
+            }
+
+            ApplicationDataBuffer::ApplicationDataBuffer(const ApplicationDataBuffer & other) :
+                type(other.type), buffer(other.buffer), buflen(other.buflen), reslen(other.reslen), offset(other.offset)
+            {
+                // No-op.
+            }
+
+            ApplicationDataBuffer::~ApplicationDataBuffer()
+            {
+                // No-op.
+            }
+
+            ApplicationDataBuffer & ApplicationDataBuffer::operator=(const ApplicationDataBuffer & other)
+            {
+                type = other.type;
+                buffer = other.buffer;
+                buflen = other.buflen;
+                reslen = other.reslen;
+                offset = other.offset;
+
+                return *this;
+            }
+
+            template<typename T>
+            void ApplicationDataBuffer::PutNum(T value)
+            {
+                using namespace type_traits;
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
+                    {
+                        PutNumToNumBuffer<signed char>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_BIT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
+                    {
+                        PutNumToNumBuffer<unsigned char>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
+                    {
+                        PutNumToNumBuffer<short>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
+                    {
+                        PutNumToNumBuffer<unsigned short>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
+                    {
+                        PutNumToNumBuffer<long>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
+                    {
+                        PutNumToNumBuffer<unsigned long>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
+                    {
+                        PutNumToNumBuffer<int64_t>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
+                    {
+                        PutNumToNumBuffer<uint64_t>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_FLOAT:
+                    {
+                        PutNumToNumBuffer<float>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_DOUBLE:
+                    {
+                        PutNumToNumBuffer<double>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        PutValToStrBuffer<char>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_WCHAR:
+                    {
+                        PutValToStrBuffer<wchar_t>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_NUMERIC:
+                    {
+                        if (GetData())
+                        {
+                            SQL_NUMERIC_STRUCT* out =
+                                reinterpret_cast<SQL_NUMERIC_STRUCT*>(GetData());
+
+                            out->precision = 20; // Max int64_t precision
+                            out->scale = 0;
+                            out->sign = value < 0 ? 2 : 1;
+
+                            memset(out->val, 0, SQL_MAX_NUMERIC_LEN);
+
+                            int64_t intVal = static_cast<int64_t>(std::abs(value));
+
+                            memcpy(out->val, &intVal, std::min<int>(SQL_MAX_NUMERIC_LEN, sizeof(intVal)));
+                        }
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_BINARY:
+                    case IGNITE_ODBC_C_TYPE_DEFAULT:
+                    {
+                        if (GetData())
+                        {
+                            if (buflen >= sizeof(value))
+                            {
+                                memcpy(GetData(), &value, sizeof(value));
+
+                                if (GetResLen())
+                                    *GetResLen() = sizeof(value);
+                            }
+                            else
+                            {
+                                memcpy(GetData(), &value, static_cast<size_t>(buflen));
+
+                                if (GetResLen())
+                                    *GetResLen() = SQL_NO_TOTAL;
+                            }
+                        }
+                        else if (GetResLen())
+                        {
+                            *GetResLen() = sizeof(value);
+                        }
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TDATE:
+                    {
+                        PutDate(Date(static_cast<int64_t>(value)));
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TTIMESTAMP:
+                    {
+                        PutTimestamp(Timestamp(static_cast<int64_t>(value)));
+
+                        break;
+                    }
+
+                    default:
+                    {
+                        if (GetResLen())
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+            }
+
+            template<typename Tbuf, typename Tin>
+            void ApplicationDataBuffer::PutNumToNumBuffer(Tin value)
+            {
+                if (GetData())
+                {
+                    Tbuf* out = reinterpret_cast<Tbuf*>(GetData());
+                    *out = static_cast<Tbuf>(value);
+                }
+            }
+
+            template<typename CharT, typename Tin>
+            void ApplicationDataBuffer::PutValToStrBuffer(const Tin & value)
+            {
+                typedef std::basic_stringstream<CharT> ConverterType;
+
+                ConverterType converter;
+
+                converter << value;
+
+                PutStrToStrBuffer<CharT>(converter.str());
+            }
+
+            template<typename CharT>
+            void ApplicationDataBuffer::PutValToStrBuffer(const int8_t & value)
+            {
+                typedef std::basic_stringstream<CharT> ConverterType;
+
+                ConverterType converter;
+
+                converter << static_cast<int>(value);
+
+                PutStrToStrBuffer<CharT>(converter.str());
+            }
+
+            template<typename OutCharT, typename InCharT>
+            void ApplicationDataBuffer::PutStrToStrBuffer(const std::basic_string<InCharT>& value)
+            {
+                SqlLen charSize = static_cast<SqlLen>(sizeof(OutCharT));
+
+                if (GetData())
+                {
+                    if (buflen >= charSize)
+                    {
+                        OutCharT* out = reinterpret_cast<OutCharT*>(GetData());
+
+                        SqlLen outLen = (buflen / charSize) - 1;
+
+                        SqlLen toCopy = std::min<size_t>(outLen, value.size());
+
+                        for (SqlLen i = 0; i < toCopy; ++i)
+                            out[i] = value[i];
+
+                        out[toCopy] = 0;
+                    }
+
+                    if (GetResLen())
+                    {
+                        if (buflen >= static_cast<SqlLen>((value.size() + 1) * charSize))
+                            *GetResLen() = static_cast<SqlLen>(value.size());
+                        else
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+                else if (GetResLen())
+                    *GetResLen() = value.size();
+            }
+
+            void ApplicationDataBuffer::PutRawDataToBuffer(void *data, size_t len)
+            {
+                SqlLen ilen = static_cast<SqlLen>(len);
+
+                if (GetData())
+                {
+                    size_t toCopy = static_cast<size_t>(std::min(buflen, ilen));
+
+                    memcpy(GetData(), data, toCopy);
+
+                    if (GetResLen())
+                    {
+                        if (buflen >= ilen)
+                            *GetResLen() = ilen;
+                        else
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+                else if (GetResLen())
+                    *GetResLen() = ilen;
+            }
+
+            void ApplicationDataBuffer::PutInt8(int8_t value)
+            {
+                PutNum(value);
+            }
+
+            void ApplicationDataBuffer::PutInt16(int16_t value)
+            {
+                PutNum(value);
+            }
+
+            void ApplicationDataBuffer::PutInt32(int32_t value)
+            {
+                PutNum(value);
+            }
+
+            void ApplicationDataBuffer::PutInt64(int64_t value)
+            {
+                PutNum(value);
+            }
+
+            void ApplicationDataBuffer::PutFloat(float value)
+            {
+                PutNum(value);
+            }
+
+            void ApplicationDataBuffer::PutDouble(double value)
+            {
+                PutNum(value);
+            }
+
+            int32_t ApplicationDataBuffer::PutString(const std::string & value)
+            {
+                using namespace type_traits;
+
+                int32_t used = 0;
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_BIT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_NUMERIC:
+                    {
+                        std::stringstream converter(value);
+
+                        int64_t numValue;
+
+                        converter >> numValue;
+
+                        PutNum(numValue);
+
+                        used = static_cast<int32_t>(value.size());
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_FLOAT:
+                    case IGNITE_ODBC_C_TYPE_DOUBLE:
+                    {
+                        std::stringstream converter(value);
+
+                        double numValue;
+
+                        converter >> numValue;
+
+                        PutNum(numValue);
+
+                        used = static_cast<int32_t>(value.size());
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    case IGNITE_ODBC_C_TYPE_BINARY:
+                    case IGNITE_ODBC_C_TYPE_DEFAULT:
+                    {
+                        PutStrToStrBuffer<char>(value);
+
+                        used = static_cast<int32_t>(GetSize()) - 1;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_WCHAR:
+                    {
+                        PutStrToStrBuffer<wchar_t>(value);
+
+                        used = (static_cast<int32_t>(GetSize()) / 2) - 1;
+
+                        break;
+                    }
+
+                    default:
+                    {
+                        if (GetResLen())
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+
+                return used < 0 ? 0 : used;
+            }
+
+            void ApplicationDataBuffer::PutGuid(const Guid & value)
+            {
+                using namespace type_traits;
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    case IGNITE_ODBC_C_TYPE_BINARY:
+                    case IGNITE_ODBC_C_TYPE_DEFAULT:
+                    {
+                        PutValToStrBuffer<char>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_WCHAR:
+                    {
+                        PutValToStrBuffer<wchar_t>(value);
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_GUID:
+                    {
+                        SQLGUID* guid = reinterpret_cast<SQLGUID*>(GetData());
+
+                        guid->Data1 = static_cast<uint32_t>(value.GetMostSignificantBits() >> 32);
+                        guid->Data2 = static_cast<uint16_t>(value.GetMostSignificantBits() >> 16);
+                        guid->Data3 = static_cast<uint16_t>(value.GetMostSignificantBits());
+
+                        uint64_t lsb = value.GetLeastSignificantBits();
+                        for (size_t i = 0; i < sizeof(guid->Data4); ++i)
+                            guid->Data4[i] = (lsb >> (sizeof(guid->Data4) - i - 1) * 8) & 0xFF;
+
+                        break;
+                    }
+
+                    default:
+                    {
+                        if (GetResLen())
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+            }
+
+            int32_t ApplicationDataBuffer::PutBinaryData(void *data, size_t len)
+            {
+                using namespace type_traits;
+
+                int32_t used = 0;
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_BINARY:
+                    case IGNITE_ODBC_C_TYPE_DEFAULT:
+                    {
+                        PutRawDataToBuffer(data, len);
+
+                        used = static_cast<int32_t>(GetSize());
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        std::stringstream converter;
+
+                        uint8_t *dataBytes = reinterpret_cast<uint8_t*>(data);
+
+                        for (size_t i = 0; i < len; ++i)
+                        {
+                            converter << std::hex
+                                      << std::setfill('0')
+                                      << std::setw(2)
+                                      << static_cast<unsigned>(dataBytes[i]);
+                        }
+
+                        PutStrToStrBuffer<char>(converter.str());
+
+                        used = static_cast<int32_t>(GetSize()) - 1;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_WCHAR:
+                    {
+                        std::wstringstream converter;
+
+                        uint8_t *dataBytes = reinterpret_cast<uint8_t*>(data);
+
+                        for (size_t i = 0; i < len; ++i)
+                        {
+                            converter << std::hex
+                                      << std::setfill<wchar_t>('0')
+                                      << std::setw(2)
+                                      << static_cast<unsigned>(dataBytes[i]);
+                        }
+
+                        PutStrToStrBuffer<wchar_t>(converter.str());
+
+                        used = static_cast<int32_t>(GetSize() / 2) - 1;
+
+                        break;
+                    }
+
+                    default:
+                    {
+                        if (GetResLen())
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+
+                return used < 0 ? 0 : used;
+            }
+
+            void ApplicationDataBuffer::PutNull()
+            {
+                if (GetResLen())
+                    *GetResLen() = SQL_NULL_DATA;
+            }
+
+            void ApplicationDataBuffer::PutDecimal(const Decimal& value)
+            {
+                using namespace type_traits;
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_BIT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_FLOAT:
+                    case IGNITE_ODBC_C_TYPE_DOUBLE:
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    case IGNITE_ODBC_C_TYPE_WCHAR:
+                    case IGNITE_ODBC_C_TYPE_NUMERIC:
+                    {
+                        PutNum<double>(static_cast<double>(value));
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_DEFAULT:
+                    {
+                        if (GetData())
+                            memcpy(GetData(), &value, std::min(static_cast<size_t>(buflen), sizeof(value)));
+
+                        if (GetResLen())
+                            *GetResLen() = sizeof(value);
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_BINARY:
+                    default:
+                    {
+                        if (GetResLen())
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+            }
+
+            void ApplicationDataBuffer::PutDate(const Date& value)
+            {
+                using namespace type_traits;
+
+                tm tmTime;
+
+                BinaryUtils::DateToCTm(value, tmTime);
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        char* buffer = reinterpret_cast<char*>(GetData());
+
+                        if (buffer)
+                        {
+                            strftime(buffer, GetSize(), "%Y-%m-%d", &tmTime);
+
+                            if (GetResLen())
+                                *GetResLen() = strlen(buffer);
+                        }
+                        else if (GetResLen())
+                            *GetResLen() = sizeof("HHHH-MM-DD") - 1;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_WCHAR:
+                    {
+                        SQLWCHAR* buffer = reinterpret_cast<SQLWCHAR*>(GetData());
+
+                        if (buffer)
+                        {
+                            std::string tmp(GetSize(), 0);
+
+                            strftime(&tmp[0], GetSize(), "%Y-%m-%d", &tmTime);
+
+                            SqlLen toCopy = std::min(static_cast<SqlLen>(strlen(tmp.c_str()) + 1), GetSize());
+
+                            for (SqlLen i = 0; i < toCopy; ++i)
+                                buffer[i] = tmp[i];
+
+                            buffer[toCopy] = 0;
+
+                            if (GetResLen())
+                                *GetResLen() = toCopy;
+                        }
+                        else if (GetResLen())
+                            *GetResLen() = sizeof("HHHH-MM-DD") - 1;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TDATE:
+                    {
+                        SQL_DATE_STRUCT* buffer = reinterpret_cast<SQL_DATE_STRUCT*>(GetData());
+
+                        buffer->year = tmTime.tm_year + 1900;
+                        buffer->month = tmTime.tm_mon + 1;
+                        buffer->day = tmTime.tm_mday;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TTIMESTAMP:
+                    {
+                        SQL_TIMESTAMP_STRUCT* buffer = reinterpret_cast<SQL_TIMESTAMP_STRUCT*>(GetData());
+
+                        buffer->year = tmTime.tm_year + 1900;
+                        buffer->month = tmTime.tm_mon + 1;
+                        buffer->day = tmTime.tm_mday;
+                        buffer->hour = tmTime.tm_hour;
+                        buffer->minute = tmTime.tm_min;
+                        buffer->second = tmTime.tm_sec;
+                        buffer->fraction = 0;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_BINARY:
+                    case IGNITE_ODBC_C_TYPE_DEFAULT:
+                    {
+                        if (GetData())
+                            memcpy(GetData(), &value, std::min(static_cast<size_t>(buflen), sizeof(value)));
+
+                        if (GetResLen())
+                            *GetResLen() = sizeof(value);
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_BIT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_FLOAT:
+                    case IGNITE_ODBC_C_TYPE_DOUBLE:
+                    case IGNITE_ODBC_C_TYPE_NUMERIC:
+                    default:
+                    {
+                        if (GetResLen())
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+            }
+
+            void ApplicationDataBuffer::PutTimestamp(const Timestamp& value)
+            {
+                using namespace type_traits;
+
+                tm tmTime;
+
+                BinaryUtils::TimestampToCTm(value, tmTime);
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        char* buffer = reinterpret_cast<char*>(GetData());
+
+                        if (buffer)
+                        {
+                            strftime(buffer, GetSize(), "%Y-%m-%d %H:%M:%S", &tmTime);
+
+                            if (GetResLen())
+                                *GetResLen() = strlen(buffer);
+                        }
+                        else if (GetResLen())
+                            *GetResLen() = sizeof("HHHH-MM-DD HH:MM:SS") - 1;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_WCHAR:
+                    {
+                        SQLWCHAR* buffer = reinterpret_cast<SQLWCHAR*>(GetData());
+
+                        if (buffer)
+                        {
+                            std::string tmp(GetSize(), 0);
+
+                            strftime(&tmp[0], GetSize(), "%Y-%m-%d %H:%M:%S", &tmTime);
+
+                            SqlLen toCopy = std::min(static_cast<SqlLen>(strlen(tmp.c_str()) + 1), GetSize());
+
+                            for (SqlLen i = 0; i < toCopy; ++i)
+                                buffer[i] = tmp[i];
+
+                            buffer[toCopy] = 0;
+
+                            if (GetResLen())
+                                *GetResLen() = toCopy;
+                        }
+                        else if (GetResLen())
+                            *GetResLen() = sizeof("HHHH-MM-DD HH:MM:SS") - 1;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TDATE:
+                    {
+                        SQL_DATE_STRUCT* buffer = reinterpret_cast<SQL_DATE_STRUCT*>(GetData());
+
+                        buffer->year = tmTime.tm_year + 1900;
+                        buffer->month = tmTime.tm_mon + 1;
+                        buffer->day = tmTime.tm_mday;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TTIMESTAMP:
+                    {
+                        SQL_TIMESTAMP_STRUCT* buffer = reinterpret_cast<SQL_TIMESTAMP_STRUCT*>(GetData());
+
+                        buffer->year = tmTime.tm_year + 1900;
+                        buffer->month = tmTime.tm_mon + 1;
+                        buffer->day = tmTime.tm_mday;
+                        buffer->hour = tmTime.tm_hour;
+                        buffer->minute = tmTime.tm_min;
+                        buffer->second = tmTime.tm_sec;
+                        buffer->fraction = value.GetSecondFraction();
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_BINARY:
+                    case IGNITE_ODBC_C_TYPE_DEFAULT:
+                    {
+                        if (GetData())
+                            memcpy(GetData(), &value, std::min(static_cast<size_t>(buflen), sizeof(value)));
+
+                        if (GetResLen())
+                            *GetResLen() = sizeof(value);
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_BIT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
+                    case IGNITE_ODBC_C_TYPE_FLOAT:
+                    case IGNITE_ODBC_C_TYPE_DOUBLE:
+                    case IGNITE_ODBC_C_TYPE_NUMERIC:
+                    default:
+                    {
+                        if (GetResLen())
+                            *GetResLen() = SQL_NO_TOTAL;
+                    }
+                }
+            }
+
+            std::string ApplicationDataBuffer::GetString(size_t maxLen) const
+            {
+                using namespace type_traits;
+                std::string res;
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        res.assign(reinterpret_cast<const char*>(GetData()),
+                                   std::min(maxLen, static_cast<size_t>(buflen)));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
+                    {
+                        std::stringstream converter;
+
+                        converter << GetNum<int64_t>();
+
+                        res = converter.str();
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_BIT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
+                    {
+                        std::stringstream converter;
+
+                        converter << GetNum<uint64_t>();
+
+                        res = converter.str();
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_FLOAT:
+                    {
+                        std::stringstream converter;
+
+                        converter << GetNum<float>();
+
+                        res = converter.str();
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_NUMERIC:
+                    case IGNITE_ODBC_C_TYPE_DOUBLE:
+                    {
+                        std::stringstream converter;
+
+                        converter << GetNum<double>();
+
+                        res = converter.str();
+
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+
+                return res;
+            }
+
+            int8_t ApplicationDataBuffer::GetInt8() const
+            {
+                return GetNum<int8_t>();
+            }
+
+            int16_t ApplicationDataBuffer::GetInt16() const
+            {
+                return GetNum<int16_t>();
+            }
+
+            int32_t ApplicationDataBuffer::GetInt32() const
+            {
+                return GetNum<int32_t>();
+            }
+
+            int64_t ApplicationDataBuffer::GetInt64() const
+            {
+                return GetNum<int64_t>();
+            }
+
+            float ApplicationDataBuffer::GetFloat() const
+            {
+                return GetNum<float>();
+            }
+
+            double ApplicationDataBuffer::GetDouble() const
+            {
+                return GetNum<double>();
+            }
+
+            Guid ApplicationDataBuffer::GetGuid() const
+            {
+                using namespace type_traits;
+
+                Guid res;
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        std::string str(reinterpret_cast<const char*>(GetData()), static_cast<size_t>(buflen));
+
+                        std::stringstream converter(str);
+
+                        converter >> res;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_GUID:
+                    {
+                        const SQLGUID* guid = reinterpret_cast<const SQLGUID*>(GetData());
+
+                        uint64_t msb = static_cast<uint64_t>(guid->Data1) << 32 |
+                                       static_cast<uint64_t>(guid->Data2) << 16 |
+                                       static_cast<uint64_t>(guid->Data3);
+
+                        uint64_t lsb = 0;
+
+                        for (size_t i = 0; i < sizeof(guid->Data4); ++i)
+                            lsb = guid->Data4[i] << (sizeof(guid->Data4) - i - 1) * 8;
+
+                        res = Guid(msb, lsb);
+
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+
+                return res;
+            }
+
+            const void* ApplicationDataBuffer::GetData() const
+            {
+                return ApplyOffset(buffer);
+            }
+
+            const SqlLen* ApplicationDataBuffer::GetResLen() const
+            {
+                return ApplyOffset(reslen);
+            }
+
+            void* ApplicationDataBuffer::GetData() 
+            {
+                return ApplyOffset(buffer);
+            }
+
+            SqlLen* ApplicationDataBuffer::GetResLen()
+            {
+                return ApplyOffset(reslen);
+            }
+
+            template<typename T>
+            T ApplicationDataBuffer::GetNum() const
+            {
+                using namespace type_traits;
+
+                T res = 0;
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        std::string str = GetString(static_cast<size_t>(buflen));
+
+                        std::stringstream converter(str);
+
+                        // Workaround for char types which are recognised as
+                        // symbolyc types and not numeric types.
+                        if (sizeof(T) == 1)
+                        {
+                            short tmp;
+
+                            converter >> tmp;
+
+                            res = static_cast<T>(tmp);
+                        }
+                        else
+                            converter >> res;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_TINYINT:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const signed char*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_BIT:
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_TINYINT:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const unsigned char*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_SHORT:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const signed short*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_SHORT:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const unsigned short*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_LONG:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const signed long*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_LONG:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const unsigned long*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_SIGNED_BIGINT:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const int64_t*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_UNSIGNED_BIGINT:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const uint64_t*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_FLOAT:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const float*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_DOUBLE:
+                    {
+                        res = static_cast<T>(*reinterpret_cast<const double*>(GetData()));
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_NUMERIC:
+                    {
+                        const SQL_NUMERIC_STRUCT* numeric =
+                            reinterpret_cast<const SQL_NUMERIC_STRUCT*>(GetData());
+
+                        int64_t resInt;
+
+                        // TODO: implement propper conversation from numeric type.
+                        memcpy(&resInt, numeric->val, std::min<int>(SQL_MAX_NUMERIC_LEN, sizeof(resInt)));
+
+                        if (numeric->sign == 2)
+                            resInt *= -1;
+
+                        double resDouble = static_cast<double>(resInt);
+
+                        for (SQLSCHAR scale = numeric->scale; scale > 0; --scale)
+                            resDouble /= 10.0;
+
+                        res = static_cast<T>(resDouble);
+
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+
+                return res;
+            }
+
+            Date ApplicationDataBuffer::GetDate() const
+            {
+                using namespace type_traits;
+
+                tm tmTime = { 0 };
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_TDATE:
+                    {
+                        const SQL_DATE_STRUCT* buffer = reinterpret_cast<const SQL_DATE_STRUCT*>(GetData());
+
+                        tmTime.tm_year = buffer->year - 1900;
+                        tmTime.tm_mon = buffer->month - 1;
+                        tmTime.tm_mday = buffer->day;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TTIMESTAMP:
+                    {
+                        const SQL_TIMESTAMP_STRUCT* buffer = reinterpret_cast<const SQL_TIMESTAMP_STRUCT*>(GetData());
+
+                        tmTime.tm_year = buffer->year - 1900;
+                        tmTime.tm_mon = buffer->month - 1;
+                        tmTime.tm_mday = buffer->day;
+                        tmTime.tm_hour = buffer->hour;
+                        tmTime.tm_min = buffer->minute;
+                        tmTime.tm_sec = buffer->second;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        std::string str = utility::SqlStringToString(
+                            reinterpret_cast<const unsigned char*>(GetData()),
+                            static_cast<int32_t>(GetSize()));
+
+                        sscanf(str.c_str(), "%d-%d-%d %d:%d:%d", &tmTime.tm_year, &tmTime.tm_mon,
+                            &tmTime.tm_mday, &tmTime.tm_hour, &tmTime.tm_min, &tmTime.tm_sec);
+
+                        tmTime.tm_year = tmTime.tm_year - 1900;
+                        tmTime.tm_mon = tmTime.tm_mon - 1;
+
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+
+                return BinaryUtils::CTmToDate(tmTime);
+            }
+
+            Timestamp ApplicationDataBuffer::GetTimestamp() const
+            {
+                using namespace type_traits;
+
+                tm tmTime = { 0 };
+
+                int32_t nanos = 0;
+
+                switch (type)
+                {
+                    case IGNITE_ODBC_C_TYPE_TDATE:
+                    {
+                        const SQL_DATE_STRUCT* buffer = reinterpret_cast<const SQL_DATE_STRUCT*>(GetData());
+
+                        tmTime.tm_year = buffer->year - 1900;
+                        tmTime.tm_mon = buffer->month - 1;
+                        tmTime.tm_mday = buffer->day;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_TTIMESTAMP:
+                    {
+                        const SQL_TIMESTAMP_STRUCT* buffer = reinterpret_cast<const SQL_TIMESTAMP_STRUCT*>(GetData());
+
+                        tmTime.tm_year = buffer->year - 1900;
+                        tmTime.tm_mon = buffer->month - 1;
+                        tmTime.tm_mday = buffer->day;
+                        tmTime.tm_hour = buffer->hour;
+                        tmTime.tm_min = buffer->minute;
+                        tmTime.tm_sec = buffer->second;
+
+                        nanos = buffer->fraction;
+
+                        break;
+                    }
+
+                    case IGNITE_ODBC_C_TYPE_CHAR:
+                    {
+                        std::string str = utility::SqlStringToString(
+                            reinterpret_cast<const unsigned char*>(GetData()),
+                            static_cast<int32_t>(GetSize()));
+
+                        sscanf(str.c_str(), "%d-%d-%d %d:%d:%d", &tmTime.tm_year, &tmTime.tm_mon,
+                            &tmTime.tm_mday, &tmTime.tm_hour, &tmTime.tm_min, &tmTime.tm_sec);
+
+                        tmTime.tm_year = tmTime.tm_year - 1900;
+                        tmTime.tm_mon = tmTime.tm_mon - 1;
+
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+
+                return BinaryUtils::CTmToTimestamp(tmTime, nanos);
+            }
+
+            template<typename T>
+            T* ApplicationDataBuffer::ApplyOffset(T* ptr) const
+            {
+                if (!ptr || !offset || !*offset)
+                    return ptr;
+
+                return utility::GetPointerWithOffset(ptr, **offset);
+            }
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/app/parameter.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/app/parameter.cpp b/modules/platforms/cpp/odbc/src/app/parameter.cpp
new file mode 100644
index 0000000..3ced3e8
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/app/parameter.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 <algorithm>
+#include <string>
+#include <sstream>
+
+#include "ignite/odbc/system/odbc_constants.h"
+#include "ignite/odbc/app/parameter.h"
+#include "ignite/odbc/utility.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace app
+        {
+            Parameter::Parameter() :
+                buffer(),
+                sqlType(),
+                columnSize(),
+                decDigits()
+            {
+                // No-op.
+            }
+
+            Parameter::Parameter(const ApplicationDataBuffer& buffer, int16_t sqlType, 
+                size_t columnSize, int16_t decDigits) :
+                buffer(buffer),
+                sqlType(sqlType),
+                columnSize(columnSize),
+                decDigits(decDigits)
+            {
+                // No-op.
+            }
+
+            Parameter::Parameter(const Parameter & other) :
+                buffer(other.buffer),
+                sqlType(other.sqlType),
+                columnSize(other.columnSize),
+                decDigits(other.decDigits)
+            {
+                // No-op.
+            }
+
+            Parameter::~Parameter()
+            {
+                // No-op.
+            }
+
+            Parameter& Parameter::operator=(const Parameter &other)
+            {
+                buffer = other.buffer;
+                sqlType = other.sqlType;
+                columnSize = other.columnSize;
+                decDigits = other.decDigits;
+
+                return *this;
+            }
+
+            void Parameter::Write(ignite::impl::binary::BinaryWriterImpl& writer) const
+            {
+                switch (sqlType)
+                {
+                    case SQL_CHAR:
+                    case SQL_VARCHAR:
+                    case SQL_LONGVARCHAR:
+                    {
+                        utility::WriteString(writer, buffer.GetString(columnSize));
+                        break;
+                    }
+
+                    case SQL_SMALLINT:
+                    {
+                        writer.WriteInt16(buffer.GetInt16());
+                        break;
+                    }
+
+                    case SQL_INTEGER:
+                    {
+                        writer.WriteInt32(buffer.GetInt32());
+                        break;
+                    }
+
+                    case SQL_FLOAT:
+                    {
+                        writer.WriteFloat(buffer.GetFloat());
+                        break;
+                    }
+
+                    case SQL_DOUBLE:
+                    {
+                        writer.WriteDouble(buffer.GetDouble());
+                        break;
+                    }
+
+                    case SQL_TINYINT:
+                    {
+                        writer.WriteInt8(buffer.GetInt8());
+                        break;
+                    }
+
+                    case SQL_BIT:
+                    {
+                        writer.WriteBool(buffer.GetInt8() != 0);
+                        break;
+                    }
+
+                    case SQL_BIGINT:
+                    {
+                        writer.WriteInt64(buffer.GetInt64());
+                        break;
+                    }
+
+                    case SQL_DATE:
+                    {
+                        writer.WriteDate(buffer.GetDate());
+                        break;
+                    }
+
+                    case SQL_TIMESTAMP:
+                    {
+                        writer.WriteTimestamp(buffer.GetTimestamp());
+                        break;
+                    }
+
+                    case SQL_BINARY:
+                    case SQL_VARBINARY:
+                    case SQL_LONGVARBINARY:
+                    {
+                        writer.WriteInt8Array(reinterpret_cast<const int8_t*>(buffer.GetData()),
+                                              static_cast<int32_t>(buffer.GetSize()));
+                        break;
+                    }
+
+                    case SQL_GUID:
+                    {
+                        writer.WriteGuid(buffer.GetGuid());
+
+                        break;
+                    }
+
+                    case SQL_DECIMAL:
+                    {
+                        //TODO: Add Decimal type support.
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+            }
+
+            ApplicationDataBuffer & Parameter::GetBuffer()
+            {
+                return buffer;
+            }
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/column.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/column.cpp b/modules/platforms/cpp/odbc/src/column.cpp
new file mode 100644
index 0000000..61a55ca
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/column.cpp
@@ -0,0 +1,488 @@
+/*
+ * 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 <ignite/impl/interop/interop_stream_position_guard.h>
+
+#include "ignite/odbc/utility.h"
+#include "ignite/odbc/column.h"
+
+namespace
+{
+    using namespace ignite::impl::interop;
+    using namespace ignite::impl::binary;
+
+    bool GetObjectLength(InteropInputStream& stream, int32_t& len)
+    {
+        InteropStreamPositionGuard<InteropInputStream> guard(stream);
+
+        int8_t hdr = stream.ReadInt8();
+
+        if (hdr != IGNITE_HDR_FULL)
+            return false;
+
+        int8_t protoVer = stream.ReadInt8();
+
+        if (protoVer != IGNITE_PROTO_VER)
+            return false;
+
+        // Skipping flags
+        stream.ReadInt16();
+
+        // Skipping typeId
+        stream.ReadInt32();
+
+        // Skipping hash code
+        stream.ReadInt32();
+
+        len = stream.ReadInt32();
+
+        return true;
+    }
+
+    /**
+     * Read column header and restores position if the column is of
+     * complex type.
+     * @return Column type header.
+     */
+    int8_t ReadColumnHeader(ignite::impl::interop::InteropInputStream& stream)
+    {
+        using namespace ignite::impl::binary;
+
+        int32_t headerPos = stream.Position();
+
+        int8_t hdr = stream.ReadInt8();
+
+        // Check if we need to restore position - to read complex types
+        // stream should have unread header, but for primitive types it
+        // should not.
+        switch (hdr)
+        {
+            case IGNITE_TYPE_BYTE:
+            case IGNITE_TYPE_SHORT:
+            case IGNITE_TYPE_CHAR:
+            case IGNITE_TYPE_INT:
+            case IGNITE_TYPE_LONG:
+            case IGNITE_TYPE_FLOAT:
+            case IGNITE_TYPE_DOUBLE:
+            case IGNITE_TYPE_BOOL:
+            case IGNITE_HDR_NULL:
+            {
+                // No-op.
+                break;
+            }
+
+            default:
+            {
+                // Restoring position.
+                stream.Position(headerPos);
+                break;
+            }
+        }
+
+        return hdr;
+    }
+}
+
+namespace ignite
+{
+    namespace odbc
+    {
+        Column::Column() :
+            type(0), startPos(-1), endPos(-1), offset(0), size(0)
+        {
+            // No-op.
+        }
+
+        Column::Column(const Column& other) :
+            type(other.type), startPos(other.startPos), endPos(other.endPos),
+            offset(other.offset), size(other.size)
+        {
+            // No-op.
+        }
+
+        Column& Column::operator=(const Column& other)
+        {
+            type = other.type;
+            startPos = other.startPos;
+            endPos = other.endPos;
+            offset = other.offset;
+            size = other.size;
+
+            return *this;
+        }
+
+        Column::~Column()
+        {
+            // No-op.
+        }
+
+        Column::Column(ignite::impl::binary::BinaryReaderImpl& reader) :
+            type(0), startPos(-1), endPos(-1), offset(0), size(0)
+        {
+            ignite::impl::interop::InteropInputStream* stream = reader.GetStream();
+
+            if (!stream)
+                return;
+
+            InteropStreamPositionGuard<InteropInputStream> guard(*stream);
+
+            int32_t sizeTmp = 0;
+
+            int8_t hdr = ReadColumnHeader(*stream);
+
+            int32_t startPosTmp = stream->Position();
+
+            switch (hdr)
+            {
+                case IGNITE_HDR_NULL:
+                {
+                    sizeTmp = 1;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_BYTE:
+                {
+                    reader.ReadInt8();
+
+                    sizeTmp = 1;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_BOOL:
+                {
+                    reader.ReadBool();
+
+                    sizeTmp = 1;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_SHORT:
+                case IGNITE_TYPE_CHAR:
+                {
+                    reader.ReadInt16();
+
+                    sizeTmp = 2;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_FLOAT:
+                {
+                    reader.ReadFloat();
+
+                    sizeTmp = 4;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_INT:
+                {
+                    reader.ReadInt32();
+
+                    sizeTmp = 4;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_DOUBLE:
+                {
+                    reader.ReadDouble();
+
+                    sizeTmp = 8;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_LONG:
+                {
+                    reader.ReadInt64();
+
+                    sizeTmp = 8;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_STRING:
+                {
+                    std::string str;
+                    utility::ReadString(reader, str);
+
+                    sizeTmp = static_cast<int32_t>(str.size());
+
+                    break;
+                }
+
+                case IGNITE_TYPE_UUID:
+                {
+                    reader.ReadGuid();
+
+                    sizeTmp = 16;
+
+                    break;
+                }
+
+                case IGNITE_HDR_FULL:
+                {
+                    int32_t len;
+
+                    if (!GetObjectLength(*stream, len))
+                        return;
+
+                    sizeTmp = len;
+
+                    stream->Position(stream->Position() + len);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_DECIMAL:
+                {
+                    Decimal res;
+
+                    utility::ReadDecimal(reader, res);
+
+                    sizeTmp = res.GetLength() + 8;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_DATE:
+                {
+                    reader.ReadDate();
+
+                    sizeTmp = 8;
+
+                    break;
+                }
+
+                case IGNITE_TYPE_TIMESTAMP:
+                {
+                    reader.ReadTimestamp();
+
+                    sizeTmp = 12;
+
+                    break;
+                }
+
+                default:
+                {
+                    // This is a fail case.
+                    return;
+                }
+            }
+
+            type = hdr;
+            startPos = startPosTmp;
+            endPos = stream->Position();
+            size = sizeTmp;
+        }
+
+        SqlResult Column::ReadToBuffer(ignite::impl::binary::BinaryReaderImpl& reader,
+            app::ApplicationDataBuffer& dataBuf)
+        {
+            using namespace ignite::impl::binary;
+            using namespace ignite::impl::interop;
+
+            if (!IsValid())
+                return SQL_RESULT_ERROR;
+
+            if (GetUnreadDataLength() == 0)
+            {
+                dataBuf.PutNull();
+
+                return SQL_RESULT_NO_DATA;
+            }
+
+            ignite::impl::interop::InteropInputStream* stream = reader.GetStream();
+
+            if (!stream)
+                return SQL_RESULT_ERROR;
+
+            InteropStreamPositionGuard<InteropInputStream> guard(*stream);
+
+            stream->Position(startPos);
+
+            switch (type)
+            {
+                case IGNITE_TYPE_BYTE:
+                {
+                    dataBuf.PutInt8(reader.ReadInt8());
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_SHORT:
+                case IGNITE_TYPE_CHAR:
+                {
+                    dataBuf.PutInt16(reader.ReadInt16());
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_INT:
+                {
+                    dataBuf.PutInt32(reader.ReadInt32());
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_LONG:
+                {
+                    dataBuf.PutInt64(reader.ReadInt64());
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_FLOAT:
+                {
+                    dataBuf.PutFloat(reader.ReadFloat());
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_DOUBLE:
+                {
+                    dataBuf.PutDouble(reader.ReadDouble());
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_BOOL:
+                {
+                    dataBuf.PutInt8(reader.ReadBool() ? 1 : 0);
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_STRING:
+                {
+                    std::string str;
+                    utility::ReadString(reader, str);
+
+                    int32_t written = dataBuf.PutString(str.substr(offset));
+
+                    IncreaseOffset(written);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_UUID:
+                {
+                    Guid guid = reader.ReadGuid();
+
+                    dataBuf.PutGuid(guid);
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_HDR_NULL:
+                {
+                    dataBuf.PutNull();
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_HDR_FULL:
+                {
+                    int32_t len;
+
+                    if (!GetObjectLength(*stream, len))
+                        return SQL_RESULT_ERROR;
+
+                    std::vector<int8_t> data(len);
+
+                    stream->ReadInt8Array(&data[0], static_cast<int32_t>(data.size()));
+
+                    int32_t written = dataBuf.PutBinaryData(data.data() + offset, static_cast<size_t>(len - offset));
+
+                    IncreaseOffset(written);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_DECIMAL:
+                {
+                    Decimal res;
+
+                    utility::ReadDecimal(reader, res);
+
+                    dataBuf.PutDecimal(res);
+
+                    IncreaseOffset(size);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_DATE:
+                {
+                    Date date = reader.ReadDate();
+
+                    dataBuf.PutDate(date);
+
+                    break;
+                }
+
+                case IGNITE_TYPE_TIMESTAMP:
+                {
+                    Timestamp ts = reader.ReadTimestamp();
+
+                    dataBuf.PutTimestamp(ts);
+
+                    break;
+                }
+
+                default:
+                {
+                    // This is a fail case. Return false.
+                    return SQL_RESULT_ERROR;
+                }
+            }
+
+            return SQL_RESULT_SUCCESS;
+        }
+
+        void Column::IncreaseOffset(int32_t value)
+        {
+            offset += value;
+
+            if (offset > size)
+                offset = size;
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/common_types.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/common_types.cpp b/modules/platforms/cpp/odbc/src/common_types.cpp
new file mode 100644
index 0000000..276d9fd
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/common_types.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 <ignite/impl/binary/binary_common.h>
+
+#include "ignite/odbc/system/odbc_constants.h"
+#include "ignite/odbc/common_types.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        int SqlResultToReturnCode(SqlResult result)
+        {
+            switch (result)
+            {
+                case SQL_RESULT_SUCCESS: 
+                    return SQL_SUCCESS;
+
+                case SQL_RESULT_SUCCESS_WITH_INFO:
+                    return SQL_SUCCESS_WITH_INFO;
+
+                case SQL_RESULT_NO_DATA:
+                    return SQL_NO_DATA;
+
+                case SQL_RESULT_ERROR:
+                default:
+                    return SQL_ERROR;
+            }
+        }
+
+        DiagnosticField DiagnosticFieldToInternal(int16_t field)
+        {
+            switch (field)
+            {
+                case SQL_DIAG_CURSOR_ROW_COUNT:
+                    return IGNITE_SQL_DIAG_HEADER_CURSOR_ROW_COUNT;
+
+                case SQL_DIAG_DYNAMIC_FUNCTION:
+                    return IGNITE_SQL_DIAG_HEADER_DYNAMIC_FUNCTION;
+
+                case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
+                    return IGNITE_SQL_DIAG_HEADER_DYNAMIC_FUNCTION_CODE;
+
+                case SQL_DIAG_NUMBER:
+                    return IGNITE_SQL_DIAG_HEADER_NUMBER;
+
+                case SQL_DIAG_RETURNCODE:
+                    return IGNITE_SQL_DIAG_HEADER_RETURNCODE;
+
+                case SQL_DIAG_ROW_COUNT:
+                    return IGNITE_SQL_DIAG_HEADER_ROW_COUNT;
+
+                case SQL_DIAG_CLASS_ORIGIN:
+                    return IGNITE_SQL_DIAG_STATUS_CLASS_ORIGIN;
+
+                case SQL_DIAG_COLUMN_NUMBER:
+                    return IGNITE_SQL_DIAG_STATUS_COLUMN_NUMBER;
+
+                case SQL_DIAG_CONNECTION_NAME:
+                    return IGNITE_SQL_DIAG_STATUS_CONNECTION_NAME;
+
+                case SQL_DIAG_MESSAGE_TEXT:
+                    return IGNITE_SQL_DIAG_STATUS_MESSAGE_TEXT;
+
+                case SQL_DIAG_NATIVE:
+                    return IGNITE_SQL_DIAG_STATUS_NATIVE;
+
+                case SQL_DIAG_ROW_NUMBER:
+                    return IGNITE_SQL_DIAG_STATUS_ROW_NUMBER;
+
+                case SQL_DIAG_SERVER_NAME:
+                    return IGNITE_SQL_DIAG_STATUS_SERVER_NAME;
+
+                case SQL_DIAG_SQLSTATE:
+                    return IGNITE_SQL_DIAG_STATUS_SQLSTATE;
+
+                case SQL_DIAG_SUBCLASS_ORIGIN:
+                    return IGNITE_SQL_DIAG_STATUS_SUBCLASS_ORIGIN;
+
+                default:
+                    break;
+            }
+
+            return IGNITE_SQL_DIAG_UNKNOWN;
+        }
+
+        EnvironmentAttribute EnvironmentAttributeToInternal(int32_t attr)
+        {
+            switch (attr)
+            {
+                case SQL_ATTR_ODBC_VERSION:
+                    return IGNITE_SQL_ENV_ATTR_ODBC_VERSION;
+
+                case SQL_ATTR_OUTPUT_NTS:
+                    return IGNITE_SQL_ENV_ATTR_OUTPUT_NTS;
+
+                default:
+                    break;
+            }
+
+            return IGNITE_SQL_ENV_ATTR_UNKNOWN;
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/config/configuration.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/config/configuration.cpp b/modules/platforms/cpp/odbc/src/config/configuration.cpp
new file mode 100644
index 0000000..8d57dee
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/config/configuration.cpp
@@ -0,0 +1,251 @@
+/*
+ * 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 <cstring>
+
+#include <string>
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+
+#include "ignite/odbc/utility.h"
+#include "ignite/odbc/config/configuration.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace config
+        {
+            /** Default values for configuration. */
+            namespace dflt
+            {
+                /** Default value for DSN attribute. */
+                const std::string dsn = "Default Apache Ignite DSN";
+
+                /** Default value for Driver attribute. */
+                const std::string driver = "Apache Ignite";
+
+                /** Default value for host attribute. */
+                const std::string host = "localhost";
+
+                /** Default value for port attribute. */
+                const uint16_t port = 10800;
+
+                /** Default value for cache attribute. */
+                const std::string cache = "";
+            }
+
+            /** Connection attribute keywords. */
+            namespace attrkey
+            {
+                /** Connection attribute keyword for DSN attribute. */
+                const std::string dsn = "dsn";
+            
+                /** Connection attribute keyword for Driver attribute. */
+                const std::string driver = "driver";
+
+                /** Connection attribute keyword for server host attribute. */
+                const std::string host = "server";
+
+                /** Connection attribute keyword for server port attribute. */
+                const std::string port = "port";
+
+                /** Connection attribute keyword for cache attribute. */
+                const std::string cache = "cache";
+            }
+
+            Configuration::Configuration() :
+                dsn(dflt::dsn), driver(dflt::driver),
+                host(dflt::host), port(dflt::port),
+                cache(dflt::cache)
+            {
+                // No-op.
+            }
+
+            Configuration::~Configuration()
+            {
+                // No-op.
+            }
+
+            void Configuration::FillFromConnectString(const char* str, size_t len)
+            {
+                ArgumentMap connect_attributes;
+
+                // Ignoring terminating zero byte if present.
+                // Some Driver Managers pass zero-terminated connection string
+                // while others don't.
+                if (len && !str[len - 1])
+                    --len;
+
+                ParseAttributeList(str, len, ';', connect_attributes);
+
+                ArgumentMap::const_iterator it;
+
+                it = connect_attributes.find(attrkey::dsn);
+                if (it != connect_attributes.end())
+                    dsn = it->second;
+                else
+                    dsn.clear();
+
+                it = connect_attributes.find(attrkey::driver);
+                if (it != connect_attributes.end())
+                    driver = it->second;
+                else
+                    driver = dflt::driver;
+
+                it = connect_attributes.find(attrkey::host);
+                if (it != connect_attributes.end())
+                    host = it->second;
+                else
+                    host = dflt::host;
+
+                it = connect_attributes.find(attrkey::port);
+                if (it != connect_attributes.end())
+                    port = atoi(it->second.c_str());
+                else
+                    port = dflt::port;
+
+                it = connect_attributes.find(attrkey::cache);
+                if (it != connect_attributes.end())
+                    cache = it->second;
+                else
+                    cache = dflt::cache;
+            }
+
+            void Configuration::FillFromConnectString(const std::string& str)
+            {
+                FillFromConnectString(str.data(), str.size());
+            }
+
+            std::string Configuration::ToConnectString() const
+            {
+                std::stringstream connect_string_buffer;
+
+                if (!driver.empty())
+                    connect_string_buffer << attrkey::driver << "={" << driver << "};";
+
+                if (!host.empty())
+                    connect_string_buffer << attrkey::host << '=' << host << ';';
+
+                if (port)
+                    connect_string_buffer << attrkey::port << '=' << port << ';';
+
+                if (!dsn.empty())
+                    connect_string_buffer << attrkey::dsn << '=' << dsn << ';';
+
+                if (!cache.empty())
+                    connect_string_buffer << attrkey::cache << '=' << cache << ';';
+
+                return connect_string_buffer.str();
+            }
+
+            void Configuration::FillFromConfigAttributes(const char * attributes)
+            {
+                ArgumentMap config_attributes;
+
+                size_t len = 0;
+
+                // Getting list length. List is terminated by two '\0'.
+                while (attributes[len] || attributes[len + 1])
+                    ++len;
+
+                ++len;
+
+                ParseAttributeList(attributes, len, '\0', config_attributes);
+
+                ArgumentMap::const_iterator it;
+
+                it = config_attributes.find(attrkey::dsn);
+                if (it != config_attributes.end())
+                    dsn = it->second;
+                else
+                    dsn = dflt::dsn;
+
+                it = config_attributes.find(attrkey::driver);
+                if (it != config_attributes.end())
+                    driver = it->second;
+                else
+                    driver.clear();
+
+                it = config_attributes.find(attrkey::host);
+                if (it != config_attributes.end())
+                    host = it->second;
+                else
+                    host.clear();
+
+                it = config_attributes.find(attrkey::port);
+                if (it != config_attributes.end())
+                    port = atoi(it->second.c_str());
+                else
+                    port = 0;
+
+                it = config_attributes.find(attrkey::cache);
+                if (it != config_attributes.end())
+                    cache = it->second;
+                else
+                    cache.clear();
+            }
+
+            void Configuration::ParseAttributeList(const char * str, size_t len, char delimeter, ArgumentMap & args) const
+            {
+                std::string connect_str(str, len);
+                args.clear();
+
+                while (!connect_str.empty())
+                {
+                    size_t attr_begin = connect_str.rfind(delimeter);
+
+                    if (attr_begin == std::string::npos)
+                        attr_begin = 0;
+                    else
+                        ++attr_begin;
+
+                    size_t attr_eq_pos = connect_str.rfind('=');
+
+                    if (attr_eq_pos == std::string::npos)
+                        attr_eq_pos = 0;
+
+                    if (attr_begin < attr_eq_pos)
+                    {
+                        const char* key_begin = connect_str.data() + attr_begin;
+                        const char* key_end = connect_str.data() + attr_eq_pos;
+
+                        const char* value_begin = connect_str.data() + attr_eq_pos + 1;
+                        const char* value_end = connect_str.data() + connect_str.size();
+
+                        std::string key = utility::RemoveSurroundingSpaces(key_begin, key_end);
+                        std::string value = utility::RemoveSurroundingSpaces(value_begin, value_end);
+
+                        utility::IntoLower(key);
+
+                        if (value.front() == '{' && value.back() == '}')
+                            value = value.substr(1, value.size() - 2);
+
+                        args[key] = value;
+                    }
+
+                    if (!attr_begin)
+                        break;
+
+                    connect_str.erase(attr_begin - 1);
+                }
+            }
+        }
+    }
+}
+


Mime
View raw message