Skip to content

[Refactor] Add ExecExpr typed expression hierarchy for physical plan layer#71251

Open
HangyuanLiu wants to merge 4 commits intoStarRocks:mainfrom
HangyuanLiu:pr-c-exec-expr-hierarchy
Open

[Refactor] Add ExecExpr typed expression hierarchy for physical plan layer#71251
HangyuanLiu wants to merge 4 commits intoStarRocks:mainfrom
HangyuanLiu:pr-c-exec-expr-hierarchy

Conversation

@HangyuanLiu
Copy link
Copy Markdown
Contributor

Why I'm doing:

The current FE uses AST Expr classes for both parsing/analysis and physical plan execution. This tight coupling prevents moving expression classes (e.g., FunctionCallExpr, SlotRef) to the fe-parser module and makes the planner depend on mutable AST state. A separate, typed, immutable expression hierarchy for the physical plan layer is needed.

What I'm doing:

Introduce the ExecExpr hierarchy — a typed, immutable expression representation for the physical plan layer, fully decoupled from AST Expr. This is a pure addition: 33 new files, zero modifications to existing code.

New components:

  • ExecExpr base class + 28 concrete types (ExecSlotRef, ExecFunctionCall, ExecLiteral, ExecCast, ExecBinaryPredicate, ExecCompoundPredicate, etc.)
  • ExecExprVisitor — type-safe visitor for traversal
  • ExecExprSerializer — serializes ExecExpr → Thrift TExpr
  • ExecExprExplain — EXPLAIN formatting for ExecExpr
  • ScalarOperatorToExecExpr — converts optimizer ScalarOperatorExecExpr
  • ThriftEnumConverter — centralized keys-type and opcode Thrift conversions
  • ExprOpcodeRegistry — maps AST expression metadata to TExprOpcode

What type of PR is this:

  • BugFix
  • Feature
  • Enhancement
  • Refactor
  • UT
  • Doc
  • Tool

Does this PR entail a change in behavior?

  • Yes, this PR will result in a change in behavior.
  • No, this PR will not result in a change in behavior.

Checklist:

  • I have added test cases for my bug fix or my new feature
  • This pr needs user documentation (for new or modified features or behaviors)
    • I have added documentation for my new feature or new function
    • This pr needs auto generate documentation
  • This is a backport pr

Bugfix cherry-pick branch check:

  • I have checked the version labels which the pr will be auto-backported to the target branch
    • 4.1
    • 4.0
    • 3.5
    • 3.4

…layer

Introduce a typed, immutable ExecExpr hierarchy that serves as the
physical plan's expression representation, decoupling it from the
AST Expr classes. This is a pure addition with no changes to existing
code paths.

New components:
- ExecExpr base class and 28 concrete types (ExecSlotRef, ExecFunctionCall,
  ExecLiteral, ExecCast, ExecBinaryPredicate, etc.)
