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 <[email protected]>
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 &empty;
-    }
+    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) {

Reply via email to