-
Type:
Task
-
Resolution: Done
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Execution
-
Fully Compatible
-
None
-
None
-
None
-
None
-
None
-
None
-
None
ExpressionNary::optimize() detects when all operands are compile-time constants and folds the expression into an ExpressionConstant by calling evaluate() with an empty ExpressionEvaluationContext (no tracker). This means any expression that allocates memory during evaluation bypasses all memory tracking when its arguments are constants. In ExpressionNary::optimize(), before the constant-fold evaluate() call, we should create a temporary SimpleMemoryUsageTracker and attach it to the eval context.
A new internalQueryMaxConstantFoldingBytes knob (default 100MB) bounds each individual constant-fold evaluation in ExpressionNary::optimize(), providing default protection regardless of the operation-level limit. Additionally, if the operation tracker is live (i.e., featureFlagExpressionMemoryTracking is on and internalQueryMaxMemoryUsageBytesPerOperation is set below its default of INT64_MAX), constant-fold memory also counts against it, so both limits apply and whichever is tighter wins. Once this is in place, per-expression fallback knobs like internalQueryMaxRangeBytes in the Classic engine become redundant and can be deprecated and removed.