github-actions[bot] commented on code in PR #68299:
URL: https://github.com/apache/doris/pull/68299#discussion_r4059309558


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCatalogCommand.java:
##########
@@ -65,9 +96,104 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor 
executor) throws Exc
                 .showCatalogs(catalogName, pattern, ctx.getCurrentCatalog() != 
null
                     ? ctx.getCurrentCatalog().getName() : null);
 
+        if (whereClause == null) {
+            return new ShowResultSet(getMetaData(), rows);
+        }
+
+        rows = executeFilter(ctx, rows);
         return new ShowResultSet(getMetaData(), rows);
     }
 
+    private List<NamedExpression> toExpressions(List<String> row) {
+        return ImmutableList.of(
+                new Alias(new BigIntLiteral(Long.parseLong(row.get(0))), 
"CatalogId"),
+                stringAlias(row.get(1), "CatalogName"),
+                stringAlias(row.get(2), "Type"),
+                stringAlias(row.get(3), "IsCurrent"),
+                stringAlias(row.get(4), "CreateTime"),
+                stringAlias(row.get(5), "LastUpdateTime"),
+                stringAlias(row.get(6), "Comment"),
+                stringAlias(row.get(7), "ErrorMsg"));
+    }
+
+    private List<NamedExpression> nullRow() {
+        return ImmutableList.of(
+                new Alias(new NullLiteral(BigIntType.INSTANCE), "CatalogId"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CatalogName"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Type"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "IsCurrent"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CreateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), 
"LastUpdateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Comment"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "ErrorMsg"));
+    }
+
+    private NamedExpression stringAlias(String value, String name) {
+        Expression literal = value == null || 
FeConstants.null_string.equals(value)
+                ? new NullLiteral(StringType.INSTANCE) : new 
StringLiteral(value);
+        return new Alias(literal, name);
+    }
+
+    private List<List<String>> executeFilter(ConnectContext outerContext, 
List<List<String>> rows) throws Exception {
+        ConnectContext filterContext = buildFilterContext(outerContext);
+        try (AutoCloseConnectContext ignored = new 
AutoCloseConnectContext(filterContext)) {
+            // The SHOW predicate must not replace the statement, state, or 
query id being audited by the caller.
+            if (rows.isEmpty()) {
+                executeFilterPlan(filterContext, filterPlan(nullRow(), true));
+                return rows;
+            }
+
+            // Multi-row VALUES plans require BE execution. Filtering one row 
at a time keeps this path in FE
+            // and preserves the CatalogMgr order instead of applying a 
different SQL string collation.
+            List<List<String>> filteredRows = new ArrayList<>(rows.size());
+            for (List<String> row : rows) {
+                filteredRows.addAll(executeFilterPlan(filterContext, 
filterPlan(toExpressions(row), false)));
+            }
+            return filteredRows;
+        }
+    }
+
+    private LogicalPlan filterPlan(List<NamedExpression> value, boolean empty) 
{
+        LogicalPlan input = new UnboundInlineTable(ImmutableList.of(value));
+        if (empty) {
+            // Keep a typed zero-row relation so invalid WHERE expressions are 
still rejected.
+            input = new LogicalLimit<>(0, 0, LimitPhase.ORIGIN, input);
+        }
+        return new UnboundResultSink<>(new 
LogicalFilter<>(ImmutableSet.of(whereClause), input));
+    }
+
+    private List<List<String>> executeFilterPlan(ConnectContext filterContext, 
LogicalPlan plan) throws Exception {
+        StatementContext statementContext = new StatementContext(
+                filterContext, new OriginStatement(toString(), 0));
+        filterContext.setStatementContext(statementContext);
+        LogicalPlanAdapter adapter = new LogicalPlanAdapter(plan, 
statementContext);
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        planner.plan(adapter, filterContext.getSessionVariable().toThrift());
+        Optional<ResultSet> resultSet = planner.handleQueryInFe(adapter);
+        if (!resultSet.isPresent()) {
+            throw new IllegalStateException("SHOW CATALOGS filter must be 
executable in FE");
+        }
+        return resultSet.get().getResultRows();
+    }
+
+    private ConnectContext buildFilterContext(ConnectContext outerContext) {
+        ConnectContext filterContext = new ConnectContext();
+        
filterContext.setSessionVariable(VariableMgr.cloneSessionVariable(outerContext.getSessionVariable()));

Review Comment:
   [P1] Preserve the caller's SQL-observable session state in the isolated 
evaluation context. This fresh context does not copy user variables, connection 
id, last query id, or the original statement clock: after `SET 
@wanted='internal'`, `SHOW CATALOGS WHERE CatalogName=@wanted` fails as an 
unsupported variable, and `connection_id()`/`last_query_id()` fold against 
default clone values. This is separate from the fixed outer-state mutation—the 
wrapper restores correctly, but the predicate reads a different session. Please 
use a complete purpose-built snapshot (while isolating mutable execution state) 
and add session-dependent predicate coverage.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCatalogCommand.java:
##########
@@ -65,9 +96,104 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor 
executor) throws Exc
                 .showCatalogs(catalogName, pattern, ctx.getCurrentCatalog() != 
null
                     ? ctx.getCurrentCatalog().getName() : null);
 
+        if (whereClause == null) {
+            return new ShowResultSet(getMetaData(), rows);
+        }
+
+        rows = executeFilter(ctx, rows);
         return new ShowResultSet(getMetaData(), rows);
     }
 