- ExecExprVisitor for type-safe traversal
- ExecExprSerializer for ExecExpr → TExpr Thrift serialization
- ExecExprExplain for EXPLAIN formatting
- ScalarOperatorToExecExpr converter (optimizer ScalarOperator → ExecExpr)
- ThriftEnumConverter for keys type / opcode conversions
- ExprOpcodeRegistry for centralized TExprOpcode mappings

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@CelerData-Reviewer
Copy link
Copy Markdown

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 61b83df019

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +50 to +52
public boolean isNullable() {
return children.get(0).isNullable();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve cast nullability for non-compatible type conversions

ExecCast.isNullable() currently returns only the child nullability, but casts like VARCHAR -> INT can yield NULL even when the input expression is non-null (e.g., invalid numeric text). This marks those casts as non-null in serialized TExprNode.is_nullable, which can cause downstream plan/execution logic to skip required null handling and produce incorrect behavior.

Useful? React with 👍 / 👎.

Comment on lines +55 to +56
public boolean isSelfMonotonic() {
return true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Mark cast nodes as non-monotonic unless proven safe

ExecCast.isSelfMonotonic() unconditionally returns true, but cast monotonicity is not guaranteed (for example, narrowing casts can overflow to NULL, which breaks monotonic order). Because ExecExprSerializer propagates this flag to TExprNode.is_monotonic, this can enable incorrect predicate/zone-map style pruning decisions and lead to wrong query results.

Useful? React with 👍 / 👎.

public static boolean isBoundByTupleIds(ExecExpr expr, List<TupleId> tids) {
if (expr instanceof ExecSlotRef) {
ExecSlotRef slotRef = (ExecSlotRef) expr;
return tids.contains(slotRef.getTupleId());
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle lambda slot refs without tuple parents in bound checks

ExecExprUtils.isBoundByTupleIds() assumes every ExecSlotRef has a tuple parent and calls getTupleId() directly. However, ScalarOperatorToExecExpr.visitLambdaFunctionOperator() creates lambda argument slots from new SlotDescriptor(...) without assigning a parent tuple, so bound checks on lambda-containing expression trees can throw NullPointerException instead of returning a boolean.

Useful? React with 👍 / 👎.

HangyuanLiu and others added 3 commits April 3, 2026 12:06
108 tests covering:
- ExecExpr type construction and properties (SlotRef, Literal, FunctionCall, Cast, BinaryPredicate)
- ExecExprVisitor dispatch correctness
- ExecExprSerializer: ExecExpr → TExpr serialization
- ExecExprExplain: EXPLAIN and verbose formatting
- ThriftEnumConverter: KeysType and opcode conversions
- ExprOpcodeRegistry: opcode lookups for all operator types

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Increase FE incremental coverage from 26% to target by adding:
- 126 new tests in ExecExprTest covering all 20 previously-uncovered
  ExecExpr subclasses (CompoundPredicate, LikePredicate, InPredicate,
  IsNullPredicate, MatchExpr, Arithmetic, CaseWhen, BetweenPredicate,
  ArrayExpr, ArraySlice, MapExpr, Clone, DictMapping, DictQuery,
  DictionaryGet, Subfield, LambdaFunction, PlaceHolder,
  InformationFunction) and ExecExprUtils
- 40 new tests in ScalarOperatorToExecExprTest covering all visitor
  methods (ColumnRef, Constant, Call, Cast, BinaryPredicate,
  CompoundPredicate, InPredicate, IsNull, Like, CaseWhen, Array,
  Map, Lambda, Subfield, Between, buildIgnoreSlot)

Total: 274 tests (234 ExecExprTest + 40 ScalarOperatorToExecExprTest)

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Add 135 more tests (369 total in ExecExprTest) targeting specific
coverage gaps reported by CI:
- ExecExprExplain: verbose/toSql/explain for ALL 22 ExecExpr types
- ExecCollectionElement: construction, toThrift, visitor, serialize
- ThriftEnumConverter: joinOperatorToThrift, assertionToThrift
- ExecExprSerializer: serialize all remaining types (Compound, In,
  IsNull, Like, Arithmetic, CaseWhen, Match, Array, Map, Clone,
  Subfield, Lambda, PlaceHolder, InfoFunc, DictionaryGet, DictQuery)
- ExecLiteral: BigInt, Float, Double, Decimal, Date, DateTime types
- ExecExprVisitor: default fallback for all 22 visitor methods
- ExecSlotRef: setNullable with descriptor, CHAR→VARCHAR conversion

Total: 409 tests (369 ExecExprTest + 40 ScalarOperatorToExecExprTest)

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

[Java-Extensions Incremental Coverage Report]

pass : 0 / 0 (0%)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

[FE Incremental Coverage Report]

pass : 1240 / 1452 (85.40%)

file detail

path covered_line new_line coverage not_covered_line_detail
🔵 com/starrocks/planner/expression/ThriftEnumConverter.java 44 69 63.77% [73, 99, 104, 105, 106, 107, 108, 110, 111, 112, 113, 115, 151, 152, 153, 154, 155, 158, 163, 164, 166, 168, 170, 172, 177]
🔵 com/starrocks/planner/expression/ExecExprSerializer.java 40 58 68.97% [68, 69, 70, 72, 79, 80, 81, 82, 83, 93, 94, 96, 98, 99, 100, 107, 108, 109]
🔵 com/starrocks/sql/plan/ScalarOperatorToExecExpr.java 185 265 69.81% [101, 135, 157, 158, 167, 213, 214, 215, 216, 221, 222, 223, 224, 225, 240, 283, 298, 326, 327, 328, 337, 406, 407, 408, 410, 411, 412, 413, 414, 421, 500, 501, 502, 503, 504, 505, 506, 507, 508, 518, 519, 520, 521, 522, 523, 541, 542, 543, 544, 547, 550, 551, 552, 554, 555, 557, 560, 561, 565, 566, 567, 568, 569, 572, 573, 578, 579, 585, 590, 591, 592, 593, 598, 599, 600, 601, 602, 603, 632, 637]
🔵 com/starrocks/sql/expression/ExprOpcodeRegistry.java 32 45 71.11% [91, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 111]
🔵 com/starrocks/planner/expression/ExecExprExplain.java 246 295 83.39% [125, 196, 223, 224, 226, 249, 250, 251, 252, 253, 254, 256, 258, 508, 521, 526, 527, 528, 530, 540, 546, 566, 567, 569, 570, 571, 572, 574, 576, 578, 579, 580, 581, 583, 585, 586, 588, 589, 591, 592, 593, 594, 596, 598, 599, 600, 601, 603, 606]
🔵 com/starrocks/planner/expression/ExecCast.java 22 26 84.62% [70, 76, 77, 79]
🔵 com/starrocks/planner/expression/ExecFunctionCall.java 48 57 84.21% [89, 105, 106, 113, 114, 116, 117, 132, 155]
🔵 com/starrocks/planner/expression/ExecSlotRef.java 40 43 93.02% [88, 119, 122]
🔵 com/starrocks/planner/expression/ExecLiteral.java 79 84 94.05% [91, 92, 94, 109, 130]
🔵 com/starrocks/planner/expression/ExecLikePredicate.java 22 23 95.65% [72]
🔵 com/starrocks/planner/expression/ExecBinaryPredicate.java 21 22 95.45% [69]
🔵 com/starrocks/planner/expression/ExecInPredicate.java 20 21 95.24% [67]
🔵 com/starrocks/planner/expression/ExecExpr.java 53 55 96.36% [113, 164]
🔵 com/starrocks/planner/expression/ExecIsNullPredicate.java 24 25 96.00% [79]
🔵 com/starrocks/planner/expression/ExecDictMapping.java 11 11 100.00% []
🔵 com/starrocks/planner/expression/ExecDictQuery.java 15 15 100.00% []
🔵 com/starrocks/planner/expression/ExecCompoundPredicate.java 18 18 100.00% []
🔵 com/starrocks/planner/expression/ExecPlaceHolder.java 21 21 100.00% []
🔵 com/starrocks/planner/expression/ExecMapExpr.java 11 11 100.00% []
🔵 com/starrocks/planner/expression/ExecArrayExpr.java 11 11 100.00% []
🔵 com/starrocks/planner/expression/ExecExprVisitor.java 25 25 100.00% []
🔵 com/starrocks/planner/expression/ExecSubfield.java 19 19 100.00% []
🔵 com/starrocks/planner/expression/ExecCaseWhen.java 19 19 100.00% []
🔵 com/starrocks/planner/expression/ExecCollectionElement.java 17 17 100.00% []
🔵 com/starrocks/planner/expression/ExecInformationFunction.java 24 24 100.00% []
🔵 com/starrocks/planner/expression/ExecMatchExpr.java 15 15 100.00% []
🔵 com/starrocks/planner/expression/ExecArraySlice.java 11 11 100.00% []
🔵 com/starrocks/planner/expression/ExecArithmetic.java 22 22 100.00% []
🔵 com/starrocks/planner/expression/ExecClone.java 11 11 100.00% []
🔵 com/starrocks/planner/expression/ExecDictionaryGet.java 29 29 100.00% []
🔵 com/starrocks/planner/expression/ExecExprUtils.java 52 52 100.00% []
🔵 com/starrocks/planner/expression/ExecLambdaFunction.java 19 19 100.00% []
🔵 com/starrocks/planner/expression/ExecBetweenPredicate.java 14 14 100.00% []

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

[BE Incremental Coverage Report]

pass : 0 / 0 (0%)

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 3, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants