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

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

commit 3cd3f995358e006a91ab02af72d53c4e128fef6e
Author: amashenkov <[email protected]>
AuthorDate: Mon Sep 1 11:56:58 2025 +0300

    wip
---
 .../sql/planner/ItSqlPlannerCommandTest.java}      | 34 ++++++------
 .../cli/call/sql/InvalidateCacheCallInput.java     | 64 ++++++++++++++++++++++
 .../cli/call/sql/InvalidatePlannerCacheCall.java   | 61 +++++++++++++++++++++
 .../internal/cli/commands/sql/SqlCommand.java      |  8 ++-
 .../sql/planner/InvalidateCacheCommand.java        | 52 ++++++++++++++++++
 .../cli/commands/sql/planner/PlanCommand.java}     | 27 ++++-----
 .../ignite/internal/sql/api/IgniteSqlImpl.java     |  7 ++-
 .../ignite/internal/sql/api/IgniteSqlInternal.java | 10 ++++
 .../ignite/internal/sql/engine/QueryProcessor.java |  4 ++
 .../internal/sql/engine/SqlQueryProcessor.java     |  5 ++
 .../sql/engine/prepare/PrepareService.java         |  2 +
 .../sql/engine/prepare/PrepareServiceImpl.java     |  6 ++
 12 files changed, 245 insertions(+), 35 deletions(-)

diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/planner/ItSqlPlannerCommandTest.java
similarity index 50%
copy from 
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
copy to 
modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/planner/ItSqlPlannerCommandTest.java
index 0cd83ea8e90..0f51473f34a 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/planner/ItSqlPlannerCommandTest.java
@@ -15,25 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.sql.engine.prepare;
+package org.apache.ignite.internal.cli.commands.sql.planner;
 
-import java.util.concurrent.CompletableFuture;
-import org.apache.ignite.internal.sql.engine.SqlOperationContext;
-import org.apache.ignite.internal.sql.engine.exec.LifecycleAware;
-import org.apache.ignite.internal.sql.engine.sql.ParsedResult;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_URL_OPTION;
+import static org.junit.jupiter.api.Assertions.assertAll;
+
+import org.apache.ignite.internal.cli.commands.sql.CliSqlCommandTestBase;
+import org.apache.ignite.internal.cli.commands.sql.SqlCommand;
+import org.junit.jupiter.api.Test;
 
 /**
- * Preparation service that accepts an AST of the query and returns a prepared 
query plan.
+ * Tests for {@link SqlCommand}.
  */
