ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From voze...@apache.org
Subject [03/31] ignite git commit: IGNITE-1786: Implemented ODBC driver.
Date Thu, 05 May 2016 13:46:40 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/meta/column_meta.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/meta/column_meta.cpp b/modules/platforms/cpp/odbc/src/meta/column_meta.cpp
new file mode 100644
index 0000000..d397618
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/meta/column_meta.cpp
@@ -0,0 +1,274 @@
+/*
+ * 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/odbc/system/odbc_constants.h"
+#include "ignite/odbc/meta/column_meta.h"
+#include "ignite/odbc/type_traits.h"
+#include "ignite/odbc/common_types.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace meta
+        {
+
+#ifdef ODBC_DEBUG
+
+#define DBG_STR_CASE(x) case x: return #x
+
+            const char* ColumnMeta::AttrIdToString(uint16_t id)
+            {
+                switch (id)
+                {
+                    DBG_STR_CASE(SQL_DESC_LABEL);
+                    DBG_STR_CASE(SQL_DESC_BASE_COLUMN_NAME);
+                    DBG_STR_CASE(SQL_DESC_NAME);
+                    DBG_STR_CASE(SQL_DESC_TABLE_NAME);
+                    DBG_STR_CASE(SQL_DESC_BASE_TABLE_NAME);
+                    DBG_STR_CASE(SQL_DESC_SCHEMA_NAME);
+                    DBG_STR_CASE(SQL_DESC_CATALOG_NAME);
+                    DBG_STR_CASE(SQL_DESC_LITERAL_PREFIX);
+                    DBG_STR_CASE(SQL_DESC_LITERAL_SUFFIX);
+                    DBG_STR_CASE(SQL_DESC_TYPE_NAME);
+                    DBG_STR_CASE(SQL_DESC_LOCAL_TYPE_NAME);
+                    DBG_STR_CASE(SQL_DESC_FIXED_PREC_SCALE);
+                    DBG_STR_CASE(SQL_DESC_AUTO_UNIQUE_VALUE);
+                    DBG_STR_CASE(SQL_DESC_CASE_SENSITIVE);
+                    DBG_STR_CASE(SQL_DESC_CONCISE_TYPE);
+                    DBG_STR_CASE(SQL_DESC_TYPE);
+                    DBG_STR_CASE(SQL_DESC_DISPLAY_SIZE);
+                    DBG_STR_CASE(SQL_DESC_LENGTH);
+                    DBG_STR_CASE(SQL_DESC_OCTET_LENGTH);
+                    DBG_STR_CASE(SQL_DESC_NULLABLE);
+                    DBG_STR_CASE(SQL_DESC_NUM_PREC_RADIX);
+                    DBG_STR_CASE(SQL_DESC_PRECISION);
+                    DBG_STR_CASE(SQL_DESC_SCALE);
+                    DBG_STR_CASE(SQL_DESC_SEARCHABLE);
+                    DBG_STR_CASE(SQL_DESC_UNNAMED);
+                    DBG_STR_CASE(SQL_DESC_UNSIGNED);
+                    DBG_STR_CASE(SQL_DESC_UPDATABLE);
+                default:
+                    break;
+                }
+                return "<< UNKNOWN ID >>";
+            }
+
+#undef DBG_STR_CASE
+
+#endif
+
+            void ColumnMeta::Read(ignite::impl::binary::BinaryReaderImpl& reader)
+            {
+                utility::ReadString(reader, schemaName);
+                utility::ReadString(reader, tableName);
+                utility::ReadString(reader, columnName);
+
+                dataType = reader.ReadInt8();
+            }
+
+            bool ColumnMeta::GetAttribute(uint16_t fieldId, std::string& value) const 
+            {
+                using namespace ignite::impl::binary;
+
+                switch (fieldId)
+                {
+                    case SQL_DESC_LABEL:
+                    case SQL_DESC_BASE_COLUMN_NAME:
+                    case SQL_DESC_NAME:
+                    {
+                        value = columnName;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_TABLE_NAME:
+                    case SQL_DESC_BASE_TABLE_NAME:
+                    {
+                        value = tableName;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_SCHEMA_NAME:
+                    {
+                        value = schemaName;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_CATALOG_NAME:
+                    {
+                        value.clear();
+
+                        return true;
+                    }
+
+                    case SQL_DESC_LITERAL_PREFIX:
+                    case SQL_DESC_LITERAL_SUFFIX:
+                    {
+                        if (dataType == IGNITE_TYPE_STRING)
+                            value = "'";
+                        else
+                            value.clear();
+
+                        return true;
+                    }
+
+                    case SQL_DESC_TYPE_NAME:
+                    case SQL_DESC_LOCAL_TYPE_NAME:
+                    {
+                        value = type_traits::BinaryTypeToSqlTypeName(dataType);
+
+                        return true;
+                    }
+
+                    default:
+                        return false;
+                }
+            }
+
+            bool ColumnMeta::GetAttribute(uint16_t fieldId, SqlLen& value) const
+            {
+                using namespace ignite::impl::binary;
+
+                switch (fieldId)
+                {
+                    case SQL_DESC_FIXED_PREC_SCALE:
+                    case SQL_DESC_AUTO_UNIQUE_VALUE:
+                    {
+                        value = SQL_FALSE;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_CASE_SENSITIVE:
+                    {
+                        if (dataType == IGNITE_TYPE_STRING)
+                            value = SQL_TRUE;
+                        else
+                            value = SQL_FALSE;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_CONCISE_TYPE:
+                    case SQL_DESC_TYPE:
+                    {
+                        value = type_traits::BinaryToSqlType(dataType);
+
+                        return true;
+                    }
+
+                    case SQL_DESC_DISPLAY_SIZE:
+                    {
+                        value = type_traits::BinaryTypeDisplaySize(dataType);
+
+                        return true;
+                    }
+
+                    case SQL_DESC_LENGTH:
+                    case SQL_DESC_OCTET_LENGTH:
+                    {
+                        value = type_traits::BinaryTypeTransferLength(dataType);
+
+                        return true;
+                    }
+
+                    case SQL_DESC_NULLABLE:
+                    {
+                        value = type_traits::BinaryTypeNullability(dataType);
+
+                        return true;
+                    }
+
+                    case SQL_DESC_NUM_PREC_RADIX:
+                    {
+                        value = type_traits::BinaryTypeNumPrecRadix(dataType);
+
+                        return true;
+                    }
+
+                    case SQL_DESC_PRECISION:
+                    {
+                        value = type_traits::BinaryTypeColumnSize(dataType);
+
+                        return true;
+                    }
+
+                    case SQL_DESC_SCALE:
+                    {
+                        value = type_traits::BinaryTypeDecimalDigits(dataType);
+
+                        if (value < 0)
+                            value = 0;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_SEARCHABLE:
+                    {
+                        value = SQL_PRED_BASIC;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_UNNAMED:
+                    {
+                        value = columnName.empty() ? SQL_UNNAMED : SQL_NAMED;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_UNSIGNED:
+                    {
+                        value = type_traits::BinaryTypeUnsigned(dataType) ? SQL_TRUE : SQL_FALSE;
+
+                        return true;
+                    }
+
+                    case SQL_DESC_UPDATABLE:
+                    {
+                        // We do not support update for now so just set all
+                        // columns to readonly.
+                        value = SQL_ATTR_READONLY;
+
+                        return true;
+                    }
+
+                    default:
+                        return false;
+                }
+            }
+
+            void ReadColumnMetaVector(ignite::impl::binary::BinaryReaderImpl& reader, ColumnMetaVector& meta)
+            {
+                int32_t metaNum = reader.ReadInt32();
+
+                meta.clear();
+                meta.reserve(static_cast<size_t>(metaNum));
+
+                for (int32_t i = 0; i < metaNum; ++i)
+                {
+                    meta.push_back(ColumnMeta());
+
+                    meta.back().Read(reader);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/meta/table_meta.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/meta/table_meta.cpp b/modules/platforms/cpp/odbc/src/meta/table_meta.cpp
new file mode 100644
index 0000000..71ced8f
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/meta/table_meta.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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/odbc/meta/table_meta.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace meta
+        {
+            void TableMeta::Read(ignite::impl::binary::BinaryReaderImpl & reader)
+            {
+                utility::ReadString(reader, catalogName);
+                utility::ReadString(reader, schemaName);
+                utility::ReadString(reader, tableName);
+                utility::ReadString(reader, tableType);
+            }
+
+            void ReadTableMetaVector(ignite::impl::binary::BinaryReaderImpl& reader, TableMetaVector& meta)
+            {
+                int32_t metaNum = reader.ReadInt32();
+
+                meta.clear();
+                meta.reserve(static_cast<size_t>(metaNum));
+
+                for (int32_t i = 0; i < metaNum; ++i)
+                {
+                    meta.push_back(TableMeta());
+
+                    meta.back().Read(reader);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/odbc.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/odbc.cpp b/modules/platforms/cpp/odbc/src/odbc.cpp
new file mode 100644
index 0000000..53717c7
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/odbc.cpp
@@ -0,0 +1,1364 @@
+/*
+ * 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 <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#include "ignite/odbc/utility.h"
+#include "ignite/odbc/system/odbc_constants.h"
+
+#include "ignite/odbc/config/configuration.h"
+#include "ignite/odbc/type_traits.h"
+#include "ignite/odbc/environment.h"
+#include "ignite/odbc/connection.h"
+#include "ignite/odbc/statement.h"
+#include "ignite/odbc.h"
+
+namespace ignite
+{
+
+    BOOL ConfigDSN(HWND     hwndParent,
+                   WORD     req,
+                   LPCSTR   driver,
+                   LPCSTR   attributes)
+    {
+        LOG_MSG("ConfigDSN called\n");
+
+        ignite::odbc::config::Configuration config;
+
+        config.FillFromConfigAttributes(attributes);
+
+        if (!SQLValidDSN(config.GetDsn().c_str()))
+            return SQL_FALSE;
+
+        LOG_MSG("Driver: %s\n", driver);
+        LOG_MSG("Attributes: %s\n", attributes);
+
+        LOG_MSG("DSN: %s\n", config.GetDsn().c_str());
+
+        switch (req)
+        {
+            case ODBC_ADD_DSN:
+            {
+                LOG_MSG("ODBC_ADD_DSN\n");
+
+                return SQLWriteDSNToIni(config.GetDsn().c_str(), driver);
+            }
+
+            case ODBC_CONFIG_DSN:
+            {
+                LOG_MSG("ODBC_CONFIG_DSN\n");
+                break;
+            }
+
+            case ODBC_REMOVE_DSN:
+            {
+                LOG_MSG("ODBC_REMOVE_DSN\n");
+
+                return SQLRemoveDSNFromIni(config.GetDsn().c_str());
+            }
+
+            default:
+            {
+                return SQL_FALSE;
+            }
+        }
+
+        return SQL_TRUE;
+    }
+
+    SQLRETURN SQLGetInfo(SQLHDBC        conn,
+                         SQLUSMALLINT   infoType,
+                         SQLPOINTER     infoValue,
+                         SQLSMALLINT    infoValueMax,
+                         SQLSMALLINT*   length)
+    {
+        using ignite::odbc::Connection;
+        using ignite::odbc::config::ConnectionInfo;
+
+        LOG_MSG("SQLGetInfo called: %d (%s), %p, %d, %p\n",
+                infoType, ConnectionInfo::InfoTypeToString(infoType),
+                infoValue, infoValueMax, length);
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        connection->GetInfo(infoType, infoValue, infoValueMax, length);
+
+        return connection->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result)
+    {
+        //LOG_MSG("SQLAllocHandle called\n");
+        switch (type)
+        {
+            case SQL_HANDLE_ENV:
+                return SQLAllocEnv(result);
+
+            case SQL_HANDLE_DBC:
+                return SQLAllocConnect(parent, result);
+
+            case SQL_HANDLE_STMT:
+                return SQLAllocStmt(parent, result);
+
+            case SQL_HANDLE_DESC:
+            default:
+                break;
+        }
+
+        *result = 0;
+        return SQL_ERROR;
+    }
+
+    SQLRETURN SQLAllocEnv(SQLHENV* env)
+    {
+        using ignite::odbc::Environment;
+
+        LOG_MSG("SQLAllocEnv called\n");
+
+        *env = reinterpret_cast<SQLHENV>(new Environment());
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLAllocConnect(SQLHENV env, SQLHDBC* conn)
+    {
+        using ignite::odbc::Environment;
+        using ignite::odbc::Connection;
+
+        LOG_MSG("SQLAllocConnect called\n");
+
+        *conn = SQL_NULL_HDBC;
+
+        Environment *environment = reinterpret_cast<Environment*>(env);
+
+        if (!environment)
+            return SQL_INVALID_HANDLE;
+
+        Connection *connection = environment->CreateConnection();
+
+        if (!connection)
+            return environment->GetDiagnosticRecords().GetReturnCode();
+
+        *conn = reinterpret_cast<SQLHDBC>(connection);
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLAllocStmt(SQLHDBC conn, SQLHSTMT* stmt)
+    {
+        using ignite::odbc::Connection;
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLAllocStmt called\n");
+
+        *stmt = SQL_NULL_HDBC;
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        Statement *statement = connection->CreateStatement();
+
+        *stmt = reinterpret_cast<SQLHSTMT>(statement);
+
+        return connection->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle)
+    {
+        switch (type)
+        {
+            case SQL_HANDLE_ENV:
+                return SQLFreeEnv(handle);
+
+            case SQL_HANDLE_DBC:
+                return SQLFreeConnect(handle);
+
+            case SQL_HANDLE_STMT:
+                return SQLFreeStmt(handle, SQL_DROP);
+
+            case SQL_HANDLE_DESC:
+            default:
+                break;
+        }
+
+        return SQL_ERROR;
+    }
+
+    SQLRETURN SQLFreeEnv(SQLHENV env)
+    {
+        using ignite::odbc::Environment;
+
+        LOG_MSG("SQLFreeEnv called\n");
+
+        Environment *environment = reinterpret_cast<Environment*>(env);
+
+        if (!environment)
+            return SQL_INVALID_HANDLE;
+
+        delete environment;
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLFreeConnect(SQLHDBC conn)
+    {
+        using ignite::odbc::Connection;
+
+        LOG_MSG("SQLFreeConnect called\n");
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        delete connection;
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT option)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLFreeStmt called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        switch (option)
+        {
+            case SQL_DROP:
+            {
+                delete statement;
+
+                break;
+            }
+
+            case SQL_CLOSE:
+            {
+                return SQLCloseCursor(stmt);
+            }
+
+            case SQL_UNBIND:
+            {
+                statement->UnbindAllColumns();
+
+                break;
+            }
+
+            case SQL_RESET_PARAMS:
+            {
+                statement->UnbindAllParameters();
+
+                break;
+            }
+
+            default:
+                return SQL_ERROR;
+        }
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLCloseCursor(SQLHSTMT stmt)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLCloseCursor called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        statement->Close();
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLDriverConnect(SQLHDBC      conn,
+                               SQLHWND      windowHandle,
+                               SQLCHAR*     inConnectionString,
+                               SQLSMALLINT  inConnectionStringLen,
+                               SQLCHAR*     outConnectionString,
+                               SQLSMALLINT  outConnectionStringBufferLen,
+                               SQLSMALLINT* outConnectionStringLen,
+                               SQLUSMALLINT driverCompletion)
+    {
+        using ignite::odbc::Connection;
+        using ignite::odbc::diagnostic::DiagnosticRecordStorage;
+        using ignite::utility::SqlStringToString;
+        using ignite::utility::CopyStringToBuffer;
+
+        UNREFERENCED_PARAMETER(windowHandle);
+
+        LOG_MSG("SQLDriverConnect called\n");
+        LOG_MSG("Connection String: [%s]\n", inConnectionString);
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        std::string connectStr = SqlStringToString(inConnectionString, inConnectionStringLen);
+
+        ignite::odbc::config::Configuration config;
+
+        config.FillFromConnectString(connectStr);
+
+        connection->Establish(config.GetHost(), config.GetPort(), config.GetCache());
+
+        const DiagnosticRecordStorage& diag = connection->GetDiagnosticRecords();
+
+        if (!diag.IsSuccessful())
+            return diag.GetReturnCode();
+
+        std::string outConnectStr = config.ToConnectString();
+
+        size_t reslen = CopyStringToBuffer(outConnectStr,
+            reinterpret_cast<char*>(outConnectionString),
+            static_cast<size_t>(outConnectionStringBufferLen));
+
+        if (outConnectionStringLen)
+            *outConnectionStringLen = static_cast<SQLSMALLINT>(reslen);
+
+        LOG_MSG("%s\n", outConnectionString);
+
+        return diag.GetReturnCode();
+    }
+
+    SQLRETURN SQLConnect(SQLHDBC        conn,
+                         SQLCHAR*       serverName,
+                         SQLSMALLINT    serverNameLen,
+                         SQLCHAR*       userName,
+                         SQLSMALLINT    userNameLen,
+                         SQLCHAR*       auth,
+                         SQLSMALLINT    authLen)
+    {
+        using ignite::odbc::Connection;
+        using ignite::odbc::diagnostic::DiagnosticRecordStorage;
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLConnect called\n");
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        std::string server = SqlStringToString(serverName, serverNameLen);
+
+        connection->Establish(server);
+
+        return connection->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLDisconnect(SQLHDBC conn)
+    {
+        using ignite::odbc::Connection;
+
+        LOG_MSG("SQLDisconnect called\n");
+
+        Connection *connection = reinterpret_cast<Connection*>(conn);
+
+        if (!connection)
+            return SQL_INVALID_HANDLE;
+
+        connection->Release();
+
+        return connection->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLPrepare(SQLHSTMT stmt, SQLCHAR* query, SQLINTEGER queryLen)
+    {
+        using ignite::odbc::Statement;
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLPrepare called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        std::string sql = SqlStringToString(query, queryLen);
+
+        LOG_MSG("SQL: %s\n", sql.c_str());
+
+        statement->PrepareSqlQuery(sql);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLExecute(SQLHSTMT stmt)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLExecute called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        statement->ExecuteSqlQuery();
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLExecDirect(SQLHSTMT stmt, SQLCHAR* query, SQLINTEGER queryLen)
+    {
+        using ignite::odbc::Statement;
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLExecDirect called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        std::string sql = SqlStringToString(query, queryLen);
+
+        LOG_MSG("SQL: %s\n", sql.c_str());
+
+        statement->ExecuteSqlQuery(sql);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLBindCol(SQLHSTMT       stmt,
+                         SQLUSMALLINT   colNum,
+                         SQLSMALLINT    targetType,
+                         SQLPOINTER     targetValue,
+                         SQLLEN         bufferLength,
+                         SQLLEN*        strLengthOrIndicator)
+    {
+        using namespace ignite::odbc::type_traits;
+
+        using ignite::odbc::Statement;
+        using ignite::odbc::app::ApplicationDataBuffer;
+
+        LOG_MSG("SQLBindCol called: index=%d, type=%d\n", colNum, targetType);
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        IgniteSqlType driverType = ToDriverType(targetType);
+
+        if (driverType == IGNITE_ODBC_C_TYPE_UNSUPPORTED)
+            return SQL_ERROR;
+
+        if (bufferLength < 0)
+            return SQL_ERROR;
+
+        if (targetValue || strLengthOrIndicator)
+        {
+            ApplicationDataBuffer dataBuffer(driverType, targetValue, bufferLength, strLengthOrIndicator);
+
+            statement->BindColumn(colNum, dataBuffer);
+        }
+        else
+            statement->UnbindColumn(colNum);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLFetch(SQLHSTMT stmt)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLFetch called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        statement->FetchRow();
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLFetchScroll(SQLHSTMT stmt, SQLSMALLINT orientation, SQLLEN offset)
+    {
+        LOG_MSG("SQLFetchScroll called\n");
+        LOG_MSG("Orientation: %d, Offset: %d\n", orientation, offset);
+
+        if (orientation != SQL_FETCH_NEXT)
+            return SQL_ERROR;
+
+        return SQLFetch(stmt);
+    }
+
+    SQLRETURN SQLExtendedFetch(SQLHSTMT         stmt,
+                               SQLUSMALLINT     orientation,
+                               SQLLEN           offset,
+                               SQLULEN*         rowCount,
+                               SQLUSMALLINT*    rowStatusArray)
+    {
+        LOG_MSG("SQLExtendedFetch called\n");
+
+        SQLRETURN res = SQLFetchScroll(stmt, orientation, offset);
+
+        if (res == SQL_SUCCESS || res == SQL_NO_DATA)
+        {
+            if (rowCount)
+                *rowCount = 1;
+
+            if (rowStatusArray)
+                rowStatusArray[0] = SQL_ROW_SUCCESS;
+        }
+
+        return res;
+    }
+
+    SQLRETURN SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *columnNum)
+    {
+        using ignite::odbc::Statement;
+        using ignite::odbc::meta::ColumnMetaVector;
+
+        LOG_MSG("SQLNumResultCols called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        int32_t res = statement->GetColumnNumber();
+
+        *columnNum = static_cast<SQLSMALLINT>(res);
+
+        LOG_MSG("columnNum: %d\n", *columnNum);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLTables(SQLHSTMT    stmt,
+                        SQLCHAR*    catalogName,
+                        SQLSMALLINT catalogNameLen,
+                        SQLCHAR*    schemaName,
+                        SQLSMALLINT schemaNameLen,
+                        SQLCHAR*    tableName,
+                        SQLSMALLINT tableNameLen,
+                        SQLCHAR*    tableType,
+                        SQLSMALLINT tableTypeLen)
+    {
+        using ignite::odbc::Statement;
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLTables called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        std::string catalog = SqlStringToString(catalogName, catalogNameLen);
+        std::string schema = SqlStringToString(schemaName, schemaNameLen);
+        std::string table = SqlStringToString(tableName, tableNameLen);
+        std::string tableTypeStr = SqlStringToString(tableType, tableTypeLen);
+
+        LOG_MSG("catalog: %s\n", catalog.c_str());
+        LOG_MSG("schema: %s\n", schema.c_str());
+        LOG_MSG("table: %s\n", table.c_str());
+        LOG_MSG("tableType: %s\n", tableTypeStr.c_str());
+
+        statement->ExecuteGetTablesMetaQuery(catalog, schema, table, tableTypeStr);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLColumns(SQLHSTMT       stmt,
+                         SQLCHAR*       catalogName,
+                         SQLSMALLINT    catalogNameLen,
+                         SQLCHAR*       schemaName,
+                         SQLSMALLINT    schemaNameLen,
+                         SQLCHAR*       tableName,
+                         SQLSMALLINT    tableNameLen,
+                         SQLCHAR*       columnName,
+                         SQLSMALLINT    columnNameLen)
+    {
+        using ignite::odbc::Statement;
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLColumns called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        std::string catalog = SqlStringToString(catalogName, catalogNameLen);
+        std::string schema = SqlStringToString(schemaName, schemaNameLen);
+        std::string table = SqlStringToString(tableName, tableNameLen);
+        std::string column = SqlStringToString(columnName, columnNameLen);
+
+        LOG_MSG("catalog: %s\n", catalog.c_str());
+        LOG_MSG("schema: %s\n", schema.c_str());
+        LOG_MSG("table: %s\n", table.c_str());
+        LOG_MSG("column: %s\n", column.c_str());
+
+        statement->ExecuteGetColumnsMetaQuery(schema, table, column);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLMoreResults(SQLHSTMT stmt)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLMoreResults called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        //TODO: reset diagnostic here.
+        return statement->DataAvailable() ? SQL_SUCCESS : SQL_NO_DATA;
+    }
+
+    SQLRETURN SQLBindParameter(SQLHSTMT     stmt,
+                               SQLUSMALLINT paramIdx,
+                               SQLSMALLINT  ioType,
+                               SQLSMALLINT  bufferType,
+                               SQLSMALLINT  paramSqlType,
+                               SQLULEN      columnSize,
+                               SQLSMALLINT  decDigits,
+                               SQLPOINTER   buffer,
+                               SQLLEN       bufferLen,
+                               SQLLEN*      resLen)
+    {
+        using namespace ignite::odbc::type_traits;
+
+        using ignite::odbc::Statement;
+        using ignite::odbc::app::ApplicationDataBuffer;
+        using ignite::odbc::app::Parameter;
+        using ignite::odbc::type_traits::IsSqlTypeSupported;
+
+        LOG_MSG("SQLBindParameter called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        if (ioType != SQL_PARAM_INPUT)
+            return SQL_ERROR;
+
+        if (*resLen == SQL_DATA_AT_EXEC || *resLen <= SQL_LEN_DATA_AT_EXEC_OFFSET)
+            return SQL_ERROR;
+
+        if (!IsSqlTypeSupported(paramSqlType))
+            return SQL_ERROR;
+
+        IgniteSqlType driverType = ToDriverType(bufferType);
+
+        if (driverType == IGNITE_ODBC_C_TYPE_UNSUPPORTED)
+            return SQL_ERROR;
+
+        if (buffer)
+        {
+            ApplicationDataBuffer dataBuffer(driverType, buffer, bufferLen, resLen);
+
+            Parameter param(dataBuffer, paramSqlType, columnSize, decDigits);
+
+            statement->BindParameter(paramIdx, param);
+        }
+        else
+            statement->UnbindParameter(paramIdx);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLNativeSql(SQLHDBC      conn,
+                           SQLCHAR*     inQuery,
+                           SQLINTEGER   inQueryLen,
+                           SQLCHAR*     outQueryBuffer,
+                           SQLINTEGER   outQueryBufferLen,
+                           SQLINTEGER*  outQueryLen)
+    {
+        using namespace ignite::utility;
+
+        LOG_MSG("SQLNativeSql called\n");
+
+        std::string in = SqlStringToString(inQuery, inQueryLen);
+
+        CopyStringToBuffer(in, reinterpret_cast<char*>(outQueryBuffer),
+            static_cast<size_t>(outQueryBufferLen));
+
+        *outQueryLen = std::min(outQueryBufferLen, static_cast<SQLINTEGER>(in.size()));
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLColAttribute(SQLHSTMT        stmt,
+                              SQLUSMALLINT    columnNum,
+                              SQLUSMALLINT    fieldId,
+                              SQLPOINTER      strAttr,
+                              SQLSMALLINT     bufferLen,
+                              SQLSMALLINT*    strAttrLen,
+                              SQLLEN*         numericAttr)
+    {
+        using ignite::odbc::Statement;
+        using ignite::odbc::meta::ColumnMetaVector;
+        using ignite::odbc::meta::ColumnMeta;
+
+        LOG_MSG("SQLColAttribute called: %d (%s)\n", fieldId, ColumnMeta::AttrIdToString(fieldId));
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        // This is a special case
+        if (fieldId == SQL_DESC_COUNT)
+        {
+            SQLSMALLINT val = 0;
+
+            SQLRETURN res = SQLNumResultCols(stmt, &val);
+
+            if (res == SQL_SUCCESS)
+                *numericAttr = val;
+
+            return res;
+        }
+
+        statement->GetColumnAttribute(columnNum, fieldId, reinterpret_cast<char*>(strAttr),
+            bufferLen, strAttrLen, numericAttr);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLDescribeCol(SQLHSTMT       stmt,
+                             SQLUSMALLINT   columnNum, 
+                             SQLCHAR*       columnNameBuf,
+                             SQLSMALLINT    columnNameBufLen,
+                             SQLSMALLINT*   columnNameLen,
+                             SQLSMALLINT*   dataType, 
+                             SQLULEN*       columnSize,
+                             SQLSMALLINT*   decimalDigits, 
+                             SQLSMALLINT*   nullable)
+    {
+        using ignite::odbc::Statement;
+        using ignite::odbc::SqlLen;
+
+        LOG_MSG("SQLDescribeCol called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        statement->GetColumnAttribute(columnNum, SQL_DESC_NAME,
+            reinterpret_cast<char*>(columnNameBuf), columnNameBufLen, columnNameLen, 0);
+
+        SqlLen dataTypeRes;
+        SqlLen columnSizeRes;
+        SqlLen decimalDigitsRes;
+        SqlLen nullableRes;
+
+        statement->GetColumnAttribute(columnNum, SQL_DESC_TYPE, 0, 0, 0, &dataTypeRes);
+        statement->GetColumnAttribute(columnNum, SQL_DESC_PRECISION, 0, 0, 0, &columnSizeRes);
+        statement->GetColumnAttribute(columnNum, SQL_DESC_SCALE, 0, 0, 0, &decimalDigitsRes);
+        statement->GetColumnAttribute(columnNum, SQL_DESC_NULLABLE, 0, 0, 0, &nullableRes);
+
+        LOG_MSG("columnNum: %lld\n", columnNum);
+        LOG_MSG("dataTypeRes: %lld\n", dataTypeRes);
+        LOG_MSG("columnSizeRes: %lld\n", columnSizeRes);
+        LOG_MSG("decimalDigitsRes: %lld\n", decimalDigitsRes);
+        LOG_MSG("nullableRes: %lld\n", nullableRes);
+        LOG_MSG("columnNameBuf: %s\n", columnNameBuf);
+        LOG_MSG("columnNameLen: %d\n", *columnNameLen);
+
+        *dataType = static_cast<SQLSMALLINT>(dataTypeRes);
+        *columnSize = static_cast<SQLULEN>(columnSizeRes);
+        *decimalDigits = static_cast<SQLSMALLINT>(decimalDigitsRes);
+        *nullable = static_cast<SQLSMALLINT>(nullableRes);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+
+    SQLRETURN SQLRowCount(SQLHSTMT stmt, SQLLEN* rowCnt)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLRowCount called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        int64_t res = statement->AffectedRows();
+
+        *rowCnt = static_cast<SQLLEN>(res);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    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)
+    {
+        using ignite::odbc::Statement;
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLForeignKeys called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        std::string primaryCatalog = SqlStringToString(primaryCatalogName, primaryCatalogNameLen);
+        std::string primarySchema = SqlStringToString(primarySchemaName, primarySchemaNameLen);
+        std::string primaryTable = SqlStringToString(primaryTableName, primaryTableNameLen);
+        std::string foreignCatalog = SqlStringToString(foreignCatalogName, foreignCatalogNameLen);
+        std::string foreignSchema = SqlStringToString(foreignSchemaName, foreignSchemaNameLen);
+        std::string foreignTable = SqlStringToString(foreignTableName, foreignTableNameLen);
+
+        LOG_MSG("primaryCatalog: %s\n", primaryCatalog.c_str());
+        LOG_MSG("primarySchema: %s\n", primarySchema.c_str());
+        LOG_MSG("primaryTable: %s\n", primaryTable.c_str());
+        LOG_MSG("foreignCatalog: %s\n", foreignCatalog.c_str());
+        LOG_MSG("foreignSchema: %s\n", foreignSchema.c_str());
+        LOG_MSG("foreignTable: %s\n", foreignTable.c_str());
+
+        statement->ExecuteGetForeignKeysQuery(primaryCatalog, primarySchema,
+            primaryTable, foreignCatalog, foreignSchema, foreignTable);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLGetStmtAttr(SQLHSTMT       stmt,
+                             SQLINTEGER     attr,
+                             SQLPOINTER     valueBuf,
+                             SQLINTEGER     valueBufLen,
+                             SQLINTEGER*    valueResLen)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLGetStmtAttr called");
+
+    #ifdef ODBC_DEBUG
+        using ignite::odbc::type_traits::StatementAttrIdToString;
+
+        LOG_MSG("Attr: %s (%d)\n", StatementAttrIdToString(attr), attr);
+    #endif //ODBC_DEBUG
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        //TODO: move this logic into Statement.
+        switch (attr)
+        {
+            case SQL_ATTR_APP_ROW_DESC:
+            case SQL_ATTR_APP_PARAM_DESC:
+            case SQL_ATTR_IMP_ROW_DESC:
+            case SQL_ATTR_IMP_PARAM_DESC:
+            {
+                SQLPOINTER *val = reinterpret_cast<SQLPOINTER*>(valueBuf);
+
+                *val = static_cast<SQLPOINTER>(stmt);
+
+                break;
+            }
+
+            case SQL_ATTR_ROW_ARRAY_SIZE:
+            {
+                SQLINTEGER *val = reinterpret_cast<SQLINTEGER*>(valueBuf);
+
+                *val = static_cast<SQLINTEGER>(1);
+
+                break;
+            }
+
+            case SQL_ATTR_ROWS_FETCHED_PTR:
+            {
+                SQLULEN** val = reinterpret_cast<SQLULEN**>(valueBuf);
+
+                *val = reinterpret_cast<SQLULEN*>(statement->GetRowsFetchedPtr());
+
+                break;
+            }
+
+            case SQL_ATTR_ROW_STATUS_PTR:
+            {
+                SQLUSMALLINT** val = reinterpret_cast<SQLUSMALLINT**>(valueBuf);
+
+                *val = reinterpret_cast<SQLUSMALLINT*>(statement->GetRowStatusesPtr());
+
+                break;
+            }
+
+            case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
+            {
+                SQLULEN** val = reinterpret_cast<SQLULEN**>(valueBuf);
+
+                *val = reinterpret_cast<SQLULEN*>(statement->GetParamBindOffsetPtr());
+
+                break;
+            }
+
+            case SQL_ATTR_ROW_BIND_OFFSET_PTR:
+            {
+                SQLULEN** val = reinterpret_cast<SQLULEN**>(valueBuf);
+
+                *val = reinterpret_cast<SQLULEN*>(statement->GetColumnBindOffsetPtr());
+
+                break;
+            }
+
+            default:
+                return SQL_ERROR;
+        }
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLSetStmtAttr(SQLHSTMT    stmt,
+                             SQLINTEGER  attr,
+                             SQLPOINTER  value,
+                             SQLINTEGER  valueLen)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLSetStmtAttr called");
+
+    #ifdef ODBC_DEBUG
+        using ignite::odbc::type_traits::StatementAttrIdToString;
+
+        LOG_MSG("Attr: %s (%d)\n", StatementAttrIdToString(attr), attr);
+    #endif //ODBC_DEBUG
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        //TODO: move this logic into Statement.
+        switch (attr)
+        {
+            case SQL_ATTR_ROW_ARRAY_SIZE:
+            {
+                SQLULEN val = reinterpret_cast<SQLULEN>(value);
+
+                LOG_MSG("Value: %d\n", val);
+
+                if (val != 1)
+                    return SQL_ERROR;
+
+                break;
+            }
+
+            case SQL_ATTR_ROWS_FETCHED_PTR:
+            {
+                statement->SetRowsFetchedPtr(reinterpret_cast<size_t*>(value));
+
+                break;
+            }
+
+            case SQL_ATTR_ROW_STATUS_PTR:
+            {
+                statement->SetRowStatusesPtr(reinterpret_cast<uint16_t*>(value));
+
+                break;
+            }
+
+            case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
+            {
+                statement->SetParamBindOffsetPtr(reinterpret_cast<size_t*>(value));
+
+                break;
+            }
+
+            case SQL_ATTR_ROW_BIND_OFFSET_PTR:
+            {
+                statement->SetColumnBindOffsetPtr(reinterpret_cast<size_t*>(value));
+
+                break;
+            }
+
+            default:
+                return SQL_ERROR;
+        }
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLPrimaryKeys(SQLHSTMT       stmt,
+                             SQLCHAR*       catalogName,
+                             SQLSMALLINT    catalogNameLen,
+                             SQLCHAR*       schemaName,
+                             SQLSMALLINT    schemaNameLen,
+                             SQLCHAR*       tableName,
+                             SQLSMALLINT    tableNameLen)
+    {
+        using ignite::odbc::Statement;
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLPrimaryKeys called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        std::string catalog = SqlStringToString(catalogName, catalogNameLen);
+        std::string schema = SqlStringToString(schemaName, schemaNameLen);
+        std::string table = SqlStringToString(tableName, tableNameLen);
+
+        LOG_MSG("catalog: %s\n", catalog.c_str());
+        LOG_MSG("schema: %s\n", schema.c_str());
+        LOG_MSG("table: %s\n", table.c_str());
+
+        statement->ExecuteGetPrimaryKeysQuery(catalog, schema, table);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLNumParams(SQLHSTMT stmt, SQLSMALLINT* paramCnt)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLNumParams called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        *paramCnt = static_cast<SQLSMALLINT>(statement->GetParametersNumber());
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLGetDiagField(SQLSMALLINT   handleType,
+                              SQLHANDLE     handle,
+                              SQLSMALLINT   recNum,
+                              SQLSMALLINT   diagId,
+                              SQLPOINTER    buffer,
+                              SQLSMALLINT   bufferLen,
+                              SQLSMALLINT*  resLen)
+    {
+        using namespace ignite::odbc;
+        using namespace ignite::odbc::diagnostic;
+        using namespace ignite::odbc::type_traits;
+
+        using ignite::odbc::app::ApplicationDataBuffer;
+
+        LOG_MSG("SQLGetDiagField called: %d\n", recNum);
+
+        SqlLen outResLen;
+        ApplicationDataBuffer outBuffer(IGNITE_ODBC_C_TYPE_DEFAULT, buffer, bufferLen, &outResLen);
+
+        SqlResult result;
+
+        DiagnosticField field = DiagnosticFieldToInternal(diagId);
+
+        switch (handleType)
+        {
+            case SQL_HANDLE_ENV:
+            case SQL_HANDLE_DBC:
+            case SQL_HANDLE_STMT:
+            {
+                Diagnosable *diag = reinterpret_cast<Diagnosable*>(handle);
+
+                result = diag->GetDiagnosticRecords().GetField(recNum, field, outBuffer);
+
+                break;
+            }
+
+            default:
+            {
+                result = SQL_RESULT_NO_DATA;
+                break;
+            }
+        }
+
+        if (result == SQL_RESULT_SUCCESS)
+            *resLen = static_cast<SQLSMALLINT>(outResLen);
+
+        return SqlResultToReturnCode(result);
+    }
+
+    SQLRETURN SQLGetDiagRec(SQLSMALLINT     handleType,
+                            SQLHANDLE       handle,
+                            SQLSMALLINT     recNum,
+                            SQLCHAR*        sqlState,
+                            SQLINTEGER*     nativeError,
+                            SQLCHAR*        msgBuffer,
+                            SQLSMALLINT     msgBufferLen,
+                            SQLSMALLINT*    msgLen)
+    {
+        using namespace ignite::utility;
+        using namespace ignite::odbc;
+        using namespace ignite::odbc::diagnostic;
+        using namespace ignite::odbc::type_traits;
+
+        using ignite::odbc::app::ApplicationDataBuffer;
+
+        LOG_MSG("SQLGetDiagRec called\n");
+
+        const DiagnosticRecordStorage* records = 0;
+
+        switch (handleType)
+        {
+            case SQL_HANDLE_ENV:
+            case SQL_HANDLE_DBC:
+            case SQL_HANDLE_STMT:
+            {
+                Diagnosable *diag = reinterpret_cast<Diagnosable*>(handle);
+
+                records = &diag->GetDiagnosticRecords();
+
+                break;
+            }
+
+            default:
+                break;
+        }
+
+        if (!records || recNum < 1 || recNum > records->GetStatusRecordsNumber())
+            return SQL_NO_DATA;
+
+        const DiagnosticRecord& record = records->GetStatusRecord(recNum);
+
+        if (sqlState)
+            CopyStringToBuffer(record.GetSqlState(), reinterpret_cast<char*>(sqlState), 6);
+
+        if (nativeError)
+            *nativeError = 0;
+
+        SqlLen outResLen;
+        ApplicationDataBuffer outBuffer(IGNITE_ODBC_C_TYPE_CHAR, msgBuffer, msgBufferLen, &outResLen);
+
+        outBuffer.PutString(record.GetMessage());
+
+        *msgLen = static_cast<SQLSMALLINT>(outResLen);
+
+        return SQL_SUCCESS;
+    }
+
+    SQLRETURN SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT type)
+    {
+        using ignite::odbc::Statement;
+
+        LOG_MSG("SQLGetTypeInfo called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        statement->ExecuteGetTypeInfoQuery(static_cast<int16_t>(type));
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLEndTran(SQLSMALLINT handleType, SQLHANDLE handle, SQLSMALLINT completionType)
+    {
+        using namespace ignite::odbc;
+
+        LOG_MSG("SQLEndTran called\n");
+
+        SQLRETURN result;
+
+        switch (handleType)
+        {
+            case SQL_HANDLE_ENV:
+            {
+                Environment *env = reinterpret_cast<Environment*>(handle);
+
+                if (!env)
+                    return SQL_INVALID_HANDLE;
+
+                if (completionType == SQL_COMMIT)
+                    env->TransactionCommit();
+                else
+                    env->TransactionRollback();
+
+                result = env->GetDiagnosticRecords().GetReturnCode();
+
+                break;
+            }
+
+            case SQL_HANDLE_DBC:
+            {
+                Connection *conn = reinterpret_cast<Connection*>(handle);
+
+                if (!conn)
+                    return SQL_INVALID_HANDLE;
+
+                if (completionType == SQL_COMMIT)
+                    conn->TransactionCommit();
+                else
+                    conn->TransactionRollback();
+
+                result = conn->GetDiagnosticRecords().GetReturnCode();
+
+                break;
+            }
+
+            default:
+            {
+                result = SQL_INVALID_HANDLE;
+
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    SQLRETURN SQLGetData(SQLHSTMT       stmt,
+                         SQLUSMALLINT   colNum,
+                         SQLSMALLINT    targetType,
+                         SQLPOINTER     targetValue,
+                         SQLLEN         bufferLength,
+                         SQLLEN*        strLengthOrIndicator)
+    {
+        using namespace ignite::odbc::type_traits;
+
+        using ignite::odbc::Statement;
+        using ignite::odbc::app::ApplicationDataBuffer;
+
+        LOG_MSG("SQLGetData called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        IgniteSqlType driverType = ToDriverType(targetType);
+
+        ApplicationDataBuffer dataBuffer(driverType, targetValue, bufferLength, strLengthOrIndicator);
+
+        statement->GetColumnData(colNum, dataBuffer);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLSetEnvAttr(SQLHENV     env,
+                            SQLINTEGER  attr,
+                            SQLPOINTER  value,
+                            SQLINTEGER  valueLen)
+    {
+        using ignite::odbc::Environment;
+
+        LOG_MSG("SQLSetEnvAttr called\n");
+
+        Environment *environment = reinterpret_cast<Environment*>(env);
+
+        if (!environment)
+            return SQL_INVALID_HANDLE;
+
+        environment->SetAttribute(attr, value, valueLen);
+
+        return environment->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLGetEnvAttr(SQLHENV     env,
+                            SQLINTEGER  attr,
+                            SQLPOINTER  valueBuf,
+                            SQLINTEGER  valueBufLen,
+                            SQLINTEGER* valueResLen)
+    {
+        using namespace ignite::odbc;
+        using namespace ignite::odbc::type_traits;
+
+        using ignite::odbc::app::ApplicationDataBuffer;
+
+        LOG_MSG("SQLGetEnvAttr called\n");
+
+        Environment *environment = reinterpret_cast<Environment*>(env);
+
+        if (!environment)
+            return SQL_INVALID_HANDLE;
+
+        SqlLen outResLen;
+        ApplicationDataBuffer outBuffer(IGNITE_ODBC_C_TYPE_DEFAULT, valueBuf,
+            static_cast<int32_t>(valueBufLen), &outResLen);
+
+        environment->GetAttribute(attr, outBuffer);
+
+        if (valueResLen)
+            *valueResLen = static_cast<SQLSMALLINT>(outResLen);
+
+        return environment->GetDiagnosticRecords().GetReturnCode();
+    }
+
+    SQLRETURN SQLSpecialColumns(SQLHSTMT    stmt,
+                                SQLSMALLINT idType,
+                                SQLCHAR*    catalogName,
+                                SQLSMALLINT catalogNameLen,
+                                SQLCHAR*    schemaName,
+                                SQLSMALLINT schemaNameLen,
+                                SQLCHAR*    tableName,
+                                SQLSMALLINT tableNameLen,
+                                SQLSMALLINT scope,
+                                SQLSMALLINT nullable)
+    {
+        using namespace ignite::odbc;
+
+        using ignite::utility::SqlStringToString;
+
+        LOG_MSG("SQLSpecialColumns called\n");
+
+        Statement *statement = reinterpret_cast<Statement*>(stmt);
+
+        if (!statement)
+            return SQL_INVALID_HANDLE;
+
+        std::string catalog = SqlStringToString(catalogName, catalogNameLen);
+        std::string schema = SqlStringToString(schemaName, schemaNameLen);
+        std::string table = SqlStringToString(tableName, tableNameLen);
+
+        LOG_MSG("catalog: %s\n", catalog.c_str());
+        LOG_MSG("schema: %s\n", schema.c_str());
+        LOG_MSG("table: %s\n", table.c_str());
+
+        statement->ExecuteSpecialColumnsQuery(idType, catalog, schema, table, scope, nullable);
+
+        return statement->GetDiagnosticRecords().GetReturnCode();
+    }
+
+} // namespace ignite;

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
new file mode 100644
index 0000000..5e764a2
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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/type_traits.h"
+#include "ignite/odbc/connection.h"
+#include "ignite/odbc/message.h"
+#include "ignite/odbc/query/column_metadata_query.h"
+
+namespace
+{
+    enum ResultColumn
+    {
+        /** Catalog name. NULL if not applicable to the data source. */
+        TABLE_CAT = 1,
+
+        /** Schema name. NULL if not applicable to the data source. */
+        TABLE_SCHEM,
+
+        /** Table name. */
+        TABLE_NAME,
+
+        /** Column name. */
+        COLUMN_NAME,
+
+        /** SQL data type. */
+        DATA_TYPE,
+
+        /** Data source�dependent data type name. */
+        TYPE_NAME,
+
+        /** Column size. */
+        COLUMN_SIZE,
+
+        /** The length in bytes of data transferred on fetch. */
+        BUFFER_LENGTH,
+
+        /** The total number of significant digits to the right of the decimal point. */
+        DECIMAL_DIGITS,
+
+        /** Precision. */
+        NUM_PREC_RADIX,
+
+        /** Nullability of the data in column. */
+        NULLABLE,
+
+        /** A description of the column. */
+        REMARKS
+    };
+}
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace query
+        {
+            ColumnMetadataQuery::ColumnMetadataQuery(diagnostic::Diagnosable& diag, 
+                Connection& connection, const std::string& schema,
+                const std::string& table, const std::string& column) :
+                Query(diag),
+                connection(connection),
+                schema(schema),
+                table(table),
+                column(column),
+                executed(false),
+                meta(),
+                columnsMeta()
+            {
+                using namespace ignite::impl::binary;
+                using namespace ignite::odbc::type_traits;
+
+                using meta::ColumnMeta;
+
+                columnsMeta.reserve(12);
+
+                const std::string sch("");
+                const std::string tbl("");
+
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_CAT",      IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM",    IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME",     IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME",    IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "DATA_TYPE",      IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "TYPE_NAME",      IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_SIZE",    IGNITE_TYPE_INT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "BUFFER_LENGTH",  IGNITE_TYPE_INT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "DECIMAL_DIGITS", IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "NUM_PREC_RADIX", IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "NULLABLE",       IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "REMARKS",        IGNITE_TYPE_STRING));
+            }
+
+            ColumnMetadataQuery::~ColumnMetadataQuery()
+            {
+                // No-op.
+            }
+
+            SqlResult ColumnMetadataQuery::Execute()
+            {
+                if (executed)
+                    Close();
+
+                SqlResult result = MakeRequestGetColumnsMeta();
+
+                if (result == SQL_RESULT_SUCCESS)
+                {
+                    executed = true;
+
+                    cursor = meta.begin();
+                }
+
+                return result;
+            }
+
+            const meta::ColumnMetaVector& ColumnMetadataQuery::GetMeta() const
+            {
+                return columnsMeta;
+            }
+
+            SqlResult ColumnMetadataQuery::FetchNextRow(app::ColumnBindingMap & columnBindings)
+            {
+                if (!executed)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (cursor == meta.end())
+                    return SQL_RESULT_NO_DATA;
+
+                app::ColumnBindingMap::iterator it;
+
+                for (it = columnBindings.begin(); it != columnBindings.end(); ++it)
+                    GetColumn(it->first, it->second);
+
+                ++cursor;
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            SqlResult ColumnMetadataQuery::GetColumn(uint16_t columnIdx, app::ApplicationDataBuffer & buffer)
+            {
+                if (!executed)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (cursor == meta.end())
+                    return SQL_RESULT_NO_DATA;
+
+                const meta::ColumnMeta& currentColumn = *cursor;
+                uint8_t columnType = currentColumn.GetDataType();
+
+                switch (columnIdx)
+                {
+                    case TABLE_CAT:
+                    {
+                        buffer.PutNull();
+                        break;
+                    }
+
+                    case TABLE_SCHEM:
+                    {
+                        buffer.PutString(currentColumn.GetSchemaName());
+                        break;
+                    }
+
+                    case TABLE_NAME:
+                    {
+                        buffer.PutString(currentColumn.GetTableName());
+                        break;
+                    }
+
+                    case COLUMN_NAME:
+                    {
+                        buffer.PutString(currentColumn.GetColumnName());
+                        break;
+                    }
+
+                    case DATA_TYPE:
+                    {
+                        buffer.PutInt16(type_traits::BinaryToSqlType(columnType));
+                        break;
+                    }
+
+                    case TYPE_NAME:
+                    {
+                        buffer.PutString(type_traits::BinaryTypeToSqlTypeName(currentColumn.GetDataType()));
+                        break;
+                    }
+
+                    case COLUMN_SIZE:
+                    {
+                        buffer.PutInt16(type_traits::BinaryTypeColumnSize(columnType));
+                        break;
+                    }
+
+                    case BUFFER_LENGTH:
+                    {
+                        buffer.PutInt16(type_traits::BinaryTypeTransferLength(columnType));
+                        break;
+                    }
+
+                    case DECIMAL_DIGITS:
+                    {
+                        int32_t decDigits = type_traits::BinaryTypeDecimalDigits(columnType);
+                        if (decDigits < 0)
+                            buffer.PutNull();
+                        else
+                            buffer.PutInt16(static_cast<int16_t>(decDigits));
+                        break;
+                    }
+
+                    case NUM_PREC_RADIX:
+                    {
+                        buffer.PutInt16(type_traits::BinaryTypeNumPrecRadix(columnType));
+                        break;
+                    }
+
+                    case NULLABLE:
+                    {
+                        buffer.PutInt16(type_traits::BinaryTypeNullability(columnType));
+                        break;
+                    }
+
+                    case REMARKS:
+                    {
+                        buffer.PutNull();
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            SqlResult ColumnMetadataQuery::Close()
+            {
+                meta.clear();
+
+                executed = false;
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            bool ColumnMetadataQuery::DataAvailable() const
+            {
+                return cursor != meta.end();
+            }
+
+            int64_t ColumnMetadataQuery::AffectedRows() const
+            {
+                return 0;
+            }
+
+            SqlResult ColumnMetadataQuery::MakeRequestGetColumnsMeta()
+            {
+                QueryGetColumnsMetaRequest req(schema, table, column);
+                QueryGetColumnsMetaResponse rsp;
+
+                try
+                {
+                    connection.SyncMessage(req, rsp);
+                }
+                catch (const IgniteError& err)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, err.GetText());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (rsp.GetStatus() != RESPONSE_STATUS_SUCCESS)
+                {
+                    LOG_MSG("Error: %s\n", rsp.GetError().c_str());
+
+                    diag.AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, rsp.GetError());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                meta = rsp.GetMeta();
+
+                for (size_t i = 0; i < meta.size(); ++i)
+                {
+                    LOG_MSG("[%d] SchemaName:     %s\n", i, meta[i].GetSchemaName().c_str());
+                    LOG_MSG("[%d] TableName:      %s\n", i, meta[i].GetTableName().c_str());
+                    LOG_MSG("[%d] ColumnName:     %s\n", i, meta[i].GetColumnName().c_str());
+                    LOG_MSG("[%d] ColumnType:     %d\n", i, meta[i].GetDataType());
+                    LOG_MSG("\n");
+                }
+
+                return SQL_RESULT_SUCCESS;
+            }
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/query/data_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/data_query.cpp b/modules/platforms/cpp/odbc/src/query/data_query.cpp
new file mode 100644
index 0000000..e96f1da
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -0,0 +1,278 @@
+/*
+ * 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/odbc/connection.h"
+#include "ignite/odbc/message.h"
+#include "ignite/odbc/query/data_query.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace query
+        {
+            DataQuery::DataQuery(diagnostic::Diagnosable& diag,
+                Connection& connection, const std::string& sql,
+                const app::ParameterBindingMap& params) :
+                Query(diag),
+                connection(connection),
+                sql(sql),
+                params(params)
+            {
+                // No-op.
+            }
+
+            DataQuery::~DataQuery()
+            {
+                Close();
+            }
+            
+            SqlResult DataQuery::Execute()
+            {
+                if (cursor.get())
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query cursor is in open state already.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                return MakeRequestExecute();
+            }
+
+            const meta::ColumnMetaVector & DataQuery::GetMeta() const
+            {
+                return resultMeta;
+            }
+
+            SqlResult DataQuery::FetchNextRow(app::ColumnBindingMap& columnBindings)
+            {
+                if (!cursor.get())
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (!cursor->HasData())
+                    return SQL_RESULT_NO_DATA;
+
+                cursor->Increment();
+
+                if (cursor->NeedDataUpdate())
+                {
+                    SqlResult result = MakeRequestFetch();
+
+                    if (result != SQL_RESULT_SUCCESS)
+                        return result;
+                }
+
+                if (!cursor->HasData())
+                    return SQL_RESULT_NO_DATA;
+
+                Row* row = cursor->GetRow();
+
+                if (!row)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, "Unknown error.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                for (int32_t i = 1; i < row->GetSize() + 1; ++i)
+                {
+                    app::ColumnBindingMap::iterator it = columnBindings.find(i);
+
+                    if (it == columnBindings.end())
+                        continue;
+
+                    SqlResult result = row->ReadColumnToBuffer(i, it->second);
+
+                    if (result == SQL_RESULT_ERROR)
+                    {
+                        diag.AddStatusRecord(SQL_STATE_01S01_ERROR_IN_ROW, "Can not retrieve row column.", 0, i);
+
+                        return SQL_RESULT_ERROR;
+                    }
+                }
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            SqlResult DataQuery::GetColumn(uint16_t columnIdx, app::ApplicationDataBuffer& buffer)
+            {
+                if (!cursor.get())
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                Row* row = cursor->GetRow();
+
+                if (!row)
+                    return SQL_RESULT_NO_DATA;
+
+                SqlResult result = row->ReadColumnToBuffer(columnIdx, buffer);
+
+                if (result == SQL_RESULT_ERROR)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, "Unknown column type.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                return result;
+            }
+
+            SqlResult DataQuery::Close()
+            {
+                if (!cursor.get())
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query cursor is not in open state.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                SqlResult result = MakeRequestClose();
+
+                if (result == SQL_RESULT_SUCCESS)
+                    cursor.reset();
+
+                return result;
+            }
+
+            bool DataQuery::DataAvailable() const
+            {
+                return cursor.get() && cursor->HasData();
+            }
+
+            int64_t DataQuery::AffectedRows() const
+            {
+                // We are only support SELECT statements so we can not affect any row.
+                return 0;
+            }
+
+            SqlResult DataQuery::MakeRequestExecute()
+            {
+                const std::string& cacheName = connection.GetCache();
+
+                QueryExecuteRequest req(cacheName, sql, params);
+                QueryExecuteResponse rsp;
+
+                try
+                {
+                    connection.SyncMessage(req, rsp);
+                }
+                catch (const IgniteError& err)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, err.GetText());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (rsp.GetStatus() != RESPONSE_STATUS_SUCCESS)
+                {
+                    LOG_MSG("Error: %s\n", rsp.GetError().c_str());
+
+                    diag.AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, rsp.GetError());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                cursor.reset(new Cursor(rsp.GetQueryId()));
+
+                resultMeta.assign(rsp.GetMeta().begin(), rsp.GetMeta().end());
+
+                LOG_MSG("Query id: %lld\n", cursor->GetQueryId());
+
+                for (size_t i = 0; i < rsp.GetMeta().size(); ++i)
+                {
+                    LOG_MSG("[%d] SchemaName:     %s\n", i, rsp.GetMeta()[i].GetSchemaName().c_str());
+                    LOG_MSG("[%d] TypeName:       %s\n", i, rsp.GetMeta()[i].GetTableName().c_str());
+                    LOG_MSG("[%d] ColumnName:     %s\n", i, rsp.GetMeta()[i].GetColumnName().c_str());
+                    LOG_MSG("[%d] ColumnType:     %d\n", i, rsp.GetMeta()[i].GetDataType());
+                    LOG_MSG("\n");
+                }
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            SqlResult DataQuery::MakeRequestClose()
+            {
+                QueryCloseRequest req(cursor->GetQueryId());
+                QueryCloseResponse rsp;
+
+                try
+                {
+                    connection.SyncMessage(req, rsp);
+                }
+                catch (const IgniteError& err)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, err.GetText());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                LOG_MSG("Query id: %lld\n", rsp.GetQueryId());
+
+                if (rsp.GetStatus() != RESPONSE_STATUS_SUCCESS)
+                {
+                    LOG_MSG("Error: %s\n", rsp.GetError().c_str());
+
+                    diag.AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, rsp.GetError());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            SqlResult DataQuery::MakeRequestFetch()
+            {
+                std::auto_ptr<ResultPage> resultPage(new ResultPage());
+
+                QueryFetchRequest req(cursor->GetQueryId(), ResultPage::DEFAULT_SIZE);
+                QueryFetchResponse rsp(*resultPage);
+
+                try
+                {
+                    connection.SyncMessage(req, rsp);
+                }
+                catch (const IgniteError& err)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, err.GetText());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (rsp.GetStatus() != RESPONSE_STATUS_SUCCESS)
+                {
+                    LOG_MSG("Error: %s\n", rsp.GetError().c_str());
+
+                    diag.AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, rsp.GetError());
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                cursor->UpdateData(resultPage);
+
+                return SQL_RESULT_SUCCESS;
+            }
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/query/foreign_keys_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/foreign_keys_query.cpp b/modules/platforms/cpp/odbc/src/query/foreign_keys_query.cpp
new file mode 100644
index 0000000..4fefa22
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/query/foreign_keys_query.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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/type_traits.h"
+#include "ignite/odbc/connection.h"
+#include "ignite/odbc/message.h"
+#include "ignite/odbc/query/foreign_keys_query.h"
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace query
+        {
+            ForeignKeysQuery::ForeignKeysQuery(diagnostic::Diagnosable& diag, Connection& connection,
+                const std::string& primaryCatalog, const std::string& primarySchema,
+                const std::string& primaryTable, const std::string& foreignCatalog,
+                const std::string& foreignSchema, const std::string& foreignTable) :
+                Query(diag),
+                connection(connection),
+                primaryCatalog(primaryCatalog),
+                primarySchema(primarySchema),
+                primaryTable(primaryTable),
+                foreignCatalog(foreignCatalog),
+                foreignSchema(foreignSchema),
+                foreignTable(foreignTable),
+                executed(false),
+                columnsMeta()
+            {
+                using namespace ignite::impl::binary;
+                using namespace ignite::odbc::type_traits;
+
+                using meta::ColumnMeta;
+
+                columnsMeta.reserve(14);
+
+                const std::string sch("");
+                const std::string tbl("");
+
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_CAT",   IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_SCHEM", IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_NAME",  IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "PKCOLUMN_NAME", IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_CAT",   IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_SCHEM", IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_NAME",  IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "FKCOLUMN_NAME", IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ",       IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "UPDATE_RULE",   IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "DELETE_RULE",   IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "FK_NAME",       IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME",       IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "DEFERRABILITY", IGNITE_TYPE_SHORT));
+            }
+
+            ForeignKeysQuery::~ForeignKeysQuery()
+            {
+                // No-op.
+            }
+
+            SqlResult ForeignKeysQuery::Execute()
+            {
+                executed = true;
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            const meta::ColumnMetaVector & ForeignKeysQuery::GetMeta() const
+            {
+                return columnsMeta;
+            }
+
+            SqlResult ForeignKeysQuery::FetchNextRow(app::ColumnBindingMap & columnBindings)
+            {
+                if (!executed)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                return SQL_RESULT_NO_DATA;
+            }
+
+            SqlResult ForeignKeysQuery::GetColumn(uint16_t columnIdx, app::ApplicationDataBuffer& buffer)
+            {
+                if (!executed)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                return SQL_RESULT_NO_DATA;
+            }
+
+            SqlResult ForeignKeysQuery::Close()
+            {
+                executed = false;
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            bool ForeignKeysQuery::DataAvailable() const
+            {
+                return false;
+            }
+            int64_t ForeignKeysQuery::AffectedRows() const
+            {
+                return 0;
+            }
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/query/primary_keys_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/primary_keys_query.cpp b/modules/platforms/cpp/odbc/src/query/primary_keys_query.cpp
new file mode 100644
index 0000000..11ff4fa
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/query/primary_keys_query.cpp
@@ -0,0 +1,210 @@
+/*
+ * 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/type_traits.h"
+#include "ignite/odbc/connection.h"
+#include "ignite/odbc/message.h"
+#include "ignite/odbc/query/primary_keys_query.h"
+
+namespace
+{
+    enum ResultColumn
+    {
+        /** Catalog name. NULL if not applicable to the data source. */
+        TABLE_CAT = 1,
+
+        /** Schema name. NULL if not applicable to the data source. */
+        TABLE_SCHEM,
+
+        /** Table name. */
+        TABLE_NAME,
+
+        /** Column name. */
+        COLUMN_NAME,
+
+        /** Column sequence number in key. */
+        KEY_SEQ,
+
+        /** Primary key name. */
+        PK_NAME
+    };
+}
+
+namespace ignite
+{
+    namespace odbc
+    {
+        namespace query
+        {
+            PrimaryKeysQuery::PrimaryKeysQuery(diagnostic::Diagnosable& diag,
+                Connection& connection, const std::string& catalog,
+                const std::string& schema, const std::string& table) :
+                Query(diag),
+                connection(connection),
+                catalog(catalog),
+                schema(schema),
+                table(table),
+                executed(false),
+                columnsMeta()
+            {
+                using namespace ignite::impl::binary;
+                using namespace ignite::odbc::type_traits;
+
+                using meta::ColumnMeta;
+
+                columnsMeta.reserve(6);
+
+                const std::string sch("");
+                const std::string tbl("");
+
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_CAT",   IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM", IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME",  IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME", IGNITE_TYPE_STRING));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ",     IGNITE_TYPE_SHORT));
+                columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME",     IGNITE_TYPE_STRING));
+            }
+
+            PrimaryKeysQuery::~PrimaryKeysQuery()
+            {
+                // No-op.
+            }
+
+            SqlResult PrimaryKeysQuery::Execute()
+            {
+                if (executed)
+                    Close();
+
+                meta.push_back(meta::PrimaryKeyMeta(catalog, schema, table, "_KEY", 1, "_KEY"));
+
+                executed = true;
+
+                cursor = meta.begin();
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            const meta::ColumnMetaVector & PrimaryKeysQuery::GetMeta() const
+            {
+                return columnsMeta;
+            }
+
+            SqlResult PrimaryKeysQuery::FetchNextRow(app::ColumnBindingMap & columnBindings)
+            {
+                if (!executed)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (cursor == meta.end())
+                    return SQL_RESULT_NO_DATA;
+
+                app::ColumnBindingMap::iterator it;
+
+                for (it = columnBindings.begin(); it != columnBindings.end(); ++it)
+                    GetColumn(it->first, it->second);
+
+                ++cursor;
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            SqlResult PrimaryKeysQuery::GetColumn(uint16_t columnIdx, app::ApplicationDataBuffer& buffer)
+            {
+                if (!executed)
+                {
+                    diag.AddStatusRecord(SQL_STATE_HY010_SEQUENCE_ERROR, "Query was not executed.");
+
+                    return SQL_RESULT_ERROR;
+                }
+
+                if (cursor == meta.end())
+                    return SQL_RESULT_NO_DATA;
+
+                const meta::PrimaryKeyMeta& currentColumn = *cursor;
+
+                switch (columnIdx)
+                {
+                    case TABLE_CAT:
+                    {
+                        buffer.PutString(currentColumn.GetCatalogName());
+                        break;
+                    }
+
+                    case TABLE_SCHEM:
+                    {
+                        buffer.PutString(currentColumn.GetSchemaName());
+                        break;
+                    }
+
+                    case TABLE_NAME:
+                    {
+                        buffer.PutString(currentColumn.GetTableName());
+                        break;
+                    }
+
+                    case COLUMN_NAME:
+                    {
+                        buffer.PutString(currentColumn.GetColumnName());
+                        break;
+                    }
+
+                    case KEY_SEQ:
+                    {
+                        buffer.PutInt16(currentColumn.GetKeySeq());
+                        break;
+                    }
+
+                    case PK_NAME:
+                    {
+                        buffer.PutString(currentColumn.GetKeyName());
+                        break;
+                    }
+
+                    default:
+                        break;
+                }
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            SqlResult PrimaryKeysQuery::Close()
+            {
+                meta.clear();
+
+                executed = false;
+
+                return SQL_RESULT_SUCCESS;
+            }
+
+            bool PrimaryKeysQuery::DataAvailable() const
+            {
+                return cursor != meta.end();
+            }
+
+            int64_t PrimaryKeysQuery::AffectedRows() const
+            {
+                return 0;
+            }
+        }
+    }
+}
+


Mime
View raw message