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
28 changes: 28 additions & 0 deletions test/check_ledger.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -2220,6 +2220,34 @@ projection_parallel projection_parallel premise: the table holds every inserted
projection_parallel projection_parallel the parallel count is a parallel covering projection scan 15;16;17;18;19 never -
projection_parallel projection_parallel the workers' rows add up to the covering rows, each returned once 15;16;17;18;19 2026-10-13 a parallel worker never wires the shared row-group counter, so every worker scans every group
projection_parallel projection_parallel workers share the covering projection scan, it is not a single claimer 15;16;17;18;19 2026-10-13 first-wins-claimer;only the first parallel worker claims row groups, so one worker scans the whole table (#1336)
projection_privilege projection_privilege a caller with no SELECT is told a privilege is missing, not that RLS is in force 15;16;17;18;19 never -
projection_privilege projection_privilege a role WITH SELECT still reads the projection 15;16;17;18;19 2026-10-14 read_projection stores no rows: its tuplestore_putvalues call removed, so every caller gets zero rows
projection_privilege projection_privilege a role with EXECUTE but no SELECT is refused read_projection 15;16;17;18;19 never -
projection_privilege projection_privilege a role with only schema USAGE is refused read_projection 15;16;17;18;19 never -
projection_privilege projection_privilege and THAT refusal is the C check, which raises 42501 from aclcheck_error 15;16;17;18;19 never -
projection_privilege projection_privilege and is refused reconstruct_via_projection 15;16;17;18;19 never -
projection_privilege projection_privilege and is refused reconstruct_via_projection, which leaks non-covered columns 15;16;17;18;19 never -
projection_privilege projection_privilege and read_projection does NOT, so the two differ as the issue says 15;16;17;18;19 2026-10-14 read_projection bound to the reconstruct_via_projection C symbol in the extension SQL, so it returns the non-covered columns too;read_projection stores no rows: its tuplestore_putvalues call removed, so every caller gets zero rows
projection_privilege projection_privilege and so does reconstruct_via_projection 15;16;17;18;19 never -
projection_privilege projection_privilege and still reconstructs 15;16;17;18;19 2026-10-14 reconstruct_via_projection stores no rows: its tuplestore_putvalues call removed, so every caller gets zero rows
projection_privilege projection_privilege and the refusal says the feature is not supported, not that a privilege is missing 15;16;17;18;19 never -
projection_privilege projection_privilege premise: t_prjexec can open a session, so a refusal below is a refusal 15;16;17;18;19 never -
projection_privilege projection_privilege premise: t_prjexec really does hold EXECUTE, so it reaches the C gate 15;16;17;18;19 never -
projection_privilege projection_privilege premise: t_prjsel CAN read the table, so its arm below tests the bar 15;16;17;18;19 never -
projection_privilege projection_privilege premise: the test roles are not superusers 15;16;17;18;19 never -
projection_privilege projection_privilege premise: the unprivileged role cannot read the table by any ordinary route 15;16;17;18;19 never -
projection_privilege projection_privilege read_projection now refuses a policy-restricted caller (#563) 15;16;17;18;19 never -
projection_privilege projection_privilege reconstruct really does return the NON-COVERED column 15;16;17;18;19 2026-10-14 reconstruct_via_projection renders every column the projection does not cover as NULL instead of the base value;reconstruct_via_projection stores no rows: its tuplestore_putvalues call removed, so every caller gets zero rows
projection_privilege projection_privilege reconstruct: a caller with no SELECT is told a privilege is missing, not that RLS is in force 15;16;17;18;19 never -
projection_privilege projection_privilege reconstruct: the EXECUTE role reaches the projection lookup on the same call 15;16;17;18;19 never -
projection_privilege projection_privilege reconstruct: the base ACL is checked before the projection name is looked up 15;16;17;18;19 never -
projection_privilege projection_privilege reconstruct: the no-EXECUTE role never reaches the body, so the grant is what stopped it 15;16;17;18;19 never -
projection_privilege projection_privilege the base ACL is checked before the projection name is looked up 15;16;17;18;19 never -
projection_privilege projection_privilege the no-EXECUTE role never reaches the body, so the grant is what stopped it 15;16;17;18;19 never -
projection_privilege projection_privilege the owner reads the projection, and gets rows 15;16;17;18;19 2026-10-14 read_projection stores no rows: its tuplestore_putvalues call removed, so every caller gets zero rows
projection_privilege projection_privilege the owner reconstructs, and gets rows 15;16;17;18;19 2026-10-14 reconstruct_via_projection stores no rows: its tuplestore_putvalues call removed, so every caller gets zero rows
projection_privilege projection_privilege the policy is in force for ordinary SQL 15;16;17;18;19 2026-10-14 the columnar custom scan drops its restriction quals (plan qual set to NIL), so the row-level-security policy qual is not applied
projection_privilege projection_privilege while the EXECUTE role reaches the projection lookup on the same call 15;16;17;18;19 never -
projection_scan_cost projection_scan_cost a clause that mentions the sort key but cannot prune on it does not cheapen a covering projection 15;16;17;18;19 2026-10-12 a covering projection is discounted for any clause that mentions the sort key, as before #1126
projection_scan_cost projection_scan_cost a non-sort-key restriction does not cheapen a covering projection 15;16;17;18;19 2026-09-18 -
projection_scan_cost projection_scan_cost a tight covering projection is cheaper relative to the base than a loose one 15;16;17;18;19 2026-10-12 no restriction ever earns the sort-key discount
Expand Down
27 changes: 25 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 238
suites_not_covered 237
#
# checks_never_observed_red -- A CENSUS. NOT a ceiling, and it must not become
# one.
Expand Down Expand Up @@ -2114,4 +2114,27 @@ suites_not_covered 238
# never 1986 + 35 + 9 - 10 = 2020
# dated 598 + 10 = 608
# 2020 + 608 == 2628
checks_never_observed_red 2020
#
# #1339, five projection_privilege checks were premises about product code
# (jdatcmd): 2020 -> 2041, and suites_not_covered 238 -> 237. Rule #1236: a
# `premise:` check must be one no repository change can turn red. These five test
# what read_projection, reconstruct_via_projection and the columnar scan return, so
# a product change can redden them. They drop the prefix in both twins, with the
# rest of each name unchanged (#1356 had already renamed the owner-read arm). The
# suite had no rows. It enters with all 28 checks from five-major runs (28/28 on
# each of 15-19). Seven are dated on PG18 by four
# mutations of the extension and one of its SQL file:
# - read_projection stores no rows: the owner arm, the "does NOT" arm and the
# SELECT-holder's read arm go red;
# - reconstruct_via_projection stores no rows: the owner arm, the NON-COVERED arm
# and "and still reconstructs" go red;
# - reconstruct renders every non-covered column as NULL: the NON-COVERED arm;
# - read_projection bound to the reconstruct C symbol: the "does NOT" arm;
# - the columnar custom scan drops its quals: "the policy is in force".
# The other 21 arrive never.
#
# ledger rows 2628 + 28 = 2656
# never 2020 + 21 = 2041
# dated 608 + 7 = 615
# 2041 + 615 == 2656
checks_never_observed_red 2041
8 changes: 4 additions & 4 deletions test/projection_privilege.sh
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,16 @@ state_as() { # state_as <role> <sql>
# function that does nothing.
check_num "the owner reads the projection, and gets rows" \
"$(q "SELECT count(*) FROM pgcolumnar.read_projection('secret','p1');")" "$ROWS"
check_num "premise: the owner reconstructs, and gets rows" \
check_num "the owner reconstructs, and gets rows" \
"$(q "SELECT count(*) FROM pgcolumnar.reconstruct_via_projection('secret','p1');")" "$ROWS"
# Both functions RETURN SETOF text: one row is a single pipe-joined string, not
# a record. A column definition list is rejected outright, which is how an
# earlier probe of these functions produced five arms that all looked like
# refusals and were actually call errors. Match the text.
check "premise: reconstruct really does return the NON-COVERED column" \
check "reconstruct really does return the NON-COVERED column" \
"$(q "SELECT pgcolumnar.reconstruct_via_projection('secret','p1') LIKE '%note-%' LIMIT 1;")" \
"t"
check "premise: and read_projection does NOT, so the two differ as the issue says" \
check "and read_projection does NOT, so the two differ as the issue says" \
"$(q "SELECT pgcolumnar.read_projection('secret','p1') LIKE '%note-%' LIMIT 1;")" \
"f"
check "premise: the test roles are not superusers" \
Expand Down Expand Up @@ -236,7 +236,7 @@ check "and still reconstructs" \
psql_run "ALTER TABLE secret ENABLE ROW LEVEL SECURITY;"
psql_run "CREATE POLICY p_one ON secret FOR SELECT TO t_prjsel USING (id = 1);"

check_num "premise: the policy is in force for ordinary SQL" \
check_num "the policy is in force for ordinary SQL" \
"$(as t_prjsel 'SELECT count(*) FROM secret;' | head -1)" "1"
check "read_projection now refuses a policy-restricted caller (#563)" \
"$(count_as t_prjsel read_projection)" "refused"
Expand Down
10 changes: 5 additions & 5 deletions test/pytest/test_projection_privilege.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,18 @@ def test_the_premises_the_fixture_is_what_the_suite_assumes(pgc_cluster, pgc_con
cur.execute(f"SELECT count(*) FROM pgcolumnar.{f}('prj_secret','p1')")
expect.num(cur.fetchone()[0], ROWS,
"the owner reads the projection, and gets rows" if f == "read_projection"
else "premise: the owner reconstructs, and gets rows")
else "the owner reconstructs, and gets rows")
cur.execute(
"SELECT pgcolumnar.reconstruct_via_projection('prj_secret','p1') "
"LIKE '%note-%' LIMIT 1"
)
expect.text(str(cur.fetchone()[0]), "True",
"premise: reconstruct really does return the NON-COVERED column")
"reconstruct really does return the NON-COVERED column")
cur.execute(
"SELECT pgcolumnar.read_projection('prj_secret','p1') LIKE '%note-%' LIMIT 1"
)
expect.text(str(cur.fetchone()[0]), "False",
"premise: and read_projection does NOT, so the two differ as the issue says")
"and read_projection does NOT, so the two differ as the issue says")
cur.execute(
"SELECT count(*) FROM pg_roles WHERE rolname = ANY(%s) AND rolsuper", (list(ROLES),)
)
Expand Down Expand Up @@ -357,7 +357,7 @@ def test_a_policy_restricted_caller_is_refused(pgc_cluster, pgc_conn, expect, fu
`PgColumnarRequireNoRowSecurity` raises ERRCODE_FEATURE_NOT_SUPPORTED, so this arm
asserts 0A000 where the shell suite greps `^ERROR:.*row-level security`. The codes are
from different SQLSTATE CLASSES -- 0A and 42 -- so this cannot be confused with either
ACL refusal by any amount of rewording, and the premise below shows the policy really
ACL refusal by any amount of rewording, and the check below shows the policy really
took effect rather than the call having broken for some other reason.
"""
with pgc_conn.cursor() as cur:
Expand All @@ -368,7 +368,7 @@ def test_a_policy_restricted_caller_is_refused(pgc_cluster, pgc_conn, expect, fu

rows, err = _as(pgc_cluster, SEL, "SELECT count(*) FROM prj_secret", schema)
assert err is None, f"{SEL} could not read the table under the policy: {err}"
expect.num(rows[0][0], 1, "premise: the policy is in force for ordinary SQL")
expect.num(rows[0][0], 1, "the policy is in force for ordinary SQL")

_, err = _as(pgc_cluster, SEL,
f"SELECT count(*) FROM pgcolumnar.{func}('prj_secret','p1')", schema)
Expand Down
Loading