This is an automated email from the ASF dual-hosted git repository.
timoninmaxim pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new fb80a121a46 IGNITE-20943 Fix deserializing cache entries for
IndexQuery on server (#11453)
fb80a121a46 is described below
commit fb80a121a46d866c3aec064401e5f8d95b91f8e9
Author: Maksim Timonin <[email protected]>
AuthorDate: Thu Jul 25 10:48:20 2024 +0300
IGNITE-20943 Fix deserializing cache entries for IndexQuery on server
(#11453)
---
.../client/cache/ClientCacheIndexQueryRequest.java | 3 +-
.../ThinClientQueryTestApplication.java | 164 +++++++++++++++++++++
.../ignitetest/tests/thin_client_query_test.py | 95 ++++++++++++
3 files changed, 261 insertions(+), 1 deletion(-)
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
index db86541fbb8..9d1a29cb730 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheIndexQueryRequest.java
@@ -155,7 +155,8 @@ public class ClientCacheIndexQueryRequest extends
ClientCacheQueryRequest {
* {@inheritDoc}
*/
@Override public ClientResponse process(ClientConnectionContext ctx) {
- IgniteCache<Object, Object> cache = !isKeepBinary() ? rawCache(ctx) :
cache(ctx);
+ IgniteCache<Object, Object> cache = qry.getFilter() != null &&
!isKeepBinary() ?
+ rawCache(ctx) : cache(ctx);
if (qry.getPartition() != null)
updateAffinityMetrics(ctx, qry.getPartition());
diff --git
a/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/thin_client_query_test/ThinClientQueryTestApplication.java
b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/thin_client_query_test/ThinClientQueryTestApplication.java
new file mode 100644
index 00000000000..6581ceefc0f
--- /dev/null
+++
b/modules/ducktests/src/main/java/org/apache/ignite/internal/ducktest/tests/thin_client_query_test/ThinClientQueryTestApplication.java
@@ -0,0 +1,164 @@
+/*
+ * 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.ducktest.tests.thin_client_query_test;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import javax.cache.Cache;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.query.IndexQuery;
+import org.apache.ignite.cache.query.ScanQuery;
+import org.apache.ignite.client.ClientCache;
+import org.apache.ignite.client.ClientCacheConfiguration;
+import org.apache.ignite.internal.ducktest.utils.IgniteAwareApplication;
+import org.apache.ignite.internal.util.typedef.F;
+
+/** Tests cache queries for thin client. */
+public class ThinClientQueryTestApplication extends IgniteAwareApplication {
+ /** */
+ private static final int CNT = 100;
+
+ /** */
+ @Override protected void run(JsonNode jsonNode) throws Exception {
+ markInitialized();
+
+ QueryEntity qe = new QueryEntity(Integer.class, EntityValue.class)
+ .setValueType(EntityValue.class.getName())
+ .setFields(new LinkedHashMap<>(F.asMap("val",
Integer.class.getName())))
+ .setIndexes(F.asList(new QueryIndex("val",
false).setName("VAL_IDX")));
+
+ ClientCacheConfiguration clnCacheCfg = new ClientCacheConfiguration()
+ .setName("testCache")
+ .setQueryEntities(qe);
+
+ ClientCache<Integer, EntityValue> cache =
client.createCache(clnCacheCfg);
+
+ for (int i = 0; i < CNT; i++)
+ cache.put(i, new EntityValue(i));
+
+ boolean filter = jsonNode.get("filter").asBoolean();
+
+ testIndexQuery(cache, filter);
+ testBinaryIndexQuery(cache, filter);
+ testScanQuery(cache, filter);
+ testBinaryScanQuery(cache, filter);
+
+ markFinished();
+ }
+
+ /** */
+ private void testIndexQuery(ClientCache<Integer, EntityValue> cache,
boolean filter) {
+ IndexQuery<Integer, EntityValue> idxQry = new
IndexQuery<>(EntityValue.class.getName(), "VAL_IDX");
+
+ if (filter)
+ idxQry.setFilter((k, v) -> v.val < CNT / 2);
+
+ List<Cache.Entry<Integer, EntityValue>> result =
cache.query(idxQry).getAll();
+
+ int cnt = filter ? CNT / 2 : CNT;
+
+ assert result.size() == cnt;
+
+ for (int i = 0; i < cnt; i++) {
+ Cache.Entry<Integer, EntityValue> e = result.get(i);
+
+ assert e.getKey() == i;
+ assert e.getValue().val == i;
+ }
+ }
+
+ /** */
+ private void testBinaryIndexQuery(ClientCache<Integer, EntityValue> cache,
boolean filter) {
+ IndexQuery<Integer, BinaryObject> idxQry = new
IndexQuery<>(EntityValue.class.getName(), "VAL_IDX");
+
+ if (filter)
+ idxQry.setFilter((k, v) -> (int)v.field("val") < CNT / 2);
+
+ List<Cache.Entry<Integer, BinaryObject>> result =
cache.withKeepBinary().query(idxQry).getAll();
+
+ int cnt = filter ? CNT / 2 : CNT;
+
+ assert result.size() == cnt;
+
+ for (int i = 0; i < cnt; i++) {
+ Cache.Entry<Integer, BinaryObject> e = result.get(i);
+
+ assert e.getKey() == i;
+ assert (int)e.getValue().field("val") == i;
+ }
+ }
+
+ /** */
+ private void testScanQuery(ClientCache<Integer, EntityValue> cache,
boolean filter) {
+ ScanQuery<Integer, EntityValue> scanQry = new ScanQuery<>();
+
+ if (filter)
+ scanQry.setFilter((k, v) -> v.val < CNT / 2);
+
+ List<Cache.Entry<Integer, EntityValue>> result =
cache.query(scanQry).getAll();
+
+ int cnt = filter ? CNT / 2 : CNT;
+
+ assert result.size() == cnt;
+
+ for (int i = 0; i < cnt; i++) {
+ Cache.Entry<Integer, EntityValue> e = result.get(i);
+
+ assert e.getKey() == e.getValue().val;
+ }
+ }
+
+ /** */
+ private void testBinaryScanQuery(ClientCache<Integer, EntityValue> cache,
boolean filter) {
+ ScanQuery<Integer, BinaryObject> scanQry = new ScanQuery<>();
+
+ if (filter)
+ scanQry.setFilter((k, v) -> (int)v.field("val") < CNT / 2);
+
+ List<Cache.Entry<Integer, BinaryObject>> result =
cache.withKeepBinary().query(scanQry).getAll();
+
+ int cnt = filter ? CNT / 2 : CNT;
+
+ assert result.size() == cnt;
+
+ for (int i = 0; i < cnt; i++) {
+ Cache.Entry<Integer, BinaryObject> e = result.get(i);
+
+ assert e.getKey() == e.getValue().field("val");
+ }
+ }
+
+ /** */
+ private static class EntityValue {
+ /** */
+ private final int val;
+
+ /** */
+ public EntityValue(int val) {
+ this.val = val;
+ }
+
+ /** */
+ public String toString() {
+ return "EntityValue [val=" + val + "]";
+ }
+ }
+}
diff --git a/modules/ducktests/tests/ignitetest/tests/thin_client_query_test.py
b/modules/ducktests/tests/ignitetest/tests/thin_client_query_test.py
new file mode 100644
index 00000000000..e008878159a
--- /dev/null
+++ b/modules/ducktests/tests/ignitetest/tests/thin_client_query_test.py
@@ -0,0 +1,95 @@
+# 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.
+
+"""
+This module contains client queries tests.
+"""
+from ducktape.mark import matrix
+
+from ignitetest.services.ignite import IgniteService
+from ignitetest.services.ignite_app import IgniteApplicationService
+from ignitetest.services.utils.ignite_configuration import
IgniteConfiguration, IgniteThinClientConfiguration
+from ignitetest.services.utils.ignite_spec import IgniteNodeSpec
+from ignitetest.services.utils.ssl.client_connector_configuration import
ClientConnectorConfiguration
+from ignitetest.utils import cluster, ignite_versions
+from ignitetest.utils.ignite_test import IgniteTest
+from ignitetest.utils.version import DEV_BRANCH, IgniteVersion
+
+
+class ThinClientQueryTest(IgniteTest):
+ """
+ cluster - cluster size.
+ JAVA_CLIENT_CLASS_NAME - running classname.
+ to use with ssl enabled:
+ export GLOBALS='{"ssl":{"enabled":true}}' .
+ """
+ @cluster(num_nodes=3)
+ @ignite_versions(str(DEV_BRANCH), version_prefix="server_version")
+ @matrix(filter=[False, True])
+ def test_thin_client_index_query(self, server_version, filter):
+ """
+ Thin client IndexQuery test.
+ :param server_version Ignite node version.
+ :param filter Whether to use filter for queries.
+ """
+
+ server_config =
IgniteConfiguration(version=IgniteVersion(server_version),
+
client_connector_configuration=ClientConnectorConfiguration())
+
+ ignite = IgniteService(self.test_context, server_config, 2)
+
+ if not filter:
+ ignite.spec = IgniteNodeSpecExcludeDucktests(service=ignite)
+
+ addresses = [ignite.nodes[0].account.hostname + ":" +
str(server_config.client_connector_configuration.port)]
+
+ cls =
"org.apache.ignite.internal.ducktest.tests.thin_client_query_test.ThinClientQueryTestApplication"
+
+ thin_clients = IgniteApplicationService(self.test_context,
+ IgniteThinClientConfiguration(
+ addresses=addresses,
+
version=IgniteVersion(str(DEV_BRANCH))),
+ java_class_name=cls,
+ num_nodes=1,
+ params={"filter": filter})
+
+ ignite.start()
+ thin_clients.run()
+ ignite.stop()
+
+
+class IgniteNodeSpecExcludeDucktests(IgniteNodeSpec):
+ """
+ Ignite node specification that excludes module 'ducktests' from classpath.
+ """
+ def modules(self):
+ """
+ Exclude module from preparing USER_LIBS environment variable.
+ """
+ modules = super().modules()
+
+ modules.remove("ducktests")
+
+ return modules
+
+ def envs(self):
+ """
+ Skip the module target directory while building classpath.
+ """
+ envs = super().envs()
+
+ envs["EXCLUDE_MODULES"] = "ducktests"
+
+ return envs