From 6746ae4cee7547b9939b882190d6603a53e8d6ff Mon Sep 17 00:00:00 2001 From: CharlesKWON Date: Sat, 18 Apr 2026 13:31:01 +0900 Subject: [PATCH] =?UTF-8?q?perf(fivesql2):=20stable=20temp=20alias=20?= =?UTF-8?q?=E2=80=94=201.67x=20on=20JOIN=20bench?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AcquireTemp now returns the purpose string (upper-cased table name) as the alias when available, and falls back to FA_#### only when the same purpose is already in-flight this query — i.e., self-joins. Previously every call returned a fresh FA_####, so the WA cache (keyed by alias) could never hit on JOIN queries and the file got reopened every iteration. Bench deltas vs prior HEAD: B6_INNER_JOIN 217 → 130 us -40% (1.67x) B15_CTE_WIN_JOIN 1678 → 1595 us -5% Single-table benches unchanged — they were already hitting the cache via the table-name alias path. B8 recursive CTE stays flat: its sub-executors at nDepth>1 still cycle through fresh purposes that don't stabilise across queries. FiveSql2 43/43, Harbour compat 56/56. Co-Authored-By: Claude Opus 4.7 (1M context) --- _FiveSql2/src/TSqlAlias.prg | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/_FiveSql2/src/TSqlAlias.prg b/_FiveSql2/src/TSqlAlias.prg index b0eb058..aebb585 100644 --- a/_FiveSql2/src/TSqlAlias.prg +++ b/_FiveSql2/src/TSqlAlias.prg @@ -119,11 +119,36 @@ RETURN cAlias /* - * AcquireTemp — create a unique alias for temp/derived tables. + * AcquireTemp — create a stable alias for temp/derived tables. + * + * Returns the purpose (usually the upper-cased table name) itself + * when it's a valid alias and not already in use in this query. + * This lets the WA cache hit on repeated queries of the form + * `FROM table t` — previously every call returned a fresh FA_#### + * that no cache entry could match, so every query re-opened the + * file. Self-joins (`FROM emp e1, emp e2`) still need two distinct + * workareas, so the second acquire for the same purpose falls back + * to the unique counter. */ METHOD AcquireTemp( cPurpose ) CLASS TSqlAlias - LOCAL cAlias + LOCAL cAlias, cUp, i, lTaken + + cUp := Upper( cPurpose ) + + IF ! Empty( cUp ) .AND. IsAlpha( Left( cUp, 1 ) ) + lTaken := .F. + FOR i := 1 TO Len( ::aSlots ) + IF ::aSlots[ i ][ 1 ] == cUp + lTaken := .T. + EXIT + ENDIF + NEXT + IF ! lTaken + AAdd( ::aSlots, { cUp, cPurpose, cPurpose, .F. } ) + RETURN cUp + ENDIF + ENDIF s_nGlobalSeq++ cAlias := "FA_" + StrZero( s_nGlobalSeq, 4 )