revert(FiveSql2): restore TSqlIndex:FindExclusive scan

Previous short-circuit (return 0 unconditionally) was a workaround
for two bugs that are both fixed now:

  1. gengo PushLocal(0) panic on unresolved identifiers
     → fixed by 08ad6f4 (PushMemvar fallback).
  2. dbInfo(DBI_FULLPATH / DBI_SHARED) returning NIL
     → fixed by d74014a (real implementations).

Restoring the original scan: walk workareas 1..250, check if any
holds an exclusive lock on the target DBF. With dbInfo now functional
and the DBI_* constants defined in include/dbinfo.ch (commit 3a00aa5),
this gives FiveSql2 real pre-flight conflict detection for concurrent
table access rather than silently proceeding into a lock failure.

Validation:
  - FiveSql2 43/43
  - standalone PRG with dbUseArea + five_SQL works (was the original
    repro that triggered the workaround)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-14 12:07:40 +09:00
parent 85541a3035
commit ad69221136

View File

@@ -132,23 +132,34 @@ RETURN nWA
METHOD FindExclusive( cTableLow ) CLASS TSqlIndex
/* Pre-flight exclusive-lock detection.
* Originally used dbInfo(DBI_FULLPATH)/DBI_SHARED to scan open
* workareas for an exclusive hold on the target DBF. In Five,
* `dbInfo()` is stubbed (returns NIL) and the DBI_* symbols are
* unresolved at compile time → runtime panic the moment any
* workarea is Used() when this runs (standalone PRGs routinely
* dbUseArea before calling five_SQL, so they tripped this).
/* Scan all used workareas for an exclusive hold on cTableLow.
* Returns the conflicting workarea number, or 0 if the table
* is free to open.
*
* The check cannot function correctly on Five regardless, so
* we short-circuit to 0 (= no conflict). Matches behavior of
* the 43-test harness which only reaches here with no Used
* workareas, so the net behavior is preserved.
*
* Future: when dbInfo(DBI_FULLPATH) lands in hbrtl, restore
* the scan. Until then use `Alias()` + filename matching if
* exclusive-lock preflight becomes necessary.
* Fully functional now that hbrtl implements dbInfo(DBI_FULLPATH)
* and DBI_SHARED. The DBI_* constants resolve via include/dbinfo.ch.
*/
LOCAL nSaved, nArea, cDbfName, lShared
nSaved := Select()
FOR nArea := 1 TO 250
IF ( nArea )->( Used() )
dbSelectArea( nArea )
IF ! Empty( Alias() )
cDbfName := Lower( AllTrim( dbInfo( DBI_FULLPATH ) ) )
IF cTableLow + ".dbf" $ cDbfName .OR. cTableLow $ cDbfName
lShared := dbInfo( DBI_SHARED )
IF lShared == .F.
dbSelectArea( nSaved )
RETURN nArea
ENDIF
ENDIF
ENDIF
ENDIF
NEXT
dbSelectArea( nSaved )
RETURN 0