github-actions[bot] commented on code in PR #67885:
URL: https://github.com/apache/doris/pull/67885#discussion_r4011725919
##########
fe/fe-core/src/main/java/org/apache/doris/qe/ShortCircuitQueryContext.java:
##########
@@ -117,12 +160,22 @@ public ShortCircuitQueryContext(Planner planner,
Queriable analzyedQuery) throws
this.tableName = this.scanNode.getTableNameInPlan();
this.schemaVersion = this.tbl.getBaseSchemaVersion();
this.partitionTopologyVersion = this.tbl.getPartitionTopologyVersion();
+ this.tableNamespaceSnapshot = TableNamespaceSnapshot.from(this.tbl);
Review Comment:
[P1] Bind the namespace fence to the authorization checks
This samples the namespace only after planning.
`NereidsPlanner.planWithLock` releases its planner resources before
`StmtExecutor` constructs this context, while `renameDatabase` can change the
same database object's name and every table's qualified database name without
advancing either security epoch. If a user passes checks for `old_db.t` and an
admin renames it to `new_db` in that window, this snapshot records `new_db`;
subsequent `matches` and version checks pass, so the prepared handle can keep
using a plan that was never authorized under the new name-scoped grant. Capture
the checked catalog/database identity and names in `SecurityDependencyContext`
and reject publication/reuse when they differ, with a deterministic test
covering the check-to-snapshot rename window.
##########
fe/fe-core/src/main/java/org/apache/doris/qe/ShortCircuitQueryContext.java:
##########
@@ -152,4 +263,247 @@ public void sanitize() {
Preconditions.checkNotNull(tbl);
Preconditions.checkNotNull(tableName);
}
+
+ /** Build state owned by one execution without modifying the cached plan
or scan conjuncts. */
+ public PointQueryExecutionContext
createPointQueryExecutionContext(StatementContext statementContext) {
+ return pointQueryKeyTemplate.bind(statementContext);
+ }
+
+ private static class PointQueryKeyTemplate {
+ private final List<Column> keyColumns;
+ private final List<PlaceholderKeyBinding> placeholderBindings;
+ private final List<List<Literal>> fixedConstraints;
+ private final boolean complete;
+
+ private PointQueryKeyTemplate(List<Column> keyColumns,
+ List<PlaceholderKeyBinding> placeholderBindings,
+ List<List<Literal>> fixedConstraints, boolean complete) {
+ this.keyColumns = Collections.unmodifiableList(new
ArrayList<>(keyColumns));
+ this.placeholderBindings = Collections.unmodifiableList(new
ArrayList<>(placeholderBindings));
+ List<List<Literal>> immutableConstraints = new
ArrayList<>(fixedConstraints.size());
+ for (List<Literal> constraints : fixedConstraints) {
+ immutableConstraints.add(Collections.unmodifiableList(new
ArrayList<>(constraints)));
+ }
+ this.fixedConstraints =
Collections.unmodifiableList(immutableConstraints);
+ this.complete = complete;
+ }
+
+ private static PointQueryKeyTemplate unsupported() {
+ return new PointQueryKeyTemplate(Collections.emptyList(),
Collections.emptyList(),
+ Collections.emptyList(), false);
+ }
+
+ private static PointQueryKeyTemplate create(OlapScanNode scanNode,
StatementContext statementContext) {
+ if (statementContext == null) {
+ return unsupported();
+ }
+ List<Column> keyColumns =
scanNode.getOlapTable().getBaseSchemaKeyColumns();
+ if (keyColumns.isEmpty()) {
+ return new PointQueryKeyTemplate(keyColumns,
Collections.emptyList(),
+ Collections.emptyList(), true);
+ }
+ if (!statementContext.arePointQueryFixedKeyConstraintsComplete()) {
+ return unsupported();
+ }
+
+ Map<String, Integer> keyOrdinals = new
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ List<List<Literal>> fixedConstraints = new
ArrayList<>(keyColumns.size());
+ for (int ordinal = 0; ordinal < keyColumns.size(); ordinal++) {
+ keyOrdinals.put(keyColumns.get(ordinal).getName(), ordinal);
+ fixedConstraints.add(new ArrayList<>());
+ }
+
+ List<PlaceholderKeyBinding> placeholderBindings = new
ArrayList<>();
+ for (Map.Entry<PlaceholderId, SlotReference> entry
Review Comment:
[P1] Derive key bindings from the accepted filter predicates
The input shape `ResultSink -> Project(k = ?0 AS flag) -> Filter(k = ?1) ->
Scan(k)` is eligible, but `registerPlaceholderIdToSlot` records both
comparisons in the statement-wide map and this loop treats both as lookup
constraints. With `?0 = 2` and `?1 = 1`, `bind` puts both values in the `k`
bucket and returns `EMPTY`; SQL must instead fetch `k = 1` and return `flag =
false`. This affects the first planned execution, and cached output expressions
are not rebound either. Build the template from the exact final filter
equalities (preserving operator and ExprId provenance) and force normal
fallback when a placeholder also appears outside them; add a server-prepared
regression for this projected comparison.
--
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]