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
31 changes: 31 additions & 0 deletions test/check_ledger.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,37 @@ encode_post_codec encode_post_codec the tail column holds no row the heap does n
encode_post_codec encode_post_codec the tail column preserves its checksum 15;16;17;18;19 2026-10-13 the reader returning row 5 of every row group as NULL
encode_post_codec encode_post_codec the tail column reads back exactly what the heap holds 15;16;17;18;19 2026-10-13 the reader returning row 5 of every row group as NULL
encode_post_codec encode_post_codec while a column where encoding genuinely wins still encodes 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege coverage: inputs == sum(buckets) 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege coverage: no entry point is unbucketed 15;16;17;18;19 2026-10-14 the install script gains a pgcolumnar function no bucket names
entry_point_privilege entry_point_privilege coverage: relation-taking == pinned + claimed-guarded + catalog-governed 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege every catalog-governed name is still a relation-taking entry point 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege export_arrow refuses a caller with no privilege before touching the file 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege export_parquet refuses a caller with no privilege before touching the file 15;16;17;18;19 2026-10-14 export_parquet without its SELECT check
entry_point_privilege entry_point_privilege get_storage_id refuses an unprivileged caller with 42501 15;16;17;18;19 2026-10-14 get_storage_id without its SELECT check
entry_point_privilege entry_point_privilege import_arrow refuses a caller with no privilege before touching the file 15;16;17;18;19 2026-10-14 import_arrow without its INSERT check
entry_point_privilege entry_point_privilege import_parquet refuses a caller with no privilege before touching the file 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege no exempt name actually takes a relation 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege no pinned name is stale (all still exist and take a relation) 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege no relation-taking C entry point is still ungated 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege premise: at least one relation-taking entry point was found 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege premise: t_ep can open a session 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege premise: t_ep cannot read the table by any ordinary route 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege premise: t_ep holds the server-file roles, so it reaches the table check 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege premise: t_ep now holds EXECUTE, so a refusal below can only be the C check 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege premise: the extension is installed and C entry points were found 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege premise: the install script declares MODULE_PATHNAME symbols at all 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege read_projection refuses an unprivileged caller with 42501 15;16;17;18;19 2026-10-14 read_projection without its SELECT check
entry_point_privilege entry_point_privilege reconstruct_via_projection refuses an unprivileged caller with 42501 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege the catalog and the install script agree on the symbol set 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege the catalog-governed class is the six from #560 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege the owner can call get_storage_id, so a refusal below is a refusal 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege the owner can call read_projection, so a refusal below is a refusal 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege the owner can call reconstruct_via_projection, so a refusal below is a refusal 15;16;17;18;19 2026-10-14 reconstruct_via_projection refuses even a superuser owner
entry_point_privilege entry_point_privilege the owner can call vm_is_visible, so a refusal below is a refusal 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege the owner can call vm_selftest, so a refusal below is a refusal 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege the relation-by-other-means class is the three that are known 15;16;17;18;19 never -
entry_point_privilege entry_point_privilege vm_is_visible refuses an unprivileged caller with 42501 15;16;17;18;19 2026-10-14 vm_is_visible without its owner check
entry_point_privilege entry_point_privilege vm_selftest refuses an unprivileged caller with 42501 15;16;17;18;19 never -
fdw_plan_privilege fdw_plan_privilege a privileged planner estimates the Iceberg table from its manifests 15;16;17;18;19 never -
fdw_plan_privilege fdw_plan_privilege a privileged planner estimates the Parquet table from the file's size 15;16;17;18;19 never -
fdw_plan_privilege fdw_plan_privilege an unprivileged planner gets the flat Parquet estimate 15;16;17;18;19 2026-10-14 the Parquet planner stats the file for any role (no pg_read_server_files gate)
Expand Down
32 changes: 30 additions & 2 deletions test/check_ledger_budget.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#
# Adding a check to a suite that is already covered does not move it, which is
# what makes it safe to bound.
suites_not_covered 241
suites_not_covered 240
#
# checks_never_observed_red -- A CENSUS. NOT a ceiling, and it must not become
# one.
Expand Down Expand Up @@ -2061,4 +2061,32 @@ suites_not_covered 241
# never 1965 - 3 = 1962
# dated 588 + 3 = 591
# 1962 + 591 == 2553
checks_never_observed_red 1962
#
# #1341, entry_point_privilege seeded with its pytest twin (OffgridwithJD): 1962 -> 1988,
# and suites_not_covered 241 -> 240. The suite had no rows. It enters with all 31
# checks from five-major runs (31/31 on each of 15-19). Five are dated, one per
# mutation: get_storage_id and read_projection without their SELECT check (each
# 42501 arm), export_parquet without its SELECT and import_arrow without its INSERT
# check (each reached the file layer), and the install script gaining a function no
# bucket names (the unbucketed arm). The other 26 arrive never. A relation-taking
# function added with no check at all survives this suite, in both twins: it is
# counted as claimed-guarded. Filed as #1386 rather than claimed here.
#
# ledger rows 2553 + 31 = 2584
# never 1962 + 26 = 1988
# dated 591 + 5 = 596
# 1988 + 596 == 2584
#
# #1387 review (OffgridwithJD): 1988 -> 1986. The five owner-call checks lose the premise
# prefix: a function refusing even its owner is a product change, and the shell now
# reads the call by psql's exit status ("q ... && echo ok" always printed ok). The
# reconstruct one is dated by reconstruct_via_projection refusing a superuser, and
# vm_is_visible's 42501 arm by its owner check removed. The shell grants EXECUTE by OID
# on every overload, so the EXECUTE premise depends on the fixture alone and stays one.
# Five-major runs: 31/31 on 15-19.
#
# ledger rows 2584 = 2584
# never 1988 - 2 = 1986
# dated 596 + 2 = 598
# 1986 + 598 == 2584
checks_never_observed_red 1986
19 changes: 15 additions & 4 deletions test/entry_point_privilege.sh
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,15 @@ call_for() { # call_for <fn> -> a valid argument vector for that function
#
# Granting EXECUTE puts the role PAST the SQL layer on purpose, so the only thing
# left that can refuse it is the C check. Now 42501 attributes to one layer.
#
# On every overload, by OID (#1387 review): a grant on a hard-coded signature, with
# its error discarded, left the role without EXECUTE when a declaration changed, and
# the premise below then reddened for the fixture's reason rather than the product's.
for fn in $GUARDED_BEHAVIOURAL; do
psql_run "GRANT EXECUTE ON FUNCTION pgcolumnar.$fn($(case "$fn" in read_projection|reconstruct_via_projection) echo "regclass,text" ;; *) echo "regclass,int" ;; esac)) TO t_ep;" 2>/dev/null
while IFS= read -r sig; do
[ -n "$sig" ] && psql_run "GRANT EXECUTE ON FUNCTION $sig TO t_ep;"
done <<<"$(q "SELECT p.oid::regprocedure FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'pgcolumnar' AND p.proname = '$fn';")"
done
check "premise: t_ep now holds EXECUTE, so a refusal below can only be the C check" \
"$(q "SELECT bool_and(has_function_privilege('t_ep', p.oid, 'EXECUTE'))
Expand All @@ -380,8 +387,12 @@ check "premise: t_ep now holds EXECUTE, so a refusal below can only be the C che

for fn in $GUARDED_BEHAVIOURAL; do
sql="$(call_for "$fn")"
check "premise: the owner can call $fn, so a refusal below is a refusal" \
"$(q "$sql" >/dev/null 2>&1 && echo ok || echo broken)" "ok"
# A check, not a premise (#1236; #1387 review): a function refusing even its owner
# is a product change. Read by psql's exit status: q ends in "|| true", so
# "q ... && echo ok" printed ok whatever the call did.
check "the owner can call $fn, so a refusal below is a refusal" \
"$(env PATH="$PGC_BINDIR:$PATH" psql -h 127.0.0.1 -p "$PGC_PORT" -U postgres -d "$PGC_DB" \
-X -At -v ON_ERROR_STOP=1 -c "$sql" >/dev/null 2>&1 && echo ok || echo broken)" "ok"
check "$fn refuses an unprivileged caller with 42501" \
"$(as_ep "$sql")" "42501"
done
Expand All @@ -405,7 +416,7 @@ check "premise: t_ep holds the server-file roles, so it reaches the table check"
# at which point they reddened and named themselves, which is what a pin is for.
for fn in export_arrow export_parquet import_arrow import_parquet; do
out="$(env PATH="$PGC_BINDIR:$PATH" psql -h 127.0.0.1 -p "$PGC_PORT" -U t_ep -d "$PGC_DB" -At \
-c "SELECT pgcolumnar.$fn('ep_target','/nonexistent/dir/x');" 2>&1 | head -1)"
-c "SELECT pgcolumnar.$fn('ep_target','/nonexistent/dir/x');" 2>&1 | grep -m1 'ERROR:')"
case "$out" in
*"permission denied for table"*) state=refused ;;
*"could not open file"*) state=reached-the-file-layer ;;
Expand Down
11 changes: 11 additions & 0 deletions test/pytest/TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ behaviour, the source of that number is named.
- [106. test_every_suite_job_installs_the_extensions.py: every job that runs the suites installs the extension packages](#106-test_every_suite_job_installs_the_extensionspy-every-job-that-runs-the-suites-installs-the-extension-packages)
- [107. test_fdw_plan_privilege.py: planning a foreign table reads no server file for a role the scan would refuse](#107-test_fdw_plan_privilegepy-planning-a-foreign-table-reads-no-server-file-for-a-role-the-scan-would-refuse)
- [108. test_arrow_import.py: import_arrow round trips, reads a foreign file, and refuses what it cannot decode](#108-test_arrow_importpy-import_arrow-round-trips-reads-a-foreign-file-and-refuses-what-it-cannot-decode)
- [109. test_entry_point_privilege.py: every relation-taking entry point has a decided privilege bar](#109-test_entry_point_privilegepy-every-relation-taking-entry-point-has-a-decided-privilege-bar)

## 1. How to read a test in here

Expand Down Expand Up @@ -6876,3 +6877,13 @@ The pytest twin of `test/arrow_import.sh` (ported for #1341), every check by the
| `test_the_refusals_and_every_temporal_carrier` | the dictionary and compressed refusals, every carrier and unit, the 22008 guards, the 42804 type matches with their controls, an empty target after a refusal, and nested units |
| `test_an_import_maintains_the_tables_indexes` | the plan really uses the index, index and sequential scans agree, the unique violation and its row count, and the partial index |
| `test_a_fifo_is_refused_not_a_hang` | XX001 within the wall clock, and the backend still up |

## 109. test_entry_point_privilege.py: every relation-taking entry point has a decided privilege bar

The pytest twin of `test/entry_point_privilege.sh` (#569, ported for #1341), every check by the shell's name. The population comes from the catalog, never the script: `prosrc` is the C symbol and `proargtypes[0] = regclass` is "takes a relation", and the install script's symbols are checked against the catalog as a set. Every entry point lands in exactly one bucket (exempt, relation-taking, relation by other means), the exempt list may not hold a relation-taking name, and the relation-taking class splits into catalog-governed (the six from #560) and claimed-guarded with none pinned as ungated. Then behaviourally: a login role holding EXECUTE, so the C check is the only refuser, is refused 42501 by the five guarded names after the owner's identical call succeeds, and the four file siblings refuse it at the table before touching the file.

### Every test

| test | what it holds |
| --- | --- |
| `test_every_relation_taking_entry_point_has_a_decided_bar` | the enumeration premises, the symbol-set agreement, the bucket and class counts, the five 42501 refusals with their owner premises, and the four file siblings refused at the table |
4 changes: 3 additions & 1 deletion test/pytest/expected_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -651,4 +651,6 @@ guard_tests 433
# six tests, by collection over the cluster files on this tree.
# cluster_tests 549 -> 550 for #1341's test_a_half_declaration_is_no_retention in
# test_ttl_expire.py, by collection over the cluster files on this tree.
cluster_tests 550
# cluster_tests 550 -> 551 for #1341's test_entry_point_privilege.py, the twin of
# entry_point_privilege.sh: one test, by collection over the cluster files on this tree.
cluster_tests 551
1 change: 1 addition & 0 deletions test/pytest/test_compare_to_bash.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"column_extent",
"differential",
"encode_post_codec",
"entry_point_privilege",
"format_downgrade",
"hilbert_cluster",
"hilbert_locality",
Expand Down
Loading
Loading