During `run`, each statement prints `[N/TOTAL] <preview> ... <message> (<elapsed>ms)` on stderr. The preview is the first non-empty, non-comment line truncated to 60 chars. Failure halts execution.
## Overview `run` emits a single-line progress record on stderr for each statement it executes. The format gives CI logs and interactive users a compact trace of which statement is running, how long each takes, and what the engine returned. Progress goes to stderr so that piping stdout through formatters or redirecting results to files does not contaminate the trace. ## Behavior - Layout: ` [N/TOTAL] <preview> ... <message> (<elapsed>ms)`. The leading two spaces are intentional (they align with the rest of the CLI's stderr output). - `N` is the one-based statement index, `TOTAL` is the total statement count after splitting. - `<preview>` is computed per statement: the first line that is neither empty nor starts with `--`, truncated to 60 characters. Comment-only statements never reach this code because the splitter drops them. - `... <message>` is appended after the engine responds. For a success with a server-supplied message (for example, `2 rows inserted`), the message is used verbatim. For a success with no message, the literal string `OK` is printed. - `(<elapsed>ms)` is the wall-clock time for that single statement measured on the client, including network round-trip. - On error, the line ends `... ERROR: <error text>` with no elapsed suffix, and `run` returns exit code 1 without advancing to the next statement. - A final summary line ` N/TOTAL statements executed successfully` is printed on clean completion. ## Compatibility - `run` is the only code path that emits this format. Piped-stdin execution and `query` do not print `[N/TOTAL]` lines. - The demo-test runner prints a visually similar but different format (80-char preview, different punctuation, report sections); the two should not be screen-scraped with the same parser. - Preview truncation is character-based, not byte-based, so multi-byte characters count as one slot each. - Elapsed time is rendered as an integer millisecond count from `Instant::elapsed().as_millis()`; sub-millisecond statements show as `0ms`.
# Typical progress trace for a three-statement script
[1/3] CREATE TABLE customers (id INT, name STRING) ... OK (45ms)
[2/3] INSERT INTO customers VALUES (1, 'alice'), (2, 'bob') ... 2 rows inserted (123ms)
[3/3] CREATE INDEX idx_customers_name ON customers(name) ... OK (18ms)
3/3 statements executed successfully
# A failure stops at the offending statement and returns exit 1
[1/3] CREATE TABLE customers (id INT, name STRING) ... OK (45ms)
[2/3] INSERT INTO customrs VALUES (1, 'alice') ... ERROR: table customrs not found
# Redirect stdout for JSON results while keeping progress visible
delta-forge-cli --format json run report.sql >results.json
# stderr still shows:
# [1/5] WITH daily AS (SELECT ... ... 31 rows (412ms)
# [2/5] ...