http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/config/connection_info.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/config/connection_info.cpp b/modules/platforms/cpp/odbc/src/config/connection_info.cpp new file mode 100644 index 0000000..7f0e3bd --- /dev/null +++ b/modules/platforms/cpp/odbc/src/config/connection_info.cpp @@ -0,0 +1,428 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cstring> +#include <algorithm> + +#include "ignite/odbc/system/odbc_constants.h" +#include "ignite/odbc/utility.h" +#include "ignite/odbc/config/connection_info.h" + + // Temporary workaround. +#ifndef SQL_ASYNC_NOTIFICATION +#define SQL_ASYNC_NOTIFICATION 10025 +#endif + +#ifndef SQL_ASYNC_NOTIFICATION_NOT_CAPABLE +#define SQL_ASYNC_NOTIFICATION_NOT_CAPABLE 0x00000000L +#endif + +#ifndef SQL_ASYNC_NOTIFICATION_CAPABLE +#define SQL_ASYNC_NOTIFICATION_CAPABLE 0x00000001L +#endif + +namespace ignite +{ + namespace odbc + { + namespace config + { + +#ifdef ODBC_DEBUG + +#define DBG_STR_CASE(x) case x: return #x + + const char * ConnectionInfo::InfoTypeToString(InfoType type) + { + switch (type) + { + DBG_STR_CASE(SQL_DRIVER_NAME); + DBG_STR_CASE(SQL_DBMS_NAME); + DBG_STR_CASE(SQL_DRIVER_ODBC_VER); + DBG_STR_CASE(SQL_DBMS_VER); + DBG_STR_CASE(SQL_DRIVER_VER); + DBG_STR_CASE(SQL_COLUMN_ALIAS); + DBG_STR_CASE(SQL_IDENTIFIER_QUOTE_CHAR); + DBG_STR_CASE(SQL_CATALOG_NAME_SEPARATOR); + DBG_STR_CASE(SQL_SPECIAL_CHARACTERS); + DBG_STR_CASE(SQL_CATALOG_TERM); + DBG_STR_CASE(SQL_TABLE_TERM); + DBG_STR_CASE(SQL_SCHEMA_TERM); + DBG_STR_CASE(SQL_ASYNC_DBC_FUNCTIONS); + DBG_STR_CASE(SQL_ASYNC_NOTIFICATION); + DBG_STR_CASE(SQL_GETDATA_EXTENSIONS); + DBG_STR_CASE(SQL_ODBC_INTERFACE_CONFORMANCE); + DBG_STR_CASE(SQL_SQL_CONFORMANCE); + DBG_STR_CASE(SQL_CATALOG_USAGE); + DBG_STR_CASE(SQL_SCHEMA_USAGE); + DBG_STR_CASE(SQL_MAX_IDENTIFIER_LEN); + DBG_STR_CASE(SQL_AGGREGATE_FUNCTIONS); + DBG_STR_CASE(SQL_NUMERIC_FUNCTIONS); + DBG_STR_CASE(SQL_STRING_FUNCTIONS); + DBG_STR_CASE(SQL_TIMEDATE_FUNCTIONS); + DBG_STR_CASE(SQL_TIMEDATE_ADD_INTERVALS); + DBG_STR_CASE(SQL_TIMEDATE_DIFF_INTERVALS); + DBG_STR_CASE(SQL_DATETIME_LITERALS); + DBG_STR_CASE(SQL_SYSTEM_FUNCTIONS); + DBG_STR_CASE(SQL_CONVERT_FUNCTIONS); + DBG_STR_CASE(SQL_OJ_CAPABILITIES); + DBG_STR_CASE(SQL_POS_OPERATIONS); + DBG_STR_CASE(SQL_MAX_CONCURRENT_ACTIVITIES); + DBG_STR_CASE(SQL_CURSOR_COMMIT_BEHAVIOR); + DBG_STR_CASE(SQL_CURSOR_ROLLBACK_BEHAVIOR); + DBG_STR_CASE(SQL_TXN_CAPABLE); + DBG_STR_CASE(SQL_QUOTED_IDENTIFIER_CASE); + DBG_STR_CASE(SQL_SQL92_NUMERIC_VALUE_FUNCTIONS); + DBG_STR_CASE(SQL_SQL92_STRING_FUNCTIONS); + DBG_STR_CASE(SQL_SQL92_DATETIME_FUNCTIONS); + DBG_STR_CASE(SQL_SQL92_PREDICATES); + DBG_STR_CASE(SQL_SQL92_RELATIONAL_JOIN_OPERATORS); + DBG_STR_CASE(SQL_SQL92_VALUE_EXPRESSIONS); + default: + break; + } + return "<< UNKNOWN TYPE >>"; + } + +#undef DBG_STR_CASE +#endif + + ConnectionInfo::ConnectionInfo() : strParams(), intParams(), + shortParams() + { + //========================= String Params ========================= + // Driver name. + strParams[SQL_DRIVER_NAME] = "Apache Ignite"; + strParams[SQL_DBMS_NAME] = "Apache Ignite"; + + // ODBC version. + strParams[SQL_DRIVER_ODBC_VER] = "03.00"; + strParams[SQL_DBMS_VER] = "03.00"; + +#ifdef SQL_DRIVER_VER + // Driver version. At a minimum, the version is of the form + // ##.##.####, where the first two digits are the major version, + // the next two digits are the minor version, and the last four + // digits are the release version. + strParams[SQL_DRIVER_VER] = "01.05.0000"; +#endif // SQL_DRIVER_VER + +#ifdef SQL_COLUMN_ALIAS + // A character string: "Y" if the data source supports column + // aliases; otherwise, "N". + strParams[SQL_COLUMN_ALIAS] = "N"; +#endif // SQL_COLUMN_ALIAS + +#ifdef SQL_IDENTIFIER_QUOTE_CHAR + // The character string that is used as the starting and ending + // delimiter of a quoted (delimited) identifier in SQL statements. + // Identifiers passed as arguments to ODBC functions do not have to + // be quoted. If the data source does not support quoted + // identifiers, a blank is returned. + strParams[SQL_IDENTIFIER_QUOTE_CHAR] = ""; +#endif // SQL_IDENTIFIER_QUOTE_CHAR + +#ifdef SQL_CATALOG_NAME_SEPARATOR + // A character string: the character or characters that the data + // source defines as the separator between a catalog name and the + // qualified name element that follows or precedes it. + strParams[SQL_CATALOG_NAME_SEPARATOR] = "."; +#endif // SQL_CATALOG_NAME_SEPARATOR + +#ifdef SQL_SPECIAL_CHARACTERS + // A character string that contains all special characters (that + // is, all characters except a through z, A through Z, 0 through 9, + // and underscore) that can be used in an identifier name, such as + // a table name, column name, or index name, on the data source. + strParams[SQL_SPECIAL_CHARACTERS] = ""; +#endif // SQL_SPECIAL_CHARACTERS + +#ifdef SQL_CATALOG_TERM + // A character string with the data source vendor's name for + // a catalog; for example, "database" or "directory". This string + // can be in upper, lower, or mixed case. + strParams[SQL_CATALOG_TERM] = "catalog"; +#endif // SQL_CATALOG_TERM + +#ifdef SQL_TABLE_TERM + // A character string with the data source vendor's name for + // a table; for example, "table" or "file". + strParams[SQL_TABLE_TERM] = "table"; +#endif // SQL_TABLE_TERM + +#ifdef SQL_SCHEMA_TERM + // A character string with the data source vendor's name for + // a schema; for example, "owner", "Authorization ID", or "Schema". + strParams[SQL_SCHEMA_TERM] = "schema"; +#endif // SQL_SCHEMA_TERM + +#ifdef SQL_ASYNC_DBC_FUNCTIONS + //======================== Integer Params ========================= + // Indicates if the driver can execute functions asynchronously + // on the connection handle. + // SQL_ASYNC_DBC_CAPABLE = The driver can execute connection + // functions asynchronously. + // SQL_ASYNC_DBC_NOT_CAPABLE = The driver can not execute + // connection functions asynchronously. + intParams[SQL_ASYNC_DBC_FUNCTIONS] = SQL_ASYNC_DBC_NOT_CAPABLE; +#endif // SQL_ASYNC_DBC_FUNCTIONS + +#ifdef SQL_ASYNC_NOTIFICATION + // Indicates if the driver supports asynchronous notification. + // SQL_ASYNC_NOTIFICATION_CAPABLE = Asynchronous execution + // notification is supported by the driver. + // SQL_ASYNC_NOTIFICATION_NOT_CAPABLE Asynchronous execution + // notification is not supported by the driver. + intParams[SQL_ASYNC_NOTIFICATION] = SQL_ASYNC_NOTIFICATION_NOT_CAPABLE; +#endif // SQL_ASYNC_NOTIFICATION + +#ifdef SQL_GETDATA_EXTENSIONS + // Bitmask enumerating extensions to SQLGetData. + intParams[SQL_GETDATA_EXTENSIONS] = SQL_GD_ANY_COLUMN; +#endif // SQL_GETDATA_EXTENSIONS + +#ifdef SQL_ODBC_INTERFACE_CONFORMANCE + // Indicates the level of the ODBC 3.x interface that the driver + // complies with. + intParams[SQL_ODBC_INTERFACE_CONFORMANCE] = SQL_OIC_CORE; +#endif // SQL_ODBC_INTERFACE_CONFORMANCE + +#ifdef SQL_SQL_CONFORMANCE + // Indicates the level of SQL-92 supported by the driver. + intParams[SQL_SQL_CONFORMANCE] = 0; // SQL_SC_SQL92_ENTRY; +#endif // SQL_SQL_CONFORMANCE + +#ifdef SQL_CATALOG_USAGE + // Bitmask enumerating the statements in which catalogs can be used. + intParams[SQL_CATALOG_USAGE] = 0; +#endif // SQL_CATALOG_USAGE + +#ifdef SQL_SCHEMA_USAGE + // Bitmask enumerating the statements in which schemas can be used. + intParams[SQL_SCHEMA_USAGE] = 0; +#endif // SQL_SCHEMA_USAGE + +#ifdef SQL_MAX_IDENTIFIER_LEN + // Indicates the maximum size in characters that the data source + // supports for user-defined names. + intParams[SQL_MAX_IDENTIFIER_LEN] = 128; +#endif // SQL_MAX_IDENTIFIER_LEN + +#ifdef SQL_AGGREGATE_FUNCTIONS + // Bitmask enumerating support for aggregation functions. + intParams[SQL_AGGREGATE_FUNCTIONS] = SQL_AF_ALL | SQL_AF_AVG | + SQL_AF_COUNT | SQL_AF_DISTINCT | SQL_AF_MAX | SQL_AF_MIN | + SQL_AF_SUM; +#endif // SQL_AGGREGATE_FUNCTIONS + +#ifdef SQL_NUMERIC_FUNCTIONS + // Bitmask enumerating the scalar numeric functions supported by + // the driver and associated data source. + intParams[SQL_NUMERIC_FUNCTIONS] = SQL_FN_NUM_ABS; +#endif // SQL_NUMERIC_FUNCTIONS + +#ifdef SQL_STRING_FUNCTIONS + // Bitmask enumerating the scalar string functions supported by the + // driver and associated data source. + intParams[SQL_STRING_FUNCTIONS] = 0; +#endif // SQL_STRING_FUNCTIONS + +#ifdef SQL_TIMEDATE_FUNCTIONS + // Bitmask enumerating the scalar date and time functions supported + // by the driver and associated data source. + intParams[SQL_TIMEDATE_FUNCTIONS] = 0; +#endif // SQL_TIMEDATE_FUNCTIONS + +#ifdef SQL_TIMEDATE_ADD_INTERVALS + // Bitmask enumerating timestamp intervals supported by the driver + // and associated data source for the TIMESTAMPADD scalar function. + intParams[SQL_TIMEDATE_ADD_INTERVALS] = 0; +#endif // SQL_TIMEDATE_ADD_INTERVALS + +#ifdef SQL_TIMEDATE_DIFF_INTERVALS + // Bitmask enumerating timestamp intervals supported by the driver + // and associated data source for the TIMESTAMPDIFF scalar function. + intParams[SQL_TIMEDATE_DIFF_INTERVALS] = 0; +#endif // SQL_TIMEDATE_DIFF_INTERVALS + +#ifdef SQL_DATETIME_LITERALS + // Bitmask enumerating the SQL-92 datetime literals supported by + // the data source. + intParams[SQL_DATETIME_LITERALS] = SQL_DL_SQL92_INTERVAL_HOUR | + SQL_DL_SQL92_DATE | SQL_DL_SQL92_INTERVAL_MINUTE_TO_SECOND | + SQL_DL_SQL92_TIME | SQL_DL_SQL92_INTERVAL_HOUR_TO_SECOND | + SQL_DL_SQL92_TIMESTAMP | SQL_DL_SQL92_INTERVAL_HOUR_TO_MINUTE | + SQL_DL_SQL92_INTERVAL_YEAR | SQL_DL_SQL92_INTERVAL_DAY_TO_SECOND | + SQL_DL_SQL92_INTERVAL_MONTH | SQL_DL_SQL92_INTERVAL_DAY_TO_HOUR | + SQL_DL_SQL92_INTERVAL_DAY | SQL_DL_SQL92_INTERVAL_DAY_TO_MINUTE | + SQL_DL_SQL92_INTERVAL_MINUTE | SQL_DL_SQL92_INTERVAL_SECOND | + SQL_DL_SQL92_INTERVAL_YEAR_TO_MONTH; +#endif // SQL_DATETIME_LITERALS + +#ifdef SQL_SYSTEM_FUNCTIONS + // Bitmask enumerating the scalar system functions supported by the + // driver and associated data source. + intParams[SQL_SYSTEM_FUNCTIONS] = 0; +#endif // SQL_SYSTEM_FUNCTIONS + +#ifdef SQL_CONVERT_FUNCTIONS + // Bitmask enumerating the scalar conversion functions supported + // by the driver and associated data source. + intParams[SQL_CONVERT_FUNCTIONS] = 0; +#endif // SQL_CONVERT_FUNCTIONS + +#ifdef SQL_OJ_CAPABILITIES + // Bitmask enumerating the types of outer joins supported by the + // driver and data source. + intParams[SQL_OJ_CAPABILITIES] = SQL_OJ_LEFT | SQL_OJ_RIGHT | + SQL_OJ_FULL | SQL_OJ_NESTED | SQL_OJ_INNER | + SQL_OJ_ALL_COMPARISON_OPS; +#endif // SQL_OJ_CAPABILITIES + +#ifdef SQL_POS_OPERATIONS + // Bitmask enumerating the support operations in SQLSetPos. + intParams[SQL_POS_OPERATIONS] = 0; +#endif // SQL_POS_OPERATIONS + +#ifdef SQL_SQL92_NUMERIC_VALUE_FUNCTIONS + // Bitmask enumerating the numeric value scalar functions. + intParams[SQL_SQL92_NUMERIC_VALUE_FUNCTIONS] = 0; +#endif // SQL_SQL92_NUMERIC_VALUE_FUNCTIONS + +#ifdef SQL_SQL92_STRING_FUNCTIONS + // Bitmask enumerating the string scalar functions. + intParams[SQL_SQL92_STRING_FUNCTIONS] = 0; +#endif // SQL_SQL92_STRING_FUNCTIONS + +#ifdef SQL_SQL92_DATETIME_FUNCTIONS + // Bitmask enumerating the datetime scalar functions. + intParams[SQL_SQL92_DATETIME_FUNCTIONS] = SQL_SDF_CURRENT_DATE | + SQL_SDF_CURRENT_TIMESTAMP; +#endif // SQL_SQL92_DATETIME_FUNCTIONS + +#ifdef SQL_SQL92_VALUE_EXPRESSIONS + // Bitmask enumerating the value expressions supported, + // as defined in SQL-92. + intParams[SQL_SQL92_VALUE_EXPRESSIONS] = SQL_SVE_CASE | + SQL_SVE_COALESCE | SQL_SVE_NULLIF; +#endif // SQL_SQL92_VALUE_EXPRESSIONS + +#ifdef SQL_SQL92_PREDICATES + // Bitmask enumerating the datetime scalar functions. + intParams[SQL_SQL92_PREDICATES] = SQL_SP_BETWEEN | + SQL_SP_COMPARISON | SQL_SP_EXISTS | SQL_SP_IN | + SQL_SP_ISNOTNULL | SQL_SP_ISNULL | SQL_SP_LIKE | + SQL_SP_MATCH_FULL | SQL_SP_MATCH_PARTIAL | + SQL_SP_MATCH_UNIQUE_FULL | SQL_SP_MATCH_UNIQUE_PARTIAL | + SQL_SP_OVERLAPS | SQL_SP_QUANTIFIED_COMPARISON | + SQL_SP_UNIQUE; +#endif // SQL_SQL92_PREDICATES + +#ifdef SQL_SQL92_RELATIONAL_JOIN_OPERATORS + // Bitmask enumerating the relational join operators supported + // in a SELECT statement, as defined in SQL-92. + intParams[SQL_SQL92_RELATIONAL_JOIN_OPERATORS] = + SQL_SRJO_CORRESPONDING_CLAUSE | SQL_SRJO_CROSS_JOIN | + SQL_SRJO_EXCEPT_JOIN | SQL_SRJO_EXCEPT_JOIN | + SQL_SRJO_INNER_JOIN | SQL_SRJO_INTERSECT_JOIN | + SQL_SRJO_LEFT_OUTER_JOIN | SQL_SRJO_NATURAL_JOIN | + SQL_SRJO_RIGHT_OUTER_JOIN | SQL_SRJO_UNION_JOIN; +#endif // SQL_SQL92_RELATIONAL_JOIN_OPERATORS + + //========================= Short Params ========================== +#ifdef SQL_MAX_CONCURRENT_ACTIVITIES + // The maximum number of active statements that the driver can + // support for a connection. Zero mean no limit. + shortParams[SQL_MAX_CONCURRENT_ACTIVITIES] = 32; +#endif // SQL_MAX_CONCURRENT_ACTIVITIES + +#ifdef SQL_CURSOR_COMMIT_BEHAVIOR + // Indicates how a COMMIT operation affects cursors and prepared + // statements in the data source. + shortParams[SQL_CURSOR_COMMIT_BEHAVIOR] = SQL_CB_PRESERVE; +#endif // SQL_CURSOR_COMMIT_BEHAVIOR + +#ifdef SQL_CURSOR_ROLLBACK_BEHAVIOR + // Indicates how a ROLLBACK operation affects cursors and prepared + // statements in the data source. + shortParams[SQL_CURSOR_ROLLBACK_BEHAVIOR] = SQL_CB_PRESERVE; +#endif // SQL_CURSOR_ROLLBACK_BEHAVIOR + +#ifdef SQL_TXN_CAPABLE + // Describs the transaction support in the driver or data source. + shortParams[SQL_TXN_CAPABLE] = SQL_TC_NONE; +#endif // SQL_TXN_CAPABLE + +#ifdef SQL_QUOTED_IDENTIFIER_CASE + // Case-sensitiveness of the quoted identifiers in SQL. + shortParams[SQL_QUOTED_IDENTIFIER_CASE] = SQL_IC_SENSITIVE; +#endif // SQL_QUOTED_IDENTIFIER_CASE + } + + ConnectionInfo::~ConnectionInfo() + { + // No-op. + } + + SqlResult ConnectionInfo::GetInfo(InfoType type, void* buf, + short buflen, short* reslen) const + { + if (!buf || !buflen) + return SQL_RESULT_ERROR; + + StringInfoMap::const_iterator itStr = strParams.find(type); + + if (itStr != strParams.cend()) + { + unsigned short strlen = static_cast<short>( + utility::CopyStringToBuffer(itStr->second, + reinterpret_cast<char*>(buf), buflen)); + + if (reslen) + *reslen = strlen; + + return SQL_RESULT_SUCCESS; + } + + UintInfoMap::const_iterator itInt = intParams.find(type); + + if (itInt != intParams.cend()) + { + unsigned int *res = reinterpret_cast<unsigned int*>(buf); + + *res = itInt->second; + + return SQL_RESULT_SUCCESS; + } + + UshortInfoMap::const_iterator itShort = shortParams.find(type); + + if (itShort != shortParams.cend()) + { + unsigned short *res = reinterpret_cast<unsigned short*>(buf); + + *res = itShort->second; + + return SQL_RESULT_SUCCESS; + } + + return SQL_RESULT_ERROR; + } + } + } +} +
http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/connection.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp new file mode 100644 index 0000000..59a25f9 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -0,0 +1,347 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cstring> + +#include <sstream> + +#include "ignite/odbc/utility.h" +#include "ignite/odbc/statement.h" +#include "ignite/odbc/connection.h" +#include "ignite/odbc/message.h" +#include "ignite/odbc/config/configuration.h" + +// TODO: implement appropriate protocol with de-/serialisation. +namespace +{ +#pragma pack(push, 1) + struct OdbcProtocolHeader + { + int32_t len; + }; +#pragma pack(pop) +} + +namespace ignite +{ + namespace odbc + { + const std::string Connection::PROTOCOL_VERSION_SINCE = "1.6.0"; + + Connection::Connection() : socket(), connected(false), cache(), parser() + { + // No-op. + } + + Connection::~Connection() + { + // No-op. + } + + const config::ConnectionInfo& Connection::GetInfo() const + { + // Connection info is the same for all connections now. + static config::ConnectionInfo info; + + return info; + } + + void Connection::GetInfo(config::ConnectionInfo::InfoType type, void* buf, short buflen, short* reslen) + { + IGNITE_ODBC_API_CALL(InternalGetInfo(type, buf, buflen, reslen)); + } + + SqlResult Connection::InternalGetInfo(config::ConnectionInfo::InfoType type, void* buf, short buflen, short* reslen) + { + const config::ConnectionInfo& info = GetInfo(); + + SqlResult res = info.GetInfo(type, buf, buflen, reslen); + + if (res != SQL_RESULT_SUCCESS) + AddStatusRecord(SQL_STATE_HYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED, "Not implemented."); + + return res; + } + + void Connection::Establish(const std::string& server) + { + IGNITE_ODBC_API_CALL(InternalEstablish(server)); + } + + SqlResult Connection::InternalEstablish(const std::string& server) + { + config::Configuration config; + + if (server != config.GetDsn()) + { + AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, "Unknown server."); + + return SQL_RESULT_ERROR; + } + + return InternalEstablish(config.GetHost(), config.GetPort(), config.GetCache()); + } + + void Connection::Establish(const std::string& host, uint16_t port, const std::string& cache) + { + IGNITE_ODBC_API_CALL(InternalEstablish(host, port, cache)); + } + + SqlResult Connection::InternalEstablish(const std::string & host, uint16_t port, const std::string & cache) + { + if (connected) + { + AddStatusRecord(SQL_STATE_08002_ALREADY_CONNECTED, "Already connected."); + + return SQL_RESULT_ERROR; + } + + this->cache = cache; + + connected = socket.Connect(host.c_str(), port); + + if (!connected) + { + AddStatusRecord(SQL_STATE_08001_CANNOT_CONNECT, "Failed to establish connection with the host."); + + return SQL_RESULT_ERROR; + } + + return MakeRequestHandshake(); + } + + void Connection::Release() + { + IGNITE_ODBC_API_CALL(InternalRelease()); + } + + SqlResult Connection::InternalRelease() + { + if (!connected) + { + AddStatusRecord(SQL_STATE_08003_NOT_CONNECTED, "Connection is not open."); + + return SQL_RESULT_ERROR; + } + + socket.Close(); + + connected = false; + + return SQL_RESULT_SUCCESS; + } + + Statement* Connection::CreateStatement() + { + Statement* statement; + + IGNITE_ODBC_API_CALL(InternalCreateStatement(statement)); + + return statement; + } + + SqlResult Connection::InternalCreateStatement(Statement*& statement) + { + statement = new Statement(*this); + + if (!statement) + { + AddStatusRecord(SQL_STATE_HY001_MEMORY_ALLOCATION, "Not enough memory."); + + return SQL_RESULT_ERROR; + } + + return SQL_RESULT_SUCCESS; + } + + void Connection::Send(const int8_t* data, size_t len) + { + if (!connected) + IGNITE_ERROR_1(IgniteError::IGNITE_ERR_ILLEGAL_STATE, "Connection is not established"); + + OdbcProtocolHeader hdr; + + hdr.len = static_cast<int32_t>(len); + + size_t sent = SendAll(reinterpret_cast<int8_t*>(&hdr), sizeof(hdr)); + + if (sent != sizeof(hdr)) + IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not send message header"); + + sent = SendAll(data, len); + + if (sent != len) + IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not send message body"); + } + + size_t Connection::SendAll(const int8_t* data, size_t len) + { + int sent = 0; + + while (sent != len) + { + int res = socket.Send(data + sent, len - sent); + + LOG_MSG("Sent: %d\n", res); + + if (res <= 0) + return sent; + + sent += res; + } + + return sent; + } + + void Connection::Receive(std::vector<int8_t>& msg) + { + if (!connected) + IGNITE_ERROR_1(IgniteError::IGNITE_ERR_ILLEGAL_STATE, "Connection is not established"); + + msg.clear(); + + OdbcProtocolHeader hdr; + + size_t received = ReceiveAll(reinterpret_cast<int8_t*>(&hdr), sizeof(hdr)); + + if (received != sizeof(hdr)) + IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not receive message header"); + + if (hdr.len < 0) + IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Message lenght is negative"); + + if (hdr.len == 0) + return; + + msg.resize(hdr.len); + + received = ReceiveAll(&msg[0], hdr.len); + + if (received != hdr.len) + { + msg.resize(received); + + IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not receive message body"); + } + } + + size_t Connection::ReceiveAll(void* dst, size_t len) + { + size_t remain = len; + int8_t* buffer = reinterpret_cast<int8_t*>(dst); + + while (remain) + { + size_t received = len - remain; + + int res = socket.Receive(buffer + received, remain); + LOG_MSG("Receive res: %d\n", res); + LOG_MSG("remain: %d\n", remain); + + if (res <= 0) + return received; + + remain -= static_cast<size_t>(res); + } + + return len; + } + + const std::string& Connection::GetCache() const + { + return cache; + } + + diagnostic::DiagnosticRecord Connection::CreateStatusRecord(SqlState sqlState, + const std::string& message, int32_t rowNum, int32_t columnNum) const + { + return diagnostic::DiagnosticRecord(sqlState, message, "", "", rowNum, columnNum); + } + + void Connection::TransactionCommit() + { + IGNITE_ODBC_API_CALL(InternalTransactionCommit()); + } + + SqlResult Connection::InternalTransactionCommit() + { + return SQL_RESULT_SUCCESS; + } + + void Connection::TransactionRollback() + { + IGNITE_ODBC_API_CALL(InternalTransactionRollback()); + } + + SqlResult Connection::InternalTransactionRollback() + { + AddStatusRecord(SQL_STATE_HYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED, + "Rollback operation is not supported."); + + return SQL_RESULT_ERROR; + } + + SqlResult Connection::MakeRequestHandshake() + { + HandshakeRequest req(PROTOCOL_VERSION); + HandshakeResponse rsp; + + try + { + SyncMessage(req, rsp); + } + catch (const IgniteError& err) + { + 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()); + + AddStatusRecord(SQL_STATE_08001_CANNOT_CONNECT, rsp.GetError()); + + InternalRelease(); + + return SQL_RESULT_ERROR; + } + + if (!rsp.IsAccepted()) + { + LOG_MSG("Hanshake message has been rejected.\n"); + + std::stringstream constructor; + + constructor << "Node rejected handshake message. " + << "Current node Apache Ignite version: " << rsp.CurrentVer() << ", " + << "node protocol version introduced in version: " << rsp.ProtoVerSince() << ", " + << "driver protocol version introduced in version: " << PROTOCOL_VERSION_SINCE << "."; + + AddStatusRecord(SQL_STATE_08001_CANNOT_CONNECT, constructor.str()); + + InternalRelease(); + + return SQL_RESULT_ERROR; + } + + return SQL_RESULT_SUCCESS; + } + } +} + http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/cursor.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/cursor.cpp b/modules/platforms/cpp/odbc/src/cursor.cpp new file mode 100644 index 0000000..2648278 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/cursor.cpp @@ -0,0 +1,82 @@ +/* + * 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/cursor.h" + +namespace ignite +{ + namespace odbc + { + Cursor::Cursor(int64_t queryId) : queryId(queryId), currentPage(), + currentPagePos(0), currentRow() + { + // No-op. + } + + Cursor::~Cursor() + { + // No-op. + } + + bool Cursor::Increment() + { + if (currentPage.get() && currentPagePos < currentPage->GetSize()) + { + ++currentPagePos; + + if (currentPagePos == currentPage->GetSize()) + currentRow.reset(); + else + { + Row *row = currentRow.get(); + + if (row) + row->MoveToNext(); + } + return true; + } + return false; + } + + bool Cursor::NeedDataUpdate() const + { + return !currentPage.get() || (!currentPage->IsLast() && + currentPagePos == currentPage->GetSize()); + } + + bool Cursor::HasData() const + { + return !currentPage.get() || !currentPage->IsLast() || + currentPagePos < currentPage->GetSize(); + } + + void Cursor::UpdateData(std::auto_ptr<ResultPage>& newPage) + { + currentPage = newPage; + + currentPagePos = 0; + + currentRow.reset(new Row(currentPage->GetData())); + } + + Row* Cursor::GetRow() + { + return currentRow.get(); + } + } +} + http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/decimal.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/decimal.cpp b/modules/platforms/cpp/odbc/src/decimal.cpp new file mode 100644 index 0000000..c1b2c44 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/decimal.cpp @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cstring> +#include <utility> + +#include "ignite/common/utils.h" + +#include "ignite/odbc/decimal.h" + +namespace ignite +{ + Decimal::Decimal() : + scale(0), len(0), magnitude(0) + { + // No-op. + } + + Decimal::Decimal(int32_t scale, const int8_t* mag, int32_t len) : + scale(scale), len(len), magnitude(0) + { + magnitude = new int8_t[len]; + + memcpy(magnitude, mag, len); + } + + Decimal::Decimal(const Decimal& other) : + scale(other.scale), len(other.len), magnitude(0) + { + magnitude = new int8_t[len]; + + memcpy(magnitude, other.magnitude, len); + } + + Decimal::~Decimal() + { + if (magnitude) + delete[] magnitude; + } + + Decimal& Decimal::operator=(const Decimal& other) + { + Decimal tmp(other); + + swap(tmp, *this); + + return *this; + } + + Decimal::operator double() const + { + double res = 0; + + for (int32_t i = 0; i < len; ++i) + res = (res * 256) + static_cast<uint8_t>(magnitude[i]); + + for (int32_t i = 0; i < GetScale(); ++i) + res /= 10.0; + + return res * GetSign(); + } + + int32_t Decimal::GetScale() const + { + return scale & 0x7FFFFFFF; + } + + int32_t Decimal::GetSign() const + { + return IsNegative() ? -1 : 1; + } + + bool Decimal::IsNegative() const + { + return (scale & 0x80000000) != 0; + } + + int32_t Decimal::GetLength() const + { + return len; + } + + int32_t Decimal::BitLength() const + { + using namespace common; + + if (len == 0) + return 0; + + int32_t bitsLen = (len - 1) * 8 + + BitLengthForOctet(magnitude[len - 1]); + + if (IsNegative()) { + + // Check if magnitude is a power of two + bool pow2 = PowerOfTwo(magnitude[len - 1]); + for (int i = 0; i < len - 1 && pow2; ++i) + pow2 = (magnitude[i] == 0); + + if (pow2) + --bitsLen; + } + + return bitsLen; + } + + const int8_t* Decimal::GetMagnitude() const + { + return magnitude; + } + + void swap(Decimal& first, Decimal& second) + { + using std::swap; + + std::swap(first.scale, second.scale); + std::swap(first.len, second.len); + std::swap(first.magnitude, second.magnitude); + } +} + http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp new file mode 100644 index 0000000..260e3e4 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp @@ -0,0 +1,51 @@ +/* + * 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/diagnostic/diagnosable_adapter.h" + +namespace ignite +{ + namespace odbc + { + namespace diagnostic + { + void DiagnosableAdapter::AddStatusRecord(SqlState sqlState, + const std::string& message, int32_t rowNum, int32_t columnNum) + { + if (connection) + { + diagnosticRecords.AddStatusRecord( + connection->CreateStatusRecord(sqlState, message, rowNum, columnNum)); + } + else + { + diagnosticRecords.AddStatusRecord( + DiagnosticRecord(sqlState, message, "", "", rowNum, columnNum)); + } + } + + void DiagnosableAdapter::AddStatusRecord(SqlState sqlState, const std::string& message) + { + LOG_MSG("Adding new record: %s\n", message.c_str()); + + AddStatusRecord(sqlState, message, 0, 0); + } + } + } +} + http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp new file mode 100644 index 0000000..568c125 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp @@ -0,0 +1,241 @@ +/* + * 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 <set> +#include <string> + +#include "ignite/odbc/diagnostic/diagnostic_record.h" + +namespace +{ + /** SQLSTATEs defined by Open Group and ISO call-level interface. */ + const std::string ORIGIN_ISO_9075 = "ISO 9075"; + + /** ODBC-specific SQLSTATEs (all those whose SQLSTATE class is "IM"). */ + const std::string ORIGIN_ODBC_3_0 = "ODBC 3.0"; + + /** SQL state unknown constant. */ + const std::string STATE_UNKNOWN = ""; + + /** SQL state 01004 constant. */ + const std::string STATE_01004 = "01004"; + + /** SQL state 01S01 constant. */ + const std::string STATE_01S01 = "01S01"; + + /** SQL state 24000 constant. */ + const std::string STATE_24000 = "24000"; + + /** SQL state 08001 constant. */ + const std::string STATE_08001 = "08001"; + + /** SQL state 08002 constant. */ + const std::string STATE_08002 = "08002"; + + /** SQL state 08003 constant. */ + const std::string STATE_08003 = "08003"; + + /** SQL state HY000 constant. */ + const std::string STATE_HY000 = "HY000"; + + /** SQL state HY001 constant. */ + const std::string STATE_HY001 = "HY001"; + + /** SQL state HY010 constant. */ + const std::string STATE_HY010 = "HY010"; + + /** SQL state HYC00 constant. */ + const std::string STATE_HYC00 = "HYC00"; + + /** SQL state HYT01 constant. */ + const std::string STATE_HYT01 = "HYT01"; +} + +namespace ignite +{ + namespace odbc + { + namespace diagnostic + { + DiagnosticRecord::DiagnosticRecord() : + sqlState(SQL_STATE_UNKNOWN), + message(), + connectionName(), + serverName(), + rowNum(0), + columnNum(0) + { + // No-op. + } + + DiagnosticRecord::DiagnosticRecord(SqlState sqlState, + const std::string& message, const std::string& connectionName, + const std::string& serverName, int32_t rowNum, int32_t columnNum) : + sqlState(sqlState), + message(message), + connectionName(connectionName), + serverName(serverName), + rowNum(rowNum), + columnNum(columnNum) + { + // No-op. + } + + DiagnosticRecord::~DiagnosticRecord() + { + // No-op. + } + + const std::string& DiagnosticRecord::GetClassOrigin() const + { + const std::string& state = GetSqlState(); + + if (state[0] == 'I' && state[1] == 'M') + return ORIGIN_ODBC_3_0; + + return ORIGIN_ISO_9075; + } + + const std::string& DiagnosticRecord::GetSubclassOrigin() const + { + static std::set<std::string> odbcSubclasses; + + if (odbcSubclasses.empty()) + { + odbcSubclasses.insert("01S00"); + odbcSubclasses.insert("01S01"); + odbcSubclasses.insert("01S02"); + odbcSubclasses.insert("01S06"); + odbcSubclasses.insert("01S07"); + odbcSubclasses.insert("07S01"); + odbcSubclasses.insert("08S01"); + odbcSubclasses.insert("21S01"); + odbcSubclasses.insert("21S02"); + odbcSubclasses.insert("25S01"); + odbcSubclasses.insert("25S02"); + odbcSubclasses.insert("25S03"); + odbcSubclasses.insert("42S01"); + odbcSubclasses.insert("42S02"); + odbcSubclasses.insert("42S11"); + odbcSubclasses.insert("42S12"); + odbcSubclasses.insert("42S21"); + odbcSubclasses.insert("42S22"); + odbcSubclasses.insert("HY095"); + odbcSubclasses.insert("HY097"); + odbcSubclasses.insert("HY098"); + odbcSubclasses.insert("HY099"); + odbcSubclasses.insert("HY100"); + odbcSubclasses.insert("HY101"); + odbcSubclasses.insert("HY105"); + odbcSubclasses.insert("HY107"); + odbcSubclasses.insert("HY109"); + odbcSubclasses.insert("HY110"); + odbcSubclasses.insert("HY111"); + odbcSubclasses.insert("HYT00"); + odbcSubclasses.insert("HYT01"); + odbcSubclasses.insert("IM001"); + odbcSubclasses.insert("IM002"); + odbcSubclasses.insert("IM003"); + odbcSubclasses.insert("IM004"); + odbcSubclasses.insert("IM005"); + odbcSubclasses.insert("IM006"); + odbcSubclasses.insert("IM007"); + odbcSubclasses.insert("IM008"); + odbcSubclasses.insert("IM010"); + odbcSubclasses.insert("IM011"); + odbcSubclasses.insert("IM012"); + } + + const std::string& state = GetSqlState(); + + if (odbcSubclasses.find(state) != odbcSubclasses.end()) + return ORIGIN_ODBC_3_0; + + return ORIGIN_ISO_9075; + } + + const std::string& DiagnosticRecord::GetMessage() const + { + return message; + } + + const std::string& DiagnosticRecord::GetConnectionName() const + { + return connectionName; + } + + const std::string& DiagnosticRecord::GetServerName() const + { + return serverName; + } + + const std::string& DiagnosticRecord::GetSqlState() const + { + switch (sqlState) + { + case SQL_STATE_01004_DATA_TRUNCATED: + return STATE_01004; + + case SQL_STATE_01S01_ERROR_IN_ROW: + return STATE_01S01; + + case SQL_STATE_24000_INVALID_CURSOR_STATE: + return STATE_24000; + + case SQL_STATE_08001_CANNOT_CONNECT: + return STATE_08001; + + case SQL_STATE_08002_ALREADY_CONNECTED: + return STATE_08002; + + case SQL_STATE_08003_NOT_CONNECTED: + return STATE_08003; + + case SQL_STATE_HY000_GENERAL_ERROR: + return STATE_HY000; + + case SQL_STATE_HY001_MEMORY_ALLOCATION: + return STATE_HY001; + + case SQL_STATE_HY010_SEQUENCE_ERROR: + return STATE_HY010; + + case SQL_STATE_HYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED: + return STATE_HYC00; + + case SQL_STATE_HYT01_CONNECTIOIN_TIMEOUT: + return STATE_HYT01; + + default: + break; + } + + return STATE_UNKNOWN; + } + + int32_t DiagnosticRecord::GetRowNumber() const + { + return rowNum; + } + + int32_t DiagnosticRecord::GetColumnNumber() const + { + return columnNum; + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp new file mode 100644 index 0000000..90c0a4f --- /dev/null +++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record_storage.cpp @@ -0,0 +1,242 @@ +/* + * 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 <set> +#include <string> + +#include "ignite/odbc/diagnostic/diagnostic_record_storage.h" + +namespace ignite +{ + namespace odbc + { + namespace diagnostic + { + DiagnosticRecordStorage::DiagnosticRecordStorage() : + rowCount(0), + dynamicFunction(), + dynamicFunctionCode(0), + result(SQL_RESULT_SUCCESS), + rowsAffected(0) + { + // No-op. + } + + DiagnosticRecordStorage::~DiagnosticRecordStorage() + { + // No-op. + } + + void DiagnosticRecordStorage::SetHeaderRecord(SqlResult result) + { + rowCount = 0; + dynamicFunction.clear(); + dynamicFunctionCode = 0; + this->result = result; + rowsAffected = 0; + } + + void DiagnosticRecordStorage::AddStatusRecord(const DiagnosticRecord& record) + { + statusRecords.push_back(record); + } + + void DiagnosticRecordStorage::Reset() + { + SetHeaderRecord(SQL_RESULT_ERROR); + + statusRecords.clear(); + } + + SqlResult DiagnosticRecordStorage::GetOperaionResult() const + { + return result; + } + + int DiagnosticRecordStorage::GetReturnCode() const + { + return SqlResultToReturnCode(result); + } + + int64_t DiagnosticRecordStorage::GetRowCount() const + { + return rowCount; + } + + const std::string & DiagnosticRecordStorage::GetDynamicFunction() const + { + return dynamicFunction; + } + + int32_t DiagnosticRecordStorage::GetDynamicFunctionCode() const + { + return dynamicFunctionCode; + } + + int32_t DiagnosticRecordStorage::GetRowsAffected() const + { + return rowsAffected; + } + + int32_t DiagnosticRecordStorage::GetStatusRecordsNumber() const + { + return static_cast<int32_t>(statusRecords.size()); + } + + const DiagnosticRecord& DiagnosticRecordStorage::GetStatusRecord(int32_t idx) const + { + return statusRecords[idx - 1]; + } + + bool DiagnosticRecordStorage::IsSuccessful() const + { + return result == SQL_RESULT_SUCCESS || + result == SQL_RESULT_SUCCESS_WITH_INFO; + } + + SqlResult DiagnosticRecordStorage::GetField(int32_t recNum, DiagnosticField field, app::ApplicationDataBuffer& buffer) const + { + // Header record. + switch (field) + { + case IGNITE_SQL_DIAG_HEADER_CURSOR_ROW_COUNT: + { + buffer.PutInt64(GetRowCount()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_HEADER_DYNAMIC_FUNCTION: + { + buffer.PutString(GetDynamicFunction()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_HEADER_DYNAMIC_FUNCTION_CODE: + { + buffer.PutInt32(GetDynamicFunctionCode()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_HEADER_NUMBER: + { + buffer.PutInt32(GetStatusRecordsNumber()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_HEADER_RETURNCODE: + { + buffer.PutInt32(GetReturnCode()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_HEADER_ROW_COUNT: + { + buffer.PutInt64(GetRowsAffected()); + + return SQL_RESULT_SUCCESS; + } + + default: + break; + } + + if (recNum < 1 || static_cast<size_t>(recNum) > statusRecords.size()) + return SQL_RESULT_NO_DATA; + + // Status record. + const DiagnosticRecord& record = GetStatusRecord(recNum); + + switch (field) + { + case IGNITE_SQL_DIAG_STATUS_CLASS_ORIGIN: + { + buffer.PutString(record.GetClassOrigin()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_COLUMN_NUMBER: + { + buffer.PutInt32(record.GetColumnNumber()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_CONNECTION_NAME: + { + buffer.PutString(record.GetConnectionName()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_MESSAGE_TEXT: + { + buffer.PutString(record.GetMessage()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_NATIVE: + { + buffer.PutInt32(0); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_ROW_NUMBER: + { + buffer.PutInt64(record.GetRowNumber()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_SERVER_NAME: + { + buffer.PutString(record.GetServerName()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_SQLSTATE: + { + buffer.PutString(record.GetSqlState()); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_DIAG_STATUS_SUBCLASS_ORIGIN: + { + buffer.PutString(record.GetSubclassOrigin()); + + return SQL_RESULT_SUCCESS; + } + + default: + break; + } + + return SQL_RESULT_ERROR; + } + + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/764c97b9/modules/platforms/cpp/odbc/src/entry_points.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/entry_points.cpp b/modules/platforms/cpp/odbc/src/entry_points.cpp new file mode 100644 index 0000000..c8e78a5 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/entry_points.cpp @@ -0,0 +1,694 @@ +/* + * 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.h" + +#include "ignite/odbc/utility.h" + +BOOL INSTAPI ConfigDSN(HWND hwndParent, + WORD req, + LPCSTR driver, + LPCSTR attributes) +{ + return ignite::ConfigDSN(hwndParent, req, driver, attributes); +} + +SQLRETURN SQL_API SQLGetInfo(SQLHDBC conn, + SQLUSMALLINT infoType, + SQLPOINTER infoValue, + SQLSMALLINT infoValueMax, + SQLSMALLINT* length) +{ + return ignite::SQLGetInfo(conn, infoType, infoValue, infoValueMax, length); +} + +SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT type, SQLHANDLE parent, SQLHANDLE* result) +{ + return ignite::SQLAllocHandle(type, parent, result); +} + +SQLRETURN SQL_API SQLAllocEnv(SQLHENV* env) +{ + return ignite::SQLAllocEnv(env); +} + +SQLRETURN SQL_API SQLAllocConnect(SQLHENV env, SQLHDBC* conn) +{ + return ignite::SQLAllocConnect(env, conn); +} + +SQLRETURN SQL_API SQLAllocStmt(SQLHDBC conn, SQLHSTMT* stmt) +{ + return ignite::SQLAllocStmt(conn, stmt); +} + +SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT type, SQLHANDLE handle) +{ + return ignite::SQLFreeHandle(type, handle); +} + +SQLRETURN SQL_API SQLFreeEnv(SQLHENV env) +{ + return ignite::SQLFreeEnv(env); +} + +SQLRETURN SQL_API SQLFreeConnect(SQLHDBC conn) +{ + return ignite::SQLFreeConnect(conn); +} + +SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT stmt, SQLUSMALLINT option) +{ + return ignite::SQLFreeStmt(stmt, option); +} + +SQLRETURN SQL_API SQLCloseCursor(SQLHSTMT stmt) +{ + return ignite::SQLCloseCursor(stmt); +} + +SQLRETURN SQL_API SQLDriverConnect(SQLHDBC conn, + SQLHWND windowHandle, + SQLCHAR* inConnectionString, + SQLSMALLINT inConnectionStringLen, + SQLCHAR* outConnectionString, + SQLSMALLINT outConnectionStringBufferLen, + SQLSMALLINT* outConnectionStringLen, + SQLUSMALLINT driverCompletion) +{ + return ignite::SQLDriverConnect(conn, windowHandle, inConnectionString, + inConnectionStringLen, outConnectionString, outConnectionStringBufferLen, + outConnectionStringLen, driverCompletion); +} + +SQLRETURN SQL_API SQLConnect(SQLHDBC conn, + SQLCHAR* serverName, + SQLSMALLINT serverNameLen, + SQLCHAR* userName, + SQLSMALLINT userNameLen, + SQLCHAR* auth, + SQLSMALLINT authLen) +{ + return ignite::SQLConnect(conn, serverName, serverNameLen, + userName, userNameLen, auth, authLen); +} + +SQLRETURN SQL_API SQLDisconnect(SQLHDBC conn) +{ + return ignite::SQLDisconnect(conn); +} + +SQLRETURN SQL_API SQLPrepare(SQLHSTMT stmt, SQLCHAR* query, SQLINTEGER queryLen) +{ + return ignite::SQLPrepare(stmt, query, queryLen); +} + +SQLRETURN SQL_API SQLExecute(SQLHSTMT stmt) +{ + return ignite::SQLExecute(stmt); +} + +SQLRETURN SQL_API SQLExecDirect(SQLHSTMT stmt, SQLCHAR* query, SQLINTEGER queryLen) +{ + return ignite::SQLExecDirect(stmt, query, queryLen); +} + +SQLRETURN SQL_API SQLBindCol(SQLHSTMT stmt, + SQLUSMALLINT colNum, + SQLSMALLINT targetType, + SQLPOINTER targetValue, + SQLLEN bufferLength, + SQLLEN* strLengthOrIndicator) +{ + return ignite::SQLBindCol(stmt, colNum, targetType, + targetValue, bufferLength, strLengthOrIndicator); +} + +SQLRETURN SQL_API SQLFetch(SQLHSTMT stmt) +{ + return ignite::SQLFetch(stmt); +} + +SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT stmt, + SQLSMALLINT orientation, + SQLLEN offset) +{ + return ignite::SQLFetchScroll(stmt, orientation, offset); +} + +SQLRETURN SQL_API SQLExtendedFetch(SQLHSTMT stmt, + SQLUSMALLINT orientation, + SQLLEN offset, + SQLULEN* rowCount, + SQLUSMALLINT* rowStatusArray) +{ + return ignite::SQLExtendedFetch(stmt, orientation, + offset, rowCount, rowStatusArray); +} + +SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT stmt, SQLSMALLINT *columnNum) +{ + return ignite::SQLNumResultCols(stmt, columnNum); +} + +SQLRETURN SQL_API SQLTables(SQLHSTMT stmt, + SQLCHAR* catalogName, + SQLSMALLINT catalogNameLen, + SQLCHAR* schemaName, + SQLSMALLINT schemaNameLen, + SQLCHAR* tableName, + SQLSMALLINT tableNameLen, + SQLCHAR* tableType, + SQLSMALLINT tableTypeLen) +{ + return ignite::SQLTables(stmt, catalogName, catalogNameLen, + schemaName, schemaNameLen, tableName, tableNameLen, + tableType, tableTypeLen); +} + +SQLRETURN SQL_API SQLColumns(SQLHSTMT stmt, + SQLCHAR* catalogName, + SQLSMALLINT catalogNameLen, + SQLCHAR* schemaName, + SQLSMALLINT schemaNameLen, + SQLCHAR* tableName, + SQLSMALLINT tableNameLen, + SQLCHAR* columnName, + SQLSMALLINT columnNameLen) +{ + return ignite::SQLColumns(stmt, catalogName, catalogNameLen, schemaName, + schemaNameLen, tableName, tableNameLen, columnName, columnNameLen); +} + +SQLRETURN SQL_API SQLMoreResults(SQLHSTMT stmt) +{ + return ignite::SQLMoreResults(stmt); +} + +SQLRETURN SQL_API SQLBindParameter(SQLHSTMT stmt, + SQLUSMALLINT paramIdx, + SQLSMALLINT ioType, + SQLSMALLINT bufferType, + SQLSMALLINT paramSqlType, + SQLULEN columnSize, + SQLSMALLINT decDigits, + SQLPOINTER buffer, + SQLLEN bufferLen, + SQLLEN* resLen) +{ + return ignite::SQLBindParameter(stmt, paramIdx, ioType, + bufferType, paramSqlType, columnSize, decDigits, + buffer, bufferLen, resLen); +} + +SQLRETURN SQL_API SQLNativeSql(SQLHDBC conn, + SQLCHAR* inQuery, + SQLINTEGER inQueryLen, + SQLCHAR* outQueryBuffer, + SQLINTEGER outQueryBufferLen, + SQLINTEGER* outQueryLen) +{ + return ignite::SQLNativeSql(conn, inQuery, inQueryLen, + outQueryBuffer, outQueryBufferLen, outQueryLen); +} + +SQLRETURN SQL_API SQLColAttribute(SQLHSTMT stmt, + SQLUSMALLINT columnNum, + SQLUSMALLINT fieldId, + SQLPOINTER strAttr, + SQLSMALLINT bufferLen, + SQLSMALLINT* strAttrLen, + SQLLEN* numericAttr) +{ + return ignite::SQLColAttribute(stmt, columnNum, fieldId, + strAttr, bufferLen, strAttrLen, numericAttr); +} + +SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT stmt, + SQLUSMALLINT columnNum, + SQLCHAR* columnNameBuf, + SQLSMALLINT columnNameBufLen, + SQLSMALLINT* columnNameLen, + SQLSMALLINT* dataType, + SQLULEN* columnSize, + SQLSMALLINT* decimalDigits, + SQLSMALLINT* nullable) +{ + return ignite::SQLDescribeCol(stmt, columnNum, columnNameBuf, + columnNameBufLen, columnNameLen, dataType, columnSize, + decimalDigits, nullable); +} + + +SQLRETURN SQL_API SQLRowCount(SQLHSTMT stmt, SQLLEN* rowCnt) +{ + return ignite::SQLRowCount(stmt, rowCnt); +} + +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) +{ + return ignite::SQLForeignKeys(stmt, primaryCatalogName, + primaryCatalogNameLen, primarySchemaName, primarySchemaNameLen, + primaryTableName, primaryTableNameLen, foreignCatalogName, + foreignCatalogNameLen, foreignSchemaName, foreignSchemaNameLen, + foreignTableName, foreignTableNameLen); +} + +SQLRETURN SQL_API SQLGetStmtAttr(SQLHSTMT stmt, + SQLINTEGER attr, + SQLPOINTER valueBuf, + SQLINTEGER valueBufLen, + SQLINTEGER* valueResLen) +{ + return ignite::SQLGetStmtAttr(stmt, attr, valueBuf, valueBufLen, valueResLen); +} + +SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT stmt, + SQLINTEGER attr, + SQLPOINTER value, + SQLINTEGER valueLen) +{ + return ignite::SQLSetStmtAttr(stmt, attr, value, valueLen); +} + +SQLRETURN SQL_API SQLPrimaryKeys(SQLHSTMT stmt, + SQLCHAR* catalogName, + SQLSMALLINT catalogNameLen, + SQLCHAR* schemaName, + SQLSMALLINT schemaNameLen, + SQLCHAR* tableName, + SQLSMALLINT tableNameLen) +{ + return ignite::SQLPrimaryKeys(stmt, catalogName, catalogNameLen, + schemaName, schemaNameLen, tableName, tableNameLen); +} + +SQLRETURN SQL_API SQLNumParams(SQLHSTMT stmt, SQLSMALLINT* paramCnt) +{ + return ignite::SQLNumParams(stmt, paramCnt); +} + +SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT handleType, + SQLHANDLE handle, + SQLSMALLINT recNum, + SQLSMALLINT diagId, + SQLPOINTER buffer, + SQLSMALLINT bufferLen, + SQLSMALLINT* resLen) +{ + return ignite::SQLGetDiagField(handleType, handle, + recNum, diagId, buffer, bufferLen, resLen); +} + +SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT handleType, + SQLHANDLE handle, + SQLSMALLINT recNum, + SQLCHAR* sqlState, + SQLINTEGER* nativeError, + SQLCHAR* msgBuffer, + SQLSMALLINT msgBufferLen, + SQLSMALLINT* msgLen) +{ + return ignite::SQLGetDiagRec(handleType, handle, recNum, + sqlState, nativeError, msgBuffer, msgBufferLen, msgLen); +} + +SQLRETURN SQL_API SQLGetTypeInfo(SQLHSTMT stmt, SQLSMALLINT type) +{ + return ignite::SQLGetTypeInfo(stmt, type); +} + +SQLRETURN SQL_API SQLEndTran(SQLSMALLINT handleType, + SQLHANDLE handle, + SQLSMALLINT completionType) +{ + return ignite::SQLEndTran(handleType, handle, completionType); +} + +SQLRETURN SQL_API SQLGetData(SQLHSTMT stmt, + SQLUSMALLINT colNum, + SQLSMALLINT targetType, + SQLPOINTER targetValue, + SQLLEN bufferLength, + SQLLEN* strLengthOrIndicator) +{ + return ignite::SQLGetData(stmt, colNum, targetType, + targetValue, bufferLength, strLengthOrIndicator); +} + +SQLRETURN SQL_API SQLSetEnvAttr(SQLHENV env, + SQLINTEGER attr, + SQLPOINTER value, + SQLINTEGER valueLen) +{ + return ignite::SQLSetEnvAttr(env, attr, value, valueLen); +} + +SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV env, + SQLINTEGER attr, + SQLPOINTER valueBuf, + SQLINTEGER valueBufLen, + SQLINTEGER* valueResLen) +{ + return ignite::SQLGetEnvAttr(env, attr, + valueBuf, valueBufLen, valueResLen); +} + +SQLRETURN SQL_API SQLSpecialColumns(SQLHSTMT stmt, + SQLSMALLINT idType, + SQLCHAR* catalogName, + SQLSMALLINT catalogNameLen, + SQLCHAR* schemaName, + SQLSMALLINT schemaNameLen, + SQLCHAR* tableName, + SQLSMALLINT tableNameLen, + SQLSMALLINT scope, + SQLSMALLINT nullable) +{ + return ignite::SQLSpecialColumns(stmt, idType, catalogName, + catalogNameLen, schemaName, schemaNameLen, tableName, + tableNameLen, scope, nullable); +} + +// +// ==== 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_ERROR; +} + +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 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) +{ + LOG_MSG("SQLSetConnectAttr called\n"); + 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/764c97b9/modules/platforms/cpp/odbc/src/environment.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/environment.cpp b/modules/platforms/cpp/odbc/src/environment.cpp new file mode 100644 index 0000000..3928295 --- /dev/null +++ b/modules/platforms/cpp/odbc/src/environment.cpp @@ -0,0 +1,172 @@ +/* + * 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/connection.h" +#include "ignite/odbc/environment.h" + +namespace ignite +{ + namespace odbc + { + Environment::Environment() : + odbcVersion(SQL_OV_ODBC3), odbcNts(SQL_TRUE) + { + // No-op. + } + + Environment::~Environment() + { + // No-op. + } + + Connection* Environment::CreateConnection() + { + Connection* connection; + + IGNITE_ODBC_API_CALL(InternalCreateConnection(connection)); + + return connection; + } + + SqlResult Environment::InternalCreateConnection(Connection*& connection) + { + connection = new Connection; + + if (!connection) + { + AddStatusRecord(SQL_STATE_HY001_MEMORY_ALLOCATION, "Not enough memory."); + + return SQL_RESULT_ERROR; + } + + return SQL_RESULT_SUCCESS; + } + + void Environment::TransactionCommit() + { + IGNITE_ODBC_API_CALL(InternalTransactionCommit()); + } + + SqlResult Environment::InternalTransactionCommit() + { + return SQL_RESULT_SUCCESS; + } + + void Environment::TransactionRollback() + { + IGNITE_ODBC_API_CALL(InternalTransactionRollback()); + } + + SqlResult Environment::InternalTransactionRollback() + { + AddStatusRecord(SQL_STATE_HYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED, + "Rollback operation is not supported."); + + return SQL_RESULT_ERROR; + } + + void Environment::SetAttribute(int32_t attr, void* value, int32_t len) + { + IGNITE_ODBC_API_CALL(InternalSetAttribute(attr, value, len)); + } + + SqlResult Environment::InternalSetAttribute(int32_t attr, void* value, int32_t len) + { + EnvironmentAttribute attribute = EnvironmentAttributeToInternal(attr); + + switch (attribute) + { + case IGNITE_SQL_ENV_ATTR_ODBC_VERSION: + { + int32_t version = static_cast<int32_t>(reinterpret_cast<intptr_t>(value)); + + if (version != odbcVersion) + { + AddStatusRecord(SQL_STATE_01S02_OPTION_VALUE_CHANGED, + "ODBC version is not supported."); + + return SQL_RESULT_SUCCESS_WITH_INFO; + } + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_ENV_ATTR_OUTPUT_NTS: + { + int32_t nts = static_cast<int32_t>(reinterpret_cast<intptr_t>(value)); + + if (nts != odbcNts) + { + AddStatusRecord(SQL_STATE_01S02_OPTION_VALUE_CHANGED, + "Only null-termination of strings is supported."); + + return SQL_RESULT_SUCCESS_WITH_INFO; + } + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_ENV_ATTR_UNKNOWN: + default: + break; + } + + AddStatusRecord(SQL_STATE_HYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED, + "Attribute is not supported."); + + return SQL_RESULT_ERROR; + } + + void Environment::GetAttribute(int32_t attr, app::ApplicationDataBuffer& buffer) + { + IGNITE_ODBC_API_CALL(InternalGetAttribute(attr, buffer)); + } + + SqlResult Environment::InternalGetAttribute(int32_t attr, app::ApplicationDataBuffer& buffer) + { + EnvironmentAttribute attribute = EnvironmentAttributeToInternal(attr); + + switch (attribute) + { + case IGNITE_SQL_ENV_ATTR_ODBC_VERSION: + { + buffer.PutInt32(odbcVersion); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_ENV_ATTR_OUTPUT_NTS: + { + buffer.PutInt32(odbcNts); + + return SQL_RESULT_SUCCESS; + } + + case IGNITE_SQL_ENV_ATTR_UNKNOWN: + default: + break; + } + + AddStatusRecord(SQL_STATE_HYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED, + "Attribute is not supported."); + + return SQL_RESULT_ERROR; + } + } +} +