+    private List<NamedExpression> toExpressions(List<String> row) {
+        return ImmutableList.of(
+                new Alias(new BigIntLiteral(Long.parseLong(row.get(0))), 
"CatalogId"),
+                stringAlias(row.get(1), "CatalogName"),
+                stringAlias(row.get(2), "Type"),
+                stringAlias(row.get(3), "IsCurrent"),
+                stringAlias(row.get(4), "CreateTime"),
+                stringAlias(row.get(5), "LastUpdateTime"),
+                stringAlias(row.get(6), "Comment"),
+                stringAlias(row.get(7), "ErrorMsg"));
+    }
+
+    private List<NamedExpression> nullRow() {
+        return ImmutableList.of(
+                new Alias(new NullLiteral(BigIntType.INSTANCE), "CatalogId"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CatalogName"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Type"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "IsCurrent"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CreateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), 
"LastUpdateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Comment"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "ErrorMsg"));
+    }
+
+    private NamedExpression stringAlias(String value, String name) {
+        Expression literal = value == null || 
FeConstants.null_string.equals(value)
+                ? new NullLiteral(StringType.INSTANCE) : new 
StringLiteral(value);
+        return new Alias(literal, name);
+    }
+
+    private List<List<String>> executeFilter(ConnectContext outerContext, 
List<List<String>> rows) throws Exception {
+        ConnectContext filterContext = buildFilterContext(outerContext);
+        try (AutoCloseConnectContext ignored = new 
AutoCloseConnectContext(filterContext)) {
+            // The SHOW predicate must not replace the statement, state, or 
query id being audited by the caller.
+            if (rows.isEmpty()) {
+                executeFilterPlan(filterContext, filterPlan(nullRow(), true));
+                return rows;
+            }
+
+            // Multi-row VALUES plans require BE execution. Filtering one row 
at a time keeps this path in FE
+            // and preserves the CatalogMgr order instead of applying a 
different SQL string collation.
+            List<List<String>> filteredRows = new ArrayList<>(rows.size());
+            for (List<String> row : rows) {
+                filteredRows.addAll(executeFilterPlan(filterContext, 
filterPlan(toExpressions(row), false)));
+            }
+            return filteredRows;
+        }
+    }
+
+    private LogicalPlan filterPlan(List<NamedExpression> value, boolean empty) 
{
+        LogicalPlan input = new UnboundInlineTable(ImmutableList.of(value));
+        if (empty) {
+            // Keep a typed zero-row relation so invalid WHERE expressions are 
still rejected.
+            input = new LogicalLimit<>(0, 0, LimitPhase.ORIGIN, input);
+        }
+        return new UnboundResultSink<>(new 
LogicalFilter<>(ImmutableSet.of(whereClause), input));
+    }
+
+    private List<List<String>> executeFilterPlan(ConnectContext filterContext, 
LogicalPlan plan) throws Exception {
+        StatementContext statementContext = new StatementContext(
+                filterContext, new OriginStatement(toString(), 0));
+        filterContext.setStatementContext(statementContext);
+        LogicalPlanAdapter adapter = new LogicalPlanAdapter(plan, 
statementContext);
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        planner.plan(adapter, filterContext.getSessionVariable().toThrift());
+        Optional<ResultSet> resultSet = planner.handleQueryInFe(adapter);
+        if (!resultSet.isPresent()) {
+            throw new IllegalStateException("SHOW CATALOGS filter must be 
executable in FE");
+        }
+        return resultSet.get().getResultRows();
+    }
+
+    private ConnectContext buildFilterContext(ConnectContext outerContext) {
+        ConnectContext filterContext = new ConnectContext();
+        
filterContext.setSessionVariable(VariableMgr.cloneSessionVariable(outerContext.getSessionVariable()));
+        filterContext.setEnv(Env.getCurrentEnv());
+        filterContext.changeDefaultCatalog(outerContext.getDefaultCatalog());
+        filterContext.setDatabase(outerContext.getDatabase());

Review Comment:
   [P1] Preserve the existing dropped-current-catalog behavior when building 
this context. `query_p0/show/test_show_catalogs.groovy` explicitly switches to 
a catalog, drops that current catalog, and requires plain `SHOW CATALOGS` to 
remain valid. In that state line 183 copies the stale name, then `setDatabase` 
unconditionally calls `getCurrentCatalog().getDb(db)`, so adding any WHERE 
clause now NPEs before filtering. Please copy the nullable namespace without 
resolving it against a missing catalog and extend that regression with a WHERE 
form.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCatalogCommand.java:
##########
@@ -65,9 +96,104 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor 
executor) throws Exc
                 .showCatalogs(catalogName, pattern, ctx.getCurrentCatalog() != 
null
                     ? ctx.getCurrentCatalog().getName() : null);
 
+        if (whereClause == null) {
+            return new ShowResultSet(getMetaData(), rows);
+        }
+
+        rows = executeFilter(ctx, rows);
         return new ShowResultSet(getMetaData(), rows);
     }
 
