Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ EXTVERSION = 0.9.2

DATA = pg_track_optimizer--$(EXTVERSION).sql

REGRESS = pg_track_optimizer interface join_filtering rstats subplan
REGRESS = interface join_filtering pg_track_optimizer rstats subplan

TAP_TESTS = 1

Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,21 @@ SELECT pg_track_optimizer_reset();
-- Re-check error metrics
```

## Regression Test Expected Output Files

PostgreSQL's `pg_regress` supports multiple alternative expected output files
(`test.out`, `test_1.out`, `test_2.out`, …). It tries each in order and
passes if any matches. This extension uses that mechanism to handle
differences in plan output across PostgreSQL versions.

| File | PostgreSQL version | Key differences |
|------|--------------------|-----------------|
| `expected/pg_track_optimizer.out` | all versions | all EXPLAIN output routed through `portable_explain_analyze`; `Heap Fetches` and `rows=N.00` normalised; `Index Searches` filtered out |
| `expected/join_filtering.out` | all versions | `Index Searches` and `rows=N.00` normalised by `portable_explain_analyze` |
| `expected/subplan.out` | PG 19+ | `SubPlan expr_1` naming (new in PG 19); output via `portable_explain_analyze` |
| `expected/subplan_1.out` | PG 17–18 | `SubPlan 1` naming; output via `portable_explain_analyze` |
| `expected/interface.out` | all versions | No version-specific differences |

## Implementation Notes

- **Filtering metrics**: The extension tracks filtering overhead separately from error calculations via `f_scan_filter` and `f_join_filter` metrics. For leaf nodes (scans), `f_scan_filter` captures `nfiltered1` weighted by relative time and output rows. For JOIN nodes, `f_join_filter` captures `nfiltered1 + nfiltered2` similarly weighted. These metrics help identify inefficient scans or joins where many rows are fetched but filtered out. Filtered tuples are **not** included in error calculations (`avg_error`, `rms_error`, etc.) to keep error metrics focused on cardinality estimation accuracy rather than filtering efficiency.
Expand Down
2 changes: 1 addition & 1 deletion expected/interface.out
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CREATE EXTENSION pg_track_optimizer;
SELECT * FROM pg_track_optimizer_reset();
pg_track_optimizer_reset
--------------------------
1
0
(1 row)

SELECT mode,entries_left,is_synced
Expand Down
9 changes: 6 additions & 3 deletions expected/join_filtering.out
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ begin
loop
out_line := regexp_replace(line, '\d+kB', 'NNkB', 'g');
out_line := regexp_replace(out_line, 'rows=(\d+)\.00', 'rows=\1', 'g');
out_line := regexp_replace(out_line, '(Heap Fetches:) \d+', '\1 N', 'g');
-- Skip Index Searches line: added in PG 18, not present in PG 17
if out_line ~ '^\s*Index Searches:' then
continue;
end if;
return next;
end loop;
end;
Expand Down Expand Up @@ -156,12 +161,11 @@ SELECT portable_explain_analyze('SELECT * FROM join_inner JOIN join_outer USING
Merge Join (actual rows=100 loops=1)
Merge Cond: (join_outer.id = join_inner.id)
-> Index Scan using join_outer_id_idx on join_outer (actual rows=101 loops=1)
Index Searches: 1
-> Sort (actual rows=100 loops=1)
Sort Key: join_inner.id
Sort Method: quicksort Memory: NNkB
-> Seq Scan on join_inner (actual rows=100 loops=1)
(8 rows)
(7 rows)

SELECT
ROUND((avg_avg::numeric), 2) AS err,
Expand Down Expand Up @@ -211,7 +215,6 @@ SELECT portable_explain_analyze('SELECT * FROM join_inner JOIN join_outer USING
RESET enable_hashjoin;
RESET enable_mergejoin;
RESET enable_material;
DROP FUNCTION portable_explain_analyze;
DROP TABLE join_inner,join_outer;
SELECT * FROM pg_track_optimizer_reset();
pg_track_optimizer_reset
Expand Down
221 changes: 0 additions & 221 deletions expected/join_filtering_1.out

This file was deleted.

Loading
Loading