From 765fa5d6da8f30f2bcc1581281916905432ec6b1 Mon Sep 17 00:00:00 2001 From: zstan Date: Mon, 1 Jun 2026 17:42:03 +0300 Subject: [PATCH 1/5] IGNITE-28737 Calcite. CacheOperationContext with keepBinary = true need to be used during dml operations --- .../jmh/sql/JmhSqlAggBenchmark.java | 15 ++ .../jmh/sql/JmhSqlCorrelateBenchmark.java | 15 ++ .../jmh/sql/JmhSqlDmlBenchmark.java | 15 ++ .../jmh/sql/JmhSqlInsertBenchmark.java | 142 ++++++++++++++++++ .../jmh/sql/JmhSqlScanBenchmark.java | 15 ++ .../jmh/sql/JmhSqlSetOpBenchmark.java | 15 ++ .../jmh/sql/JmhSqlSortBenchmark.java | 15 ++ .../jmh/sql/JmhSqlUdfBenchmark.java | 15 ++ modules/calcite/pom.xml | 7 - .../query/calcite/exec/rel/ModifyNode.java | 19 ++- .../query/calcite/util/Commons.java | 36 +++++ .../integration/PublicApiIntegrationTest.java | 64 ++++++++ .../testsuites/IntegrationTestSuite.java | 2 + 13 files changed, 364 insertions(+), 11 deletions(-) create mode 100644 modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlInsertBenchmark.java create mode 100644 modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/PublicApiIntegrationTest.java diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlAggBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlAggBenchmark.java index e767c1936deb4..c4ef1bee72b18 100644 --- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlAggBenchmark.java +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlAggBenchmark.java @@ -18,7 +18,16 @@ package org.apache.ignite.internal.benchmarks.jmh.sql; import java.util.List; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; @@ -26,6 +35,12 @@ /** * Benchmark aggregate SQL queries. */ +@Fork(1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Warmup(iterations = 3, time = 5) +@Measurement(iterations = 3, time = 5) +@State(Scope.Benchmark) public class JmhSqlAggBenchmark extends JmhSqlAbstractBenchmark { /** * Query with group by and aggregate. diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlCorrelateBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlCorrelateBenchmark.java index 07004ae63ee41..64d8a3eab7ec9 100644 --- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlCorrelateBenchmark.java +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlCorrelateBenchmark.java @@ -19,7 +19,16 @@ import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; @@ -27,6 +36,12 @@ /** * Benchmark correlated SQL queries. */ +@Fork(1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Warmup(iterations = 3, time = 5) +@Measurement(iterations = 3, time = 5) +@State(Scope.Benchmark) public class JmhSqlCorrelateBenchmark extends JmhSqlAbstractBenchmark { /** * Query with correlated subquery. diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlDmlBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlDmlBenchmark.java index 6cdb00ff48ed1..ee809a7bf480e 100644 --- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlDmlBenchmark.java +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlDmlBenchmark.java @@ -19,8 +19,17 @@ import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; import org.apache.ignite.IgniteDataStreamer; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; @@ -28,6 +37,12 @@ /** * Benchmark DML queries. */ +@Fork(1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Warmup(iterations = 3, time = 5) +@Measurement(iterations = 3, time = 5) +@State(Scope.Benchmark) public class JmhSqlDmlBenchmark extends JmhSqlAbstractBenchmark { /** * Initiate new cache. diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlInsertBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlInsertBenchmark.java new file mode 100644 index 0000000000000..578dc1d8bab94 --- /dev/null +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlInsertBenchmark.java @@ -0,0 +1,142 @@ +/* + * 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.benchmarks.jmh.sql; + +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import static java.lang.String.format; +import static java.util.stream.Collectors.joining; + +/** + * Benchmark for insertion operation, comparing SQL APIs. + */ +@State(Scope.Benchmark) +@Fork(1) +@Threads(1) +@Warmup(iterations = 10, time = 2) +@Measurement(iterations = 10, time = 2) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +public class JmhSqlInsertBenchmark extends JmhSqlAbstractBenchmark { + /** */ + private int id; + + /** */ + private static final String FIELD_VAL = "a".repeat(100); + + /** */ + private static final String TABLE_NAME = "dept"; + + /** */ + private String insertStr; + + /** */ + private String multiInsertStr; + + /** + * Initiate new tables. + */ + @Override public void setup() { + super.setup(); + + insertStr = createInsertStatement(); + multiInsertStr = createMultiInsertStatement(); + + executeSql("CREATE TABLE " + TABLE_NAME + + "(ycsb_key int PRIMARY KEY," + + "field1 varchar(100)," + + "field2 varchar(100)," + + "field3 varchar(100)," + + "field4 varchar(100)," + + "field5 varchar(100)," + + "field6 varchar(100)," + + "field7 varchar(100)," + + "field8 varchar(100)," + + "field9 varchar(100)," + + "field10 varchar(100))" + ); + } + + /** + * Benchmark for SQL insert via embedded client. + */ + @Benchmark + public void sqlSimpleInsert() { + executeSql(insertStr, id++); + } + + /** + * Benchmark for batch SQL insert via embedded client. + */ + @Benchmark + public void sqlBatchInsert() { + id += 2; + + executeSql(multiInsertStr, id, id + 1); + } + + /** + * Run benchmarks. + * + * @param args Args. + * @throws Exception Exception. + */ + public static void main(String[] args) throws Exception { + final Options options = new OptionsBuilder() + .include(JmhSqlInsertBenchmark.class.getSimpleName()) + .build(); + + new Runner(options).run(); + } + + /** */ + private static String createInsertStatement() { + /** */ + String insertQryTemplate = "insert into %s(%s, %s) values(?, %s)"; + + String fieldsQ = IntStream.range(1, 11).mapToObj(i -> "field" + i).collect(joining(",")); + String valQ = IntStream.range(1, 11).mapToObj(i -> "'" + FIELD_VAL + "'").collect(joining(",")); + + return format(insertQryTemplate, TABLE_NAME, "ycsb_key", fieldsQ, valQ); + } + + /** */ + private static String createMultiInsertStatement() { + /** */ + String insertQryTemplate = "insert into %s(%s, %s) values(?, %s), (?, %s)"; + + String fieldsQ = IntStream.range(1, 11).mapToObj(i -> "field" + i).collect(joining(",")); + String valQ = IntStream.range(1, 11).mapToObj(i -> "'" + FIELD_VAL + "'").collect(joining(",")); + + return format(insertQryTemplate, TABLE_NAME, "ycsb_key", fieldsQ, valQ, valQ); + } +} diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlScanBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlScanBenchmark.java index 42080465b805c..6c888815e8308 100644 --- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlScanBenchmark.java +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlScanBenchmark.java @@ -19,7 +19,16 @@ import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; @@ -27,6 +36,12 @@ /** * Benchmark scan SQL queries. */ +@Fork(1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Warmup(iterations = 3, time = 5) +@Measurement(iterations = 3, time = 5) +@State(Scope.Benchmark) public class JmhSqlScanBenchmark extends JmhSqlAbstractBenchmark { /** * Query unique value (full scan). diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSetOpBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSetOpBenchmark.java index 09f8891218b78..b4b7a50221a8c 100644 --- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSetOpBenchmark.java +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSetOpBenchmark.java @@ -19,7 +19,16 @@ import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.profile.GCProfiler; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; @@ -28,6 +37,12 @@ /** * Benchmark set op SQL queries. */ +@Fork(1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Warmup(iterations = 3, time = 5) +@Measurement(iterations = 3, time = 5) +@State(Scope.Benchmark) public class JmhSqlSetOpBenchmark extends JmhSqlAbstractBenchmark { /** * Query with EXCEPT set op. diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSortBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSortBenchmark.java index 8493a2a91389e..48ba21053b4d4 100644 --- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSortBenchmark.java +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlSortBenchmark.java @@ -19,7 +19,16 @@ import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; @@ -27,6 +36,12 @@ /** * Benchmark sort SQL queries. */ +@Fork(1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Warmup(iterations = 3, time = 5) +@Measurement(iterations = 3, time = 5) +@State(Scope.Benchmark) public class JmhSqlSortBenchmark extends JmhSqlAbstractBenchmark { /** * Query with sorting (full set). diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlUdfBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlUdfBenchmark.java index c3d24ca055b27..5a606b447dd18 100644 --- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlUdfBenchmark.java +++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/sql/JmhSqlUdfBenchmark.java @@ -18,9 +18,18 @@ package org.apache.ignite.internal.benchmarks.jmh.sql; import java.util.List; +import java.util.concurrent.TimeUnit; import org.apache.ignite.cache.query.annotations.QuerySqlFunction; import org.apache.ignite.configuration.CacheConfiguration; import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; @@ -28,6 +37,12 @@ /** * Benchmark user defined functions in SQL queries. */ +@Fork(1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@Warmup(iterations = 3, time = 5) +@Measurement(iterations = 3, time = 5) +@State(Scope.Benchmark) public class JmhSqlUdfBenchmark extends JmhSqlAbstractBenchmark { /** {@inheritDoc} */ @Override protected CacheConfiguration cacheConfiguration() { diff --git a/modules/calcite/pom.xml b/modules/calcite/pom.xml index fb42c00c24094..5daf56bf1e633 100644 --- a/modules/calcite/pom.xml +++ b/modules/calcite/pom.xml @@ -37,7 +37,6 @@ 1.26.0 1.40.0 - 3.10.0 1.0.1 2.8.2 3.1.12 @@ -94,12 +93,6 @@ failureaccess - - org.checkerframework - checker-qual - ${checker.version} - - org.codehaus.janino commons-compiler diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java index fcf2b8ebd3315..81999b40bf03d 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java @@ -32,6 +32,7 @@ import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.cache.context.SessionContextImpl; +import org.apache.ignite.internal.processors.cache.CacheOperationContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal; @@ -238,13 +239,23 @@ private void flushTuples(boolean force) throws Exception { QueryProperties props = context().unwrap(QueryProperties.class); boolean keepBinaryMode = props == null || props.keepBinary(); + CacheOperationContext opCtx = null; + if (keepBinaryMode) cache = cache.keepBinary(); - - if (tx == null) - invokeOutsideTransaction(tuples, cache); else - invokeInsideTransaction(tuples, cache, tx); + opCtx = cctx != null ? Commons.setKeepBinaryContext(cctx) : null; + + try { + if (tx == null) + invokeOutsideTransaction(tuples, cache); + else + invokeInsideTransaction(tuples, cache, tx); + } + finally { + if (opCtx != null) + Commons.restoreKeepBinaryContext(cctx, opCtx); + } } /** diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java index fc91eb4483286..c70f0560b46b6 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/Commons.java @@ -62,6 +62,8 @@ import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.binary.BinaryUtils; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; +import org.apache.ignite.internal.processors.cache.CacheOperationContext; +import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.GridCacheSharedContext; import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx; @@ -569,4 +571,38 @@ public static boolean isBinaryComparable(Object o1, Object o2) { public static int compareBinary(Object o1, Object o2) { return BinaryUtils.binariesFactory.compareForDml(o1, o2); } + + /** + * Makes current operation context as keepBinary. + * + * @param cctx Cache context. + * @return Old operation context. + */ + public static CacheOperationContext setKeepBinaryContext(GridCacheContext cctx) { + CacheOperationContext opCtx = cctx.operationContextPerCall(); + + // Force keepBinary for operation context to avoid binary deserialization inside entry processor + CacheOperationContext newOpCtx = null; + + if (opCtx == null) + // Mimics behavior of GridCacheAdapter#keepBinary and GridCacheProxyImpl#keepBinary + newOpCtx = new CacheOperationContext(false, false, true, null, false, null, false, null, null); + else if (!opCtx.isKeepBinary()) + newOpCtx = opCtx.keepBinary(); + + if (newOpCtx != null) + cctx.operationContextPerCall(newOpCtx); + + return opCtx; + } + + /** + * Restore previous binary context. + * + * @param cctx Cache context. + * @param oldOpCtx Old operation context. + */ + public static void restoreKeepBinaryContext(GridCacheContext cctx, CacheOperationContext oldOpCtx) { + cctx.operationContextPerCall(oldOpCtx); + } } diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/PublicApiIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/PublicApiIntegrationTest.java new file mode 100644 index 0000000000000..a56f4d79b0c52 --- /dev/null +++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/PublicApiIntegrationTest.java @@ -0,0 +1,64 @@ +/* + * 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.processors.query.calcite.integration; + +import java.util.List; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.cache.query.SqlFieldsQuery; +import org.apache.ignite.calcite.CalciteQueryEngineConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.configuration.SqlConfiguration; +import org.junit.Test; + +/** Public api integration tests. */ +public class PublicApiIntegrationTest extends AbstractBasicIntegrationTest { + /** */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + cfg.setSqlConfiguration(new SqlConfiguration() + .setQueryEnginesConfiguration(new CalciteQueryEngineConfiguration().setDefault(true))); + + return cfg; + } + + /** */ + @Test + public void testSimpleInsert() { + IgniteCache cache = client.getOrCreateCache(DEFAULT_CACHE_NAME); + + cache.query(new SqlFieldsQuery("CREATE TABLE emp(empid INTEGER, deptid INTEGER, name VARCHAR, salary INTEGER, " + + "PRIMARY KEY(empid, deptid)) WITH \"AFFINITY_KEY=deptid\"")); + + for (int i = 0; i < nodeCount() * 10; i++) { + cache.query(new SqlFieldsQuery("INSERT INTO emp (empid, deptid, name, salary) VALUES (?, ?, ?, ?)").setArgs( + i, i % 2, "Employee " + i, i / 10)); + } + + cache = cache.withKeepBinary(); + + for (int i = nodeCount() * 10; i < 2 * nodeCount() * 10; i++) { + cache.query(new SqlFieldsQuery("INSERT INTO emp (empid, deptid, name, salary) VALUES (?, ?, ?, ?)").setArgs( + i, i % 2, "Employee " + i, i / 10)); + } + + List> res = cache.query(new SqlFieldsQuery("SELECT * FROM emp")).getAll(); + + assertEquals("Unexpected result set size: " + res.size(), 2 * nodeCount() * 10, res.size()); + } +} diff --git a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java index f4e123c6a7c40..39726224cf074 100644 --- a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java +++ b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java @@ -61,6 +61,7 @@ import org.apache.ignite.internal.processors.query.calcite.integration.OperatorsExtensionIntegrationTest; import org.apache.ignite.internal.processors.query.calcite.integration.PartitionPruneTest; import org.apache.ignite.internal.processors.query.calcite.integration.PartitionsReservationIntegrationTest; +import org.apache.ignite.internal.processors.query.calcite.integration.PublicApiIntegrationTest; import org.apache.ignite.internal.processors.query.calcite.integration.QueryBlockingTaskExecutorIntegrationTest; import org.apache.ignite.internal.processors.query.calcite.integration.QueryEngineConfigurationIntegrationTest; import org.apache.ignite.internal.processors.query.calcite.integration.QueryMetadataIntegrationTest; @@ -183,6 +184,7 @@ CacheWithInterceptorIntegrationTest.class, TxThreadLockingTest.class, SelectByKeyFieldTest.class, + PublicApiIntegrationTest.class, }) public class IntegrationTestSuite { } From 7ebc93a081d8053926a3bb15f684a555ab9ae3d5 Mon Sep 17 00:00:00 2001 From: zstan Date: Tue, 2 Jun 2026 10:00:27 +0300 Subject: [PATCH 2/5] check --- .../query/calcite/exec/rel/ModifyNode.java | 19 ++++--------------- .../GridNearAtomicAbstractUpdateFuture.java | 2 +- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java index 81999b40bf03d..fcf2b8ebd3315 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java @@ -32,7 +32,6 @@ import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.cache.context.SessionContextImpl; -import org.apache.ignite.internal.processors.cache.CacheOperationContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal; @@ -239,23 +238,13 @@ private void flushTuples(boolean force) throws Exception { QueryProperties props = context().unwrap(QueryProperties.class); boolean keepBinaryMode = props == null || props.keepBinary(); - CacheOperationContext opCtx = null; - if (keepBinaryMode) cache = cache.keepBinary(); - else - opCtx = cctx != null ? Commons.setKeepBinaryContext(cctx) : null; - try { - if (tx == null) - invokeOutsideTransaction(tuples, cache); - else - invokeInsideTransaction(tuples, cache, tx); - } - finally { - if (opCtx != null) - Commons.restoreKeepBinaryContext(cctx, opCtx); - } + if (tx == null) + invokeOutsideTransaction(tuples, cache); + else + invokeInsideTransaction(tuples, cache, tx); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java index a9b194b10e0ac..5e5be9ec797b4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java @@ -360,7 +360,7 @@ final void completeFuture(@Nullable GridCacheReturn ret, Throwable err, @Nullabl : (this.retval || op == TRANSFORM) ? cctx.unwrapBinaryIfNeeded( ret.value(), - keepBinary, + true, U.deploymentClassLoader(cctx.kernalContext(), deploymentLdrId)) : ret.success(); From d776b245df32c9eff356ba6b836fd5de236058dd Mon Sep 17 00:00:00 2001 From: zstan Date: Tue, 2 Jun 2026 16:36:41 +0300 Subject: [PATCH 3/5] Revert "check" This reverts commit 7ebc93a081d8053926a3bb15f684a555ab9ae3d5. --- .../query/calcite/exec/rel/ModifyNode.java | 19 +++++++++++++++---- .../GridNearAtomicAbstractUpdateFuture.java | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java index fcf2b8ebd3315..81999b40bf03d 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java @@ -32,6 +32,7 @@ import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.cache.context.SessionContextImpl; +import org.apache.ignite.internal.processors.cache.CacheOperationContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal; @@ -238,13 +239,23 @@ private void flushTuples(boolean force) throws Exception { QueryProperties props = context().unwrap(QueryProperties.class); boolean keepBinaryMode = props == null || props.keepBinary(); + CacheOperationContext opCtx = null; + if (keepBinaryMode) cache = cache.keepBinary(); - - if (tx == null) - invokeOutsideTransaction(tuples, cache); else - invokeInsideTransaction(tuples, cache, tx); + opCtx = cctx != null ? Commons.setKeepBinaryContext(cctx) : null; + + try { + if (tx == null) + invokeOutsideTransaction(tuples, cache); + else + invokeInsideTransaction(tuples, cache, tx); + } + finally { + if (opCtx != null) + Commons.restoreKeepBinaryContext(cctx, opCtx); + } } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java index 5e5be9ec797b4..a9b194b10e0ac 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java @@ -360,7 +360,7 @@ final void completeFuture(@Nullable GridCacheReturn ret, Throwable err, @Nullabl : (this.retval || op == TRANSFORM) ? cctx.unwrapBinaryIfNeeded( ret.value(), - true, + keepBinary, U.deploymentClassLoader(cctx.kernalContext(), deploymentLdrId)) : ret.success(); From d471287676271e2a6ee3a08ca63bd804368fb84b Mon Sep 17 00:00:00 2001 From: zstan Date: Tue, 2 Jun 2026 16:47:59 +0300 Subject: [PATCH 4/5] check2 --- .../query/calcite/exec/rel/ModifyNode.java | 19 ++++--------------- .../GridNearAtomicAbstractUpdateFuture.java | 5 ++++- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java index 81999b40bf03d..fcf2b8ebd3315 100644 --- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java +++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ModifyNode.java @@ -32,7 +32,6 @@ import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.cache.context.SessionContextImpl; -import org.apache.ignite.internal.processors.cache.CacheOperationContext; import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.IgniteInternalCache; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal; @@ -239,23 +238,13 @@ private void flushTuples(boolean force) throws Exception { QueryProperties props = context().unwrap(QueryProperties.class); boolean keepBinaryMode = props == null || props.keepBinary(); - CacheOperationContext opCtx = null; - if (keepBinaryMode) cache = cache.keepBinary(); - else - opCtx = cctx != null ? Commons.setKeepBinaryContext(cctx) : null; - try { - if (tx == null) - invokeOutsideTransaction(tuples, cache); - else - invokeInsideTransaction(tuples, cache, tx); - } - finally { - if (opCtx != null) - Commons.restoreKeepBinaryContext(cctx, opCtx); - } + if (tx == null) + invokeOutsideTransaction(tuples, cache); + else + invokeInsideTransaction(tuples, cache, tx); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java index a9b194b10e0ac..1b694ec3830a8 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java @@ -357,7 +357,7 @@ else if (res.remapTopologyVersion() != null) final void completeFuture(@Nullable GridCacheReturn ret, Throwable err, @Nullable Long futId) { Object retval = ret == null ? null - : (this.retval || op == TRANSFORM) + : (this.retval /*|| op == TRANSFORM*/) ? cctx.unwrapBinaryIfNeeded( ret.value(), keepBinary, @@ -367,6 +367,9 @@ final void completeFuture(@Nullable GridCacheReturn ret, Throwable err, @Nullabl if (op == TRANSFORM && retval == null) retval = Collections.emptyMap(); + if (op == TRANSFORM && !this.retval) + retval = Collections.emptyMap(); + if (futId != null) cctx.mvcc().removeAtomicFuture(futId); From 220ffe36189e5c57ae40f50b40ee6c37af928aa4 Mon Sep 17 00:00:00 2001 From: zstan Date: Tue, 2 Jun 2026 17:02:58 +0300 Subject: [PATCH 5/5] check3 --- .../dht/atomic/GridNearAtomicAbstractUpdateFuture.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java index 1b694ec3830a8..31d8d22c22266 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicAbstractUpdateFuture.java @@ -357,19 +357,16 @@ else if (res.remapTopologyVersion() != null) final void completeFuture(@Nullable GridCacheReturn ret, Throwable err, @Nullable Long futId) { Object retval = ret == null ? null - : (this.retval /*|| op == TRANSFORM*/) + : (this.retval || op == TRANSFORM) ? cctx.unwrapBinaryIfNeeded( ret.value(), - keepBinary, + op == TRANSFORM || keepBinary, U.deploymentClassLoader(cctx.kernalContext(), deploymentLdrId)) : ret.success(); if (op == TRANSFORM && retval == null) retval = Collections.emptyMap(); - if (op == TRANSFORM && !this.retval) - retval = Collections.emptyMap(); - if (futId != null) cctx.mvcc().removeAtomicFuture(futId);