+    private List<NamedExpression> toExpressions(List<String> row) {
+        return ImmutableList.of(
+                new Alias(new BigIntLiteral(Long.parseLong(row.get(0))), 
"CatalogId"),
+                stringAlias(row.get(1), "CatalogName"),
+                stringAlias(row.get(2), "Type"),
+                stringAlias(row.get(3), "IsCurrent"),
+                stringAlias(row.get(4), "CreateTime"),
+                stringAlias(row.get(5), "LastUpdateTime"),
+                stringAlias(row.get(6), "Comment"),
+                stringAlias(row.get(7), "ErrorMsg"));
+    }
+
+    private List<NamedExpression> nullRow() {
+        return ImmutableList.of(
+                new Alias(new NullLiteral(BigIntType.INSTANCE), "CatalogId"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CatalogName"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Type"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "IsCurrent"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CreateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), 
"LastUpdateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Comment"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "ErrorMsg"));
+    }
+
+    private NamedExpression stringAlias(String value, String name) {
+        Expression literal = value == null || 
FeConstants.null_string.equals(value)
+                ? new NullLiteral(StringType.INSTANCE) : new 
StringLiteral(value);
+        return new Alias(literal, name);
+    }
+
+    private List<List<String>> executeFilter(ConnectContext outerContext, 
List<List<String>> rows) throws Exception {
+        ConnectContext filterContext = buildFilterContext(outerContext);
+        try (AutoCloseConnectContext ignored = new 
AutoCloseConnectContext(filterContext)) {
+            // The SHOW predicate must not replace the statement, state, or 
query id being audited by the caller.
+            if (rows.isEmpty()) {
+                executeFilterPlan(filterContext, filterPlan(nullRow(), true));
+                return rows;
+            }
+
+            // Multi-row VALUES plans require BE execution. Filtering one row 
at a time keeps this path in FE
+            // and preserves the CatalogMgr order instead of applying a 
different SQL string collation.
+            List<List<String>> filteredRows = new ArrayList<>(rows.size());
+            for (List<String> row : rows) {
+                filteredRows.addAll(executeFilterPlan(filterContext, 
filterPlan(toExpressions(row), false)));

Review Comment:
   [P2] Install the per-row `StatementContext` before constructing these 
aliases. At this call site Java evaluates `toExpressions(row)` first, while the 
installed fresh `ConnectContext` still has no statement context, so every 
`Alias` draws from `StatementScopeIdGenerator`'s shared test-only fallback. 
That generator uses an unsynchronized `nextId++`; concurrent SHOWs can 
therefore give two columns in one row the same ExprId. Because `SlotReference` 
equality is ExprId-only and `generateReplaceMap` uses `putIfAbsent`, a 
predicate on `Type` can then be substituted with the earlier `CatalogName` 
literal and silently return the wrong row set. Please allocate these IDs from 
the installed per-row context and add concurrent uniqueness coverage.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCatalogCommand.java:
##########
@@ -65,9 +96,104 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor 
executor) throws Exc
                 .showCatalogs(catalogName, pattern, ctx.getCurrentCatalog() != 
null
                     ? ctx.getCurrentCatalog().getName() : null);
 
+        if (whereClause == null) {
+            return new ShowResultSet(getMetaData(), rows);
+        }
+
+        rows = executeFilter(ctx, rows);
         return new ShowResultSet(getMetaData(), rows);
     }
 
+    private List<NamedExpression> toExpressions(List<String> row) {
+        return ImmutableList.of(
+                new Alias(new BigIntLiteral(Long.parseLong(row.get(0))), 
"CatalogId"),
+                stringAlias(row.get(1), "CatalogName"),
+                stringAlias(row.get(2), "Type"),
+                stringAlias(row.get(3), "IsCurrent"),
+                stringAlias(row.get(4), "CreateTime"),
+                stringAlias(row.get(5), "LastUpdateTime"),
+                stringAlias(row.get(6), "Comment"),
+                stringAlias(row.get(7), "ErrorMsg"));
+    }
+
+    private List<NamedExpression> nullRow() {
+        return ImmutableList.of(
+                new Alias(new NullLiteral(BigIntType.INSTANCE), "CatalogId"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CatalogName"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Type"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "IsCurrent"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CreateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), 
"LastUpdateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Comment"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "ErrorMsg"));
+    }
+
+    private NamedExpression stringAlias(String value, String name) {
+        Expression literal = value == null || 
FeConstants.null_string.equals(value)
+                ? new NullLiteral(StringType.INSTANCE) : new 
StringLiteral(value);
+        return new Alias(literal, name);
+    }
+
+    private List<List<String>> executeFilter(ConnectContext outerContext, 
List<List<String>> rows) throws Exception {
+        ConnectContext filterContext = buildFilterContext(outerContext);
+        try (AutoCloseConnectContext ignored = new 
AutoCloseConnectContext(filterContext)) {
+            // The SHOW predicate must not replace the statement, state, or 
query id being audited by the caller.
+            if (rows.isEmpty()) {
+                executeFilterPlan(filterContext, filterPlan(nullRow(), true));
+                return rows;
+            }
+
+            // Multi-row VALUES plans require BE execution. Filtering one row 
at a time keeps this path in FE
+            // and preserves the CatalogMgr order instead of applying a 
different SQL string collation.
+            List<List<String>> filteredRows = new ArrayList<>(rows.size());
+            for (List<String> row : rows) {
+                filteredRows.addAll(executeFilterPlan(filterContext, 
filterPlan(toExpressions(row), false)));
+            }
+            return filteredRows;
+        }
+    }
+
+    private LogicalPlan filterPlan(List<NamedExpression> value, boolean empty) 
{
+        LogicalPlan input = new UnboundInlineTable(ImmutableList.of(value));
+        if (empty) {
+            // Keep a typed zero-row relation so invalid WHERE expressions are 
still rejected.
+            input = new LogicalLimit<>(0, 0, LimitPhase.ORIGIN, input);
+        }
+        return new UnboundResultSink<>(new 
LogicalFilter<>(ImmutableSet.of(whereClause), input));
+    }
+
+    private List<List<String>> executeFilterPlan(ConnectContext filterContext, 
LogicalPlan plan) throws Exception {
+        StatementContext statementContext = new StatementContext(
+                filterContext, new OriginStatement(toString(), 0));
+        filterContext.setStatementContext(statementContext);
+        LogicalPlanAdapter adapter = new LogicalPlanAdapter(plan, 
statementContext);
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        planner.plan(adapter, filterContext.getSessionVariable().toThrift());
+        Optional<ResultSet> resultSet = planner.handleQueryInFe(adapter);

Review Comment:
   [P1] Keep these synthetic per-row plans out of the global SQL cache. With 
default `enable_sql_cache=true`, every iteration uses this same full SHOW text, 
and `handleQueryInFe` caches the first one-row (or empty) result. For two 
matching catalogs, the first execution assembles both rows, but the next 
identical canonical command can be replaced before parsing by that first 
partial `LogicalSqlCache`; it also has no catalog-list or SHOW-grant dependency 
to invalidate after metadata/privilege changes. Please disable cache admission 
for this internal evaluation and add a connection-level test that executes the 
same two-match SHOW twice.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCatalogCommand.java:
##########
@@ -65,9 +96,104 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor 
executor) throws Exc
                 .showCatalogs(catalogName, pattern, ctx.getCurrentCatalog() != 
null
                     ? ctx.getCurrentCatalog().getName() : null);
 
