This is an automated email from the ASF dual-hosted git repository.

isapego pushed a commit to branch ignite-17607
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 0cea5d2779158893162b2a6bbb3b1d6a3ed4f576
Author: Igor Sapego <[email protected]>
AuthorDate: Mon Mar 20 10:38:35 2023 +0300

    IGNITE-17607 Execute colocated stub
---
 .../cpp/ignite/client/compute/compute.cpp          |   3 +-
 .../platforms/cpp/ignite/client/compute/compute.h  |   2 +-
 .../ignite/client/detail/compute/compute_impl.cpp  |  48 +++++
 .../ignite/client/detail/compute/compute_impl.h    |  23 ++-
 .../cpp/ignite/client/detail/ignite_client_impl.h  |   2 +-
 .../cpp/ignite/client/detail/table/table_impl.cpp  | 215 +--------------------
 .../cpp/ignite/client/detail/table/table_impl.h    |  21 ++
 .../platforms/cpp/ignite/client/detail/utils.cpp   | 194 +++++++++++++++++++
 modules/platforms/cpp/ignite/client/detail/utils.h |  24 +++
 modules/platforms/cpp/ignite/client/table/table.h  |   1 +
 10 files changed, 318 insertions(+), 215 deletions(-)

diff --git a/modules/platforms/cpp/ignite/client/compute/compute.cpp 
b/modules/platforms/cpp/ignite/client/compute/compute.cpp
index 77e803d306..7f710bffb6 100644
--- a/modules/platforms/cpp/ignite/client/compute/compute.cpp
+++ b/modules/platforms/cpp/ignite/client/compute/compute.cpp
@@ -83,9 +83,10 @@ void compute::execute_colocated_async(const std::string 
&table_name, const ignit
     std::string_view job_class_name, const std::vector<primitive> &args,
     ignite_callback<std::optional<primitive>> callback) {
     detail::arg_check::container_non_empty(table_name, "Table name");
+    detail::arg_check::tuple_non_empty(key, "Key tuple");
     detail::arg_check::container_non_empty(job_class_name, "Job class name");
 
-    // TODO: Implement me.
+    m_impl->execute_colocated_async(table_name, key, job_class_name, args, 
std::move(callback));
 }
 
 } // namespace ignite
diff --git a/modules/platforms/cpp/ignite/client/compute/compute.h 
b/modules/platforms/cpp/ignite/client/compute/compute.h
index ff40355d8a..130ebb7abf 100644
--- a/modules/platforms/cpp/ignite/client/compute/compute.h
+++ b/modules/platforms/cpp/ignite/client/compute/compute.h
@@ -101,7 +101,7 @@ public:
     }
 
     /**
-     * Executes a compute job represented by the given class on one of the 
specified nodes asynchronously.
+     * Asynchronously executes a job represented by the given class on one 
node where the given key is located.
      *
      * @param tableName Name of the table to be used with @c key to determine 
target node.
      * @param key Table key to be used to determine the target node for job 
execution.
diff --git 
a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp 
b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp
index 4cd9a00335..ef845a3ff6 100644
--- a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp
+++ b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.cpp
@@ -66,4 +66,52 @@ void compute_impl::execute_on_one_node(cluster_node node, 
std::string_view job_c
         client_operation::COMPUTE_EXECUTE, writer_func, 
std::move(reader_func), std::move(callback));
 }
 
+void compute_impl::execute_colocated_async(const std::string &table_name, 
const ignite_tuple &key,
+    std::string_view job, const std::vector<primitive> &args,
+    ignite_callback<std::optional<primitive>> callback) {
+    m_tables->get_table_async(table_name,
+        [table_name, callback = std::move(callback), key, job = 
std::string(job), args, conn = m_connection]
+        (auto &&res) mutable {
+        if (res.has_error()) {
+            callback({std::move(res.error())});
+            return;
+        }
+        auto &table_opt = res.value();
+        if (!table_opt) {
+            callback({ignite_error("Table does not exist: '" + table_name + 
"'")});
+            return;
+        }
+
+        auto table = table_impl::from_facade(*table_opt);
+        table->template 
with_latest_schema_async<std::optional<primitive>>(std::move(callback),
+            [table, key = std::move(key), job = std::move(job), args = 
std::move(args), conn] // NOLINT(performance-move-const-arg)
+            (const schema& sch, auto callback) mutable {
+                auto writer_func = [&key, &sch, &table, &job](protocol::writer 
&writer) {
+                    writer.write(table->get_id());
+                    writer.write(sch.version);
+                    write_tuple(writer, sch, key, true);
+                    writer.write(job);
+                    // TODO: write arguments.
+                };
+
+                auto reader_func = [](protocol::reader &reader) -> 
std::optional<primitive> {
+                    if (reader.try_read_nil())
+                        return std::nullopt;
+
+                    // TODO: Tuple to object.
+                    auto tuple_data = reader.read_binary();
+                    ignite_tuple res(3);
+                    binary_tuple_parser parser(3, tuple_data);
+                    auto typ = 
column_type(binary_tuple_parser::get_int32(*parser.get_next()));
+                    auto scale = 
binary_tuple_parser::get_int32(*parser.get_next());
+
+                    return read_next_column(parser, typ, scale);
+                };
+
+                conn->perform_request<std::optional<primitive>>(
+                    client_operation::COMPUTE_EXECUTE_COLOCATED, writer_func, 
std::move(reader_func), std::move(callback));
+            });
+        });
+}
+
 } // namespace ignite::detail
diff --git a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h 
b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h
index 7328d402f3..222c22481c 100644
--- a/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h
+++ b/modules/platforms/cpp/ignite/client/detail/compute/compute_impl.h
@@ -18,8 +18,10 @@
 #pragma once
 
 #include "ignite/client/detail/cluster_connection.h"
+#include "ignite/client/detail/table/tables_impl.h"
 #include "ignite/client/network/cluster_node.h"
 #include "ignite/client/primitive.h"
+#include "ignite/client/table/ignite_tuple.h"
 #include "ignite/common/ignite_result.h"
 
 #include <memory>
@@ -39,8 +41,9 @@ public:
      *
      * @param connection Connection.
      */
-    explicit compute_impl(std::shared_ptr<cluster_connection> connection)
-        : m_connection(std::move(connection)) {}
+    explicit compute_impl(std::shared_ptr<cluster_connection> connection, 
std::shared_ptr<tables_impl> tables)
+        : m_connection(std::move(connection))
+        , m_tables(std::move(tables)) {}
 
     /**
      * Executes a compute job represented by the given class on the specified 
node asynchronously.
@@ -53,9 +56,25 @@ public:
     void execute_on_one_node(cluster_node node, std::string_view 
job_class_name, const std::vector<primitive>& args,
         ignite_callback<std::optional<primitive>> callback);
 
+    /**
+     * Asynchronously executes a job represented by the given class on one 
node where the given key is located.
+     *
+     * @param tableName Name of the table to be used with @c key to determine 
target node.
+     * @param key Table key to be used to determine the target node for job 
execution.
+     * @param job_class_name Java class name of the job to execute.
+     * @param args Job arguments.
+     * @param callback A callback called on operation completion with job 
execution result.
+     */
+    void execute_colocated_async(const std::string &table_name, const 
ignite_tuple& key,
+        std::string_view job_class_name, const std::vector<primitive>& args,
+        ignite_callback<std::optional<primitive>> callback);
+
 private:
     /** Cluster connection. */
     std::shared_ptr<cluster_connection> m_connection;
+
+    /** Tables. */
+    std::shared_ptr<tables_impl> m_tables;
 };
 
 } // namespace ignite::detail
diff --git a/modules/platforms/cpp/ignite/client/detail/ignite_client_impl.h 
b/modules/platforms/cpp/ignite/client/detail/ignite_client_impl.h
index 55274053f5..6357252e50 100644
--- a/modules/platforms/cpp/ignite/client/detail/ignite_client_impl.h
+++ b/modules/platforms/cpp/ignite/client/detail/ignite_client_impl.h
@@ -53,7 +53,7 @@ public:
         , m_connection(cluster_connection::create(m_configuration))
         , m_tables(std::make_shared<tables_impl>(m_connection))
         , m_sql(std::make_shared<sql_impl>(m_connection))
-        , m_compute(std::make_shared<compute_impl>(m_connection))
+        , m_compute(std::make_shared<compute_impl>(m_connection, m_tables))
         , m_transactions(std::make_shared<transactions_impl>(m_connection)) {}
 
     /**
diff --git a/modules/platforms/cpp/ignite/client/detail/table/table_impl.cpp 
b/modules/platforms/cpp/ignite/client/detail/table/table_impl.cpp
index 221aa2238d..eb6b3a4db9 100644
--- a/modules/platforms/cpp/ignite/client/detail/table/table_impl.cpp
+++ b/modules/platforms/cpp/ignite/client/detail/table/table_impl.cpp
@@ -18,226 +18,17 @@
 #include "ignite/client/detail/table/table_impl.h"
 #include "ignite/client/detail/transaction/transaction_impl.h"
 #include "ignite/client/detail/utils.h"
+#include "ignite/client/table/table.h"
 
 #include "ignite/common/bits.h"
 #include "ignite/common/ignite_error.h"
 #include "ignite/protocol/bitset_span.h"
 #include "ignite/protocol/reader.h"
 #include "ignite/protocol/writer.h"
-#include "ignite/schema/binary_tuple_builder.h"
 #include "ignite/schema/binary_tuple_parser.h"
 
 namespace ignite::detail {
 
-/**
- * Claim space for the column.
- *
- * @param builder Binary tuple builder.
- * @param typ Column type.
- * @param value Value.
- * @param scale Column scale.
- */
-void claim_column(binary_tuple_builder &builder, ignite_type typ, const 
primitive &value, std::int32_t scale) {
-    switch (typ) {
-        case ignite_type::INT8:
-            builder.claim_int8(value.get<std::int8_t>());
-            break;
-        case ignite_type::INT16:
-            builder.claim_int16(value.get<std::int16_t>());
-            break;
-        case ignite_type::INT32:
-            builder.claim_int32(value.get<std::int32_t>());
-            break;
-        case ignite_type::INT64:
-            builder.claim_int64(value.get<std::int64_t>());
-            break;
-        case ignite_type::FLOAT:
-            builder.claim_float(value.get<float>());
-            break;
-        case ignite_type::DOUBLE:
-            builder.claim_double(value.get<double>());
-            break;
-        case ignite_type::UUID:
-            builder.claim_uuid(value.get<uuid>());
-            break;
-        case ignite_type::STRING:
-            builder.claim_string(value.get<std::string>());
-            break;
-        case ignite_type::BINARY:
-            builder.claim_bytes(value.get<std::vector<std::byte>>());
-            break;
-        case ignite_type::DECIMAL: {
-            big_decimal to_write;
-            value.get<big_decimal>().set_scale(scale, to_write);
-            builder.claim_number(to_write);
-            break;
-        }
-        case ignite_type::NUMBER:
-            builder.claim_number(value.get<big_integer>());
-            break;
-        case ignite_type::DATE:
-            builder.claim_date(value.get<ignite_date>());
-            break;
-        case ignite_type::TIME:
-            builder.claim_time(value.get<ignite_time>());
-            break;
-        case ignite_type::DATETIME:
-            builder.claim_date_time(value.get<ignite_date_time>());
-            break;
-        case ignite_type::TIMESTAMP:
-            builder.claim_timestamp(value.get<ignite_timestamp>());
-            break;
-        case ignite_type::BITMASK:
-            builder.claim_bytes(value.get<bit_array>().get_raw());
-            break;
-        default:
-            throw ignite_error("Type with id " + std::to_string(int(typ)) + " 
is not yet supported");
-    }
-}
-
-/**
- * Append column value to binary tuple.
- *
- * @param builder Binary tuple builder.
- * @param typ Column type.
- * @param value Value.
- * @param scale Column scale.
- */
-void append_column(binary_tuple_builder &builder, ignite_type typ, const 
primitive &value, std::int32_t scale) {
-    switch (typ) {
-        case ignite_type::INT8:
-            builder.append_int8(value.get<std::int8_t>());
-            break;
-        case ignite_type::INT16:
-            builder.append_int16(value.get<std::int16_t>());
-            break;
-        case ignite_type::INT32:
-            builder.append_int32(value.get<std::int32_t>());
-            break;
-        case ignite_type::INT64:
-            builder.append_int64(value.get<std::int64_t>());
-            break;
-        case ignite_type::FLOAT:
-            builder.append_float(value.get<float>());
-            break;
-        case ignite_type::DOUBLE:
-            builder.append_double(value.get<double>());
-            break;
-        case ignite_type::UUID:
-            builder.append_uuid(value.get<uuid>());
-            break;
-        case ignite_type::STRING:
-            builder.append_string(value.get<std::string>());
-            break;
-        case ignite_type::BINARY:
-            builder.append_bytes(value.get<std::vector<std::byte>>());
-            break;
-        case ignite_type::DECIMAL: {
-            big_decimal to_write;
-            value.get<big_decimal>().set_scale(scale, to_write);
-            builder.append_number(to_write);
-            break;
-        }
-        case ignite_type::NUMBER:
-            builder.append_number(value.get<big_integer>());
-            break;
-        case ignite_type::DATE:
-            builder.append_date(value.get<ignite_date>());
-            break;
-        case ignite_type::TIME:
-            builder.append_time(value.get<ignite_time>());
-            break;
-        case ignite_type::DATETIME:
-            builder.append_date_time(value.get<ignite_date_time>());
-            break;
-        case ignite_type::TIMESTAMP:
-            builder.append_timestamp(value.get<ignite_timestamp>());
-            break;
-        case ignite_type::BITMASK:
-            builder.append_bytes(value.get<bit_array>().get_raw());
-            break;
-        default:
-            throw ignite_error("Type with id " + std::to_string(int(typ)) + " 
is not yet supported");
-    }
-}
-
-/**
- * Serialize tuple using table schema.
- *
- * @param sch Schema.
- * @param tuple Tuple.
- * @param key_only Should only key fields be serialized.
- * @param no_value No value bitset.
- * @return Serialized binary tuple.
- */
-std::vector<std::byte> pack_tuple(
-    const schema &sch, const ignite_tuple &tuple, bool key_only, 
protocol::bitset_span &no_value) {
-    auto count = std::int32_t(key_only ? sch.key_column_count : 
sch.columns.size());
-    binary_tuple_builder builder{count};
-
-    builder.start();
-
-    for (std::int32_t i = 0; i < count; ++i) {
-        const auto &col = sch.columns[i];
-        auto col_idx = tuple.column_ordinal(col.name);
-
-        if (col_idx >= 0)
-            claim_column(builder, col.type, tuple.get(col_idx), col.scale);
-        else
-            builder.claim(std::nullopt);
-    }
-
-    builder.layout();
-    for (std::int32_t i = 0; i < count; ++i) {
-        const auto &col = sch.columns[i];
-        auto col_idx = tuple.column_ordinal(col.name);
-
-        if (col_idx >= 0)
-            append_column(builder, col.type, tuple.get(col_idx), col.scale);
-        else {
-            builder.append(std::nullopt);
-            no_value.set(std::size_t(i));
-        }
-    }
-
-    return builder.build();
-}
-
-/**
- * Write tuple using table schema and writer.
- *
- * @param writer Writer.
- * @param sch Schema.
- * @param tuple Tuple.
- * @param key_only Should only key fields be written or not.
- */
-void write_tuple(protocol::writer &writer, const schema &sch, const 
ignite_tuple &tuple, bool key_only) {
-    const std::size_t count = key_only ? sch.key_column_count : 
sch.columns.size();
-    const std::size_t bytes_num = bytes_for_bits(count);
-
-    auto no_value_bytes = reinterpret_cast<std::byte *>(alloca(bytes_num));
-    protocol::bitset_span no_value(no_value_bytes, bytes_num);
-
-    auto tuple_data = pack_tuple(sch, tuple, key_only, no_value);
-
-    writer.write_bitset(no_value.data());
-    writer.write_binary(tuple_data);
-}
-
-/**
- * Write tuples using table schema and writer.
- *
- * @param writer Writer.
- * @param sch Schema.
- * @param tuples Tuples.
- * @param key_only Should only key fields be written or not.
- */
-void write_tuples(protocol::writer &writer, const schema &sch, const 
std::vector<ignite_tuple> &tuples, bool key_only) {
-    writer.write(std::int32_t(tuples.size()));
-    for (auto &tuple : tuples)
-        write_tuple(writer, sch, tuple, key_only);
-}
-
 /**
  * Write table operation header.
  *
@@ -696,4 +487,8 @@ void table_impl::remove_all_exact_async(
         });
 }
 
+std::shared_ptr<table_impl> table_impl::from_facade(table &tb) {
+    return tb.m_impl;
+}
+
 } // namespace ignite::detail
diff --git a/modules/platforms/cpp/ignite/client/detail/table/table_impl.h 
b/modules/platforms/cpp/ignite/client/detail/table/table_impl.h
index ed69979038..5b88f3b29b 100644
--- a/modules/platforms/cpp/ignite/client/detail/table/table_impl.h
+++ b/modules/platforms/cpp/ignite/client/detail/table/table_impl.h
@@ -27,6 +27,10 @@
 #include <mutex>
 #include <unordered_map>
 
+namespace ignite {
+class table;
+}
+
 namespace ignite::detail {
 
 /**
@@ -284,6 +288,23 @@ public:
     void remove_all_exact_async(
         transaction *tx, std::vector<ignite_tuple> records, 
ignite_callback<std::vector<ignite_tuple>> callback);
 
+    /**
+     * Extract implementation from facade.
+     *
+     * @param tb Table.
+     * @return Implementation.
+     */
+    [[nodiscard]] static std::shared_ptr<table_impl> from_facade(table& tb);
+
+    /**
+     * Get table ID.
+     *
+     * @return ID.
+     */
+    [[nodiscard]] uuid get_id() const {
+        return m_id;
+    }
+
 private:
     /**
      * Load latest schema from server asynchronously.
diff --git a/modules/platforms/cpp/ignite/client/detail/utils.cpp 
b/modules/platforms/cpp/ignite/client/detail/utils.cpp
index 60a5aa9e79..7e66c97ab0 100644
--- a/modules/platforms/cpp/ignite/client/detail/utils.cpp
+++ b/modules/platforms/cpp/ignite/client/detail/utils.cpp
@@ -16,12 +16,187 @@
  */
 
 #include "ignite/client/detail/utils.h"
+#include "ignite/common/bits.h"
 #include "ignite/common/uuid.h"
 
 #include <string>
 
 namespace ignite::detail {
 
+/**
+ * Claim space for the column.
+ *
+ * @param builder Binary tuple builder.
+ * @param typ Column type.
+ * @param value Value.
+ * @param scale Column scale.
+ */
+void claim_column(binary_tuple_builder &builder, ignite_type typ, const 
primitive &value, std::int32_t scale) {
+    switch (typ) {
+        case ignite_type::INT8:
+            builder.claim_int8(value.get<std::int8_t>());
+            break;
+        case ignite_type::INT16:
+            builder.claim_int16(value.get<std::int16_t>());
+            break;
+        case ignite_type::INT32:
+            builder.claim_int32(value.get<std::int32_t>());
+            break;
+        case ignite_type::INT64:
+            builder.claim_int64(value.get<std::int64_t>());
+            break;
+        case ignite_type::FLOAT:
+            builder.claim_float(value.get<float>());
+            break;
+        case ignite_type::DOUBLE:
+            builder.claim_double(value.get<double>());
+            break;
+        case ignite_type::UUID:
+            builder.claim_uuid(value.get<uuid>());
+            break;
+        case ignite_type::STRING:
+            builder.claim_string(value.get<std::string>());
+            break;
+        case ignite_type::BINARY:
+            builder.claim_bytes(value.get<std::vector<std::byte>>());
+            break;
+        case ignite_type::DECIMAL: {
+            big_decimal to_write;
+            value.get<big_decimal>().set_scale(scale, to_write);
+            builder.claim_number(to_write);
+            break;
+        }
+        case ignite_type::NUMBER:
+            builder.claim_number(value.get<big_integer>());
+            break;
+        case ignite_type::DATE:
+            builder.claim_date(value.get<ignite_date>());
+            break;
+        case ignite_type::TIME:
+            builder.claim_time(value.get<ignite_time>());
+            break;
+        case ignite_type::DATETIME:
+            builder.claim_date_time(value.get<ignite_date_time>());
+            break;
+        case ignite_type::TIMESTAMP:
+            builder.claim_timestamp(value.get<ignite_timestamp>());
+            break;
+        case ignite_type::BITMASK:
+            builder.claim_bytes(value.get<bit_array>().get_raw());
+            break;
+        default:
+            throw ignite_error("Type with id " + std::to_string(int(typ)) + " 
is not yet supported");
+    }
+}
+
+/**
+ * Append column value to binary tuple.
+ *
+ * @param builder Binary tuple builder.
+ * @param typ Column type.
+ * @param value Value.
+ * @param scale Column scale.
+ */
+void append_column(binary_tuple_builder &builder, ignite_type typ, const 
primitive &value, std::int32_t scale) {
+    switch (typ) {
+        case ignite_type::INT8:
+            builder.append_int8(value.get<std::int8_t>());
+            break;
+        case ignite_type::INT16:
+            builder.append_int16(value.get<std::int16_t>());
+            break;
+        case ignite_type::INT32:
+            builder.append_int32(value.get<std::int32_t>());
+            break;
+        case ignite_type::INT64:
+            builder.append_int64(value.get<std::int64_t>());
+            break;
+        case ignite_type::FLOAT:
+            builder.append_float(value.get<float>());
+            break;
+        case ignite_type::DOUBLE:
+            builder.append_double(value.get<double>());
+            break;
+        case ignite_type::UUID:
+            builder.append_uuid(value.get<uuid>());
+            break;
+        case ignite_type::STRING:
+            builder.append_string(value.get<std::string>());
+            break;
+        case ignite_type::BINARY:
+            builder.append_bytes(value.get<std::vector<std::byte>>());
+            break;
+        case ignite_type::DECIMAL: {
+            big_decimal to_write;
+            value.get<big_decimal>().set_scale(scale, to_write);
+            builder.append_number(to_write);
+            break;
+        }
+        case ignite_type::NUMBER:
+            builder.append_number(value.get<big_integer>());
+            break;
+        case ignite_type::DATE:
+            builder.append_date(value.get<ignite_date>());
+            break;
+        case ignite_type::TIME:
+            builder.append_time(value.get<ignite_time>());
+            break;
+        case ignite_type::DATETIME:
+            builder.append_date_time(value.get<ignite_date_time>());
+            break;
+        case ignite_type::TIMESTAMP:
+            builder.append_timestamp(value.get<ignite_timestamp>());
+            break;
+        case ignite_type::BITMASK:
+            builder.append_bytes(value.get<bit_array>().get_raw());
+            break;
+        default:
+            throw ignite_error("Type with id " + std::to_string(int(typ)) + " 
is not yet supported");
+    }
+}
+
+/**
+ * Serialize tuple using table schema.
+ *
+ * @param sch Schema.
+ * @param tuple Tuple.
+ * @param key_only Should only key fields be serialized.
+ * @param no_value No value bitset.
+ * @return Serialized binary tuple.
+ */
+std::vector<std::byte> pack_tuple(
+    const schema &sch, const ignite_tuple &tuple, bool key_only, 
protocol::bitset_span &no_value) {
+    auto count = std::int32_t(key_only ? sch.key_column_count : 
sch.columns.size());
+    binary_tuple_builder builder{count};
+
+    builder.start();
+
+    for (std::int32_t i = 0; i < count; ++i) {
+        const auto &col = sch.columns[i];
+        auto col_idx = tuple.column_ordinal(col.name);
+
+        if (col_idx >= 0)
+            claim_column(builder, col.type, tuple.get(col_idx), col.scale);
+        else
+            builder.claim(std::nullopt);
+    }
+
+    builder.layout();
+    for (std::int32_t i = 0; i < count; ++i) {
+        const auto &col = sch.columns[i];
+        auto col_idx = tuple.column_ordinal(col.name);
+
+        if (col_idx >= 0)
+            append_column(builder, col.type, tuple.get(col_idx), col.scale);
+        else {
+            builder.append(std::nullopt);
+            no_value.set(std::size_t(i));
+        }
+    }
+
+    return builder.build();
+}
+
 /**
  * Claim type and scale header for a value written in binary tuple.
  *
@@ -362,4 +537,23 @@ ignite_tuple concat(const ignite_tuple &left, const 
ignite_tuple &right) {
     return res;
 }
 
+void write_tuple(protocol::writer &writer, const schema &sch, const 
ignite_tuple &tuple, bool key_only) {
+    const std::size_t count = key_only ? sch.key_column_count : 
sch.columns.size();
+    const std::size_t bytes_num = bytes_for_bits(count);
+
+    auto no_value_bytes = reinterpret_cast<std::byte *>(alloca(bytes_num));
+    protocol::bitset_span no_value(no_value_bytes, bytes_num);
+
+    auto tuple_data = pack_tuple(sch, tuple, key_only, no_value);
+
+    writer.write_bitset(no_value.data());
+    writer.write_binary(tuple_data);
+}
+
+void write_tuples(protocol::writer &writer, const schema &sch, const 
std::vector<ignite_tuple> &tuples, bool key_only) {
+    writer.write(std::int32_t(tuples.size()));
+    for (auto &tuple : tuples)
+        write_tuple(writer, sch, tuple, key_only);
+}
+
 } // namespace ignite::detail
diff --git a/modules/platforms/cpp/ignite/client/detail/utils.h 
b/modules/platforms/cpp/ignite/client/detail/utils.h
index fc248954a1..62f640d0e0 100644
--- a/modules/platforms/cpp/ignite/client/detail/utils.h
+++ b/modules/platforms/cpp/ignite/client/detail/utils.h
@@ -17,9 +17,12 @@
 
 #pragma once
 
+#include "ignite/client/detail/table/schema.h"
 #include "ignite/client/primitive.h"
 #include "ignite/client/table/ignite_tuple.h"
 #include "ignite/client/transaction/transaction.h"
+
+#include "ignite/protocol/writer.h"
 #include "ignite/schema/binary_tuple_builder.h"
 #include "ignite/schema/binary_tuple_parser.h"
 #include "ignite/schema/ignite_type.h"
@@ -71,4 +74,25 @@ void append_primitive_with_type(binary_tuple_builder 
&builder, const primitive &
  */
 [[nodiscard]] ignite_tuple concat(const ignite_tuple &left, const ignite_tuple 
&right);
 
+
+/**
+ * Write tuple using table schema and writer.
+ *
+ * @param writer Writer.
+ * @param sch Schema.
+ * @param tuple Tuple.
+ * @param key_only Should only key fields be written or not.
+ */
+void write_tuple(protocol::writer &writer, const schema &sch, const 
ignite_tuple &tuple, bool key_only);
+
+/**
+ * Write tuples using table schema and writer.
+ *
+ * @param writer Writer.
+ * @param sch Schema.
+ * @param tuples Tuples.
+ * @param key_only Should only key fields be written or not.
+ */
+void write_tuples(protocol::writer &writer, const schema &sch, const 
std::vector<ignite_tuple> &tuples, bool key_only);
+
 } // namespace ignite::detail
diff --git a/modules/platforms/cpp/ignite/client/table/table.h 
b/modules/platforms/cpp/ignite/client/table/table.h
index 4d71cb94f6..d946d93fb0 100644
--- a/modules/platforms/cpp/ignite/client/table/table.h
+++ b/modules/platforms/cpp/ignite/client/table/table.h
@@ -38,6 +38,7 @@ class tables_impl;
  * Table view.
  */
 class table {
+    friend class detail::table_impl;
     friend class detail::tables_impl;
 
 public:

Reply via email to