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

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

commit 3a86330bac8197d8ee46f0ae1fa86eb986c2fb91
Author: amashenkov <[email protected]>
AuthorDate: Mon Jul 1 16:28:45 2024 +0300

    Add test
---
 .../internal/sql/engine/SqlQueryProcessor.java     |  1 +
 .../sql/engine/exec/ExecutionServiceImpl.java      |  2 +
 .../internal/sql/engine/exec/QueryRetryTest.java   | 82 ++++++++++++++++++++++
 .../sql/engine/framework/ImplicitTxContext.java    |  4 +-
 .../sql/engine/framework/NoOpTransaction.java      | 13 +++-
 5 files changed, 100 insertions(+), 2 deletions(-)

diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
index a7b3cae271..b74dd87fde 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
@@ -68,6 +68,7 @@ import org.apache.ignite.internal.sql.SqlCommon;
 import 
org.apache.ignite.internal.sql.configuration.distributed.SqlDistributedConfiguration;
 import 
org.apache.ignite.internal.sql.configuration.local.SqlLocalConfiguration;
 import org.apache.ignite.internal.sql.engine.exec.AsyncDataCursor;
+import 
org.apache.ignite.internal.sql.engine.exec.ConcurrentSchemaModificationException;
 import org.apache.ignite.internal.sql.engine.exec.ExchangeServiceImpl;
 import org.apache.ignite.internal.sql.engine.exec.ExecutableTableRegistryImpl;
 import 
org.apache.ignite.internal.sql.engine.exec.ExecutionDependencyResolverImpl;
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
index c314582b68..82e1f1b34c 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
@@ -320,6 +320,8 @@ public class ExecutionServiceImpl<RowT> implements 
ExecutionService, TopologyEve
 
         QueryTransactionWrapper txWrapper = 
txContext.getOrStartImplicit(plan.type() != SqlQueryType.DML);
 
+        assert sqlSchemaManager.schema(plan.catalogVersion()) == 
sqlSchemaManager.schema(txWrapper.unwrap().startTimestamp().longValue());
+
         AsyncCursor<InternalSqlRow> dataCursor = 
queryManager.execute(txWrapper.unwrap(), plan);
 
         PrefetchCallback prefetchCallback = 
operationContext.prefetchCallback();
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/QueryRetryTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/QueryRetryTest.java
new file mode 100644
index 0000000000..0bc9c73230
--- /dev/null
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/QueryRetryTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.sql.engine.exec;
+
+import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrows;
+
+import java.util.List;
+import org.apache.ignite.internal.hlc.HybridClockImpl;
+import org.apache.ignite.internal.sql.engine.framework.DataProvider;
+import org.apache.ignite.internal.sql.engine.framework.ImplicitTxContext;
+import org.apache.ignite.internal.sql.engine.framework.TestBuilders;
+import org.apache.ignite.internal.sql.engine.framework.TestCluster;
+import org.apache.ignite.internal.sql.engine.framework.TestNode;
+import org.apache.ignite.internal.sql.engine.prepare.QueryPlan;
+import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class QueryRetryTest extends BaseIgniteAbstractTest {
+    private TestCluster cluster;
+
+    @BeforeEach
+    public void init() {
+        cluster = TestBuilders.cluster()
+                .nodes("N1")
+                .dataProvider("N1", "TEST_TBL", 
TestBuilders.tableScan(DataProvider.fromCollection(List.of())))
+                .build();
+
+        cluster.start();
+    }
+
+    @AfterEach
+    public void tearDown() throws Exception {
+        cluster.stop();
+    }
+
+    @Test
+    void testQuery() {
+        TestNode node = cluster.node("N1");
+
+        node.initSchema("CREATE TABLE test_tbl (ID INT PRIMARY KEY, VAL INT, 
VAL2 INT)");
+
+        QueryPlan plan = node.prepare("SELECT * FROM test_tbl");
+
+        node.initSchema("ALTER TABLE test_tbl DROP COLUMN VAL2");
+        ImplicitTxContext.INSTANCE.updateObservableTime(new 
HybridClockImpl().now());
+
+        assertThrows(ConcurrentSchemaModificationException.class, () -> 
node.executePlan(plan), null);
+    }
+
+
+    @Test
+    void testLookupQuery() throws Exception {
+        TestNode node = cluster.node("N1");
+
+        node.initSchema("CREATE TABLE test_tbl (ID INT PRIMARY KEY, VAL INT, 
VAL2 INT)");
+
+        QueryPlan plan = node.prepare("SELECT * FROM test_tbl WHERE id = 1");
+
+        node.initSchema("ALTER TABLE test_tbl DROP COLUMN VAL2");
+        ImplicitTxContext.INSTANCE.updateObservableTime(new 
HybridClockImpl().now());
+
+        assertThrows(ConcurrentSchemaModificationException.class, () -> 
node.executePlan(plan).requestNextAsync(10).get(), null);
+    }
+
+}
\ No newline at end of file
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ImplicitTxContext.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ImplicitTxContext.java
index b22b24fa03..27bd07d10b 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ImplicitTxContext.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ImplicitTxContext.java
@@ -48,7 +48,9 @@ public class ImplicitTxContext implements 
QueryTransactionContext {
 
     @Override
     public QueryTransactionWrapper getOrStartImplicit(boolean readOnly) {
-        return new QueryTransactionWrapperImpl(new NoOpTransaction("dummy"), 
true, TX_INFLIGHTS);
+        HybridTimestamp ts = observableTimeTracker.get();
+
+        return new QueryTransactionWrapperImpl(new NoOpTransaction("dummy", 
true, ts), true, TX_INFLIGHTS);
     }
 
     @Override
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/NoOpTransaction.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/NoOpTransaction.java
index 4ad153c175..aaf3493e0f 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/NoOpTransaction.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/NoOpTransaction.java
@@ -37,7 +37,7 @@ public final class NoOpTransaction implements 
InternalTransaction {
 
     private final UUID id = UUID.randomUUID();
 
-    private final HybridTimestamp hybridTimestamp = new HybridTimestamp(1, 1);
+    private final HybridTimestamp hybridTimestamp;
 
     private final IgniteBiTuple<ClusterNode, Long> tuple;
 
@@ -75,8 +75,19 @@ public final class NoOpTransaction implements 
InternalTransaction {
      * @param readOnly Read-only or not.
      */
     private NoOpTransaction(String name, boolean readOnly) {
+        this(name, readOnly,  new HybridTimestamp(1, 1));
+    }
+
+    /**
+     * Constructs a transaction.
+     *
+     * @param name Name of the node.
+     * @param readOnly Read-only or not.
+     */
+    NoOpTransaction(String name, boolean readOnly, HybridTimestamp timestamp) {
         var networkAddress = NetworkAddress.from(new 
InetSocketAddress("localhost", 1234));
         this.tuple = new IgniteBiTuple<>(new ClusterNodeImpl(name, name, 
networkAddress), 1L);
+        this.hybridTimestamp = timestamp;
         this.readOnly = readOnly;
     }
 

Reply via email to