-public interface PrepareService extends LifecycleAware {
+class ItSqlPlannerCommandTest extends CliSqlCommandTestBase {
+    @Test
+    void clearCache() {
+        execute("sql", "plan", "clear-cache", CLUSTER_URL_OPTION, NODE_URL);
 
-    /**
-     * Prepare query plan.
-     *
-     * @param parsedResult Represent of parsed query as AST, which need to be 
planned.
-     * @param ctx Query context.
-     *
-     * @return Future that contains prepared query plan when completes.
-     */
-    CompletableFuture<QueryPlan> prepareAsync(ParsedResult parsedResult, 
SqlOperationContext ctx);
+        assertAll(
+                () -> assertExitCodeIs(1),
+                this::assertOutputIsEmpty,
+                this::assertErrOutputIsEmpty
+        );
+    }
 }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/sql/InvalidateCacheCallInput.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/sql/InvalidateCacheCallInput.java
new file mode 100644
index 00000000000..0c7acefec57
--- /dev/null
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/sql/InvalidateCacheCallInput.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.cli.call.sql;
+
+import java.util.List;
+import org.apache.ignite.internal.cli.core.call.CallInput;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Input for {@link InvalidatePlannerCacheCall}.
+ */
+public class InvalidateCacheCallInput implements CallInput {
+    /**
+     * Cluster url.
+     */
+    private final String clusterUrl;
+
+    /**
+     * Tables filter.
+     */
+    @Nullable
+    private final List<String> tables;
+
+    @Nullable
+    private final List<String> targetNodes;
+
+    public InvalidateCacheCallInput(String clusterUrl, @Nullable List<String> 
tables, @Nullable List<String> targetNodes) {
+        this.clusterUrl = clusterUrl;
+        this.tables = tables;
+        this.targetNodes = targetNodes;
+    }
+
+    /** Cluster url. */
+    public String clusterUrl() {
+        return clusterUrl;
+    }
+
+    /** Returns names specifying nodes to restart partitions. Empty/null means 
"all nodes". */
+    @Nullable
+    public List<String> targetNodes() {
+        return targetNodes;
+    }
+
+    /** Return tables that SQL plans contains any of these tables should be 
invalidated. */
+    @Nullable
+    public List<String> getTables() {
+        return tables;
+    }
+}
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/sql/InvalidatePlannerCacheCall.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/sql/InvalidatePlannerCacheCall.java
new file mode 100644
index 00000000000..19ee55db064
--- /dev/null
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/sql/InvalidatePlannerCacheCall.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.internal.cli.call.sql;
+
+import jakarta.inject.Singleton;
+import org.apache.ignite.internal.cli.call.configuration.JsonString;
+import org.apache.ignite.internal.cli.core.call.Call;
+import org.apache.ignite.internal.cli.core.call.CallOutput;
+import org.apache.ignite.internal.cli.core.call.DefaultCallOutput;
+import org.apache.ignite.internal.cli.core.exception.IgniteCliApiException;
+import org.apache.ignite.internal.cli.core.rest.ApiClientFactory;
+import org.apache.ignite.rest.client.api.SqlApi;
+import org.apache.ignite.rest.client.invoker.ApiException;
+
+/**
+ * Shows node configuration from ignite cluster.
+ */
+@Singleton
+public class InvalidatePlannerCacheCall implements 
Call<InvalidateCacheCallInput, JsonString> {
+    private final ApiClientFactory clientFactory;
+
+    public InvalidatePlannerCacheCall(ApiClientFactory clientFactory) {
+        this.clientFactory = clientFactory;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public CallOutput<JsonString> execute(InvalidateCacheCallInput input) {
+        SqlApi client = createApiClient(input);
+
+        try {
+            return DefaultCallOutput.success(invalidateSqlPlannerCache(client, 
input));
+        } catch (ApiException | IllegalArgumentException e) {
+            return DefaultCallOutput.failure(new IgniteCliApiException(e, 
input.clusterUrl()));
+        }
+    }
+
+    private JsonString invalidateSqlPlannerCache(SqlApi api, 
InvalidateCacheCallInput input) throws ApiException {
+        // TODO: IGNITE-25872 serialize table names and implement api call.
+        return JsonString.fromString("");
+    }
+
+    private SqlApi createApiClient(InvalidateCacheCallInput input) {
+        return new SqlApi(clientFactory.getClient(input.clusterUrl()));
+    }
+}
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/SqlCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/SqlCommand.java
index 0c23597b4db..3cb6f3d1b6f 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/SqlCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/SqlCommand.java
@@ -33,6 +33,7 @@ import java.sql.SQLException;
 import java.util.concurrent.Callable;
 import org.apache.ignite.internal.cli.call.sql.SqlQueryCall;
 import org.apache.ignite.internal.cli.commands.BaseCommand;
+import org.apache.ignite.internal.cli.commands.sql.planner.PlanCommand;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
 import org.apache.ignite.internal.cli.core.call.StringCallInput;
 import org.apache.ignite.internal.cli.core.exception.ExceptionWriter;
@@ -48,7 +49,12 @@ import picocli.CommandLine.Parameters;
 /**
  * Command for sql execution.
  */
-@Command(name = "sql", description = "Executes SQL query")
+@Command(name = "sql",
+        subcommands = {
+                PlanCommand.class
+        },
+        description = "Executes SQL query"
+)
 public class SqlCommand extends BaseCommand implements Callable<Integer> {
     @Option(names = JDBC_URL_OPTION, required = true, descriptionKey = 
JDBC_URL_KEY, description = JDBC_URL_OPTION_DESC)
     private String jdbc;
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/planner/InvalidateCacheCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/planner/InvalidateCacheCommand.java
new file mode 100644
index 00000000000..731ad0e3c52
--- /dev/null
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/planner/InvalidateCacheCommand.java
@@ -0,0 +1,52 @@
+/*
+ * 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.cli.commands.sql.planner;
+
+import jakarta.inject.Inject;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.apache.ignite.internal.cli.call.sql.InvalidateCacheCallInput;
+import org.apache.ignite.internal.cli.call.sql.InvalidatePlannerCacheCall;
+import org.apache.ignite.internal.cli.commands.BaseCommand;
+import org.apache.ignite.internal.cli.commands.cluster.ClusterUrlProfileMixin;
+import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Mixin;
+
+/**
+ * Sql planner cache invalidation command.
+ */
+@Command(name = "clear-cache", description = "Invalidates SQL planner cache")
+public class InvalidateCacheCommand extends BaseCommand implements 
Callable<Integer> {
+    /** Cluster endpoint URL option. */
+    @Mixin
+    private ClusterUrlProfileMixin clusterUrl;
+
+    @Inject
+    private InvalidatePlannerCacheCall call;
+
+    /** {@inheritDoc} */
+    @Override
+    public Integer call() {
+        return runPipeline(CallExecutionPipeline.builder(call)
+                .inputProvider(() -> new 
InvalidateCacheCallInput(clusterUrl.getClusterUrl(), List.of(), List.of()))
+                
.exceptionHandler(ClusterNotInitializedExceptionHandler.createHandler("Failed 
to invalidate SQL planner cache"))
+        );
+    }
+}
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/planner/PlanCommand.java
similarity index 50%
copy from 
modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
copy to 
modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/planner/PlanCommand.java
index 0cd83ea8e90..fe3a237885d 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/sql/planner/PlanCommand.java
@@ -15,25 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.sql.engine.prepare;
+package org.apache.ignite.internal.cli.commands.sql.planner;
 
-import java.util.concurrent.CompletableFuture;
-import org.apache.ignite.internal.sql.engine.SqlOperationContext;
-import org.apache.ignite.internal.sql.engine.exec.LifecycleAware;
-import org.apache.ignite.internal.sql.engine.sql.ParsedResult;
+import org.apache.ignite.internal.cli.commands.BaseCommand;
+import picocli.CommandLine.Command;
 
 /**
- * Preparation service that accepts an AST of the query and returns a prepared 
query plan.
+ * Sql planner command.
  */
-public interface PrepareService extends LifecycleAware {
-
-    /**
-     * Prepare query plan.
-     *
-     * @param parsedResult Represent of parsed query as AST, which need to be 
planned.
-     * @param ctx Query context.
-     *
-     * @return Future that contains prepared query plan when completes.
-     */
-    CompletableFuture<QueryPlan> prepareAsync(ParsedResult parsedResult, 
SqlOperationContext ctx);
+@Command(name = "plan",
+        subcommands = {
+                InvalidateCacheCommand.class
+        },
+        description = "SQL planner operations")
+public class PlanCommand extends BaseCommand {
 }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/api/IgniteSqlImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/api/IgniteSqlImpl.java
index bb2705e43b3..2e4abcb7aa8 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/api/IgniteSqlImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/api/IgniteSqlImpl.java
@@ -83,7 +83,7 @@ import org.jetbrains.annotations.TestOnly;
  * Embedded implementation of the Ignite SQL query facade.
  */
 @SuppressWarnings("rawtypes")
-public class IgniteSqlImpl implements IgniteSql, IgniteComponent {
+public class IgniteSqlImpl implements IgniteSqlInternal, IgniteComponent {
     private static final IgniteLogger LOG = 
Loggers.forClass(IgniteSqlImpl.class);
 
     private static final int AWAIT_CURSOR_CLOSE_ON_STOP_IN_SECONDS = 10;
@@ -649,6 +649,11 @@ public class IgniteSqlImpl implements IgniteSql, 
IgniteComponent {
         });
     }
 
+    @Override
+    public void invalidatePlannerCache() {
+        queryProcessor.invalidatePlannerCache();
+    }
+
     private static void 
validateDmlResult(AsyncCursor.BatchedResult<InternalSqlRow> page) {
         if (page == null
                 || page.items() == null
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/api/IgniteSqlInternal.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/api/IgniteSqlInternal.java
new file mode 100644
index 00000000000..a560c28728a
--- /dev/null
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/api/IgniteSqlInternal.java
@@ -0,0 +1,10 @@
+package org.apache.ignite.internal.sql.api;
+
+import org.apache.ignite.sql.IgniteSql;
+
+/**
+ * Internal SQL facade.
+ */
+public interface IgniteSqlInternal extends IgniteSql {
+    void invalidatePlannerCache();
+}
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/QueryProcessor.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/QueryProcessor.java
index 29e497a3dfa..4d0fc33d5b1 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/QueryProcessor.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/QueryProcessor.java
@@ -70,4 +70,8 @@ public interface QueryProcessor extends IgniteComponent {
             String qry,
             Object... params
     );
+
+    default void invalidatePlannerCache() {
+
+    }
 }
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 f2e11594072..cd2f7eaa992 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
@@ -604,6 +604,11 @@ public class SqlQueryProcessor implements QueryProcessor, 
SystemViewProvider {
         return List.of(queriesViewProvider.get());
     }
 
+    @Override
+    public void invalidatePlannerCache() {
+        prepareSvc.invalidateCache();
+    }
+
     /** Completes the provided future when the callback is called. */
     public static class PrefetchCallback implements QueryPrefetchCallback {
         private final CompletableFuture<Void> prefetchFuture = new 
CompletableFuture<>();
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
index 0cd83ea8e90..172da6c2a9f 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareService.java
@@ -36,4 +36,6 @@ public interface PrepareService extends LifecycleAware {
      * @return Future that contains prepared query plan when completes.
      */
     CompletableFuture<QueryPlan> prepareAsync(ParsedResult parsedResult, 
SqlOperationContext ctx);
+
+    default void invalidateCache() {};
 }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
index 16a7cfcce28..964524581ba 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
@@ -305,6 +305,12 @@ public class PrepareServiceImpl implements PrepareService {
         );
     }
 
+    /** Invalidates planner cache. */
+    @Override
+    public void invalidateCache() {
+        cache.clear();
+    }
+
     private CompletableFuture<QueryPlan> prepareAsync0(
             ParsedResult parsedResult,
             PlanningContext planningContext

Reply via email to