Three medium-priority audit items in one commit, each independently
revertible.
* **#18 JOIN hash-join fast path.** New std.ch shape:
JOIN WITH <alias> TO <file> [FIELDS ...] ON <mfield> = <dfield>
expands to a 6-arg __dbJoin call with the master/detail key
field names. Runtime detects the extra args, builds an O(M)
hash over the detail's key column, then probes per master row
for O(N+M) total — vs the FOR form's O(N*M). For 1k×1k that's
2k vs 1M operations; the gap widens with N. The original FOR
form is unchanged and stays the fallback for arbitrary
predicates. New helper dbHashKey type-tags the key string so
`1` (numeric), `"1"` (string), and `.T.` (logical) don't
collide in the bucket map.
* **#38 PP rule result-marker validation.** ParseRule now walks
the result template after parseMarkers and warns about every
`<name>` (or `<(name)>` / `<.name.>` / `<{name}>` / `#<name>`
/ `<"name">`) that doesn't match a pattern marker. Warnings
flow into pp.errors via handleDirective with the directive's
filename:line, so a typo'd `<NaMe>` in an `#xcommand`
case-sensitive rule fails the build with a clear diagnostic
instead of silently producing broken expansions.
* **#44 looksLikeInlineC heuristic strengthened.** Catches more
of the common Harbour-PRG-with-C-inline-block shapes that
used to fall through and produce cryptic Go-side errors:
function-like #define, `extern "C"` linkage blocks, C return-
type declarations (`int foo(`, `static char* bar(`), and the
hb_ret*() helper family used by Harbour's C FFI return
setters. Two small predicate helpers (allLetters,
allIdentChars) keep the C-vs-Go disambiguation tight enough
that legit Go code (`func name() int { ... }`) doesn't trip.
* **#28 LIST/DISPLAY pagination** — explicitly deferred. Proper
pagination requires interactive terminal handling (Inkey(0)
for the keypress) which would hang in CI / batch mode. Will
revisit when an interactive terminal layer needs it for
other reasons.
Test fixtures: tests/std_ch/test_join_hash.prg verifies the new
ON-form path produces the same output as the FOR form would.
std.ch runner now stands at 16/16.
Other gates green:
go test ./... : PASS
FiveSql2 SQL:1999 : 43/43
Harbour compat : 56/56
std.ch suite : 16/16
FRB suite : 7/7
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
75 lines
1.8 KiB
Bash
Executable File
75 lines
1.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# std.ch regression runner. Build each PRG against the current Five
|
|
# compiler (caller's PWD must be the repo root) and execute it; non-zero
|
|
# exit or "FAIL"/"NOT REJECTED" in stdout marks the run as failed.
|
|
#
|
|
# This deliberately runs in a temp scratch directory so the DBF/NTX
|
|
# artifacts don't collide with each other across tests.
|
|
set -e
|
|
|
|
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
FIVE="$ROOT/five"
|
|
if [ ! -x "$FIVE" ]; then
|
|
echo "five binary not found at $FIVE — run 'go build -o five ./cmd/five' first" >&2
|
|
exit 2
|
|
fi
|
|
|
|
TESTS=(
|
|
test_pp_stdch
|
|
test_count
|
|
test_sum_avg
|
|
test_sum_multi
|
|
test_copy
|
|
test_sort
|
|
test_list
|
|
test_list_to_file
|
|
test_total
|
|
test_join
|
|
test_update
|
|
test_set_deleted
|
|
test_unsupported
|
|
test_block_comma
|
|
test_compound_lhs
|
|
test_join_hash
|
|
)
|
|
|
|
work="$(mktemp -d)"
|
|
trap 'rm -rf "$work"' EXIT
|
|
|
|
pass=0
|
|
fail=0
|
|
for name in "${TESTS[@]}"; do
|
|
src="$ROOT/tests/std_ch/${name}.prg"
|
|
bin="$work/${name}"
|
|
if ! "$FIVE" build "$src" -o "$bin" >/dev/null 2>"$work/${name}.err"; then
|
|
echo "FAIL build $name"
|
|
cat "$work/${name}.err" | sed 's/^/ /'
|
|
fail=$((fail+1))
|
|
continue
|
|
fi
|
|
pushd "$work" >/dev/null
|
|
if ! out="$("$bin" 2>&1)"; then
|
|
echo "FAIL run $name"
|
|
echo "$out" | sed 's/^/ /'
|
|
fail=$((fail+1))
|
|
popd >/dev/null
|
|
continue
|
|
fi
|
|
popd >/dev/null
|
|
if echo "$out" | grep -qE 'FAIL|NOT REJECTED|expect.*got'; then
|
|
echo "FAIL assert $name"
|
|
echo "$out" | sed 's/^/ /'
|
|
fail=$((fail+1))
|
|
continue
|
|
fi
|
|
echo "PASS $name"
|
|
pass=$((pass+1))
|
|
done
|
|
|
|
echo
|
|
echo "================================================================"
|
|
echo " Results: $pass / $((pass+fail)) passed"
|
|
echo "================================================================"
|
|
[ $fail -eq 0 ]
|