+        if (whereClause == null) {
+            return new ShowResultSet(getMetaData(), rows);
+        }
+
+        rows = executeFilter(ctx, rows);
         return new ShowResultSet(getMetaData(), rows);
     }
 
+    private List<NamedExpression> toExpressions(List<String> row) {
+        return ImmutableList.of(
+                new Alias(new BigIntLiteral(Long.parseLong(row.get(0))), 
"CatalogId"),
+                stringAlias(row.get(1), "CatalogName"),
+                stringAlias(row.get(2), "Type"),
+                stringAlias(row.get(3), "IsCurrent"),
+                stringAlias(row.get(4), "CreateTime"),
+                stringAlias(row.get(5), "LastUpdateTime"),
+                stringAlias(row.get(6), "Comment"),
+                stringAlias(row.get(7), "ErrorMsg"));
+    }
+
+    private List<NamedExpression> nullRow() {
+        return ImmutableList.of(
+                new Alias(new NullLiteral(BigIntType.INSTANCE), "CatalogId"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CatalogName"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Type"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "IsCurrent"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CreateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), 
"LastUpdateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Comment"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "ErrorMsg"));
+    }
+
+    private NamedExpression stringAlias(String value, String name) {
+        Expression literal = value == null || 
FeConstants.null_string.equals(value)
+                ? new NullLiteral(StringType.INSTANCE) : new 
StringLiteral(value);
+        return new Alias(literal, name);
+    }
+
+    private List<List<String>> executeFilter(ConnectContext outerContext, 
List<List<String>> rows) throws Exception {
+        ConnectContext filterContext = buildFilterContext(outerContext);
+        try (AutoCloseConnectContext ignored = new 
AutoCloseConnectContext(filterContext)) {
+            // The SHOW predicate must not replace the statement, state, or 
query id being audited by the caller.
+            if (rows.isEmpty()) {
+                executeFilterPlan(filterContext, filterPlan(nullRow(), true));
+                return rows;
+            }
+
+            // Multi-row VALUES plans require BE execution. Filtering one row 
at a time keeps this path in FE
+            // and preserves the CatalogMgr order instead of applying a 
different SQL string collation.
+            List<List<String>> filteredRows = new ArrayList<>(rows.size());
+            for (List<String> row : rows) {
+                filteredRows.addAll(executeFilterPlan(filterContext, 
filterPlan(toExpressions(row), false)));
+            }
+            return filteredRows;
+        }
+    }
+
+    private LogicalPlan filterPlan(List<NamedExpression> value, boolean empty) 
{
+        LogicalPlan input = new UnboundInlineTable(ImmutableList.of(value));
+        if (empty) {
+            // Keep a typed zero-row relation so invalid WHERE expressions are 
still rejected.
+            input = new LogicalLimit<>(0, 0, LimitPhase.ORIGIN, input);
+        }
+        return new UnboundResultSink<>(new 
LogicalFilter<>(ImmutableSet.of(whereClause), input));
+    }
+
+    private List<List<String>> executeFilterPlan(ConnectContext filterContext, 
LogicalPlan plan) throws Exception {
+        StatementContext statementContext = new StatementContext(
+                filterContext, new OriginStatement(toString(), 0));
+        filterContext.setStatementContext(statementContext);
+        LogicalPlanAdapter adapter = new LogicalPlanAdapter(plan, 
statementContext);
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        planner.plan(adapter, filterContext.getSessionVariable().toThrift());
+        Optional<ResultSet> resultSet = planner.handleQueryInFe(adapter);
+        if (!resultSet.isPresent()) {

Review Comment:
   [P1] Do not require every valid WHERE predicate to fold entirely in FE. For 
example, `SHOW CATALOGS WHERE hex(CatalogName) = '696E7465726E616C'` is 
accepted, but `hex` has no FE executable registration, so the reduced tree 
still contains `PhysicalFilter`. That node is not `ComputeResultSet`; 
`handleQueryInFe` returns empty and this path throws the internal invariant 
instead of evaluating the valid predicate. Please execute the full accepted 
expression language (or deliberately validate a narrower language with a 
user-facing analysis error) and cover a non-FE-foldable scalar.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCatalogCommand.java:
##########
@@ -65,9 +96,104 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor 
executor) throws Exc
                 .showCatalogs(catalogName, pattern, ctx.getCurrentCatalog() != 
null
                     ? ctx.getCurrentCatalog().getName() : null);
 
+        if (whereClause == null) {
+            return new ShowResultSet(getMetaData(), rows);
+        }
+
+        rows = executeFilter(ctx, rows);
         return new ShowResultSet(getMetaData(), rows);
     }
 
