You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug] array_sort's second comparator argument takes the first argument's name: a nested lambda reads the wrong argument, and alias functions sort nothing #69919
I had searched in the issues and found no similar issues.
Version
master and branch-4.1 (the translator code is the same on both). Reproduced on a 4.1 build that includes the nested-lambda capture changes (#68062, #68471).
What's wrong?
ExpressionTranslator builds the ColumnRef of array_sort's second comparator argument as a copy of the first one, and keeps the first argument's name:
1. A nested lambda in the comparator reads the wrong argument. The BE identifies comparator arguments by name when it rejects a nested lambda that captures one, and both arguments are named after the first. So a nested lambda that re-declares the first argument's name and reads the second passes that check. At run time it reads its own argument instead, the comparator returns a constant, and the array comes back unsorted with no error:
2. Alias functions with an array_sort comparator sort nothing, even with a flat comparator.CREATE ALIAS FUNCTION stores the translated expression and rebuilds the function from it, so both comparator arguments come back under the first name, as (x, y) -> ... (x < x) ...:
CREATE ALIAS FUNCTION db.asc_sort(ARRAY<INT>) WITH PARAMETER(arr)
AS array_sort((x, y) -> IF(x < y, -1, IF(x = y, 0, 1)), arr);
selectdb.asc_sort([3, 1, 2]);
-- returns [3, 1, 2]
The same comparator in a plain query returns [1, 2, 3].
What you expected to happen
The first query is rejected, like any nested lambda that captures a comparator argument (array_sort comparator does not support nested lambda capturing comparator argument 'y').
The alias returns [1, 2, 3].
How to reproduce
Run the statements above.
Anything else?
Fix: give the second ColumnRef its own name. The comparator frame is position-based (column ids 0 and 1), so flat comparators in queries are unaffected:
With that change, query 1 is rejected with the error above, and a flat comparator still sorts [3, 1, 2] to [1, 2, 3]. Aliases created before the fix keep the stored broken body until they are dropped and recreated.
The source supports treating this as a correctness bug in FE translation, with two downstream effects: an unsupported nested capture escapes validation, and alias reconstruction changes the comparator expression. Suggested ownership: Nereids/expression translation, with BE lambda regression coverage. The issue currently has no labels.
I inspected local source snapshots of master at 2a4191c1dc94e789e1725d6cb345f46c31a17272 and branch-4.1 at 5fc51d21256d598dc89afe5732550b62baeac4a9. Both contain the missing rename. This is source verification; I have not independently executed the SQL or tested the proposed patch, and these snapshots do not establish the latest branch-tip status.
Verified mechanism
visitArraySort copies the first ColumnRefExpr and changes only its column ID. The copy constructor preserves its name. Consequently, references to y carry (name=x, id=1), while references to x carry (name=x, id=0). The lambda declaration itself still retains x,y; the corruption is in the references. See translator and copy constructor.
The BE nested-capture guard accepts a reference whose name belongs to an enclosing nested lambda before checking whether it captures a comparator argument. Thus the incorrectly named y matches the inner x. Runtime name resolution also selects that inner binding. For the supplied non-null integers, this explains why x < y becomes an effective self-comparison and the comparator returns 1. This supports the reported wrong result; the exact returned order remains a runtime observation from the report. See capture guard and reference resolution.
Alias creation stores the translated expression. Reconstruction renders that expression as SQL and reparses it; ColumnRefExpr SQL rendering uses the name, losing the distinction supplied by IDs. The example therefore becomes comparisons of x with itself and returns zero for non-null values. See alias creation, SQL rendering, and alias reconstruction.
Recommended next step
The proposed column2.setName(arrayItemReference.getName()) addresses the verified metadata defect. Keep IDs 0/1 and the existing positional comparator frame. Update the misleading “just a placeholder” comment as well. Validate the patch on both target branches before selecting backports.
Please include regression coverage for:
The reported nested-shadowing query failing with the capture error naming y; also capture of x, and legal nested shadowing without comparator capture.
A flat comparator sorting correctly in a plain query and in a newly created alias, including duplicate values and an alias reload/reconstruction check.
FE translation preserving distinct reference names and IDs. Existing BE capture tests construct expression nodes directly, so they cannot alone catch this FE translation defect.
The fix affects newly translated expressions; it does not repair already persisted alias bodies. Recreate affected aliases from their original intended DDL after upgrading. Until then, use an inline flat comparator, or ordinary array_sort(arr) for the ascending integer example.
Remaining evidence needed
Please provide the exact FE and BE build commits and before/after SQL outputs on the patched build, including the alias's rendered definition. No profile or broad log bundle is needed to establish this source defect. Also clarify the related-issue link: #68977 currently points to a cloud load/storage tracking issue, rather than a lambda issue. The supplied reproductions are otherwise sufficient to proceed with a focused PR.
Hi, I'd like to work on this. I'll start by reproducing the nested-lambda case and
then fix the missing column name in visitArraySort with regression coverage.
Is there anything I should keep in mind for the backport to branch-4.1?
Activity
Doris-Breakwater commentedon Oct 31, 2026
Breakwater-GitHub-Analysis-Slot: slot_69d75b8c6c1a
The source supports treating this as a correctness bug in FE translation, with two downstream effects: an unsupported nested capture escapes validation, and alias reconstruction changes the comparator expression. Suggested ownership: Nereids/expression translation, with BE lambda regression coverage. The issue currently has no labels.
I inspected local source snapshots of
masterat2a4191c1dc94e789e1725d6cb345f46c31a17272andbranch-4.1at5fc51d21256d598dc89afe5732550b62baeac4a9. Both contain the missing rename. This is source verification; I have not independently executed the SQL or tested the proposed patch, and these snapshots do not establish the latest branch-tip status.Verified mechanism
visitArraySortcopies the firstColumnRefExprand changes only its column ID. The copy constructor preserves its name. Consequently, references toycarry(name=x, id=1), while references toxcarry(name=x, id=0). The lambda declaration itself still retainsx,y; the corruption is in the references. See translator and copy constructor.ymatches the innerx. Runtime name resolution also selects that inner binding. For the supplied non-null integers, this explains whyx < ybecomes an effective self-comparison and the comparator returns1. This supports the reported wrong result; the exact returned order remains a runtime observation from the report. See capture guard and reference resolution.ColumnRefExprSQL rendering uses the name, losing the distinction supplied by IDs. The example therefore becomes comparisons ofxwith itself and returns zero for non-null values. See alias creation, SQL rendering, and alias reconstruction.Recommended next step
The proposed
column2.setName(arrayItemReference.getName())addresses the verified metadata defect. Keep IDs0/1and the existing positional comparator frame. Update the misleading “just a placeholder” comment as well. Validate the patch on both target branches before selecting backports.Please include regression coverage for:
y; also capture ofx, and legal nested shadowing without comparator capture.The fix affects newly translated expressions; it does not repair already persisted alias bodies. Recreate affected aliases from their original intended DDL after upgrading. Until then, use an inline flat comparator, or ordinary
array_sort(arr)for the ascending integer example.Remaining evidence needed
Please provide the exact FE and BE build commits and before/after SQL outputs on the patched build, including the alias's rendered definition. No profile or broad log bundle is needed to establish this source defect. Also clarify the related-issue link: #68977 currently points to a cloud load/storage tracking issue, rather than a lambda issue. The supplied reproductions are otherwise sufficient to proceed with a focused PR.
adarshomrey commentedon Nov 1, 2026
Hi, I'd like to work on this. I'll start by reproducing the nested-lambda case and
then fix the missing column name in visitArraySort with regression coverage.
Is there anything I should keep in mind for the backport to branch-4.1?