You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by is...@apache.org on 2023/10/17 06:30:43 UTC
[ignite-3] branch main updated: IGNITE-19219 Implement primary keys query in ODBC (#2699)
This is an automated email from the ASF dual-hosted git repository.
isapego pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new b49dd9611c IGNITE-19219 Implement primary keys query in ODBC (#2699)
b49dd9611c is described below
commit b49dd9611c2dc5a732d41a7f7cc725339ecb27b9
Author: Igor Sapego <is...@apache.org>
AuthorDate: Tue Oct 17 10:30:38 2023 +0400
IGNITE-19219 Implement primary keys query in ODBC (#2699)
---
modules/platforms/cpp/ignite/odbc/CMakeLists.txt | 1 +
.../ignite/odbc/query/column_metadata_query.cpp | 6 +-
...e_metadata_query.cpp => primary_keys_query.cpp} | 204 +++++++++++----------
.../cpp/ignite/odbc/query/primary_keys_query.h | 137 ++++++++++++++
modules/platforms/cpp/ignite/odbc/query/query.h | 3 +
.../cpp/ignite/odbc/query/table_metadata_query.cpp | 6 +-
.../platforms/cpp/ignite/odbc/sql_statement.cpp | 9 +-
modules/platforms/cpp/ignite/odbc/sql_statement.h | 2 +-
.../cpp/ignite/protocol/client_operation.h | 3 +
.../cpp/tests/odbc-test/api_robustness_test.cpp | 146 ++++++++-------
.../cpp/tests/odbc-test/meta_queries_test.cpp | 75 ++++++++
11 files changed, 413 insertions(+), 179 deletions(-)
diff --git a/modules/platforms/cpp/ignite/odbc/CMakeLists.txt b/modules/platforms/cpp/ignite/odbc/CMakeLists.txt
index 3fea05ef88..581b3b89af 100644
--- a/modules/platforms/cpp/ignite/odbc/CMakeLists.txt
+++ b/modules/platforms/cpp/ignite/odbc/CMakeLists.txt
@@ -38,6 +38,7 @@ set(SOURCES
query/column_metadata_query.cpp
query/data_query.cpp
query/foreign_keys_query.cpp
+ query/primary_keys_query.cpp
query/table_metadata_query.cpp
query/type_info_query.cpp
odbc.cpp
diff --git a/modules/platforms/cpp/ignite/odbc/query/column_metadata_query.cpp b/modules/platforms/cpp/ignite/odbc/query/column_metadata_query.cpp
index fb31c62911..9edab15e3d 100644
--- a/modules/platforms/cpp/ignite/odbc/query/column_metadata_query.cpp
+++ b/modules/platforms/cpp/ignite/odbc/query/column_metadata_query.cpp
@@ -167,10 +167,8 @@ sql_result column_metadata_query::fetch_next_row(column_binding_map &column_bind
if (m_cursor == m_meta.end())
return sql_result::AI_NO_DATA;
- column_binding_map::iterator it;
-
- for (it = column_bindings.begin(); it != column_bindings.end(); ++it)
- get_column(it->first, it->second);
+ for (auto &binding : column_bindings)
+ get_column(binding.first, binding.second);
return sql_result::AI_SUCCESS;
}
diff --git a/modules/platforms/cpp/ignite/odbc/query/table_metadata_query.cpp b/modules/platforms/cpp/ignite/odbc/query/primary_keys_query.cpp
similarity index 53%
copy from modules/platforms/cpp/ignite/odbc/query/table_metadata_query.cpp
copy to modules/platforms/cpp/ignite/odbc/query/primary_keys_query.cpp
index 710ca8eb28..6d81f467ac 100644
--- a/modules/platforms/cpp/ignite/odbc/query/table_metadata_query.cpp
+++ b/modules/platforms/cpp/ignite/odbc/query/primary_keys_query.cpp
@@ -18,10 +18,8 @@
#include <utility>
#include "ignite/odbc/log.h"
-#include "ignite/odbc/odbc_error.h"
-#include "ignite/odbc/query/table_metadata_query.h"
+#include "ignite/odbc/query/primary_keys_query.h"
#include "ignite/odbc/sql_connection.h"
-#include "ignite/odbc/string_utils.h"
#include "ignite/odbc/type_traits.h"
namespace {
@@ -36,26 +34,65 @@ enum class result_column {
/** Table name. */
TABLE_NAME,
- /** Table type. */
- TABLE_TYPE,
+ /** Column name. */
+ COLUMN_NAME,
- /** A description of the column. */
- REMARKS
+ /** Column sequence number in key. */
+ KEY_SEQ,
+
+ /** Primary key name. */
+ PK_NAME
};
-} // namespace
+using namespace ignite;
+
+/**
+ * Reads primary keys.
+ *
+ * @param reader Reader.
+ * @return Primary keys meta.
+ */
+primary_key_meta_vector read_meta(protocol::reader &reader) {
+ auto has_no_data = reader.try_read_nil();
+ if (has_no_data)
+ return {};
+
+ auto tables_num = reader.read_int32();
+
+ primary_key_meta_vector keys;
+ keys.reserve(tables_num);
+
+ for (std::int32_t table_idx = 0; table_idx < tables_num; ++table_idx) {
+ auto schema_name = reader.read_string();
+ auto table_name = reader.read_string();
+ auto key_name = reader.read_string();
+
+ auto have_no_fields = reader.try_read_nil();
+ if (have_no_fields)
+ continue;
+
+ auto fields_num = reader.read_int32();
+ for (std::int32_t field_idx = 0; field_idx < fields_num; ++field_idx) {
+ auto field_name = reader.read_string();
+
+ keys.emplace_back("", schema_name, table_name, field_name, std::int16_t(field_idx + 1), key_name);
+ }
+ }
+
+ return keys;
+}
+
+} // anonymous namespace
namespace ignite {
-table_metadata_query::table_metadata_query(diagnosable_adapter &diag, sql_connection &connection, std::string catalog,
- std::string schema, std::string table, std::string table_type)
- : query(diag, query_type::TABLE_METADATA)
+primary_keys_query::primary_keys_query(
+ diagnosable_adapter &diag, sql_connection &connection, std::string schema, std::string table)
+ : query(diag, query_type::PRIMARY_KEYS)
, m_connection(connection)
- , m_catalog(std::move(catalog))
, m_schema(std::move(schema))
- , m_table(std::move(table))
- , m_table_type(std::move(table_type)) {
- m_columns_meta.reserve(5);
+ , m_table(std::move(table)) {
+ m_columns_meta.reserve(6);
const std::string sch;
const std::string tbl;
@@ -63,15 +100,16 @@ table_metadata_query::table_metadata_query(diagnosable_adapter &diag, sql_connec
m_columns_meta.emplace_back(sch, tbl, "TABLE_CAT", ignite_type::STRING);
m_columns_meta.emplace_back(sch, tbl, "TABLE_SCHEM", ignite_type::STRING);
m_columns_meta.emplace_back(sch, tbl, "TABLE_NAME", ignite_type::STRING);
- m_columns_meta.emplace_back(sch, tbl, "TABLE_TYPE", ignite_type::STRING);
- m_columns_meta.emplace_back(sch, tbl, "REMARKS", ignite_type::STRING);
+ m_columns_meta.emplace_back(sch, tbl, "COLUMN_NAME", ignite_type::STRING);
+ m_columns_meta.emplace_back(sch, tbl, "KEY_SEQ", ignite_type::INT16);
+ m_columns_meta.emplace_back(sch, tbl, "PK_NAME", ignite_type::STRING);
}
-sql_result table_metadata_query::execute() {
+sql_result primary_keys_query::execute() {
if (m_executed)
close();
- sql_result result = make_request_get_tables_meta();
+ sql_result result = make_request_get_primary_keys();
if (result == sql_result::AI_SUCCESS) {
m_executed = true;
@@ -83,11 +121,45 @@ sql_result table_metadata_query::execute() {
return result;
}
-const column_meta_vector *table_metadata_query::get_meta() {
- return &m_columns_meta;
+sql_result primary_keys_query::make_request_get_primary_keys() {
+ auto success = m_diag.catch_errors([&] {
+ auto response =
+ m_connection.sync_request(protocol::client_operation::JDBC_PK_META, [&](protocol::writer &writer) {
+ writer.write(m_schema);
+ writer.write(m_table);
+ });
+
+ protocol::reader reader{response.get_bytes_view()};
+ bool has_result_set = reader.read_bool();
+
+ auto status = reader.read_int32();
+ auto err_msg = reader.read_string_nullable();
+ if (err_msg)
+ throw odbc_error(response_status_to_sql_state(status), *err_msg);
+
+ if (has_result_set)
+ m_meta = read_meta(reader);
+
+ m_executed = true;
+ });
+
+ if (!success)
+ return sql_result::AI_ERROR;
+
+ std::size_t i = 0;
+ for (const auto &meta : m_meta) {
+ LOG_MSG("[" << i << "] SchemaName: " << meta.get_schema_name());
+ LOG_MSG("[" << i << "] TableName: " << meta.get_table_name());
+ LOG_MSG("[" << i << "] ColumnName: " << meta.get_column_name());
+ LOG_MSG("[" << i << "] KeyName: " << meta.get_key_name());
+ LOG_MSG("[" << i << "] KeySequence: " << meta.get_key_seq());
+ ++i;
+ }
+
+ return sql_result::AI_SUCCESS;
}
-sql_result table_metadata_query::fetch_next_row(column_binding_map &column_bindings) {
+sql_result primary_keys_query::fetch_next_row(column_binding_map &column_bindings) {
if (!m_executed) {
m_diag.add_status_record(sql_state::SHY010_SEQUENCE_ERROR, "Query was not executed.");
@@ -102,28 +174,23 @@ sql_result table_metadata_query::fetch_next_row(column_binding_map &column_bindi
if (m_cursor == m_meta.end())
return sql_result::AI_NO_DATA;
- column_binding_map::iterator it;
-
- for (it = column_bindings.begin(); it != column_bindings.end(); ++it)
- get_column(it->first, it->second);
+ for (auto &binding : column_bindings)
+ get_column(binding.first, binding.second);
return sql_result::AI_SUCCESS;
}
-sql_result table_metadata_query::get_column(std::uint16_t column_idx, application_data_buffer &buffer) {
+sql_result primary_keys_query::get_column(std::uint16_t column_idx, application_data_buffer &buffer) {
if (!m_executed) {
m_diag.add_status_record(sql_state::SHY010_SEQUENCE_ERROR, "Query was not executed.");
return sql_result::AI_ERROR;
}
- if (m_cursor == m_meta.end()) {
- m_diag.add_status_record(sql_state::S24000_INVALID_CURSOR_STATE, "Cursor has reached end of the result set.");
-
- return sql_result::AI_ERROR;
- }
+ if (m_cursor == m_meta.end())
+ return sql_result::AI_NO_DATA;
- const table_meta ¤t_column = *m_cursor;
+ auto ¤t_column = *m_cursor;
switch (result_column(column_idx)) {
case result_column::TABLE_CAT: {
@@ -141,13 +208,18 @@ sql_result table_metadata_query::get_column(std::uint16_t column_idx, applicatio
break;
}
- case result_column::TABLE_TYPE: {
- buffer.put_string(current_column.get_table_type());
+ case result_column::COLUMN_NAME: {
+ buffer.put_string(current_column.get_column_name());
+ break;
+ }
+
+ case result_column::KEY_SEQ: {
+ buffer.put_int16(current_column.get_key_seq());
break;
}
- case result_column::REMARKS: {
- buffer.put_null();
+ case result_column::PK_NAME: {
+ buffer.put_string(current_column.get_key_name());
break;
}
@@ -158,7 +230,7 @@ sql_result table_metadata_query::get_column(std::uint16_t column_idx, applicatio
return sql_result::AI_SUCCESS;
}
-sql_result table_metadata_query::close() {
+sql_result primary_keys_query::close() {
m_meta.clear();
m_executed = false;
@@ -166,60 +238,4 @@ sql_result table_metadata_query::close() {
return sql_result::AI_SUCCESS;
}
-bool table_metadata_query::is_data_available() const {
- return m_cursor != m_meta.end();
-}
-
-int64_t table_metadata_query::affected_rows() const {
- return 0;
-}
-
-sql_result table_metadata_query::next_result_set() {
- return sql_result::AI_NO_DATA;
-}
-
-sql_result table_metadata_query::make_request_get_tables_meta() {
- auto table_types = split(m_table_type, ',');
-
- auto success = m_diag.catch_errors([&] {
- auto response =
- m_connection.sync_request(protocol::client_operation::JDBC_TABLE_META, [&](protocol::writer &writer) {
- writer.write(m_schema);
- writer.write(m_table);
-
- writer.write(static_cast<int32_t>(table_types.size()));
- for (auto table_type : table_types) {
- writer.write(table_type);
- }
- });
-
- protocol::reader reader{response.get_bytes_view()};
- m_has_result_set = reader.read_bool();
-
- auto status = reader.read_int32();
- auto err_msg = reader.read_string_nullable();
- if (err_msg)
- throw odbc_error(response_status_to_sql_state(status), *err_msg);
-
- if (m_has_result_set) {
- m_meta = read_table_meta_vector(reader);
- }
-
- m_executed = true;
- });
-
- if (!success)
- return sql_result::AI_ERROR;
-
- int idx = 0;
- for (auto &column : m_meta) {
- LOG_MSG("\n[" << idx << "] catalog_name: " << column.get_catalog_name() << "\n[" << idx << "] schema_name: "
- << column.get_schema_name() << "\n[" << idx << "] table_name: " << column.get_table_name()
- << "\n[" << idx << "] table_type: " << column.get_table_type());
- ++idx;
- }
-
- return sql_result::AI_SUCCESS;
-}
-
} // namespace ignite
diff --git a/modules/platforms/cpp/ignite/odbc/query/primary_keys_query.h b/modules/platforms/cpp/ignite/odbc/query/primary_keys_query.h
new file mode 100644
index 0000000000..c7b2e3e48d
--- /dev/null
+++ b/modules/platforms/cpp/ignite/odbc/query/primary_keys_query.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "ignite/odbc/meta/primary_key_meta.h"
+#include "ignite/odbc/query/query.h"
+#include "ignite/odbc/sql_connection.h"
+
+namespace ignite {
+
+/**
+ * Primary keys query.
+ */
+class primary_keys_query : public query {
+public:
+ /**
+ * Constructor.
+ *
+ * @param diag Diagnostics collector.
+ * @param connection Statement-associated connection.
+ * @param schema Schema name.
+ * @param table Table name.
+ */
+ primary_keys_query(diagnosable_adapter &diag, sql_connection &connection, std::string schema, std::string table);
+
+ /**
+ * Destructor.
+ */
+ ~primary_keys_query() override = default;
+
+ /**
+ * Execute query.
+ *
+ * @return True on success.
+ */
+ sql_result execute() override;
+
+ /**
+ * Get column metadata.
+ *
+ * @return Column metadata.
+ */
+ const column_meta_vector *get_meta() override { return &m_columns_meta; }
+
+ /**
+ * Fetch next result row to application buffers.
+ *
+ * @return Operation result.
+ */
+ sql_result fetch_next_row(column_binding_map &column_bindings) override;
+
+ /**
+ * Get data of the specified column in the result set.
+ *
+ * @param columnIdx Column index.
+ * @param buffer Buffer to put column data to.
+ * @return Operation result.
+ */
+ sql_result get_column(std::uint16_t columnIdx, application_data_buffer &buffer) override;
+
+ /**
+ * Close query.
+ *
+ * @return True on success.
+ */
+ sql_result close() override;
+
+ /**
+ * Check if data is available.
+ *
+ * @return True if data is available.
+ */
+ bool is_data_available() const override { return m_cursor != m_meta.end(); }
+
+ /**
+ * Get number of rows affected by the statement.
+ *
+ * @return Number of rows affected by the statement.
+ */
+ std::int64_t affected_rows() const override { return 0; }
+
+ /**
+ * Move to the next result set.
+ *
+ * @return Operation result.
+ */
+ sql_result next_result_set() override { return sql_result::AI_NO_DATA; }
+
+private:
+ /**
+ * Make get primary keys requests and use response to set internal state.
+ *
+ * @return Operation result.
+ */
+ sql_result make_request_get_primary_keys();
+
+ /** Connection associated with the statement. */
+ sql_connection &m_connection;
+
+ /** Schema name. */
+ std::string m_schema;
+
+ /** Table name. */
+ std::string m_table;
+
+ /** Query executed. */
+ bool m_executed{false};
+
+ /** Result set fetched. */
+ bool m_fetched{false};
+
+ /** Columns metadata. */
+ column_meta_vector m_columns_meta;
+
+ /** Primary keys metadata. */
+ primary_key_meta_vector m_meta;
+
+ /** Result set cursor. */
+ primary_key_meta_vector::iterator m_cursor;
+};
+
+} // namespace ignite
diff --git a/modules/platforms/cpp/ignite/odbc/query/query.h b/modules/platforms/cpp/ignite/odbc/query/query.h
index 8a1450996f..1833fdd019 100644
--- a/modules/platforms/cpp/ignite/odbc/query/query.h
+++ b/modules/platforms/cpp/ignite/odbc/query/query.h
@@ -42,6 +42,9 @@ enum class query_type {
/** Foreign keys. */
FOREIGN_KEYS,
+
+ /** Primary keys. */
+ PRIMARY_KEYS,
};
/**
diff --git a/modules/platforms/cpp/ignite/odbc/query/table_metadata_query.cpp b/modules/platforms/cpp/ignite/odbc/query/table_metadata_query.cpp
index 710ca8eb28..e7ca838bd1 100644
--- a/modules/platforms/cpp/ignite/odbc/query/table_metadata_query.cpp
+++ b/modules/platforms/cpp/ignite/odbc/query/table_metadata_query.cpp
@@ -102,10 +102,8 @@ sql_result table_metadata_query::fetch_next_row(column_binding_map &column_bindi
if (m_cursor == m_meta.end())
return sql_result::AI_NO_DATA;
- column_binding_map::iterator it;
-
- for (it = column_bindings.begin(); it != column_bindings.end(); ++it)
- get_column(it->first, it->second);
+ for (auto &binding : column_bindings)
+ get_column(binding.first, binding.second);
return sql_result::AI_SUCCESS;
}
diff --git a/modules/platforms/cpp/ignite/odbc/sql_statement.cpp b/modules/platforms/cpp/ignite/odbc/sql_statement.cpp
index e94477e848..b115b799e0 100644
--- a/modules/platforms/cpp/ignite/odbc/sql_statement.cpp
+++ b/modules/platforms/cpp/ignite/odbc/sql_statement.cpp
@@ -22,6 +22,7 @@
#include "ignite/odbc/query/column_metadata_query.h"
#include "ignite/odbc/query/data_query.h"
#include "ignite/odbc/query/foreign_keys_query.h"
+#include "ignite/odbc/query/primary_keys_query.h"
#include "ignite/odbc/query/table_metadata_query.h"
#include "ignite/odbc/query/type_info_query.h"
#include "ignite/odbc/sql_statement.h"
@@ -607,15 +608,13 @@ void sql_statement::execute_get_primary_keys_query(
sql_result sql_statement::internal_execute_get_primary_keys_query(
const std::string &catalog, const std::string &schema, const std::string &table) {
UNUSED_VALUE catalog;
- UNUSED_VALUE schema;
- UNUSED_VALUE table;
if (m_current_query)
m_current_query->close();
- // TODO: IGNITE-19219 Implement primary keys query
- add_status_record(sql_state::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED, "Primary keys query is not supported.");
- return sql_result::AI_ERROR;
+ m_current_query = std::make_unique<primary_keys_query>(*this, m_connection, schema, table);
+
+ return m_current_query->execute();
}
void sql_statement::execute_special_columns_query(uint16_t type, const std::string &catalog, const std::string &schema,
diff --git a/modules/platforms/cpp/ignite/odbc/sql_statement.h b/modules/platforms/cpp/ignite/odbc/sql_statement.h
index 17bc46a5da..cd37b0c5c0 100644
--- a/modules/platforms/cpp/ignite/odbc/sql_statement.h
+++ b/modules/platforms/cpp/ignite/odbc/sql_statement.h
@@ -628,7 +628,7 @@ private:
sql_result update_params_meta();
/**
- * Convert SQLRESULT to SQL_ROW_RESULT.
+ * Convert sql_result to SQL_ROW_RESULT.
*
* @return Operation result.
*/
diff --git a/modules/platforms/cpp/ignite/protocol/client_operation.h b/modules/platforms/cpp/ignite/protocol/client_operation.h
index 1652977482..6cb7cc086e 100644
--- a/modules/platforms/cpp/ignite/protocol/client_operation.h
+++ b/modules/platforms/cpp/ignite/protocol/client_operation.h
@@ -86,6 +86,9 @@ enum class client_operation {
/** Get column metadata. */
JDBC_COLUMN_META = 39,
+ /** Get primary key metadata. */
+ JDBC_PK_META = 41,
+
/** Begin transaction. */
TX_BEGIN = 43,
diff --git a/modules/platforms/cpp/tests/odbc-test/api_robustness_test.cpp b/modules/platforms/cpp/tests/odbc-test/api_robustness_test.cpp
index cd88abb09a..f169c23b18 100644
--- a/modules/platforms/cpp/tests/odbc-test/api_robustness_test.cpp
+++ b/modules/platforms/cpp/tests/odbc-test/api_robustness_test.cpp
@@ -236,22 +236,22 @@ TEST_F(api_robustness_test, sql_columns) {
odbc_connect(get_basic_connection_string());
- SQLCHAR catalogName[] = "";
- SQLCHAR schemaName[] = "";
- SQLCHAR tableName[] = "";
+ SQLCHAR catalog_name[] = "";
+ SQLCHAR schema_name[] = "";
+ SQLCHAR table_name[] = "";
SQLCHAR columnName[] = "";
// Everything is ok.
- SQLRETURN ret = SQLColumns(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), columnName, sizeof(columnName));
+ SQLRETURN ret = SQLColumns(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
+ table_name, sizeof(table_name), columnName, sizeof(columnName));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
// Sizes are nulls.
- SQLColumns(m_conn, catalogName, 0, schemaName, 0, tableName, 0, columnName, 0);
+ SQLColumns(m_conn, catalog_name, 0, schema_name, 0, table_name, 0, columnName, 0);
// Values are nulls.
- SQLColumns(m_conn, 0, sizeof(catalogName), 0, sizeof(schemaName), 0, sizeof(tableName), 0, sizeof(columnName));
+ SQLColumns(m_conn, 0, sizeof(catalog_name), 0, sizeof(schema_name), 0, sizeof(table_name), 0, sizeof(columnName));
// All nulls.
SQLColumns(m_conn, 0, 0, 0, 0, 0, 0, 0, 0);
@@ -480,76 +480,80 @@ TEST_F(api_robustness_test, sql_foreign_keys) {
odbc_connect(get_basic_connection_string());
- SQLCHAR catalogName[] = "";
- SQLCHAR schemaName[] = "cache";
- SQLCHAR tableName[] = "TestType";
+ SQLCHAR catalog_name[] = "";
+ SQLCHAR schema_name[] = "cache";
+ SQLCHAR table_name[] = "TestType";
// Everything is ok.
- SQLRETURN ret = SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName),
- tableName, sizeof(tableName), catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName));
+ SQLRETURN ret = SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
+ table_name, sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
+ table_name, sizeof(table_name));
ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, 0, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName),
- catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, 0, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, 0, schemaName, sizeof(schemaName), tableName, sizeof(tableName),
- catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, 0, schema_name, sizeof(schema_name), table_name, sizeof(table_name),
+ catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), 0, sizeof(schemaName), tableName, sizeof(tableName),
- catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), 0, sizeof(schema_name), table_name,
+ sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, 0, tableName, sizeof(tableName),
- catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, 0, table_name, sizeof(table_name),
+ catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), 0, sizeof(tableName),
- catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), 0,
+ sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, 0,
- catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, 0,
+ catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), 0, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), 0, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), catalogName, 0, schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), catalog_name, 0, schema_name, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), catalogName, sizeof(catalogName), 0, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), catalog_name, sizeof(catalog_name), 0, sizeof(schema_name), table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), catalogName, sizeof(catalogName), schemaName, 0, tableName, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, 0, table_name, sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), 0, sizeof(tableName));
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), 0,
+ sizeof(table_name));
SQLCloseCursor(m_statement);
- SQLForeignKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, 0);
+ SQLForeignKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, 0);
SQLCloseCursor(m_statement);
@@ -603,24 +607,25 @@ TEST_F(api_robustness_test, sql_primary_keys) {
odbc_connect(get_basic_connection_string());
- SQLCHAR catalogName[] = "";
- SQLCHAR schemaName[] = "cache";
- SQLCHAR tableName[] = "TestType";
+ SQLCHAR catalog_name[] = "";
+ SQLCHAR schema_name[] = "cache";
+ SQLCHAR table_name[] = "TestType";
// Everything is ok.
- SQLRETURN ret = SQLPrimaryKeys(
- m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
+ SQLRETURN ret = SQLPrimaryKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
+ table_name, sizeof(table_name));
- UNUSED_VALUE ret;
- // TODO IGNITE-19219: Uncomment once primary keys query execution is implemented.
- // ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
- SQLPrimaryKeys(m_statement, 0, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, sizeof(tableName));
- SQLPrimaryKeys(m_statement, catalogName, 0, schemaName, sizeof(schemaName), tableName, sizeof(tableName));
- SQLPrimaryKeys(m_statement, catalogName, sizeof(catalogName), 0, sizeof(schemaName), tableName, sizeof(tableName));
- SQLPrimaryKeys(m_statement, catalogName, sizeof(catalogName), schemaName, 0, tableName, sizeof(tableName));
- SQLPrimaryKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), 0, sizeof(tableName));
- SQLPrimaryKeys(m_statement, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), tableName, 0);
+ SQLPrimaryKeys(
+ m_statement, 0, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, sizeof(table_name));
+ SQLPrimaryKeys(m_statement, catalog_name, 0, schema_name, sizeof(schema_name), table_name, sizeof(table_name));
+ SQLPrimaryKeys(
+ m_statement, catalog_name, sizeof(catalog_name), 0, sizeof(schema_name), table_name, sizeof(table_name));
+ SQLPrimaryKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, 0, table_name, sizeof(table_name));
+ SQLPrimaryKeys(
+ m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), 0, sizeof(table_name));
+ SQLPrimaryKeys(m_statement, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name), table_name, 0);
SQLPrimaryKeys(m_statement, 0, 0, 0, 0, 0, 0);
}
@@ -642,8 +647,7 @@ TEST_F(api_robustness_test, sql_num_params) {
// Everything is ok.
ret = SQLNumParams(m_statement, ¶ms);
- UNUSED_VALUE ret;
- // TODO IGNITE-19219: Uncomment once query execution is implemented.
+ // TODO IGNITE-19854: Uncomment once query execution is implemented.
// ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLNumParams(m_statement, 0);
@@ -668,7 +672,7 @@ TEST_F(api_robustness_test, sql_num_params_escaped) {
ret = SQLNumParams(m_statement, ¶ms);
UNUSED_VALUE ret;
- // TODO IGNITE-19219: Uncomment once query execution is implemented.
+ // TODO IGNITE-19854: Uncomment once query execution is implemented.
// ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
SQLNumParams(m_statement, 0);
@@ -759,13 +763,13 @@ TEST_F(api_robustness_test, sql_special_columns) {
odbc_connect(get_basic_connection_string());
- SQLCHAR catalogName[] = "";
- SQLCHAR schemaName[] = "cache";
- SQLCHAR tableName[] = "TestType";
+ SQLCHAR catalog_name[] = "";
+ SQLCHAR schema_name[] = "cache";
+ SQLCHAR table_name[] = "TestType";
// Everything is ok.
- SQLRETURN ret = SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalogName, sizeof(catalogName), schemaName,
- sizeof(schemaName), tableName, sizeof(tableName), SQL_SCOPE_CURROW, SQL_NO_NULLS);
+ SQLRETURN ret = SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name,
+ sizeof(schema_name), table_name, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
UNUSED_VALUE ret;
// TODO IGNITE-19218: Uncomment once special columns query execution is implemented.
@@ -773,33 +777,33 @@ TEST_F(api_robustness_test, sql_special_columns) {
SQLCloseCursor(m_statement);
- SQLSpecialColumns(m_statement, SQL_BEST_ROWID, 0, sizeof(catalogName), schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), SQL_SCOPE_CURROW, SQL_NO_NULLS);
+ SQLSpecialColumns(m_statement, SQL_BEST_ROWID, 0, sizeof(catalog_name), schema_name, sizeof(schema_name),
+ table_name, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
- SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalogName, 0, schemaName, sizeof(schemaName), tableName,
- sizeof(tableName), SQL_SCOPE_CURROW, SQL_NO_NULLS);
+ SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, 0, schema_name, sizeof(schema_name), table_name,
+ sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
- SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalogName, sizeof(catalogName), 0, sizeof(schemaName), tableName,
- sizeof(tableName), SQL_SCOPE_CURROW, SQL_NO_NULLS);
+ SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), 0, sizeof(schema_name),
+ table_name, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
- SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalogName, sizeof(catalogName), schemaName, 0, tableName,
- sizeof(tableName), SQL_SCOPE_CURROW, SQL_NO_NULLS);
+ SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name, 0, table_name,
+ sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
- SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName), 0,
- sizeof(tableName), SQL_SCOPE_CURROW, SQL_NO_NULLS);
+ SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
+ 0, sizeof(table_name), SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
- SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalogName, sizeof(catalogName), schemaName, sizeof(schemaName),
- tableName, 0, SQL_SCOPE_CURROW, SQL_NO_NULLS);
+ SQLSpecialColumns(m_statement, SQL_BEST_ROWID, catalog_name, sizeof(catalog_name), schema_name, sizeof(schema_name),
+ table_name, 0, SQL_SCOPE_CURROW, SQL_NO_NULLS);
SQLCloseCursor(m_statement);
diff --git a/modules/platforms/cpp/tests/odbc-test/meta_queries_test.cpp b/modules/platforms/cpp/tests/odbc-test/meta_queries_test.cpp
index 11af9248b4..f70e32104e 100644
--- a/modules/platforms/cpp/tests/odbc-test/meta_queries_test.cpp
+++ b/modules/platforms/cpp/tests/odbc-test/meta_queries_test.cpp
@@ -867,3 +867,78 @@ TEST_F(meta_queries_test, sqlcol_attribute_precision_and_scale_after_prepare) {
TEST_F(meta_queries_test, sqlcol_attribute_precision_and_scale_after_exec) {
check_col_precision_and_scale(&odbc_suite::exec_query, &check_column_meta_with_sqlcol_attribute);
}
+
+TEST_F(meta_queries_test, primary_keys_single_column) {
+ odbc_connect(get_basic_connection_string());
+
+ auto ret = exec_query("drop table if exists primary_keys_single_column");
+
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ ret = exec_query("create table if not exists primary_keys_single_column(ID int primary key, TEST_COLUMN varchar)");
+
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ SQLCHAR any[] = "%";
+ SQLCHAR table[] = "PRIMARY_KEYS_SINGLE_COLUMN";
+
+ ret = SQLPrimaryKeys(m_statement, any, SQL_NTS, any, SQL_NTS, table, SQL_NTS);
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ ret = SQLFetch(m_statement);
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ check_string_column(m_statement, 1, "");
+ check_string_column(m_statement, 2, "PUBLIC");
+ check_string_column(m_statement, 3, "PRIMARY_KEYS_SINGLE_COLUMN");
+ check_string_column(m_statement, 4, "ID");
+ check_string_column(m_statement, 5, "1");
+ check_string_column(m_statement, 6, "PK_PRIMARY_KEYS_SINGLE_COLUMN");
+
+ ret = SQLFetch(m_statement);
+
+ ASSERT_EQ(ret, SQL_NO_DATA);
+}
+
+TEST_F(meta_queries_test, primary_keys_multiple_columns) {
+ odbc_connect(get_basic_connection_string());
+
+ auto ret = exec_query("drop table if exists primary_keys_multiple_columns");
+
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ ret = exec_query(
+ "create table if not exists primary_keys_multiple_columns(ID1 int, ID2 varchar, primary key (ID1, ID2))");
+
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ SQLCHAR any[] = "%";
+ SQLCHAR table[] = "PRIMARY_KEYS_MULTIPLE_COLUMNS";
+
+ ret = SQLPrimaryKeys(m_statement, any, SQL_NTS, any, SQL_NTS, table, SQL_NTS);
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ ret = SQLFetch(m_statement);
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ check_string_column(m_statement, 1, "");
+ check_string_column(m_statement, 2, "PUBLIC");
+ check_string_column(m_statement, 3, "PRIMARY_KEYS_MULTIPLE_COLUMNS");
+ check_string_column(m_statement, 4, "ID1");
+ check_string_column(m_statement, 5, "1");
+ check_string_column(m_statement, 6, "PK_PRIMARY_KEYS_MULTIPLE_COLUMNS");
+
+ ret = SQLFetch(m_statement);
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, m_statement);
+
+ check_string_column(m_statement, 1, "");
+ check_string_column(m_statement, 2, "PUBLIC");
+ check_string_column(m_statement, 3, "PRIMARY_KEYS_MULTIPLE_COLUMNS");
+ check_string_column(m_statement, 4, "ID2");
+ check_string_column(m_statement, 5, "2");
+ check_string_column(m_statement, 6, "PK_PRIMARY_KEYS_MULTIPLE_COLUMNS");
+
+ ret = SQLFetch(m_statement);
+
+ ASSERT_EQ(ret, SQL_NO_DATA);
+}