+    private List<NamedExpression> toExpressions(List<String> row) {
+        return ImmutableList.of(
+                new Alias(new BigIntLiteral(Long.parseLong(row.get(0))), 
"CatalogId"),
+                stringAlias(row.get(1), "CatalogName"),
+                stringAlias(row.get(2), "Type"),
+                stringAlias(row.get(3), "IsCurrent"),
+                stringAlias(row.get(4), "CreateTime"),
+                stringAlias(row.get(5), "LastUpdateTime"),
+                stringAlias(row.get(6), "Comment"),
+                stringAlias(row.get(7), "ErrorMsg"));
+    }
+
+    private List<NamedExpression> nullRow() {
+        return ImmutableList.of(
+                new Alias(new NullLiteral(BigIntType.INSTANCE), "CatalogId"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CatalogName"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Type"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "IsCurrent"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CreateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), 
"LastUpdateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Comment"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "ErrorMsg"));
+    }
+
+    private NamedExpression stringAlias(String value, String name) {
+        Expression literal = value == null || 
FeConstants.null_string.equals(value)
+                ? new NullLiteral(StringType.INSTANCE) : new 
StringLiteral(value);
+        return new Alias(literal, name);
+    }
+
+    private List<List<String>> executeFilter(ConnectContext outerContext, 
List<List<String>> rows) throws Exception {
+        ConnectContext filterContext = buildFilterContext(outerContext);
+        try (AutoCloseConnectContext ignored = new 
AutoCloseConnectContext(filterContext)) {
+            // The SHOW predicate must not replace the statement, state, or 
query id being audited by the caller.
+            if (rows.isEmpty()) {
+                executeFilterPlan(filterContext, filterPlan(nullRow(), true));
+                return rows;
+            }
+
+            // Multi-row VALUES plans require BE execution. Filtering one row 
at a time keeps this path in FE
+            // and preserves the CatalogMgr order instead of applying a 
different SQL string collation.
+            List<List<String>> filteredRows = new ArrayList<>(rows.size());
+            for (List<String> row : rows) {
+                filteredRows.addAll(executeFilterPlan(filterContext, 
filterPlan(toExpressions(row), false)));
+            }
+            return filteredRows;
+        }
+    }
+
+    private LogicalPlan filterPlan(List<NamedExpression> value, boolean empty) 
{
+        LogicalPlan input = new UnboundInlineTable(ImmutableList.of(value));
+        if (empty) {
+            // Keep a typed zero-row relation so invalid WHERE expressions are 
still rejected.
+            input = new LogicalLimit<>(0, 0, LimitPhase.ORIGIN, input);
+        }
+        return new UnboundResultSink<>(new 
LogicalFilter<>(ImmutableSet.of(whereClause), input));
+    }
+
+    private List<List<String>> executeFilterPlan(ConnectContext filterContext, 
LogicalPlan plan) throws Exception {
+        StatementContext statementContext = new StatementContext(

Review Comment:
   [P1] Preserve bound server-prepared parameters in this inner statement 
context. COM_STMT_EXECUTE has already placed the literal for `SHOW CATALOGS 
WHERE CatalogName = ?` in the caller's `StatementContext`, but this replacement 
context starts with an empty `idToPlaceholderRealExpr`. Since it is no longer 
in prepare stage, `ExpressionAnalyzer.visitPlaceholder` receives no real 
expression and the parameterized SHOW fails during analysis instead of 
filtering. Please carry the execution's placeholder bindings into this isolated 
context (or bind the retained predicate before replacing it) and add a 
server-prepared regression with a bound catalog name.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowCatalogCommand.java:
##########
@@ -65,9 +96,104 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor 
executor) throws Exc
                 .showCatalogs(catalogName, pattern, ctx.getCurrentCatalog() != 
null
                     ? ctx.getCurrentCatalog().getName() : null);
 
+        if (whereClause == null) {
+            return new ShowResultSet(getMetaData(), rows);
+        }
+
+        rows = executeFilter(ctx, rows);
         return new ShowResultSet(getMetaData(), rows);
     }
 
