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/09/18 23:52:19 UTC
[ignite-3] 01/04: IGNITE-19216 Ported type_info_query
This is an automated email from the ASF dual-hosted git repository.
isapego pushed a commit to branch ignite-19216
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit 88a3efe1d0961d174bff4143d677cbab0bb213bc
Author: Igor Sapego <is...@apache.org>
AuthorDate: Tue Sep 19 02:00:29 2023 +0400
IGNITE-19216 Ported type_info_query
---
modules/platforms/cpp/ignite/odbc/CMakeLists.txt | 1 +
modules/platforms/cpp/ignite/odbc/query/query.h | 3 +
.../cpp/ignite/odbc/query/type_info_query.cpp | 380 +++++++++++++++++++++
.../odbc/query/{query.h => type_info_query.h} | 103 +++---
.../platforms/cpp/ignite/odbc/sql_statement.cpp | 11 +-
5 files changed, 433 insertions(+), 65 deletions(-)
diff --git a/modules/platforms/cpp/ignite/odbc/CMakeLists.txt b/modules/platforms/cpp/ignite/odbc/CMakeLists.txt
index 58f02b7ec8..ea20e78785 100644
--- a/modules/platforms/cpp/ignite/odbc/CMakeLists.txt
+++ b/modules/platforms/cpp/ignite/odbc/CMakeLists.txt
@@ -37,6 +37,7 @@ set(SOURCES
meta/table_meta.cpp
query/data_query.cpp
query/table_metadata_query.cpp
+ query/type_info_query.cpp
odbc.cpp
entry_points.cpp
ssl_mode.cpp
diff --git a/modules/platforms/cpp/ignite/odbc/query/query.h b/modules/platforms/cpp/ignite/odbc/query/query.h
index 279c36184a..ce596eff70 100644
--- a/modules/platforms/cpp/ignite/odbc/query/query.h
+++ b/modules/platforms/cpp/ignite/odbc/query/query.h
@@ -33,6 +33,9 @@ enum class query_type {
/** Table metadata. */
TABLE_METADATA,
+
+ /** Type info. */
+ TYPE_INFO,
};
/**
diff --git a/modules/platforms/cpp/ignite/odbc/query/type_info_query.cpp b/modules/platforms/cpp/ignite/odbc/query/type_info_query.cpp
new file mode 100644
index 0000000000..2ac8611fb2
--- /dev/null
+++ b/modules/platforms/cpp/ignite/odbc/query/type_info_query.cpp
@@ -0,0 +1,380 @@
+/*
+ * 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/type_traits.h"
+#include "ignite/odbc/query/type_info_query.h"
+
+#include <cassert>
+
+namespace
+{
+
+enum class result_column
+{
+ /** Data source-dependent data-type name. */
+ TYPE_NAME = 1,
+
+ /** SQL data type. */
+ DATA_TYPE,
+
+ /** The maximum column size that the server supports for this data type. */
+ COLUMN_SIZE,
+
+ /** Character or characters used to prefix a literal. */
+ LITERAL_PREFIX,
+
+ /** Character or characters used to terminate a literal. */
+ LITERAL_SUFFIX,
+
+ /**
+ * A list of keywords, separated by commas, corresponding to each
+ * parameter that the application may specify in parentheses when using
+ * the name that is returned in the TYPE_NAME field.
+ */
+ CREATE_PARAMS,
+
+ /** Whether the data type accepts a NULL value. */
+ NULLABLE,
+
+ /**
+ * Whether a character data type is case-sensitive in collations and
+ * comparisons.
+ */
+ CASE_SENSITIVE,
+
+ /** How the data type is used in a WHERE clause. */
+ SEARCHABLE,
+
+ /** Whether the data type is unsigned. */
+ UNSIGNED_ATTRIBUTE,
+
+ /** Whether the data type has predefined fixed precision and scale. */
+ FIXED_PREC_SCALE,
+
+ /** Whether the data type is auto-incrementing. */
+ AUTO_UNIQUE_VALUE,
+
+ /**
+ * Localized version of the data source–dependent name of the data
+ * type.
+ */
+ LOCAL_TYPE_NAME,
+
+ /** The minimum scale of the data type on the data source. */
+ MINIMUM_SCALE,
+
+ /** The maximum scale of the data type on the data source. */
+ MAXIMUM_SCALE,
+
+ /**
+ * The value of the SQL data type as it appears in the SQL_DESC_TYPE
+ * field of the descriptor.
+ */
+ SQL_DATA_TYPE,
+
+ /**
+ * When the value of SQL_DATA_TYPE is SQL_DATETIME or SQL_INTERVAL,
+ * this column contains the datetime/interval sub-code.
+ */
+ SQL_DATETIME_SUB,
+
+ /**
+ * If the data type is an approximate numeric type, this column
+ * contains the value 2 to indicate that COLUMN_SIZE specifies a number
+ * of bits.
+ */
+ NUM_PREC_RADIX,
+
+ /**
+ * If the data type is an interval data type, then this column contains
+ * the value of the interval leading precision.
+ */
+ INTERVAL_PRECISION
+};
+
+} // anonymous namespace
+
+namespace ignite
+{
+type_info_query::type_info_query(diagnosable_adapter &diag, std::int16_t sql_type) :
+ query(diag, query_type::TYPE_INFO)
+{
+ m_columns_meta.reserve(19);
+
+ const std::string sch;
+ const std::string tbl;
+
+ m_columns_meta.push_back(column_meta(sch, tbl, "TYPE_NAME", ignite_type::STRING));
+ m_columns_meta.push_back(column_meta(sch, tbl, "DATA_TYPE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "COLUMN_SIZE", ignite_type::INT32));
+ m_columns_meta.push_back(column_meta(sch, tbl, "LITERAL_PREFIX", ignite_type::STRING));
+ m_columns_meta.push_back(column_meta(sch, tbl, "LITERAL_SUFFIX", ignite_type::STRING));
+ m_columns_meta.push_back(column_meta(sch, tbl, "CREATE_PARAMS", ignite_type::STRING));
+ m_columns_meta.push_back(column_meta(sch, tbl, "NULLABLE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "CASE_SENSITIVE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "SEARCHABLE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "UNSIGNED_ATTRIBUTE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "FIXED_PREC_SCALE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "AUTO_UNIQUE_VALUE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "LOCAL_TYPE_NAME", ignite_type::STRING));
+ m_columns_meta.push_back(column_meta(sch, tbl, "MINIMUM_SCALE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "MAXIMUM_SCALE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "SQL_DATA_TYPE", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "SQL_DATETIME_SUB", ignite_type::INT16));
+ m_columns_meta.push_back(column_meta(sch, tbl, "NUM_PREC_RADIX", ignite_type::INT32));
+ m_columns_meta.push_back(column_meta(sch, tbl, "INTERVAL_PRECISION", ignite_type::INT16));
+
+ assert(is_sql_type_supported(sql_type) || sql_type == SQL_ALL_TYPES);
+
+ if (sql_type == SQL_ALL_TYPES)
+ {
+ m_types.push_back(ignite_type::STRING);
+ m_types.push_back(ignite_type::INT16);
+ m_types.push_back(ignite_type::INT32);
+ m_types.push_back(ignite_type::DECIMAL);
+ m_types.push_back(ignite_type::FLOAT);
+ m_types.push_back(ignite_type::DOUBLE);
+ m_types.push_back(ignite_type::BOOLEAN);
+ m_types.push_back(ignite_type::INT8);
+ m_types.push_back(ignite_type::INT64);
+ m_types.push_back(ignite_type::UUID);
+ m_types.push_back(ignite_type::BYTE_ARRAY);
+ }
+ else
+ m_types.push_back(sql_type_to_ignite_type(sql_type));
+}
+
+sql_result type_info_query::execute()
+{
+ m_cursor = m_types.begin();
+
+ m_executed = true;
+ m_fetched = false;
+
+ return sql_result::AI_SUCCESS;
+}
+
+const column_meta_vector* type_info_query::get_meta()
+{
+ return &m_columns_meta;
+}
+
+sql_result type_info_query::fetch_next_row(column_binding_map & columnBindings)
+{
+ if (!m_executed)
+ {
+ m_diag.add_status_record(sql_state::SHY010_SEQUENCE_ERROR, "Query was not m_executed.");
+
+ return sql_result::AI_ERROR;
+ }
+
+ if (!m_fetched)
+ m_fetched = true;
+ else
+ ++m_cursor;
+
+ if (m_cursor == m_types.end())
+ return sql_result::AI_NO_DATA;
+
+ column_binding_map::iterator it;
+
+ for (it = columnBindings.begin(); it != columnBindings.end(); ++it)
+ get_column(it->first, it->second);
+
+ return sql_result::AI_SUCCESS;
+}
+
+sql_result type_info_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 m_executed.");
+
+ return sql_result::AI_ERROR;
+ }
+
+ if (m_cursor == m_types.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;
+ }
+
+ auto current_type = *m_cursor;
+
+ switch (result_column(column_idx))
+ {
+ case result_column::TYPE_NAME:
+ {
+ buffer.put_string(ignite_type_to_sql_type_name(current_type));
+
+ break;
+ }
+
+ case result_column::DATA_TYPE:
+ case result_column::SQL_DATA_TYPE:
+ {
+ buffer.put_int16(ignite_type_to_sql_type(current_type));
+
+ break;
+ }
+
+ case result_column::COLUMN_SIZE:
+ {
+ buffer.put_int32(ignite_type_column_size(current_type));
+
+ break;
+ }
+
+ case result_column::LITERAL_PREFIX:
+ {
+ if (current_type == ignite_type::STRING)
+ buffer.put_string("'");
+ else if (current_type == ignite_type::BYTE_ARRAY)
+ buffer.put_string("0x");
+ else
+ buffer.put_null();
+
+ break;
+ }
+
+ case result_column::LITERAL_SUFFIX:
+ {
+ if (current_type == ignite_type::STRING)
+ buffer.put_string("'");
+ else
+ buffer.put_null();
+
+ break;
+ }
+
+ case result_column::CREATE_PARAMS:
+ {
+ buffer.put_null();
+
+ break;
+ }
+
+ case result_column::NULLABLE:
+ {
+ buffer.put_int32(ignite_type_nullability(current_type));
+
+ break;
+ }
+
+ case result_column::CASE_SENSITIVE:
+ {
+ if (current_type == ignite_type::STRING)
+ buffer.put_int16(SQL_TRUE);
+ else
+ buffer.put_int16(SQL_FALSE);
+
+ break;
+ }
+
+ case result_column::SEARCHABLE:
+ {
+ buffer.put_int16(SQL_SEARCHABLE);
+
+ break;
+ }
+
+ case result_column::UNSIGNED_ATTRIBUTE:
+ {
+ buffer.put_int16(is_ignite_type_unsigned(current_type));
+
+ break;
+ }
+
+ case result_column::FIXED_PREC_SCALE:
+ case result_column::AUTO_UNIQUE_VALUE:
+ {
+ buffer.put_int16(SQL_FALSE);
+
+ break;
+ }
+
+ case result_column::LOCAL_TYPE_NAME:
+ {
+ buffer.put_null();
+
+ break;
+ }
+
+ case result_column::MINIMUM_SCALE:
+ case result_column::MAXIMUM_SCALE:
+ {
+ buffer.put_int16(ignite_type_decimal_digits(current_type));
+
+ break;
+ }
+
+ case result_column::SQL_DATETIME_SUB:
+ {
+ buffer.put_null();
+
+ break;
+ }
+
+ case result_column::NUM_PREC_RADIX:
+ {
+ buffer.put_int32(ignite_type_num_precision_radix(current_type));
+
+ break;
+ }
+
+ case result_column::INTERVAL_PRECISION:
+ {
+ buffer.put_null();
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return sql_result::AI_SUCCESS;
+}
+
+sql_result type_info_query::close()
+{
+ m_cursor = m_types.end();
+
+ m_executed = false;
+
+ return sql_result::AI_SUCCESS;
+}
+
+bool type_info_query::is_data_available() const
+{
+ return m_cursor != m_types.end();
+}
+
+int64_t type_info_query::affected_rows() const
+{
+ return 0;
+}
+
+sql_result type_info_query::next_result_set()
+{
+ return sql_result::AI_NO_DATA;
+}
+
+} // namespace ignite
+
diff --git a/modules/platforms/cpp/ignite/odbc/query/query.h b/modules/platforms/cpp/ignite/odbc/query/type_info_query.h
similarity index 55%
copy from modules/platforms/cpp/ignite/odbc/query/query.h
copy to modules/platforms/cpp/ignite/odbc/query/type_info_query.h
index 279c36184a..4cb75227ac 100644
--- a/modules/platforms/cpp/ignite/odbc/query/query.h
+++ b/modules/platforms/cpp/ignite/odbc/query/type_info_query.h
@@ -17,48 +17,49 @@
#pragma once
-#include "ignite/odbc/common_types.h"
-#include "ignite/odbc/diagnostic/diagnosable_adapter.h"
-#include "ignite/odbc/meta/column_meta.h"
+#include "ignite/odbc/query/query.h"
-#include <cstdint>
-#include <map>
-
-namespace ignite {
-
-/** Query type. */
-enum class query_type {
- /** Data query type. */
- DATA,
-
- /** Table metadata. */
- TABLE_METADATA,
-};
+namespace ignite
+{
/**
- * Query.
+ * Type info query.
*/
-class query {
+class type_info_query : public query {
public:
/**
- * Virtual destructor
+ * Constructor.
+ *
+ * @param diag Diagnostics collector.
+ * @param sql_type SQL type.
*/
- virtual ~query() = default;
+ type_info_query(diagnosable_adapter &diag, std::int16_t sql_type);
+
+ /**
+ * Destructor.
+ */
+ virtual ~type_info_query() = default;
/**
* Execute query.
*
- * @return Execution result.
+ * @return True on success.
+ */
+ virtual sql_result execute();
+
+ /**
+ * Get column metadata.
+ *
+ * @return Column metadata.
*/
- virtual sql_result execute() = 0;
+ virtual const column_meta_vector* get_meta();
/**
* Fetch next result row to application buffers.
*
- * @param column_bindings Application buffers to put data to.
* @return Operation result.
*/
- virtual sql_result fetch_next_row(column_binding_map &m_column_bindings) = 0;
+ virtual sql_result fetch_next_row(column_binding_map& column_bindings);
/**
* Get data of the specified column in the result set.
@@ -67,67 +68,51 @@ public:
* @param buffer Buffer to put column data to.
* @return Operation result.
*/
- virtual sql_result get_column(std::uint16_t column_idx, application_data_buffer &buffer) = 0;
+ virtual sql_result get_column(std::uint16_t column_idx, application_data_buffer& buffer);
/**
* Close query.
*
- * @return Operation result.
- */
- virtual sql_result close() = 0;
-
- /**
- * Get column metadata.
- *
- * @return Column metadata.
+ * @return True on success.
*/
- [[nodiscard]] virtual const column_meta_vector *get_meta() {
- static const column_meta_vector empty;
-
- return ∅
- }
+ virtual sql_result close();
/**
* Check if data is available.
*
* @return True if data is available.
*/
- [[nodiscard]] virtual bool is_data_available() const = 0;
+ virtual bool is_data_available() const;
/**
* Get number of rows affected by the statement.
*
* @return Number of rows affected by the statement.
*/
- [[nodiscard]] virtual std::int64_t affected_rows() const = 0;
+ virtual std::int64_t affected_rows() const;
/**
* Move to the next result set.
*
* @return Operation result.
*/
- virtual sql_result next_result_set() = 0;
+ virtual sql_result next_result_set();
- /**
- * Get query type.
- *
- * @return Query type.
- */
- [[nodiscard]] query_type get_type() const { return m_type; }
+private:
+ /** Columns metadata. */
+ column_meta_vector m_columns_meta;
-protected:
- /**
- * Constructor.
- */
- query(diagnosable_adapter &diag, query_type type)
- : m_diag(diag)
- , m_type(type) {}
+ /** Executed flag. */
+ bool m_executed = false;
+
+ /** Fetched flag. */
+ bool m_fetched = false;
- /** Diagnostics collector. */
- diagnosable_adapter &m_diag;
+ /** Requested types. */
+ std::vector<ignite_type> m_types;
- /** Query type. */
- query_type m_type;
+ /** Query cursor. */
+ std::vector<ignite_type>::const_iterator m_cursor = m_types.end();
};
-} // namespace ignite
+}
diff --git a/modules/platforms/cpp/ignite/odbc/sql_statement.cpp b/modules/platforms/cpp/ignite/odbc/sql_statement.cpp
index 26779ab8bc..690030af47 100644
--- a/modules/platforms/cpp/ignite/odbc/sql_statement.cpp
+++ b/modules/platforms/cpp/ignite/odbc/sql_statement.cpp
@@ -21,7 +21,7 @@
#include "ignite/odbc/odbc_error.h"
#include "ignite/odbc/query/data_query.h"
#include "ignite/odbc/query/table_metadata_query.h"
-#include "ignite/odbc/sql_connection.h"
+#include "ignite/odbc/query/type_info_query.h"
#include "ignite/odbc/sql_statement.h"
#include "ignite/odbc/system/odbc_constants.h"
#include "ignite/odbc/utility.h"
@@ -651,11 +651,11 @@ sql_result sql_statement::internal_execute_special_columns_query(uint16_t type,
return sql_result::AI_ERROR;
}
-void sql_statement::execute_get_type_info_query(int16_t sql_type) {
+void sql_statement::execute_get_type_info_query(std::int16_t sql_type) {
IGNITE_ODBC_API_CALL(internal_execute_get_type_info_query(sql_type));
}
-sql_result sql_statement::internal_execute_get_type_info_query(int16_t sql_type) {
+sql_result sql_statement::internal_execute_get_type_info_query(std::int16_t sql_type) {
if (sql_type != SQL_ALL_TYPES && !is_sql_type_supported(sql_type)) {
std::stringstream builder;
builder << "Data type is not supported. [typeId=" << sql_type << ']';
@@ -668,9 +668,8 @@ sql_result sql_statement::internal_execute_get_type_info_query(int16_t sql_type)
if (m_current_query)
m_current_query->close();
- // TODO: IGNITE-19216 Implement type info query
- add_status_record(sql_state::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED, "Type info query is not supported.");
- return sql_result::AI_ERROR;
+ m_current_query = std::make_unique<type_info_query>(*this, sql_type);
+ return m_current_query->execute();
}
void sql_statement::free_resources(uint16_t option) {