Three audit findings around polish + a release-readiness commit:
* #UX1 LIST/DISPLAY output: dropped \r\n (unix terminals showed a
stray ^M), moved the newline to AFTER each row (no more leading
blank line), and added the `*` deleted-record marker after the
record number — matches xBase LIST/DISPLAY convention. With
SET DELETED ON the marker is unreachable since the row would
have been skipped at Area.Skip level; with SET DELETED OFF the
user now sees which rows are tombstoned.
* #26 temp aliases: `__copytmp` / `__sorttmp` / `__totaltmp` /
`__jointmp` were process-global string constants. A nested
invocation (e.g., COPY inside a FOR clause whose expression
runs another COPY) collided on the alias and the inner Open
failed with "alias already in use" — surfacing as `.F.` with
no clear cause. Each Open now goes through a new helper
`nextTmpAlias(prefix)` backed by an atomic counter, so every
call gets `__copytmp_1`, `__copytmp_2`, etc. — no collisions.
* #J test coverage gap: the 13 std.ch regression tests were all
sitting in `/tmp` — lost on tmpfs reboot, never in git, never
in CI. Move them into `tests/std_ch/` and add a simple
`run.sh` runner that builds + executes each one in a temp
scratch directory and grep-asserts on FAIL / NOT REJECTED /
expectation-mismatch markers. 13/13 pass against the current
head:
PASS test_pp_stdch PASS test_count
PASS test_sum_avg PASS test_sum_multi
PASS test_copy PASS test_sort
PASS test_list PASS test_total
PASS test_join PASS test_update
PASS test_set_deleted PASS test_unsupported
PASS test_block_comma
test_block_comma in particular guards the gengo SeqExpr fix
from Wave 1 — without it the comma-in-block miscompile would
silently come back.
Gates green:
go test ./... : PASS
FiveSql2 SQL:1999 : 43/43
Harbour compat : 56/56
std.ch suite : 13/13
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
1.9 KiB
Plaintext
71 lines
1.9 KiB
Plaintext
/* JOIN WITH ... TO ... FOR ... — uses non-reserved alias names. */
|
|
|
|
PROCEDURE Main()
|
|
LOCAL aStruct, n
|
|
|
|
FErase( "cust.dbf" )
|
|
FErase( "ord.dbf" )
|
|
FErase( "out.dbf" )
|
|
|
|
/* Customers (master) */
|
|
aStruct := { ;
|
|
{ "CID", "N", 4, 0 }, ;
|
|
{ "CNAME", "C", 12, 0 } }
|
|
dbCreate( "cust.dbf", aStruct )
|
|
USE cust.dbf NEW EXCLUSIVE ALIAS cu
|
|
dbAppend() ; FieldPut(1, 1) ; FieldPut(2, "Alice")
|
|
dbAppend() ; FieldPut(1, 2) ; FieldPut(2, "Bob")
|
|
dbAppend() ; FieldPut(1, 3) ; FieldPut(2, "Carol")
|
|
dbCommit()
|
|
dbCloseArea()
|
|
|
|
/* Orders (detail) */
|
|
aStruct := { ;
|
|
{ "OID", "N", 4, 0 }, ;
|
|
{ "CID", "N", 4, 0 }, ;
|
|
{ "AMT", "N", 8, 2 } }
|
|
dbCreate( "ord.dbf", aStruct )
|
|
USE ord.dbf NEW EXCLUSIVE ALIAS od
|
|
dbAppend() ; FieldPut(1, 100) ; FieldPut(2, 1) ; FieldPut(3, 50)
|
|
dbAppend() ; FieldPut(1, 101) ; FieldPut(2, 1) ; FieldPut(3, 30)
|
|
dbAppend() ; FieldPut(1, 102) ; FieldPut(2, 2) ; FieldPut(3, 200)
|
|
dbAppend() ; FieldPut(1, 103) ; FieldPut(2, 4) ; FieldPut(3, 99) /* no-match cid */
|
|
dbCommit()
|
|
dbCloseArea()
|
|
|
|
/* Open both */
|
|
USE cust.dbf NEW EXCLUSIVE ALIAS cu
|
|
USE ord.dbf NEW EXCLUSIVE ALIAS od
|
|
SELECT cu
|
|
|
|
? "--- JOIN WITH od TO out FIELDS cid, cname, oid, amt FOR cu->cid = od->cid ---"
|
|
JOIN WITH od TO out.dbf FIELDS cid, cname, oid, amt FOR cu->cid = od->cid
|
|
|
|
/* Close both source areas */
|
|
SELECT cu
|
|
dbCloseArea()
|
|
SELECT od
|
|
dbCloseArea()
|
|
|
|
USE out.dbf NEW EXCLUSIVE
|
|
COUNT TO n
|
|
? "Joined rows =", n, "(expect 3)"
|
|
|
|
dbGoTop()
|
|
? "Field count =", FCount(), "(expect 4: cid, cname, oid, amt)"
|
|
? ""
|
|
? "rows:"
|
|
DO WHILE !Eof()
|
|
? " cid:", FieldGet(1), "name:", AllTrim(FieldGet(2)), "oid:", FieldGet(3), "amt:", FieldGet(4)
|
|
dbSkip()
|
|
ENDDO
|
|
? "(expect: 1 Alice 100 50 / 1 Alice 101 30 / 2 Bob 102 200)"
|
|
|
|
dbCloseArea()
|
|
|
|
FErase( "cust.dbf" )
|
|
FErase( "ord.dbf" )
|
|
FErase( "out.dbf" )
|
|
? "DONE"
|
|
RETURN
|