+    private List<NamedExpression> toExpressions(List<String> row) {
+        return ImmutableList.of(
+                new Alias(new BigIntLiteral(Long.parseLong(row.get(0))), 
"CatalogId"),
+                stringAlias(row.get(1), "CatalogName"),
+                stringAlias(row.get(2), "Type"),
+                stringAlias(row.get(3), "IsCurrent"),
+                stringAlias(row.get(4), "CreateTime"),
+                stringAlias(row.get(5), "LastUpdateTime"),
+                stringAlias(row.get(6), "Comment"),
+                stringAlias(row.get(7), "ErrorMsg"));
+    }
+
+    private List<NamedExpression> nullRow() {
+        return ImmutableList.of(
+                new Alias(new NullLiteral(BigIntType.INSTANCE), "CatalogId"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CatalogName"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Type"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "IsCurrent"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "CreateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), 
"LastUpdateTime"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "Comment"),
+                new Alias(new NullLiteral(StringType.INSTANCE), "ErrorMsg"));
+    }
+
+    private NamedExpression stringAlias(String value, String name) {
+        Expression literal = value == null || 
FeConstants.null_string.equals(value)
+                ? new NullLiteral(StringType.INSTANCE) : new 
StringLiteral(value);
+        return new Alias(literal, name);
+    }
+
+    private List<List<String>> executeFilter(ConnectContext outerContext, 
List<List<String>> rows) throws Exception {
+        ConnectContext filterContext = buildFilterContext(outerContext);
+        try (AutoCloseConnectContext ignored = new 
AutoCloseConnectContext(filterContext)) {
+            // The SHOW predicate must not replace the statement, state, or 
query id being audited by the caller.
+            if (rows.isEmpty()) {
+                executeFilterPlan(filterContext, filterPlan(nullRow(), true));
+                return rows;
+            }
+
+            // Multi-row VALUES plans require BE execution. Filtering one row 
at a time keeps this path in FE
+            // and preserves the CatalogMgr order instead of applying a 
different SQL string collation.
+            List<List<String>> filteredRows = new ArrayList<>(rows.size());
+            for (List<String> row : rows) {

Review Comment:
   [P2] Avoid running a complete Nereids planning/translation cycle once per 
visible catalog. Each iteration creates a fresh planner and calls `plan`, which 
reaches analysis, rewrites, memo optimization, post-processing, fragment 
splitting, and physical translation; `CatalogMgr.showCatalogs` places no bound 
on the number of external catalogs. This makes one metadata filter consume 
planner CPU and allocations proportional to catalog count. Please bind/plan 
once for the row set (carrying an ordinal if needed to retain manager order), 
or compile the predicate once for repeated row evaluation.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to