You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/01/27 11:39:46 UTC
[13/28] ignite git commit: IGNITE-2442: ODBC projects moved to main
cpp solution.
http://git-wip-us.apache.org/repos/asf/ignite/blob/e8287063/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..84e312a
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/odbc.cpp
@@ -0,0 +1,1687 @@
+/*
+ * 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"
+
+#ifdef ODBC_DEBUG
+
+FILE* log_file = NULL;
+
+void logInit(const char* path)
+{
+ if (!log_file)
+ {
+ log_file = fopen(path, "w");
+ }
+}
+
+#endif //ODBC_DEBUG
+
+BOOL INSTAPI 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 SQL_API 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)\n", infoType, ConnectionInfo::InfoTypeToString(infoType));
+
+ Connection *connection = reinterpret_cast<Connection*>(conn);
+
+ if (!connection)
+ return SQL_INVALID_HANDLE;
+
+ connection->GetInfo(infoType, infoValue, infoValueMax, length);
+
+ return connection->GetDiagnosticRecords().GetReturnCode();
+}
+
+SQLRETURN SQL_API 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 SQL_API SQLAllocEnv(SQLHENV* env)
+{
+ using ignite::odbc::Environment;
+
+ LOG_MSG("SQLAllocEnv called\n");
+
+ *env = reinterpret_cast<SQLHENV>(new Environment());
+
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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 SQL_API 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);
+
+ *valueResLen = static_cast<SQLSMALLINT>(outResLen);
+
+ return environment->GetDiagnosticRecords().GetReturnCode();
+}
+
+SQLRETURN SQL_API 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();
+}
+
+//
+// ==== Not implemented ====
+//
+
+SQLRETURN SQL_API SQLCancel(SQLHSTMT stmt)
+{
+ LOG_MSG("SQLCancel called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLColAttributes(SQLHSTMT stmt,
+ SQLUSMALLINT colNum,
+ SQLUSMALLINT fieldId,
+ SQLPOINTER strAttrBuf,
+ SQLSMALLINT strAttrBufLen,
+ SQLSMALLINT* strAttrResLen,
+ SQLLEN* numAttrBuf)
+{
+ LOG_MSG("SQLColAttributes called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLError(SQLHENV env,
+ SQLHDBC conn,
+ SQLHSTMT stmt,
+ SQLCHAR* state,
+ SQLINTEGER* error,
+ SQLCHAR* msgBuf,
+ SQLSMALLINT msgBufLen,
+ SQLSMALLINT* msgResLen)
+{
+ LOG_MSG("SQLError called\n");
+ return(SQL_NO_DATA_FOUND);
+}
+
+SQLRETURN SQL_API SQLGetCursorName(SQLHSTMT stmt,
+ SQLCHAR* nameBuf,
+ SQLSMALLINT nameBufLen,
+ SQLSMALLINT* nameResLen)
+{
+ LOG_MSG("SQLGetCursorName called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetCursorName(SQLHSTMT stmt,
+ SQLCHAR* name,
+ SQLSMALLINT nameLen)
+{
+ LOG_MSG("SQLSetCursorName called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLGetConnectOption(SQLHDBC conn,
+ SQLUSMALLINT option,
+ SQLPOINTER value)
+{
+ LOG_MSG("SQLGetConnectOption called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLGetFunctions(SQLHDBC conn,
+ SQLUSMALLINT funcId,
+ SQLUSMALLINT* supported)
+{
+ LOG_MSG("SQLGetFunctions called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLGetStmtOption(SQLHSTMT stmt,
+ SQLUSMALLINT option,
+ SQLPOINTER value)
+{
+ LOG_MSG("SQLGetStmtOption called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLParamData(SQLHSTMT stmt,
+ SQLPOINTER* value)
+{
+ LOG_MSG("SQLParamData called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLPutData(SQLHSTMT stmt,
+ SQLPOINTER data,
+ SQLLEN strLengthOrIndicator)
+{
+ LOG_MSG("SQLPutData called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetConnectOption(SQLHDBC conn,
+ SQLUSMALLINT option,
+ SQLULEN value)
+{
+ LOG_MSG("SQLSetConnectOption called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetStmtOption(SQLHSTMT stmt,
+ SQLUSMALLINT option,
+ SQLULEN value)
+{
+ LOG_MSG("SQLSetStmtOption called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLStatistics(SQLHSTMT stmt,
+ SQLCHAR* catalogName,
+ SQLSMALLINT catalogNameLen,
+ SQLCHAR* schemaName,
+ SQLSMALLINT schemaNameLen,
+ SQLCHAR* tableName,
+ SQLSMALLINT tableNameLen,
+ SQLUSMALLINT unique,
+ SQLUSMALLINT reserved)
+{
+ LOG_MSG("SQLStatistics called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLBrowseConnect(SQLHDBC conn,
+ SQLCHAR* inConnectionStr,
+ SQLSMALLINT inConnectionStrLen,
+ SQLCHAR* outConnectionStrBuf,
+ SQLSMALLINT outConnectionStrBufLen,
+ SQLSMALLINT* outConnectionStrResLen)
+{
+ LOG_MSG("SQLBrowseConnect called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLProcedureColumns(SQLHSTMT stmt,
+ SQLCHAR * catalogName,
+ SQLSMALLINT catalogNameLen,
+ SQLCHAR * schemaName,
+ SQLSMALLINT schemaNameLen,
+ SQLCHAR * procName,
+ SQLSMALLINT procNameLen,
+ SQLCHAR * columnName,
+ SQLSMALLINT columnNameLen)
+{
+ LOG_MSG("SQLProcedureColumns called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetPos(SQLHSTMT stmt,
+ SQLSETPOSIROW rowNum,
+ SQLUSMALLINT operation,
+ SQLUSMALLINT lockType)
+{
+ LOG_MSG("SQLSetPos called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetScrollOptions(SQLHSTMT stmt,
+ SQLUSMALLINT concurrency,
+ SQLLEN crowKeyset,
+ SQLUSMALLINT crowRowset)
+{
+ LOG_MSG("SQLSetScrollOptions called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC conn,
+ SQLINTEGER attr,
+ SQLPOINTER valueBuf,
+ SQLINTEGER valueBufLen,
+ SQLINTEGER* valueResLen)
+{
+ LOG_MSG("SQLGetConnectAttr called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC conn,
+ SQLINTEGER attr,
+ SQLPOINTER value,
+ SQLINTEGER valueLen)
+{
+ using ignite::odbc::Connection;
+
+ LOG_MSG("SQLSetConnectAttr called\n");
+
+ Connection *connection = reinterpret_cast<Connection*>(conn);
+
+ if (!connection)
+ return SQL_INVALID_HANDLE;
+
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLBulkOperations(SQLHSTMT stmt,
+ SQLUSMALLINT operation)
+{
+ LOG_MSG("SQLBulkOperations called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLTablePrivileges(SQLHSTMT stmt,
+ SQLCHAR* catalogName,
+ SQLSMALLINT catalogNameLen,
+ SQLCHAR* schemaName,
+ SQLSMALLINT schemaNameLen,
+ SQLCHAR* tableName,
+ SQLSMALLINT tableNameLen)
+{
+ LOG_MSG("SQLTablePrivileges called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLCopyDesc(SQLHDESC src, SQLHDESC dst)
+{
+ LOG_MSG("SQLCopyDesc called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLGetDescField(SQLHDESC descr,
+ SQLSMALLINT recNum,
+ SQLSMALLINT fieldId,
+ SQLPOINTER buffer,
+ SQLINTEGER bufferLen,
+ SQLINTEGER* resLen)
+{
+ LOG_MSG("SQLGetDescField called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLGetDescRec(SQLHDESC DescriptorHandle,
+ SQLSMALLINT RecNumber,
+ SQLCHAR* nameBuffer,
+ SQLSMALLINT nameBufferLen,
+ SQLSMALLINT* strLen,
+ SQLSMALLINT* type,
+ SQLSMALLINT* subType,
+ SQLLEN* len,
+ SQLSMALLINT* precision,
+ SQLSMALLINT* scale,
+ SQLSMALLINT* nullable)
+{
+ LOG_MSG("SQLGetDescRec called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetDescField(SQLHDESC descr,
+ SQLSMALLINT recNum,
+ SQLSMALLINT fieldId,
+ SQLPOINTER buffer,
+ SQLINTEGER bufferLen)
+{
+ LOG_MSG("SQLSetDescField called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLSetDescRec(SQLHDESC descr,
+ SQLSMALLINT recNum,
+ SQLSMALLINT type,
+ SQLSMALLINT subType,
+ SQLLEN len,
+ SQLSMALLINT precision,
+ SQLSMALLINT scale,
+ SQLPOINTER buffer,
+ SQLLEN* resLen,
+ SQLLEN* id)
+{
+ LOG_MSG("SQLSetDescRec called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLColumnPrivileges(SQLHSTMT stmt,
+ SQLCHAR* catalogName,
+ SQLSMALLINT catalogNameLen,
+ SQLCHAR* schemaName,
+ SQLSMALLINT schemaNameLen,
+ SQLCHAR* tableName,
+ SQLSMALLINT tableNameLen,
+ SQLCHAR* columnName,
+ SQLSMALLINT columnNameLen)
+{
+ LOG_MSG("SQLColumnPrivileges called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLDescribeParam(SQLHSTMT stmt,
+ SQLUSMALLINT paramNum,
+ SQLSMALLINT* dataType,
+ SQLULEN* paramSize,
+ SQLSMALLINT* decimalDigits,
+ SQLSMALLINT* nullable)
+{
+ LOG_MSG("SQLDescribeParam called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLParamOptions(SQLHSTMT stmt,
+ SQLULEN paramSetSize,
+ SQLULEN* paramsProcessed)
+{
+ LOG_MSG("SQLParamOptions called\n");
+ return SQL_SUCCESS;
+}
+
+SQLRETURN SQL_API SQLProcedures(SQLHSTMT stmt,
+ SQLCHAR* catalogName,
+ SQLSMALLINT catalogNameLen,
+ SQLCHAR* schemaName,
+ SQLSMALLINT schemaNameLen,
+ SQLCHAR* tableName,
+ SQLSMALLINT tableNameLen)
+{
+ LOG_MSG("SQLProcedures called\n");
+ return SQL_SUCCESS;
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e8287063/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..69a08b1
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp
@@ -0,0 +1,317 @@
+/*
+ * 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", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "DATA_TYPE", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "TYPE_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_SIZE", SqlTypeName::INTEGER, IGNITE_TYPE_INT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "BUFFER_LENGTH", SqlTypeName::INTEGER, IGNITE_TYPE_INT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "DECIMAL_DIGITS", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "NUM_PREC_RADIX", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "NULLABLE", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "REMARKS", SqlTypeName::VARCHAR, 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(currentColumn.GetColumnTypeName());
+ 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;
+
+ bool success = connection.SyncMessage(req, rsp);
+
+ if (!success)
+ {
+ diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, "Connection terminated.");
+
+ 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] ColumnTypeName: %s\n", i, meta[i].GetColumnTypeName().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/e8287063/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..4e9239b
--- /dev/null
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -0,0 +1,277 @@
+/*
+ * 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->HasNext())
+ return SQL_RESULT_NO_DATA;
+
+ if (cursor->NeedDataUpdate())
+ {
+ SqlResult result = MakeRequestFetch();
+
+ if (result != SQL_RESULT_SUCCESS)
+ return result;
+
+ if (!cursor->HasNext())
+ return SQL_RESULT_NO_DATA;
+ }
+ else
+ cursor->Increment();
+
+ 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);
+
+ SqlResult result;
+
+ if (it != columnBindings.end())
+ 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->HasNext();
+ }
+
+ int64_t DataQuery::AffectedRows() const
+ {
+ // We are only support SELECT statements so we should not
+ // return anything particullar.
+ return 0;
+ }
+
+ SqlResult DataQuery::MakeRequestExecute()
+ {
+ const std::string& cacheName = connection.GetCache();
+
+ QueryExecuteRequest req(cacheName, sql, params);
+ QueryExecuteResponse rsp;
+
+ bool success = connection.SyncMessage(req, rsp);
+
+ if (!success)
+ {
+ diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, "Connection terminated.");
+
+ 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] ColumnTypeName: %s\n", i, rsp.GetMeta()[i].GetColumnTypeName().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;
+
+ bool success = connection.SyncMessage(req, rsp);
+
+ if (!success)
+ {
+ diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, "Connection terminated.");
+
+ 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);
+
+ bool success = connection.SyncMessage(req, rsp);
+
+ LOG_MSG("Query id: %lld\n", rsp.GetQueryId());
+ LOG_MSG("Request status: %s\n", success ? "Success" : "Failure");
+
+ if (!success)
+ {
+ diag.AddStatusRecord(SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT, "Connection terminated.");
+
+ 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/e8287063/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..78e1464
--- /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", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_SCHEM", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "PKCOLUMN_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_CAT", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_SCHEM", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "FKCOLUMN_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "UPDATE_RULE", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "DELETE_RULE", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "FK_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "DEFERRABILITY", SqlTypeName::SMALLINT, 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/e8287063/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..b616db3
--- /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", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME", SqlTypeName::VARCHAR, IGNITE_TYPE_STRING));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", SqlTypeName::SMALLINT, IGNITE_TYPE_SHORT));
+ columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", SqlTypeName::VARCHAR, 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;
+ }
+ }
+ }
+}
+