| /* |
| * 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/app/parameter_set.h" |
| #include "ignite/tuple/binary_tuple_builder.h" |
| |
| #include <algorithm> |
| |
| namespace ignite { |
| |
| void parameter_set_impl::set_param_set_size(SQLULEN size) { |
| m_param_set_size = size; |
| } |
| |
| void parameter_set_impl::bind_parameter(std::uint16_t param_idx, const parameter ¶m) { |
| m_params[param_idx] = param; |
| } |
| |
| void parameter_set_impl::unbind_parameter(std::uint16_t param_idx) { |
| m_params.erase(param_idx); |
| } |
| |
| void parameter_set_impl::unbind_all() { |
| m_params.clear(); |
| } |
| |
| std::uint16_t parameter_set_impl::get_parameters_number() const { |
| return static_cast<std::uint16_t>(m_params.size()); |
| } |
| |
| void parameter_set_impl::set_param_bind_offset_ptr(int *ptr) { |
| m_param_bind_offset = ptr; |
| } |
| |
| int *parameter_set_impl::get_param_bind_offset_ptr() { |
| return m_param_bind_offset; |
| } |
| |
| void parameter_set_impl::prepare() { |
| m_param_set_pos = 0; |
| |
| for (auto ¶m : m_params) |
| param.second.reset_stored_data(); |
| } |
| |
| bool parameter_set_impl::is_data_at_exec_needed() const { |
| return std::any_of( |
| m_params.begin(), m_params.end(), [](const auto ¶m) { return !param.second.is_data_ready(); }); |
| } |
| |
| void parameter_set_impl::set_params_processed_ptr(SQLULEN *ptr) { |
| m_processed_param_rows = ptr; |
| } |
| |
| SQLULEN *parameter_set_impl::get_params_processed_ptr() const { |
| return m_processed_param_rows; |
| } |
| |
| void parameter_set_impl::set_params_status_ptr(SQLUSMALLINT *value) { |
| m_params_status = value; |
| } |
| |
| SQLUSMALLINT *parameter_set_impl::get_params_status_ptr() const { |
| return m_params_status; |
| } |
| |
| void parameter_set_impl::set_params_status(int64_t idx, SQLUSMALLINT status) const { |
| if (idx < 0 || !m_params_status || idx >= static_cast<int64_t>(m_param_set_size)) |
| return; |
| |
| m_params_status[idx] = status; |
| } |
| |
| void parameter_set_impl::set_params_processed(SQLULEN processed) { |
| if (m_processed_param_rows) |
| *m_processed_param_rows = processed; |
| } |
| |
| bool parameter_set_impl::is_parameter_selected() const { |
| return m_current_param_idx != 0; |
| } |
| |
| parameter *parameter_set_impl::get_parameter(std::uint16_t idx) { |
| auto it = m_params.find(idx); |
| if (it != m_params.end()) |
| return &it->second; |
| |
| return nullptr; |
| } |
| |
| const parameter *parameter_set_impl::get_parameter(std::uint16_t idx) const { |
| auto it = m_params.find(idx); |
| if (it != m_params.end()) |
| return &it->second; |
| |
| return nullptr; |
| } |
| |
| parameter *parameter_set_impl::get_selected_parameter() { |
| return get_parameter(m_current_param_idx); |
| } |
| |
| parameter *parameter_set_impl::select_next_parameter() { |
| for (auto it = m_params.begin(); it != m_params.end(); ++it) { |
| std::uint16_t param_idx = it->first; |
| parameter ¶m = it->second; |
| |
| if (!param.is_data_ready()) { |
| m_current_param_idx = param_idx; |
| return ¶m; |
| } |
| } |
| |
| return nullptr; |
| } |
| |
| void parameter_set_impl::write(protocol::writer &writer) const { |
| auto args_num = calculate_row_len(); |
| if (args_num == 0) { |
| writer.write_nil(); |
| return; |
| } |
| |
| writer.write(args_num); |
| |
| write_row(writer, 0); |
| } |
| |
| void parameter_set_impl::write(protocol::writer &writer, SQLULEN begin, SQLULEN end, bool last) const { |
| std::int32_t row_len = calculate_row_len(); |
| |
| writer.write(row_len); |
| |
| SQLULEN interval_end = std::min(m_param_set_size, end); |
| |
| assert(begin < interval_end); |
| |
| auto interval_len = static_cast<std::int32_t>(interval_end - begin); |
| |
| writer.write(interval_len); |
| writer.write_bool(last); |
| |
| if (row_len) { |
| for (SQLULEN i = begin; i < interval_end; ++i) |
| write_row(writer, i); |
| } |
| } |
| |
| void parameter_set_impl::write_row(protocol::writer &writer, SQLULEN idx) const { |
| auto args_num = calculate_row_len(); |
| binary_tuple_builder row_builder{args_num * 3}; |
| |
| row_builder.start(); |
| |
| std::uint16_t prev = 0; |
| |
| int app_offset = m_param_bind_offset ? *m_param_bind_offset : 0; |
| for (const auto &pair : m_params) { |
| std::uint16_t param_idx = pair.first; |
| const parameter ¶m = pair.second; |
| |
| while ((param_idx - prev) > 1) { |
| row_builder.claim_null(); |
| ++prev; |
| } |
| |
| param.claim(row_builder, app_offset, idx); |
| |
| prev = param_idx; |
| } |
| |
| row_builder.layout(); |
| |
| for (const auto &pair : m_params) { |
| std::uint16_t param_idx = pair.first; |
| const parameter ¶m = pair.second; |
| |
| while ((param_idx - prev) > 1) { |
| row_builder.append_null(); |
| ++prev; |
| } |
| |
| param.append(row_builder, app_offset, idx); |
| |
| prev = param_idx; |
| } |
| |
| auto args_data = row_builder.build(); |
| writer.write_binary(args_data); |
| } |
| |
| std::int32_t parameter_set_impl::calculate_row_len() const { |
| if (!m_params.empty()) |
| return static_cast<std::int32_t>(m_params.rbegin()->first); |
| |
| return 0; |
| } |
| |
| std::int32_t parameter_set_impl::get_param_set_size() const { |
| return static_cast<std::int32_t>(m_param_set_size); |
| } |
| |
| } // namespace ignite |