Skip to content

feat(backend): add PostgreSQL Row-Level Security POLICY DDL expressions - #52

Merged
vistart merged 3 commits into
release/v1.0.0.dev16from
feature/postgres-policy-expression
Aug 7, 2026
Merged

vistart merged 3 commits into
release/v1.0.0.dev16from
feature/postgres-policy-expression

Conversation

@vistart

@vistart vistart commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

Adds PostgreSQL Row-Level Security (RLS) POLICY DDL expressions so policies can be administered through the Expression-Dialect pipeline. New expressions:

  • PostgresCreatePolicyExpression — CREATE POLICY ... ON ... AS ... FOR ... TO ... USING ... WITH CHECK ...
  • PostgresAlterPolicyExpression — ALTER POLICY ... RENAME TO ... / ALTER POLICY ... TO ... USING ... WITH CHECK ...
  • PostgresDropPolicyExpression — DROP POLICY ... [CASCADE | RESTRICT]

plus PolicyType, PolicyCommand, AlterPolicyMode enums in expression/ddl/policy.py.

The new PostgresPolicyMixin provides version-gated format_* methods and capability switches:

  • PG 9.5+ — basic CREATE / ALTER / DROP POLICY
  • PG 10+ — AS RESTRICTIVE and explicit AS PERMISSIVE keyword (AS PERMISSIVE is silently omitted on 9.5)
  • PG 15+ — the CURRENT_ROLE role keyword in the TO clause

PostgresPolicySupport is the corresponding @runtime_checkable Protocol, wired into the dialect alongside the mixin.

Design note (归层): POLICY is a PostgreSQL extension, not a SQL-standard statement, so all implementation lives in the python-activerecord-postgres backend package only; the core library (backend/expression/statements/) is untouched.

Scope note: This PR intentionally does NOT include the RLS ALTER TABLE ... ENABLE/FORCE/DISABLE ROW LEVEL SECURITY expressions nor policy introspection (planned as a follow-up).

Type of change

  • feat: A new feature
  • ci: Bump the postgres 19 CI job from 19beta1 to 19beta2 (PGQ)

Breaking Change

  • No breaking changes

Impact on End-Users:
No backward-incompatible changes; this adds opt-in RLS policy expressions only.

Impact on Backend Developers (Custom Implementations):
No breaking changes.

Related Repositories/Packages

None — PostgreSQL-only feature, contained within this repository.

Testing

  • I have added new tests to cover my changes.
  • I have updated existing tests to reflect my changes.
  • All existing tests pass.

Test Plan:

  • New tests/rhosocial/activerecord_postgres_test/feature/backend/postgres/test_policy.py (64 assertions).
  • Updated test_ddl_protocols.py (2 runtime-checkable conformance cases).
  • Local full regression: 797 passed via PYTHONPATH=src pytest tests/.
  • CI (test.yml): matrix of Python 3.8–3.14 × PostgreSQL 9–18 all success; PG19beta2/PGQ job success (5353 passed, skipped = the extension-not-available/version-gated cases).

Checklist

  • My code follows the project's code style guidelines.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation (Docstrings).
  • My changes generate no new warnings.
  • I have added a Changelog fragment (changelog.d/0.added.md — placeholder; will be renamed to the PR number once assigned).
  • I have verified that my changes do not introduce SQL injection vulnerabilities.
  • I have checked for potential performance regressions.

Additional Notes

  • The changelog fragment is currently changelog.d/0.added.md. After this PR is created, the fragment will be renamed to changelog.d/<pr_number>.added.md in a follow-up commit (per .claude/version_control.md and the 49→50 precedent).

vistart added 2 commits August 7, 2026 20:04
Add PostgresCreatePolicyExpression, PostgresAlterPolicyExpression, and
PostgresDropPolicyExpression (plus PolicyType/PolicyCommand/AlterPolicyMode
enums) so RLS policies can be administered through the Expression-Dialect
pipeline. The new PostgresPolicyMixin provides version-gated formatters
(PG 9.5+ for basic CREATE/ALTER/DROP, 10+ for AS RESTRICTIVE and explicit
AS PERMISSIVE, 15+ for the CURRENT_ROLE role keyword) and capability
switches; PostgresPolicySupport is the matching @runtime_checkable Protocol.

POLICY is a PostgreSQL extension, not SQL-standard, so it is implemented in
the postgres backend package only; the core library is untouched.

Note: changelog.d/0.added.md is a placeholder fragment — rename it to the
actual PR number once assigned before merging.
@vistart vistart added the feature label Aug 7, 2026
@codecov

codecov Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.15044% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.58%. Comparing base (5b83d05) to head (10c4205).

Files with missing lines Patch % Lines
...cord/backend/impl/postgres/protocols/ddl/policy.py 52.00% 11 Missing and 1 partial ⚠️
...erecord/backend/impl/postgres/mixins/ddl/policy.py 95.62% 3 Missing and 3 partials ⚠️
...ord/backend/impl/postgres/expression/ddl/policy.py 96.61% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@                   Coverage Diff                    @@
##           release/v1.0.0.dev16      #52      +/-   ##
========================================================
+ Coverage                 73.24%   73.58%   +0.34%     
========================================================
  Files                       278      281       +3     
  Lines                     11364    11590     +226     
  Branches                   1841     1879      +38     
========================================================
+ Hits                       8323     8529     +206     
- Misses                     2441     2456      +15     
- Partials                    600      605       +5     
Flag Coverage Δ
postgres-18 73.58% <91.15%> (+0.34%) ⬆️
python-3.14 73.58% <91.15%> (+0.34%) ⬆️
unittests 73.58% <91.15%> (+0.34%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

@vistart vistart self-assigned this Aug 7, 2026
@vistart
vistart merged commit 226867d into release/v1.0.0.dev16 Aug 7, 2026
17 checks passed
@vistart vistart mentioned this pull request Aug 15, 2026
8 of 12 tasks
vistart added a commit that referenced this pull request Aug 15, 2026
…ns (#52)

* feat(backend): add PostgreSQL Row-Level Security POLICY DDL expressions

Add PostgresCreatePolicyExpression, PostgresAlterPolicyExpression, and
PostgresDropPolicyExpression (plus PolicyType/PolicyCommand/AlterPolicyMode
enums) so RLS policies can be administered through the Expression-Dialect
pipeline. The new PostgresPolicyMixin provides version-gated formatters
(PG 9.5+ for basic CREATE/ALTER/DROP, 10+ for AS RESTRICTIVE and explicit
AS PERMISSIVE, 15+ for the CURRENT_ROLE role keyword) and capability
switches; PostgresPolicySupport is the matching @runtime_checkable Protocol.

POLICY is a PostgreSQL extension, not SQL-standard, so it is implemented in
the postgres backend package only; the core library is untouched.

Note: changelog.d/0.added.md is a placeholder fragment — rename it to the
actual PR number once assigned before merging.

* ci: bump postgres 19 job from 19beta1 to 19beta2 (PGQ)

* chore: add changelog fragment for PR #52
@vistart
vistart deleted the feature/postgres-policy-expression branch October 1, 2026 03:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant