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

sanpwc 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 cccb376830 IGNITE-22567 Add `containsAll` to `RecordView` and 
`KeyValueView` (#4018)
cccb376830 is described below

commit cccb376830d4b3cc7456e5f7b0e0ab18c14c3d4e
Author: Mikhail Efremov <[email protected]>
AuthorDate: Thu Jul 4 15:31:15 2024 +0600

    IGNITE-22567 Add `containsAll` to `RecordView` and `KeyValueView` (#4018)
---
 .../java/org/apache/ignite/table/KeyValueView.java |  23 ++++-
 .../java/org/apache/ignite/table/RecordView.java   |  23 ++++-
 .../ignite/internal/client/proto/ClientOp.java     |   3 +
 .../handler/ClientInboundMessageHandler.java       |   4 +
 .../table/ClientTupleContainsAllKeysRequest.java   |  61 +++++++++++
 .../apache/ignite/client/ClientOperationType.java  |   5 +
 .../org/apache/ignite/client/IgniteClient.java     |   2 +-
 .../org/apache/ignite/client/RetryReadPolicy.java  |   1 +
 .../apache/ignite/internal/client/ClientUtils.java |  73 +------------
 .../ignite/internal/client/TcpClientChannel.java   |   3 +-
 .../ignite/internal/client/TcpIgniteClient.java    |   2 +-
 .../internal/client/compute/ClientCompute.java     |   4 +-
 .../internal/client/table/AbstractClientView.java  |   2 +-
 .../client/table/ClientKeyValueBinaryView.java     |  27 ++++-
 .../internal/client/table/ClientKeyValueView.java  |  27 ++++-
 .../client/table/ClientRecordBinaryView.java       |  27 ++++-
 .../internal/client/table/ClientRecordView.java    |  27 ++++-
 .../ignite/internal/client/table/ClientTables.java |   2 +-
 .../internal/client/tx/ClientTransaction.java      |   2 +-
 .../internal/client/tx/ClientTransactions.java     |   2 +-
 .../apache/ignite/client/ClientApiArchTest.java    |   5 +-
 .../client/ClientKeyValueBinaryViewTest.java       |  28 +++++
 .../ignite/client/ClientKeyValueViewTest.java      |  29 ++++++
 .../apache/ignite/client/ClientRecordViewTest.java |  41 ++++++++
 .../org/apache/ignite/client/ClientTableTest.java  |  53 ++++++++++
 .../ignite/internal/client/ClientUtilsTest.java    |   3 +-
 .../org/apache/ignite/internal/util/ViewUtils.java | 115 +++++++++++++++++++++
 .../sql/engine/ItPkOnlyTableCrossApiTest.java      |   2 +-
 .../ignite/internal/table/AbstractTableView.java   |  24 +----
 .../internal/table/KeyValueBinaryViewImpl.java     |  39 +++++--
 .../ignite/internal/table/KeyValueViewImpl.java    |  41 ++++++--
 .../table/PublicApiThreadingKeyValueView.java      |  10 ++
 .../table/PublicApiThreadingRecordView.java        |  10 ++
 .../internal/table/RecordBinaryViewImpl.java       |  33 ++++++
 .../ignite/internal/table/RecordViewImpl.java      |  33 ++++++
 .../table/KeyValueBinaryViewOperationsTest.java    |  40 +++++++
 .../internal/table/KeyValueViewOperationsTest.java |  34 ++++++
 .../table/RecordBinaryViewOperationsTest.java      |  45 ++++++++
 .../internal/table/RecordViewOperationsTest.java   |  37 +++++++
 39 files changed, 814 insertions(+), 128 deletions(-)

diff --git 
a/modules/api/src/main/java/org/apache/ignite/table/KeyValueView.java 
b/modules/api/src/main/java/org/apache/ignite/table/KeyValueView.java
index 76a9e7b929..c3940e2752 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/KeyValueView.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/KeyValueView.java
@@ -142,7 +142,7 @@ public interface KeyValueView<K, V> extends 
DataStreamerTarget<Entry<K, V>>, Cri
      *
      * @param tx Transaction or {@code null} to auto-commit.
      * @param key Key whose presence is to be verified. The key cannot be 
{@code null}.
-     * @return {@code True} if a value exists for the specified key, {@code 
false} otherwise.
+     * @return {@code True} if a value exists for every specified key, {@code 
false} otherwise.
      * @throws MarshallerException if the key doesn't match the schema.
      */
     boolean contains(@Nullable Transaction tx, K key);
@@ -157,6 +157,27 @@ public interface KeyValueView<K, V> extends 
DataStreamerTarget<Entry<K, V>>, Cri
      */
     CompletableFuture<Boolean> containsAsync(@Nullable Transaction tx, K key);
 
+    /**
+     * Determines whether a table contains entries for all given keys.
+     *
+     * @param tx Transaction or {@code null} to auto-commit.
+     * @param keys Keys whose presence is to be verified. The collection and 
it's values cannot be {@code null}.
+     * @return {@code True} if a value exists for every specified key, {@code 
false} otherwise.
+     * @throws MarshallerException if the key doesn't match the schema.
+     */
+    boolean containsAll(@Nullable Transaction tx, Collection<K> keys);
+
+    /**
+     * Determines whether a table contains entries for all given keys.
+     *
+     * @param tx Transaction or {@code null} to auto-commit.
+     * @param keys Keys whose presence is to be verified. The collection and 
it's values cannot be {@code null}.
+     * @return Future that represents the pending completion of the operation. 
The result of the future will be {@code true} if a value
+     *      exists for every specified key, {@code false} otherwise.
+     * @throws MarshallerException if the key doesn't match the schema.
+     */
+    CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction tx, 
Collection<K> keys);
+
     /**
      * Puts into a table a value associated with the given key.
      *
diff --git a/modules/api/src/main/java/org/apache/ignite/table/RecordView.java 
b/modules/api/src/main/java/org/apache/ignite/table/RecordView.java
index cbe91746ea..846e846393 100644
--- a/modules/api/src/main/java/org/apache/ignite/table/RecordView.java
+++ b/modules/api/src/main/java/org/apache/ignite/table/RecordView.java
@@ -77,7 +77,7 @@ public interface RecordView<R> extends DataStreamerTarget<R>, 
CriteriaQuerySourc
      *
      * @param tx Transaction or {@code null} to auto-commit.
      * @param keyRec A record with key columns set. The key cannot be {@code 
null}.
-     * @return {@code True} if a value exists for the specified key, {@code 
false} otherwise.
+     * @return {@code True} if a value exists for every specified key, {@code 
false} otherwise.
      * @throws MarshallerException if the key doesn't match the schema.
      */
     boolean contains(@Nullable Transaction tx, R keyRec);
@@ -92,6 +92,27 @@ public interface RecordView<R> extends 
DataStreamerTarget<R>, CriteriaQuerySourc
      */
     CompletableFuture<Boolean> containsAsync(@Nullable Transaction tx, R 
keyRec);
 
+    /**
+     * Determines whether a table contains entries for all given keys.
+     *
+     * @param tx Transaction or {@code null} to auto-commit.
+     * @param keys Keys whose presence is to be verified. The collection and 
it's values cannot be {@code null}.
+     * @return {@code True} if a value exists for every specified key, {@code 
false} otherwise.
+     * @throws MarshallerException if the key doesn't match the schema.
+     */
+    boolean containsAll(@Nullable Transaction tx, Collection<R> keys);
+
+    /**
+     * Determines whether a table contains entries for all given keys.
+     *
+     * @param tx Transaction or {@code null} to auto-commit.
+     * @param keys Keys whose presence is to be verified. The collection and 
it's values cannot be {@code null}.
+     * @return Future that represents the pending completion of the operation. 
The result of the future will be {@code true} if a value
+     *      exists for every specified key, {@code false} otherwise.
+     * @throws MarshallerException if the key doesn't match the schema.
+     */
+    CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction tx, 
Collection<R> keys);
+
     /**
      * Inserts a record into a table, if it does not exist, or replaces an 
existing one.
      *
diff --git 
a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientOp.java
 
b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientOp.java
index 45706d23a7..f48959a018 100644
--- 
a/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientOp.java
+++ 
b/modules/client-common/src/main/java/org/apache/ignite/internal/client/proto/ClientOp.java
@@ -176,4 +176,7 @@ public class ClientOp {
 
     /** Send streamer batch with receiver. */
     public static final int STREAMER_WITH_RECEIVER_BATCH_SEND = 66;
+
+    /** Check if all tuples with the given keys collection exist. */
+    public static final int TUPLE_CONTAINS_ALL_KEYS = 67;
 }
diff --git 
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/ClientInboundMessageHandler.java
 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/ClientInboundMessageHandler.java
index a1f40a502f..8a58f478fa 100644
--- 
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/ClientInboundMessageHandler.java
+++ 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/ClientInboundMessageHandler.java
@@ -74,6 +74,7 @@ import 
org.apache.ignite.client.handler.requests.table.ClientStreamerWithReceive
 import org.apache.ignite.client.handler.requests.table.ClientTableGetRequest;
 import 
org.apache.ignite.client.handler.requests.table.ClientTablePartitionPrimaryReplicasGetRequest;
 import org.apache.ignite.client.handler.requests.table.ClientTablesGetRequest;
+import 
org.apache.ignite.client.handler.requests.table.ClientTupleContainsAllKeysRequest;
 import 
org.apache.ignite.client.handler.requests.table.ClientTupleContainsKeyRequest;
 import 
org.apache.ignite.client.handler.requests.table.ClientTupleDeleteAllExactRequest;
 import 
org.apache.ignite.client.handler.requests.table.ClientTupleDeleteAllRequest;
@@ -692,6 +693,9 @@ public class ClientInboundMessageHandler extends 
ChannelInboundHandlerAdapter im
             case ClientOp.TUPLE_CONTAINS_KEY:
                 return ClientTupleContainsKeyRequest.process(in, out, 
igniteTables, resources);
 
+            case ClientOp.TUPLE_CONTAINS_ALL_KEYS:
+                return ClientTupleContainsAllKeysRequest.process(in, out, 
igniteTables, resources);
+
             case ClientOp.JDBC_CONNECT:
                 return ClientJdbcConnectRequest.execute(in, out, 
jdbcQueryEventHandler);
 
diff --git 
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/table/ClientTupleContainsAllKeysRequest.java
 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/table/ClientTupleContainsAllKeysRequest.java
new file mode 100644
index 0000000000..3e10a3fd0b
--- /dev/null
+++ 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/table/ClientTupleContainsAllKeysRequest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.client.handler.requests.table;
+
+import static 
org.apache.ignite.client.handler.requests.table.ClientTableCommon.readTableAsync;
+import static 
org.apache.ignite.client.handler.requests.table.ClientTableCommon.readTuples;
+import static 
org.apache.ignite.client.handler.requests.table.ClientTableCommon.readTx;
+
+import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.client.handler.ClientResourceRegistry;
+import org.apache.ignite.internal.client.proto.ClientMessagePacker;
+import org.apache.ignite.internal.client.proto.ClientMessageUnpacker;
+import org.apache.ignite.table.IgniteTables;
+
+/**
+ * Client tuple contains all keys request.
+ */
+public class ClientTupleContainsAllKeysRequest {
+    /**
+     * Processes the request.
+     *
+     * @param in        Unpacker.
+     * @param out       Packer.
+     * @param tables    Ignite tables.
+     * @param resources Resource registry.
+     * @return Future.
+     */
+    public static CompletableFuture<Void> process(
+            ClientMessageUnpacker in,
+            ClientMessagePacker out,
+            IgniteTables tables,
+            ClientResourceRegistry resources
+    ) {
+        return readTableAsync(in, tables).thenCompose(table -> {
+            var tx = readTx(in, out, resources);
+            return readTuples(in, table, true).thenCompose(keyTuples -> table
+                    .recordView()
+                    .containsAllAsync(tx, keyTuples)
+                    .thenAccept(containsAll -> {
+                        
out.packInt(table.schemaView().lastKnownSchemaVersion());
+                        out.packBoolean(containsAll);
+                    })
+            );
+        });
+    }
+}
diff --git 
a/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java
 
b/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java
index a5b37d8fe0..b8c97c8dda 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/client/ClientOperationType.java
@@ -129,6 +129,11 @@ public enum ClientOperationType {
      */
     TUPLE_CONTAINS_KEY,
 
+    /**
+     * Contains All Keys ({@link 
org.apache.ignite.table.KeyValueView#containsAll(Transaction, Collection)}).
+     */
+    TUPLE_CONTAINS_ALL_KEYS,
+
     /**
      * Compute Execute ({@link 
org.apache.ignite.compute.IgniteCompute#submit(JobTarget, JobDescriptor, 
Object)}).
      */
diff --git 
a/modules/client/src/main/java/org/apache/ignite/client/IgniteClient.java 
b/modules/client/src/main/java/org/apache/ignite/client/IgniteClient.java
index 75eb23d893..7b3e84c260 100644
--- a/modules/client/src/main/java/org/apache/ignite/client/IgniteClient.java
+++ b/modules/client/src/main/java/org/apache/ignite/client/IgniteClient.java
@@ -24,7 +24,7 @@ import static 
org.apache.ignite.client.IgniteClientConfiguration.DFLT_OPERATION_
 import static 
org.apache.ignite.client.IgniteClientConfiguration.DFLT_RECONNECT_INTERVAL;
 import static 
org.apache.ignite.client.IgniteClientConfiguration.DFLT_RECONNECT_THROTTLING_PERIOD;
 import static 
org.apache.ignite.client.IgniteClientConfiguration.DFLT_RECONNECT_THROTTLING_RETRIES;
-import static org.apache.ignite.internal.client.ClientUtils.sync;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.List;
 import java.util.Objects;
diff --git 
a/modules/client/src/main/java/org/apache/ignite/client/RetryReadPolicy.java 
b/modules/client/src/main/java/org/apache/ignite/client/RetryReadPolicy.java
index e5af02e18e..15f0a6540a 100644
--- a/modules/client/src/main/java/org/apache/ignite/client/RetryReadPolicy.java
+++ b/modules/client/src/main/java/org/apache/ignite/client/RetryReadPolicy.java
@@ -31,6 +31,7 @@ public class RetryReadPolicy extends RetryLimitPolicy {
         switch (context.operation()) {
             case TABLES_GET:
             case TUPLE_CONTAINS_KEY:
+            case TUPLE_CONTAINS_ALL_KEYS:
             case TUPLE_GET_ALL:
             case TUPLE_GET:
             case TABLE_GET:
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/ClientUtils.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/ClientUtils.java
index ff886ef002..ea48fd6346 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/ClientUtils.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/ClientUtils.java
@@ -17,87 +17,17 @@
 
 package org.apache.ignite.internal.client;
 
-import static org.apache.ignite.lang.ErrorGroups.Common.INTERNAL_ERR;
-
-import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
 import org.apache.ignite.client.ClientOperationType;
 import org.apache.ignite.client.IgniteClientConfiguration;
 import org.apache.ignite.internal.client.proto.ClientOp;
-import org.apache.ignite.internal.lang.IgniteExceptionMapperUtil;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
-import org.apache.ignite.internal.util.ExceptionUtils;
-import org.apache.ignite.lang.IgniteCheckedException;
-import org.apache.ignite.lang.IgniteException;
 import org.apache.ignite.lang.LoggerFactory;
-import org.apache.ignite.lang.TraceableException;
 
 /**
  * Client utilities.
  */
 public class ClientUtils {
-    /**
-     * Wraps an exception in an IgniteException, extracting trace identifier 
and error code when the specified exception or one of its
-     * causes is an IgniteException itself.
-     *
-     * @param e Internal exception.
-     * @return Public exception.
-     */
-    public static Throwable ensurePublicException(Throwable e) {
-        Objects.requireNonNull(e);
-
-        e = ExceptionUtils.unwrapCause(e);
-
-        if (e instanceof IgniteException) {
-            return copyExceptionWithCauseIfPossible((IgniteException) e);
-        }
-
-        if (e instanceof IgniteCheckedException) {
-            return copyExceptionWithCauseIfPossible((IgniteCheckedException) 
e);
-        }
-
-        e = IgniteExceptionMapperUtil.mapToPublicException(e);
-
-        return new IgniteException(INTERNAL_ERR, e.getMessage(), e);
-    }
-
-    /**
-     * Try to copy exception using ExceptionUtils.copyExceptionWithCause and 
return new exception if it was not possible.
-     *
-     * @param e Exception.
-     * @return Properly copied exception or a new error, if exception can not 
be copied.
-     */
-    private static <T extends Throwable & TraceableException> Throwable 
copyExceptionWithCauseIfPossible(T e) {
-        Throwable copy = ExceptionUtils.copyExceptionWithCause(e.getClass(), 
e.traceId(), e.code(), e.getMessage(), e);
-        if (copy != null) {
-            return copy;
-        }
-
-        return new IgniteException(INTERNAL_ERR, "Public Ignite 
exception-derived class does not have required constructor: "
-                + e.getClass().getName(), e);
-    }
-
-    /**
-     * Waits for async operation completion.
-     *
-     * @param fut Future to wait to.
-     * @param <T> Future result type.
-     * @return Future result.
-     */
-    public static <T> T sync(CompletableFuture<T> fut) {
-        try {
-            return fut.get();
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt(); // Restore interrupt flag.
-
-            throw ExceptionUtils.sneakyThrow(ensurePublicException(e));
-        } catch (ExecutionException e) {
-            throw ExceptionUtils.sneakyThrow(ensurePublicException(e));
-        }
-    }
-
     /**
      * Converts internal op code to public {@link ClientOperationType}.
      *
@@ -170,6 +100,9 @@ public class ClientUtils {
             case ClientOp.TUPLE_CONTAINS_KEY:
                 return ClientOperationType.TUPLE_CONTAINS_KEY;
 
+            case ClientOp.TUPLE_CONTAINS_ALL_KEYS:
+                return ClientOperationType.TUPLE_CONTAINS_ALL_KEYS;
+
             case ClientOp.JDBC_CONNECT:
                 return null;
 
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/TcpClientChannel.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/TcpClientChannel.java
index 30e4faf85a..252505e5f4 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/TcpClientChannel.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/TcpClientChannel.java
@@ -54,6 +54,7 @@ import 
org.apache.ignite.internal.client.proto.ProtocolVersion;
 import org.apache.ignite.internal.client.proto.ResponseFlags;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.internal.util.ViewUtils;
 import org.apache.ignite.lang.ErrorGroups.Table;
 import org.apache.ignite.lang.IgniteException;
 import org.apache.ignite.network.NetworkAddress;
@@ -361,7 +362,7 @@ class TcpClientChannel implements ClientChannel, 
ClientMessageHandler, ClientCon
 
             metrics.requestsActiveDecrement();
 
-            throw sneakyThrow(ClientUtils.ensurePublicException(t));
+            throw sneakyThrow(ViewUtils.ensurePublicException(t));
         }
     }
 
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java
index 6088023ecd..7a7f508820 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/TcpIgniteClient.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.client;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java
index f3a9aab616..061f078861 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/compute/ClientCompute.java
@@ -44,7 +44,6 @@ import org.apache.ignite.compute.JobExecutionOptions;
 import org.apache.ignite.compute.JobTarget;
 import org.apache.ignite.compute.task.TaskExecution;
 import org.apache.ignite.deployment.DeploymentUnit;
-import org.apache.ignite.internal.client.ClientUtils;
 import org.apache.ignite.internal.client.PayloadInputChannel;
 import org.apache.ignite.internal.client.PayloadOutputChannel;
 import org.apache.ignite.internal.client.ReliableChannel;
@@ -59,6 +58,7 @@ import 
org.apache.ignite.internal.client.table.ClientTupleSerializer;
 import org.apache.ignite.internal.client.table.PartitionAwarenessProvider;
 import org.apache.ignite.internal.sql.SqlCommon;
 import org.apache.ignite.internal.util.ExceptionUtils;
+import org.apache.ignite.internal.util.ViewUtils;
 import org.apache.ignite.lang.IgniteException;
 import org.apache.ignite.lang.TableNotFoundException;
 import org.apache.ignite.marshaling.Marshaler;
@@ -471,7 +471,7 @@ public class ClientCompute implements IgniteCompute {
         try {
             return future.join();
         } catch (CompletionException e) {
-            throw 
ExceptionUtils.sneakyThrow(ClientUtils.ensurePublicException(e));
+            throw 
ExceptionUtils.sneakyThrow(ViewUtils.ensurePublicException(e));
         }
     }
 }
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/AbstractClientView.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/AbstractClientView.java
index b0553f4aa1..e5722e21c5 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/AbstractClientView.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/AbstractClientView.java
@@ -18,9 +18,9 @@
 package org.apache.ignite.internal.client.table;
 
 import static java.util.stream.Collectors.toSet;
-import static org.apache.ignite.internal.client.ClientUtils.sync;
 import static 
org.apache.ignite.internal.table.criteria.CriteriaExceptionMapperUtil.mapToPublicCriteriaException;
 import static org.apache.ignite.internal.util.ExceptionUtils.unwrapCause;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 import static org.apache.ignite.lang.util.IgniteNameUtils.parseSimpleName;
 
 import java.util.Arrays;
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java
index cf83698a5e..2a6c84c248 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueBinaryView.java
@@ -17,10 +17,12 @@
 
 package org.apache.ignite.internal.client.table;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
 import static 
org.apache.ignite.internal.util.CompletableFutures.emptyCollectionCompletedFuture;
 import static 
org.apache.ignite.internal.util.CompletableFutures.emptyMapCompletedFuture;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -174,6 +176,29 @@ public class ClientKeyValueBinaryView extends 
AbstractClientView<Entry<Tuple, Tu
                 tx);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<Tuple> 
keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<Tuple> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return tbl.doSchemaOutOpAsync(
+                ClientOp.TUPLE_CONTAINS_ALL_KEYS,
+                (s, w) -> ser.writeTuples(tx, keys, s, w, true),
+                r -> r.in().unpackBoolean(),
+                ClientTupleSerializer.getPartitionAwarenessProvider(tx, 
keys.iterator().next()),
+                tx);
+    }
+
     /** {@inheritDoc} */
     @Override
     public void put(@Nullable Transaction tx, Tuple key, @Nullable Tuple val) {
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java
index fc82797b57..231e76b457 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientKeyValueView.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.client.table;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
 import static org.apache.ignite.internal.client.table.ClientTable.writeTx;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static 
org.apache.ignite.internal.marshaller.ValidationUtils.validateNullableOperation;
@@ -25,6 +24,9 @@ import static 
org.apache.ignite.internal.marshaller.ValidationUtils.validateNull
 import static 
org.apache.ignite.internal.util.CompletableFutures.emptyCollectionCompletedFuture;
 import static 
org.apache.ignite.internal.util.CompletableFutures.emptyMapCompletedFuture;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.BitSet;
 import java.util.Collection;
@@ -213,6 +215,29 @@ public class ClientKeyValueView<K, V> extends 
AbstractClientView<Entry<K, V>> im
                 tx);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<K> keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<K> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return tbl.doSchemaOutOpAsync(
+                ClientOp.TUPLE_CONTAINS_ALL_KEYS,
+                (s, w) -> keySer.writeRecs(tx, keys, s, w, TuplePart.KEY),
+                r -> r.in().unpackBoolean(),
+                ClientTupleSerializer.getPartitionAwarenessProvider(tx, 
keySer.mapper(), keys.iterator().next()),
+                tx);
+    }
+
     /** {@inheritDoc} */
     @Override
     public void put(@Nullable Transaction tx, K key, V val) {
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java
index 4c91b7ffeb..f8ebe6412e 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordBinaryView.java
@@ -17,9 +17,11 @@
 
 package org.apache.ignite.internal.client.table;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
 import static 
org.apache.ignite.internal.util.CompletableFutures.emptyListCompletedFuture;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -122,6 +124,29 @@ public class ClientRecordBinaryView extends 
AbstractClientView<Tuple> implements
                 tx);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<Tuple> 
keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<Tuple> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return tbl.doSchemaOutOpAsync(
+                ClientOp.TUPLE_CONTAINS_ALL_KEYS,
+                (s, w) -> ser.writeTuples(tx, keys, s, w, true),
+                r -> r.in().unpackBoolean(),
+                ClientTupleSerializer.getPartitionAwarenessProvider(tx, 
keys.iterator().next()),
+                tx);
+    }
+
     /** {@inheritDoc} */
     @Override
     public void upsert(@Nullable Transaction tx, Tuple rec) {
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java
index 7b58792401..3e726d820d 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientRecordView.java
@@ -17,9 +17,11 @@
 
 package org.apache.ignite.internal.client.table;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
 import static 
org.apache.ignite.internal.util.CompletableFutures.emptyListCompletedFuture;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -129,6 +131,29 @@ public class ClientRecordView<R> extends 
AbstractClientView<R> implements Record
                 tx);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<R> keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<R> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return tbl.doSchemaOutOpAsync(
+                ClientOp.TUPLE_CONTAINS_ALL_KEYS,
+                (s, w) -> ser.writeRecs(tx, keys, s, w, TuplePart.KEY),
+                r -> r.in().unpackBoolean(),
+                ClientTupleSerializer.getPartitionAwarenessProvider(tx, 
ser.mapper(), keys.iterator().next()),
+                tx);
+    }
+
     /** {@inheritDoc} */
     @Override
     public void upsert(@Nullable Transaction tx, R rec) {
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java
index 08704a2d57..ba9d44adf7 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/table/ClientTables.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.client.table;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
index 8f8492b048..ade1e53aff 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransaction.java
@@ -17,8 +17,8 @@
 
 package org.apache.ignite.internal.client.tx;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 import static org.apache.ignite.lang.ErrorGroups.Common.INTERNAL_ERR;
 import static 
org.apache.ignite.lang.ErrorGroups.Transactions.TX_ALREADY_FINISHED_ERR;
 
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
index fd5fb93f44..325ed680a7 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/tx/ClientTransactions.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.internal.client.tx;
 
-import static org.apache.ignite.internal.client.ClientUtils.sync;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.client.PayloadInputChannel;
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/ClientApiArchTest.java 
b/modules/client/src/test/java/org/apache/ignite/client/ClientApiArchTest.java
index 5bb1186089..ee56557008 100644
--- 
a/modules/client/src/test/java/org/apache/ignite/client/ClientApiArchTest.java
+++ 
b/modules/client/src/test/java/org/apache/ignite/client/ClientApiArchTest.java
@@ -60,8 +60,9 @@ public class ClientApiArchTest {
                         f,
                         "internal.client.IgniteClientConfigurationImpl;",
                         "internal.client.TcpIgniteClient;",
-                        "internal.client.ClientUtils.sync;",
-                        "internal.client.SslConfigurationBuilder;");
+                        "internal.client.SslConfigurationBuilder;",
+                        "internal.util.ViewUtils.sync;"
+                );
             });
         }
 
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueBinaryViewTest.java
 
b/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueBinaryViewTest.java
index 70384fdd32..fcc31af18e 100644
--- 
a/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueBinaryViewTest.java
+++ 
b/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueBinaryViewTest.java
@@ -182,6 +182,34 @@ public class ClientKeyValueBinaryViewTest extends 
AbstractClientTableTest {
         assertThat(Arrays.asList(ex.getStackTrace()), 
anyOf(hasToString(containsString("ClientKeyValueBinaryView"))));
     }
 
+    @Test
+    public void testContainsAll() {
+        KeyValueView<Tuple, Tuple> kvView = defaultTable().keyValueView();
+
+        Tuple firstKeyTuple = tupleKey(101L);
+        Tuple secondKeyTuple = tupleKey(102L);
+        Tuple thirdKeyTuple = tupleKey(103L);
+
+        Map<Tuple, Tuple> kvs = Map.of(
+                firstKeyTuple, tupleVal("201"),
+                secondKeyTuple, tupleVal("202"),
+                thirdKeyTuple, tupleVal("203")
+        );
+
+        kvView.putAll(null, kvs);
+
+        assertThrows(NullPointerException.class, () -> 
kvView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
kvView.containsAll(null, List.of(firstKeyTuple, null, thirdKeyTuple)));
+
+        assertTrue(kvView.containsAll(null, List.of()));
+        assertTrue(kvView.containsAll(null, List.of(firstKeyTuple)));
+        assertTrue(kvView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, thirdKeyTuple)));
+
+        Tuple zeroKeyTuple = tupleKey(0L);
+        assertFalse(kvView.containsAll(null, List.of(zeroKeyTuple)));
+        assertFalse(kvView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, zeroKeyTuple)));
+    }
+
     @Test
     public void testPutAll() {
         KeyValueView<Tuple, Tuple> kvView = defaultTable().keyValueView();
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueViewTest.java
 
b/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueViewTest.java
index ba8e895a99..c3a0743fd8 100644
--- 
a/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueViewTest.java
+++ 
b/modules/client/src/test/java/org/apache/ignite/client/ClientKeyValueViewTest.java
@@ -29,6 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.math.BigDecimal;
@@ -489,6 +490,34 @@ public class ClientKeyValueViewTest extends 
AbstractClientTableTest {
         assertFalse(pojoView.contains(null, -1L));
     }
 
+    @Test
+    public void testContainsAll() {
+        KeyValueView<Long, String> pojoView = 
defaultTable().keyValueView(Mapper.of(Long.class), Mapper.of(String.class));
+
+        long firstKey = 101L;
+        long secondKey = 102L;
+        long thirdKey = 103L;
+
+        Map<Long, String> pojos = Map.of(
+                firstKey, "201",
+                secondKey, "202",
+                thirdKey, "203"
+        );
+
+        pojoView.putAll(null, pojos);
+
+        assertThrows(NullPointerException.class, () -> 
pojoView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
pojoView.containsAll(null, List.of(firstKey, null, thirdKey)));
+
+        assertTrue(pojoView.containsAll(null, List.of()));
+        assertTrue(pojoView.containsAll(null, List.of(firstKey)));
+        assertTrue(pojoView.containsAll(null, List.of(firstKey, secondKey, 
thirdKey)));
+
+        long zeroKey = 0L;
+        assertFalse(pojoView.containsAll(null, List.of(zeroKey)));
+        assertFalse(pojoView.containsAll(null, List.of(firstKey, secondKey, 
zeroKey)));
+    }
+
     @Test
     public void testNullableColumnWithDefaultValueSetNullReturnsNull() {
         Table table = tableWithDefaultValues();
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/ClientRecordViewTest.java
 
b/modules/client/src/test/java/org/apache/ignite/client/ClientRecordViewTest.java
index 0c9243feae..2c91b133eb 100644
--- 
a/modules/client/src/test/java/org/apache/ignite/client/ClientRecordViewTest.java
+++ 
b/modules/client/src/test/java/org/apache/ignite/client/ClientRecordViewTest.java
@@ -290,6 +290,47 @@ public class ClientRecordViewTest extends 
AbstractClientTableTest {
         assertFalse(recordView.contains(null, new PersonPojo(DEFAULT_ID - 1, 
DEFAULT_NAME)));
     }
 
+    @Test
+    public void testContainsAll() {
+        RecordView<PersonPojo> recordView = 
defaultTable().recordView(PersonPojo.class);
+
+        long firstKey = 101L;
+        PersonPojo firstPerson = new PersonPojo(firstKey, "201");
+
+        long secondKey = 102L;
+        PersonPojo secondPerson = new PersonPojo(secondKey, "202");
+
+        long thirdKey = 103L;
+        PersonPojo thirdPerson = new PersonPojo(thirdKey, "203");
+
+        List<PersonPojo> recs = List.of(firstPerson, secondPerson, 
thirdPerson);
+
+        recordView.insertAll(null, recs);
+
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, List.of(firstPerson, null, thirdPerson)));
+
+        assertTrue(recordView.containsAll(null, List.of()));
+        assertTrue(recordView.containsAll(null, List.of(firstPerson)));
+        assertTrue(recordView.containsAll(null, List.of(firstPerson, 
secondPerson, thirdPerson)));
+        assertTrue(recordView.containsAll(null, List.of(
+                new PersonPojo(firstKey, " "),
+                new PersonPojo(secondKey, " "),
+                new PersonPojo(thirdKey, " ")
+        )));
+
+        long zeroKey = 0L;
+        PersonPojo missedPojo = new PersonPojo(zeroKey, DEFAULT_NAME);
+
+        assertFalse(recordView.containsAll(null, List.of(missedPojo)));
+        assertFalse(recordView.containsAll(null, List.of(firstPerson, 
secondPerson, missedPojo)));
+        assertFalse(recordView.containsAll(null, List.of(
+                new PersonPojo(firstKey, " "),
+                new PersonPojo(secondKey, " "),
+                new PersonPojo(zeroKey, " ")
+        )));
+    }    
+
     @Test
     public void testUpsertAll() {
         RecordView<PersonPojo> pojoView = 
defaultTable().recordView(Mapper.of(PersonPojo.class));
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/ClientTableTest.java 
b/modules/client/src/test/java/org/apache/ignite/client/ClientTableTest.java
index a23653e336..cd050c6e1e 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/ClientTableTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/ClientTableTest.java
@@ -201,6 +201,59 @@ public class ClientTableTest extends 
AbstractClientTableTest {
         assertEquals("3", res[1].stringValue("name"));
     }
 
+    @Test
+    public void testContains() {
+        RecordView<Tuple> recordView = defaultTable().recordView();
+
+        long key = 101L;
+        Tuple keyTuple = tuple(key);
+        Tuple valTuple = tuple(key, "201");
+
+        recordView.insert(null, valTuple);
+
+        assertThrows(NullPointerException.class, () -> 
recordView.contains(null, null));
+
+        assertTrue(recordView.contains(null, keyTuple));
+
+        Tuple missedKeyTuple = tuple(0L);
+
+        assertFalse(recordView.contains(null, missedKeyTuple));
+    }
+
+    @Test
+    public void testContainsAll() {
+        RecordView<Tuple> recordView = defaultTable().recordView();
+
+        long firstKey = 101L;
+        Tuple firstKeyTuple = tuple(firstKey);
+        Tuple firstValTuple = tuple(firstKey, "201");
+
+        long secondKey = 102L;
+        Tuple secondKeyTuple = tuple(secondKey);
+        Tuple secondValTuple = tuple(secondKey, "202");
+
+        long thirdKey = 103L;
+        Tuple thirdKeyTuple = tuple(thirdKey);
+        Tuple thirdValTuple = tuple(thirdKey, "203");
+
+        List<Tuple> recs = List.of(firstValTuple, secondValTuple, 
thirdValTuple);
+
+        recordView.insertAll(null, recs);
+
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, List.of(firstKeyTuple, null, thirdKeyTuple)));
+
+        assertTrue(recordView.containsAll(null, List.of()));
+        assertTrue(recordView.containsAll(null, List.of(firstKeyTuple)));
+        assertTrue(recordView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, thirdKeyTuple)));
+
+        long missedKey = 0L;
+        Tuple missedKeyTuple = tuple(missedKey);
+
+        assertFalse(recordView.containsAll(null, List.of(missedKeyTuple)));
+        assertFalse(recordView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, missedKeyTuple)));
+    }
+
     @Test
     public void testUpsertAll() {
         var table = defaultTable().recordView();
diff --git 
a/modules/client/src/test/java/org/apache/ignite/internal/client/ClientUtilsTest.java
 
b/modules/client/src/test/java/org/apache/ignite/internal/client/ClientUtilsTest.java
index eb41308fb2..357539585f 100644
--- 
a/modules/client/src/test/java/org/apache/ignite/internal/client/ClientUtilsTest.java
+++ 
b/modules/client/src/test/java/org/apache/ignite/internal/client/ClientUtilsTest.java
@@ -28,6 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Arrays;
+import org.apache.ignite.internal.util.ViewUtils;
 import org.apache.ignite.lang.IgniteCheckedException;
 import org.apache.ignite.lang.IgniteException;
 import org.jetbrains.annotations.Nullable;
@@ -98,7 +99,7 @@ public class ClientUtilsTest {
      * Method that should present in resulting stack trace.
      */
     private static Throwable checkableTestMethod(Throwable ex) {
-        return ClientUtils.ensurePublicException(ex);
+        return ViewUtils.ensurePublicException(ex);
     }
 
     /**
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/util/ViewUtils.java 
b/modules/core/src/main/java/org/apache/ignite/internal/util/ViewUtils.java
new file mode 100644
index 0000000000..da3ff46506
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/ViewUtils.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.internal.util;
+
+import static org.apache.ignite.internal.util.ExceptionUtils.sneakyThrow;
+import static org.apache.ignite.internal.util.ExceptionUtils.unwrapCause;
+import static org.apache.ignite.lang.ErrorGroups.Common.INTERNAL_ERR;
+
+import java.util.Collection;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import org.apache.ignite.internal.lang.IgniteExceptionMapperUtil;
+import org.apache.ignite.lang.IgniteCheckedException;
+import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.lang.TraceableException;
+
+/**
+ * Table view utilities.
+ */
+public final class ViewUtils {
+    /**
+     * Waits for async operation completion.
+     *
+     * @param fut Future to wait to.
+     * @param <T> Future result type.
+     * @return Future result.
+     */
+    public static <T> T sync(CompletableFuture<T> fut) {
+        try {
+            return fut.get();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt(); // Restore interrupt flag.
+
+            throw sneakyThrow(ensurePublicException(e));
+        } catch (ExecutionException e) {
+            Throwable cause = unwrapCause(e);
+
+            throw sneakyThrow(ensurePublicException(cause));
+        }
+    }
+
+    /**
+     * Wraps an exception in an IgniteException, extracting trace identifier 
and error code when the specified exception or one of its
+     * causes is an IgniteException itself.
+     *
+     * @param e Internal exception.
+     * @return Public exception.
+     */
+    public static Throwable ensurePublicException(Throwable e) {
+        Objects.requireNonNull(e);
+
+        e = unwrapCause(e);
+
+        if (e instanceof IgniteException) {
+            return copyExceptionWithCauseIfPossible((IgniteException) e);
+        }
+
+        if (e instanceof IgniteCheckedException) {
+            return copyExceptionWithCauseIfPossible((IgniteCheckedException) 
e);
+        }
+
+        e = IgniteExceptionMapperUtil.mapToPublicException(e);
+
+        return new IgniteException(INTERNAL_ERR, e.getMessage(), e);
+    }
+
+    /**
+     * Try to copy exception using ExceptionUtils.copyExceptionWithCause and 
return new exception if it was not possible.
+     *
+     * @param e Exception.
+     * @return Properly copied exception or a new error, if exception can not 
be copied.
+     */
+    private static <T extends Throwable & TraceableException> Throwable 
copyExceptionWithCauseIfPossible(T e) {
+        Throwable copy = ExceptionUtils.copyExceptionWithCause(e.getClass(), 
e.traceId(), e.code(), e.getMessage(), e);
+        if (copy != null) {
+            return copy;
+        }
+
+        return new IgniteException(INTERNAL_ERR, "Public Ignite 
exception-derived class does not have required constructor: "
+                + e.getClass().getName(), e);
+    }
+
+    /**
+     * Checks that given keys collection isn't null and there is no a 
null-value key.
+     *
+     * @param keys Given keys collection.
+     * @param <K> Keys type.
+     * @throws NullPointerException In case if the collection null either any 
key is null.
+     */
+    public static <K> void checkKeysForNulls(Collection<K> keys) {
+        Objects.requireNonNull(keys, "keys");
+
+        for (K key : keys) {
+            Objects.requireNonNull(key, "key");
+        }
+    }
+
+    private ViewUtils() { }
+}
diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java
index 3560cce7a4..96a1fe4bce 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItPkOnlyTableCrossApiTest.java
@@ -156,7 +156,7 @@ public class ItPkOnlyTableCrossApiTest extends 
BaseSqlIntegrationTest {
                 rwTx -> {
                     IgniteException ex = assertThrows(IgniteException.class,
                             () -> tab.keyValueView(KeyObject.class, 
Integer.class).put(rwTx, key, 1));
-                    assertThat(ex.getCause(), 
is(instanceOf(IllegalArgumentException.class)));
+                    assertThat(ex.getCause().getCause(), 
is(instanceOf(IllegalArgumentException.class)));
 
                     kvView.put(rwTx, key, null);
 
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java
index bfffdf5956..70ff46fb76 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/AbstractTableView.java
@@ -22,14 +22,13 @@ import static java.util.function.Function.identity;
 import static 
org.apache.ignite.internal.lang.IgniteExceptionMapperUtil.convertToPublicFuture;
 import static 
org.apache.ignite.internal.table.criteria.CriteriaExceptionMapperUtil.mapToPublicCriteriaException;
 import static org.apache.ignite.internal.util.ExceptionUtils.isOrCausedBy;
-import static org.apache.ignite.internal.util.ExceptionUtils.sneakyThrow;
 import static org.apache.ignite.internal.util.ExceptionUtils.unwrapCause;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionException;
-import java.util.concurrent.ExecutionException;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.lang.IgniteExceptionMapperUtil;
@@ -99,26 +98,6 @@ abstract class AbstractTableView<R> implements 
CriteriaQuerySource<R> {
         this.rowConverter = new TableViewRowConverter(schemaReg);
     }
 
-    /**
-     * Waits for operation completion.
-     *
-     * @param future Future to wait to.
-     * @param <T> Future result type.
-     * @return Future result.
-     */
-    protected static <T> T sync(CompletableFuture<T> future) {
-        try {
-            return future.get();
-        } catch (InterruptedException e) {
-            Thread.currentThread().interrupt(); // Restore interrupt flag.
-
-            throw 
sneakyThrow(IgniteExceptionMapperUtil.mapToPublicException(e));
-        } catch (ExecutionException e) {
-            Throwable cause = unwrapCause(e);
-            throw sneakyThrow(cause);
-        }
-    }
-
     /**
      * Combines the effect of {@link #withSchemaSync(Transaction, KvAction)} 
and
      * {@link 
IgniteExceptionMapperUtil#convertToPublicFuture(CompletableFuture)}.
@@ -275,7 +254,6 @@ abstract class AbstractTableView<R> implements 
CriteriaQuerySource<R> {
         });
     }
 
-
     /**
      * Action representing some KV operation. When executed, the action is 
supplied with schema version corresponding
      * to the operation timestamp (see {@link #doOperation(Transaction, 
KvAction)} for details).
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java
index d450b60d76..d608e65081 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueBinaryViewImpl.java
@@ -18,6 +18,9 @@
 package org.apache.ignite.internal.table;
 
 import static 
org.apache.ignite.internal.lang.IgniteExceptionMapperUtil.convertToPublicFuture;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.ArrayList;
 import java.util.BitSet;
@@ -162,14 +165,6 @@ public class KeyValueBinaryViewImpl extends 
AbstractTableView<Entry<Tuple, Tuple
         });
     }
 
-    private static void checkKeysForNulls(Collection<Tuple> keys) {
-        Objects.requireNonNull(keys, "keys");
-
-        for (Tuple key : keys) {
-            Objects.requireNonNull(key, "key");
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public boolean contains(@Nullable Transaction tx, Tuple key) {
@@ -182,6 +177,34 @@ public class KeyValueBinaryViewImpl extends 
AbstractTableView<Entry<Tuple, Tuple
         return getAsync(tx, key).thenApply(Objects::nonNull);
     }
 
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<Tuple> 
keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<Tuple> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return doOperation(tx, (schemaVersion) -> {
+            List<BinaryRowEx> keyRows = marshalKeys(keys, schemaVersion);
+
+            return tbl.getAll(keyRows, (InternalTransaction) 
tx).thenApply(rows -> {
+                for (BinaryRow row : rows) {
+                    if (row == null) {
+                        return false;
+                    }
+                }
+
+                return true;
+            });
+        });
+    }
+
     /** {@inheritDoc} */
     @Override
     public void put(@Nullable Transaction tx, Tuple key, Tuple val) {
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java
index ad3f771d42..e523e52efc 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/KeyValueViewImpl.java
@@ -21,6 +21,9 @@ import static 
org.apache.ignite.internal.lang.IgniteExceptionMapperUtil.convertT
 import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
 import static 
org.apache.ignite.internal.marshaller.ValidationUtils.validateNullableOperation;
 import static 
org.apache.ignite.internal.marshaller.ValidationUtils.validateNullableValue;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.ArrayList;
 import java.util.BitSet;
@@ -201,14 +204,6 @@ public class KeyValueViewImpl<K, V> extends 
AbstractTableView<Entry<K, V>> imple
         });
     }
 
-    private static <K> void checkKeysForNulls(Collection<K> keys) {
-        Objects.requireNonNull(keys, "keys");
-
-        for (K key : keys) {
-            Objects.requireNonNull(key, "key");
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public boolean contains(@Nullable Transaction tx, K key) {
@@ -227,6 +222,36 @@ public class KeyValueViewImpl<K, V> extends 
AbstractTableView<Entry<K, V>> imple
         });
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<K> keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<K> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return doOperation(tx, (schemaVersion) -> {
+            Collection<BinaryRowEx> keyRows = marshal(keys, schemaVersion);
+
+            return tbl.getAll(keyRows, (InternalTransaction) 
tx).thenApply(rows -> {
+                for (BinaryRow row : rows) {
+                    if (row == null) {
+                        return false;
+                    }
+                }
+
+                return true;
+            });
+        });
+    }
+
     /** {@inheritDoc} */
     @Override
     public void put(@Nullable Transaction tx, K key, @Nullable V val) {
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingKeyValueView.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingKeyValueView.java
index 0963fd85a1..f4e941a39c 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingKeyValueView.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingKeyValueView.java
@@ -102,6 +102,16 @@ public class PublicApiThreadingKeyValueView<K, V> extends 
PublicApiThreadingView
         return executeAsyncOp(() -> view.containsAsync(tx, key));
     }
 
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<K> keys) {
+        return executeSyncOp(() -> view.containsAll(tx, keys));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<K> keys) {
+        return executeSyncOp(() -> view.containsAllAsync(tx, keys));
+    }
+
     @Override
     public void put(@Nullable Transaction tx, K key, @Nullable V val) {
         executeSyncOp(() -> view.put(tx, key, val));
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingRecordView.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingRecordView.java
index 076e01b211..dbab23bf99 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingRecordView.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/PublicApiThreadingRecordView.java
@@ -81,6 +81,16 @@ public class PublicApiThreadingRecordView<R> extends 
PublicApiThreadingViewBase<
         return executeAsyncOp(() -> view.containsAsync(tx, keyRec));
     }
 
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<R> keys) {
+        return executeSyncOp(() -> view.containsAll(tx, keys));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<R> keys) {
+        return executeSyncOp(() -> view.containsAllAsync(tx, keys));
+    }
+
     @Override
     public void upsert(@Nullable Transaction tx, R rec) {
         executeSyncOp(() -> view.upsert(tx, rec));
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java
index b901499305..8649fe26bf 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordBinaryViewImpl.java
@@ -19,6 +19,9 @@ package org.apache.ignite.internal.table;
 
 import static java.util.concurrent.CompletableFuture.completedFuture;
 import static 
org.apache.ignite.internal.lang.IgniteExceptionMapperUtil.convertToPublicFuture;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.ArrayList;
 import java.util.BitSet;
@@ -139,6 +142,36 @@ public class RecordBinaryViewImpl extends 
AbstractTableView<Tuple> implements Re
         });
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<Tuple> 
keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<Tuple> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return doOperation(tx, (schemaVersion) -> {
+            Collection<BinaryRowEx> keysRows = mapToBinary(keys, 
schemaVersion, true);
+
+            return tbl.getAll(keysRows, (InternalTransaction) 
tx).thenApply(rows -> {
+                for (BinaryRow row : rows) {
+                    if (row == null) {
+                        return false;
+                    }
+                }
+
+                return true;
+            });
+        });
+    }
+
     /** {@inheritDoc} */
     @Override
     public void upsert(@Nullable Transaction tx, Tuple rec) {
diff --git 
a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
 
b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
index 57bc3903e0..e633bfb57a 100644
--- 
a/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
+++ 
b/modules/table/src/main/java/org/apache/ignite/internal/table/RecordViewImpl.java
@@ -18,6 +18,9 @@
 package org.apache.ignite.internal.table;
 
 import static 
org.apache.ignite.internal.lang.IgniteExceptionMapperUtil.convertToPublicFuture;
+import static 
org.apache.ignite.internal.util.CompletableFutures.trueCompletedFuture;
+import static org.apache.ignite.internal.util.ViewUtils.checkKeysForNulls;
+import static org.apache.ignite.internal.util.ViewUtils.sync;
 
 import java.util.ArrayList;
 import java.util.BitSet;
@@ -146,6 +149,36 @@ public class RecordViewImpl<R> extends 
AbstractTableView<R> implements RecordVie
         });
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean containsAll(@Nullable Transaction tx, Collection<R> keys) {
+        return sync(containsAllAsync(tx, keys));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CompletableFuture<Boolean> containsAllAsync(@Nullable Transaction 
tx, Collection<R> keys) {
+        checkKeysForNulls(keys);
+
+        if (keys.isEmpty()) {
+            return trueCompletedFuture();
+        }
+
+        return doOperation(tx, (schemaVersion) -> {
+            Collection<BinaryRowEx> keyRows = marshalKeys(keys, schemaVersion);
+
+            return tbl.getAll(keyRows, (InternalTransaction) 
tx).thenApply(rows -> {
+                for (BinaryRow row : rows) {
+                    if (row == null) {
+                        return false;
+                    }
+                }
+
+                return true;
+            });
+        });
+    }
+
     /** {@inheritDoc} */
     @Override
     public void upsert(@Nullable Transaction tx, R rec) {
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueBinaryViewOperationsTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueBinaryViewOperationsTest.java
index 72112cd76e..f9e8ed9757 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueBinaryViewOperationsTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueBinaryViewOperationsTest.java
@@ -234,6 +234,46 @@ public class KeyValueBinaryViewOperationsTest extends 
TableKvOperationsTestBase
         assertFalse(tbl.contains(null, Tuple.create().set("id", 2L)));
     }
 
+
+    @Test
+    public void testContainsAll() {
+        SchemaDescriptor schema = schemaDescriptor();
+
+        KeyValueView<Tuple, Tuple> kvView = createTable(schema).keyValueView();
+
+        long firstKey = 101L;
+        Tuple firstKeyTuple = Tuple.create().set("id", firstKey);
+        Tuple firstValTuple = Tuple.create().set("val", 201L);
+
+        long secondKey = 102L;
+        Tuple secondKeyTuple = Tuple.create().set("id", secondKey);
+        Tuple secondValTuple = Tuple.create().set("val", 202L);
+
+        long thirdKey = 103L;
+        Tuple thirdKeyTuple = Tuple.create().set("id", thirdKey);
+        Tuple thirdValTuple = Tuple.create().set("val", 203L);
+
+        Map<Tuple, Tuple> kvs = Map.of(
+                firstKeyTuple, firstValTuple,
+                secondKeyTuple, secondValTuple,
+                thirdKeyTuple, thirdValTuple
+        );
+
+        kvView.putAll(null, kvs);
+
+        assertThrows(NullPointerException.class, () -> 
kvView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
kvView.containsAll(null, List.of(firstKeyTuple, null, thirdKeyTuple)));
+
+        assertTrue(kvView.containsAll(null, List.of()));
+        assertTrue(kvView.containsAll(null, List.of(firstKeyTuple)));
+        assertTrue(kvView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, thirdKeyTuple)));
+
+        Tuple missedKeyTuple = Tuple.create().set("id", 0L);
+
+        assertFalse(kvView.containsAll(null, List.of(missedKeyTuple)));
+        assertFalse(kvView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, missedKeyTuple)));
+    }
+
     @Test
     public void remove() {
         SchemaDescriptor schema = schemaDescriptor();
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueViewOperationsTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueViewOperationsTest.java
index 58589c2159..7aab26ce9b 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueViewOperationsTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/KeyValueViewOperationsTest.java
@@ -292,6 +292,40 @@ public class KeyValueViewOperationsTest extends 
TableKvOperationsTestBase {
         assertFalse(tbl.contains(null, key2));
     }
 
+    @Test
+    public void testContainsAll() {
+        KeyValueView<TestKeyObject, TestObjectWithAllTypes> kvView = kvView();
+
+        TestKeyObject firstKey = TestKeyObject.randomObject(rnd);
+        TestObjectWithAllTypes firstVal = 
TestObjectWithAllTypes.randomObject(rnd);
+
+        TestKeyObject secondKey = TestKeyObject.randomObject(rnd);
+        TestObjectWithAllTypes secondVal = 
TestObjectWithAllTypes.randomObject(rnd);
+
+        TestKeyObject thirdKey = TestKeyObject.randomObject(rnd);
+        TestObjectWithAllTypes thirdVal = 
TestObjectWithAllTypes.randomObject(rnd);
+
+        Map<TestKeyObject, TestObjectWithAllTypes> kvs = Map.of(
+                firstKey, firstVal,
+                secondKey, secondVal,
+                thirdKey, thirdVal
+        );
+
+        kvView.putAll(null, kvs);
+
+        assertThrows(NullPointerException.class, () -> 
kvView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
kvView.containsAll(null, List.of(firstKey, null, thirdKey)));
+
+        assertTrue(kvView.containsAll(null, List.of()));
+        assertTrue(kvView.containsAll(null, List.of(firstKey)));
+        assertTrue(kvView.containsAll(null, List.of(firstKey, secondKey, 
thirdKey)));
+
+        TestKeyObject missedKey = TestKeyObject.randomObject(rnd);
+
+        assertFalse(kvView.containsAll(null, List.of(missedKey)));
+        assertFalse(kvView.containsAll(null, List.of(firstKey, secondKey, 
missedKey)));
+    }
+
     @Test
     public void remove() {
         final TestKeyObject key = TestKeyObject.randomObject(rnd);
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/RecordBinaryViewOperationsTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/RecordBinaryViewOperationsTest.java
index 43d2c6cc32..27e68fbbfb 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/RecordBinaryViewOperationsTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/RecordBinaryViewOperationsTest.java
@@ -367,6 +367,51 @@ public class RecordBinaryViewOperationsTest extends 
TableKvOperationsTestBase {
         assertTrue(tbl.contains(null, keyRec));
     }
 
+    @Test
+    public void testContainsAll() {
+        SchemaDescriptor schema = schemaDescriptor();
+        RecordView<Tuple> recordView = createTable(schema).recordView();
+
+        long firstKey = 101L;
+        Tuple firstKeyTuple = Tuple.create()
+                .set("id", firstKey);
+        Tuple firstValTuple = Tuple.create()
+                .set("id", firstKey)
+                .set("val", 201L);
+
+        long secondKey = 102L;
+        Tuple secondKeyTuple = Tuple.create()
+                .set("id", secondKey);
+        Tuple secondValTuple = Tuple.create()
+                .set("id", secondKey)
+                .set("val", 202L);
+
+        long thirdKey = 103L;
+        Tuple thirdKeyTuple = Tuple.create()
+                .set("id", thirdKey);
+        Tuple thirdValTuple = Tuple.create()
+                .set("id", thirdKey)
+                .set("val", 203L);
+
+        List<Tuple> recs = List.of(firstValTuple, secondValTuple, 
thirdValTuple);
+
+        recordView.insertAll(null, recs);
+
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, List.of(firstKeyTuple, null, thirdKeyTuple)));
+
+        assertTrue(recordView.containsAll(null, List.of()));
+        assertTrue(recordView.containsAll(null, List.of(firstKeyTuple)));
+        assertTrue(recordView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, thirdKeyTuple)));
+
+        long missedKey = 0L;
+        Tuple missedKeyTuple = Tuple.create()
+                .set("id", missedKey);
+
+        assertFalse(recordView.containsAll(null, List.of(missedKeyTuple)));
+        assertFalse(recordView.containsAll(null, List.of(firstKeyTuple, 
secondKeyTuple, missedKeyTuple)));
+    }
+
     @Test
     public void upsertAllAfterInsertAll() {
         SchemaDescriptor schema = schemaDescriptor();
diff --git 
a/modules/table/src/test/java/org/apache/ignite/internal/table/RecordViewOperationsTest.java
 
b/modules/table/src/test/java/org/apache/ignite/internal/table/RecordViewOperationsTest.java
index 72d5382a73..551dc0e23b 100644
--- 
a/modules/table/src/test/java/org/apache/ignite/internal/table/RecordViewOperationsTest.java
+++ 
b/modules/table/src/test/java/org/apache/ignite/internal/table/RecordViewOperationsTest.java
@@ -38,6 +38,7 @@ import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Answers.RETURNS_DEEP_STUBS;
 import static org.mockito.ArgumentMatchers.any;
@@ -364,6 +365,42 @@ public class RecordViewOperationsTest extends 
TableKvOperationsTestBase {
         assertFalse(tbl.contains(null, randomObject(rnd, wrongKey)));
     }
 
+    @Test
+    public void testContainsAll() {
+        RecordView<TestObjectWithAllTypes> recordView = recordView();
+
+        TestObjectWithAllTypes firstKey = key(rnd);
+        TestObjectWithAllTypes firstVal = randomObject(rnd, firstKey);
+
+        TestObjectWithAllTypes secondKey = key(rnd);
+        TestObjectWithAllTypes secondVal = randomObject(rnd, secondKey);
+
+        TestObjectWithAllTypes thirdKey = key(rnd);
+        TestObjectWithAllTypes thirdVal = randomObject(rnd, thirdKey);
+
+        List<TestObjectWithAllTypes> recs = List.of(firstVal, secondVal, 
thirdVal);
+
+        recordView.insertAll(null, recs);
+
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, null));
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, List.of(firstKey, null, thirdKey)));
+        assertThrows(NullPointerException.class, () -> 
recordView.containsAll(null, List.of(firstVal, null, thirdVal)));
+
+        assertTrue(recordView.containsAll(null, List.of()));
+        assertTrue(recordView.containsAll(null, List.of(firstKey)));
+        assertTrue(recordView.containsAll(null, List.of(firstVal)));
+        assertTrue(recordView.containsAll(null, List.of(firstKey, secondKey, 
thirdKey)));
+        assertTrue(recordView.containsAll(null, List.of(firstVal, secondVal, 
thirdVal)));
+
+        TestObjectWithAllTypes missedKey = key(rnd);
+        TestObjectWithAllTypes missedVal = randomObject(rnd, missedKey);
+
+        assertFalse(recordView.containsAll(null, List.of(missedKey)));
+        assertFalse(recordView.containsAll(null, List.of(missedVal)));
+        assertFalse(recordView.containsAll(null, List.of(firstKey, secondKey, 
missedKey)));
+        assertFalse(recordView.containsAll(null, List.of(firstVal, secondVal, 
missedVal)));
+    }
+
     @Test
     void retriesOnInternalSchemaVersionMismatchException() throws Exception {
         RecordView<TestObjectWithAllTypes> view = recordView();

Reply via email to