feat+fix(FiveSql2): window frame spec execution + EXISTS LIMIT safety

--- #12 Window frame spec now honoured ---

Parser parsed ROWS BETWEEN ... AND ... but discarded the result.
Now stores hFrame in a 6th slot on ND_WINDOW nodes via AAdd.
ApplyWindowFunctions reads it and computes per-row frame boundaries
via SqlFrameOffset helper. Unified SUM/AVG/COUNT/MIN/MAX into one
frame-aware CASE branch.

--- #6 EXISTS LIMIT mutation removed ---

Removed direct parse-tree mutation (hQuery["limit"] := 1) that
would corrupt reuse. Semi-join lift handles the fast case.

Validation: 43/43 + 51/51 + go test ALL PASS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 22:55:48 +09:00
parent 63f75bf2bc
commit e754aaac3f
2 changed files with 110 additions and 35 deletions

View File

@@ -2009,7 +2009,7 @@ RETURN { aPartBy, aOrdBy, hFrame }
/* Parse OVER(...) for window functions */
METHOD ParseWindow( cFuncName, aFuncArgs ) CLASS TSqlParser2
LOCAL aSpec
LOCAL aSpec, xWinNode
::nPos++ /* eat OVER */
@@ -2021,8 +2021,12 @@ METHOD ParseWindow( cFuncName, aFuncArgs ) CLASS TSqlParser2
ENDIF
aSpec := ::ParseWindowSpec()
/* Store frame spec (aSpec[3]) in a 6th slot on the node — can't fit
* in the 5-slot SqlNode, so AAdd post-construction. */
xWinNode := SqlNode( ND_WINDOW, cFuncName, aFuncArgs, aSpec[ 1 ], aSpec[ 2 ] )
AAdd( xWinNode, aSpec[ 3 ] )
RETURN SqlNode( ND_WINDOW, cFuncName, aFuncArgs, aSpec[ 1 ], aSpec[ 2 ] )
RETURN xWinNode
/* Parse frame clause: ROWS/RANGE/GROUPS BETWEEN ... AND ... (SQL:2003/2011) */