Skip to content

feat(postgres): add comprehensive backend examples for PostgreSQL - #30

Merged
vistart merged 39 commits into
release/v1.0.0.dev11from
feature/backend-examples
Apr 17, 2026
Merged

vistart merged 39 commits into
release/v1.0.0.dev11from
feature/backend-examples

Conversation

@vistart

@vistart vistart commented Apr 17, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds comprehensive PostgreSQL backend examples including:

  • Connection quickstart and protocol-specific examples
  • CRUD operations (single insert, update, delete)
  • Transaction handling with various isolation levels
  • Common table expressions (CTEs)
  • Window functions
  • Upsert operations
  • Materialized views
  • UUID generation
  • NULL handling functions
  • Array operations
  • DISTINCT and UNION operations
  • CREATE VIEW examples
  • Pagination and predicates
  • Basic transaction examples
  • PostgreSQL-specific locking mechanisms
  • Expression API usage through Expression-based DDL examples

Type of change

  • feat: A new feature
  • docs: Documentation only changes (if related to the new feature)
  • perf: A code change that improves performance (if part of the feature)
  • test: Adding missing tests or correcting existing tests (for the new feature)
  • chore: Changes to the build process or auxiliary tools and libraries suchs as documentation generation (if related to the new feature)
  • ci: Changes to our CI configuration files and scripts (if related to the new feature)
  • build: Changes that affect the build system or external dependencies (if related to the new feature)
  • revert: Reverts a previous commit

Breaking Change

  • Yes
  • No

Related Repositories/Packages

N/A

Testing

  • I have added new tests to cover my changes.
  • I have updated existing tests to reflect my changes.
  • All existing tests pass.
  • This change has been tested on PostgreSQL 14+.

Test Plan:
Ran full test suite with pytest.

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, README.md, etc.).
  • My changes generate no new warnings.
  • I have added a Changelog fragment (changelog.d/<issue_number>.<type>.md).
  • I have verified that my changes do not introduce SQL injection vulnerabilities.
  • I have checked for potential performance regressions.

Additional Notes

37 commits targeting release/v1.0.0.dev11.

vistart and others added 30 commits April 14, 2026 00:19
… subdirectory

- Move DDL expression classes from expressions.py to expression/ddl/ subdirectory
- Create expression/ddl/ with: vacuum, partition, index, statistics, comment, mv, type
- Update expression/__init__.py to export from ddl submodule
- Update protocols/ and mixins/ import paths accordingly
- Update test files to use new import paths
- Add comprehensive docstrings to all DDL expression classes
- Delete obsolete expressions.py and statements.py files

BREAKING CHANGE: Import paths have changed:
- Old: from rhosocial.activerecord.backend.impl.postgres.expressions import ...
- New: from rhosocial.activerecord.backend.impl.postgres.expression.ddl import ...
- Use ColumnDefinition with constraints=[ColumnConstraint(...)] pattern
- Use InsertExpression with into= and source=ValuesSource()
- Use DropTableExpression instead of dialect.format_drop_table_statement()
- Fix array type syntax using {} instead of ARRAY[]
- Add proper JSONB and array operations

All examples now run successfully.
- Add min_version/max_version to conftest.py for all examples
- Document version-specific features (JSONB 9.4+, window functions 8.4+, etc.)
- All examples tested on PostgreSQL 10 and 18
…ostgres prefix

- MultirangeSupport -> PostgresMultirangeSupport
- EnumTypeSupport -> PostgresEnumTypeSupport

These are backend-specific protocols and should follow the naming convention.
- MultirangeSupport -> PostgresMultirangeSupport
- EnumTypeSupport -> PostgresEnumTypeSupport
- Add aliases for backward compatibility
- EnumTypeSupport -> PostgresEnumTypeSupport
- Update test class names
- Add query category for examples
- Add Postgres window_functions.py (WindowFunctionSupport)
- Add Postgres cte.py (CTESupport)
- Add MySQL fulltext_search.py (MySQLFullTextSearchSupport)
…n parameter usage

- Replace or_replace=True with replace=True in view.py example
- Replace operation='UNION ALL' with operation='UNION', all_=True in union.py
- Rewrite quickstart.py as self-contained example using Expression API
  instead of raw SQL strings
…QL to Expression API

Severe fixes:
- query/window_functions.py: rewrite using WindowFunctionCall+WindowSpecification+WindowFrameSpecification
  (was using non-existent WindowFunctionExpression/WindowFrameBounded/WindowFrameRows/ColumnExpression)
- query/cte.py: rewrite using CTEExpression+WithQueryExpression
  (was using non-existent CTEType/CTEClause)
- update/basic.py: replace set_columns/set_values with assignments dict

Config fixes (user→username, PostgresBackend(config)→(connection_config=config)):
- query/window_functions.py, query/cte.py

High-priority fixes:
- insert/upsert.py: rewrite raw SQL using InsertExpression+OnConflictClause
- transaction/for_update.py: rewrite raw SQL using ForUpdateClause+QueryExpression+UpdateExpression
- ddl/materialized_view.py: add comment noting MV is not covered by Expression API

Low-priority fixes:
- query/array_func.py, types/json_basic.py, types/array_postgres84.py:
  use imported helper functions to generate SQL fragments (with usage comments)
… Expression API in examples

- Create PostgresLockingMixin with supports_for_no_key_update/share/key_share/skip_locked
  and format_postgres_for_update_clause implementation
- Create PostgresLockingSupport Protocol with method declarations
- Move PostgresLockingMixin before LockingMixin in MRO to fix shadowing
- Remove redundant supports_for_* methods from PostgresDialect (now in mixin)
- PostgresForUpdateClause.to_sql() delegates to dialect.format_postgres_for_update_clause
- Replace all backend.execute("raw SQL") in examples with Expression API
  (materialized_view, for_update, view, batch/single insert)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…action, predicates, pagination, and isolation levels

Add 5 new example files covering DDL, transaction control, complex
predicates, and pagination patterns specific to PostgreSQL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d remove all RawSQLExpression from examples

- Add format_on_conflict_clause in PostgresDialect to handle EXCLUDED
  pseudo-table without double-quoting (EXCLUDED must not be quoted in PG)
- Add AddTableConstraint/TableConstraint to TYPE_CHECKING imports (F821 fix)
- Replace RawSQLExpression with proper Expression API in all example files:
  - DEFAULT values: use FunctionCall(dialect, 'now') for TIMESTAMP, Python
    bool for BOOLEAN, string '0' for numeric
  - EXCLUDED references: use Column(dialect, 'col', table='EXCLUDED')
  - Text search: use FunctionCall + ComparisonPredicate instead of
    specialized function imports
- Fix IsNullPredicate usage for IS NULL conditions
- Fix transaction examples to use transaction_manager API
- Fix set_values -> assignments in update expressions
- Remove unused imports (F401) and fix f-string issues (F541)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…factory

Replace FunctionCall(dialect, 'now') with current_timestamp(dialect)
factory function that generates the SQL:2003 standard niladic form
CURRENT_TIMESTAMP (no parentheses), which PostgreSQL DDL DEFAULT accepts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Split long SQL string and text search literals across multiple lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…RETURNING, upsert, unique index, partition, UUID, and niladic functions

Also register existing but unregistered examples (materialized_view, upsert)
in conftest.py metadata.
@vistart vistart self-assigned this Apr 17, 2026
@codecov

codecov Bot commented Apr 17, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 67.99065% with 137 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.12%. Comparing base (1f4b98d) to head (5ddf5aa).
⚠️ Report is 1 commits behind head on release/v1.0.0.dev11.

Files with missing lines Patch % Lines
...ecord/backend/impl/postgres/expression/ddl/type.py 57.14% 40 Missing and 5 partials ⚠️
...cial/activerecord/backend/impl/postgres/dialect.py 36.06% 38 Missing and 1 partial ⚠️
...record/backend/impl/postgres/mixins/dml/locking.py 68.29% 7 Missing and 6 partials ⚠️
...erecord/backend/impl/postgres/mixins/types/enum.py 70.37% 5 Missing and 3 partials ⚠️
...ord/backend/impl/postgres/protocols/dml/locking.py 61.53% 5 Missing ⚠️
...backend/impl/postgres/expression/ddl/statistics.py 84.61% 3 Missing and 1 partial ⚠️
...cord/backend/impl/postgres/expression/ddl/index.py 82.35% 2 Missing and 1 partial ⚠️
...rd/backend/impl/postgres/expression/ddl/comment.py 86.66% 1 Missing and 1 partial ⚠️
...erecord/backend/impl/postgres/expression/ddl/mv.py 86.66% 1 Missing and 1 partial ⚠️
.../backend/impl/postgres/expression/ddl/partition.py 95.00% 1 Missing and 1 partial ⚠️
... and 13 more
Additional details and impacted files
@@                   Coverage Diff                    @@
##           release/v1.0.0.dev11      #30      +/-   ##
========================================================
+ Coverage                 72.51%   73.12%   +0.61%     
========================================================
  Files                       128      136       +8     
  Lines                      7261     7365     +104     
  Branches                   1194     1218      +24     
========================================================
+ Hits                       5265     5386     +121     
+ Misses                     1565     1546      -19     
- Partials                    431      433       +2     
Flag Coverage Δ
postgres-18 73.12% <67.99%> (+0.61%) ⬆️
python-3.14 73.12% <67.99%> (+0.61%) ⬆️
unittests 73.12% <67.99%> (+0.61%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 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.

vistart added 2 commits April 17, 2026 16:12
- Add test_ddl_expressions.py: tests for RefreshMaterializedViewPgExpression,
  CommentExpression, CreatePartitionExpression, DetachPartitionExpression,
  AttachPartitionExpression
- Add test_ddl_protocols.py: tests for PostgresPartitionSupport,
  PostgresIndexSupport, PostgresMaterializedViewSupport protocols

Total: 92 tests
@sonarqubecloud

Copy link
Copy Markdown

@vistart
vistart merged commit 39d5034 into release/v1.0.0.dev11 Apr 17, 2026
13 of 14 checks passed
@vistart vistart mentioned this pull request Apr 17, 2026
8 of 12 tasks
vistart added a commit that referenced this pull request Apr 17, 2026
* chore: bump version to 1.0.0.dev11

* feat(postgres): add comprehensive backend examples for PostgreSQL (#30)

* refactor(expression): reorganize DDL expressions into expression/ddl/ subdirectory

- Move DDL expression classes from expressions.py to expression/ddl/ subdirectory
- Create expression/ddl/ with: vacuum, partition, index, statistics, comment, mv, type
- Update expression/__init__.py to export from ddl submodule
- Update protocols/ and mixins/ import paths accordingly
- Update test files to use new import paths
- Add comprehensive docstrings to all DDL expression classes
- Delete obsolete expressions.py and statements.py files

BREAKING CHANGE: Import paths have changed:
- Old: from rhosocial.activerecord.backend.impl.postgres.expressions import ...
- New: from rhosocial.activerecord.backend.impl.postgres.expression.ddl import ...

* Fix postgres enum type formatting compatibility

* fix: register pytest markers to suppress unknown mark warnings

* docs: add comprehensive PostgreSQL function version support info

* test: add SQLFunctionSupport tests for PostgreSQL dialect

* chore: remove automatic publish trigger and fix function support check

* feat: add comprehensive PostgreSQL backend examples for expression usage

* fix: correct API usage in PostgreSQL backend examples

- Use ColumnDefinition with constraints=[ColumnConstraint(...)] pattern
- Use InsertExpression with into= and source=ValuesSource()
- Use DropTableExpression instead of dialect.format_drop_table_statement()
- Fix array type syntax using {} instead of ARRAY[]
- Add proper JSONB and array operations

All examples now run successfully.

* feat: add version support metadata to PostgreSQL examples

- Add min_version/max_version to conftest.py for all examples
- Document version-specific features (JSONB 9.4+, window functions 8.4+, etc.)
- All examples tested on PostgreSQL 10 and 18

* fix(postgres): rename MultirangeSupport and EnumTypeSupport to have Postgres prefix

- MultirangeSupport -> PostgresMultirangeSupport
- EnumTypeSupport -> PostgresEnumTypeSupport

These are backend-specific protocols and should follow the naming convention.

* fix(postgres): add backward compatibility aliases for renamed protocols

- MultirangeSupport -> PostgresMultirangeSupport
- EnumTypeSupport -> PostgresEnumTypeSupport
- Add aliases for backward compatibility

* fix(tests): update test references to renamed protocols

- EnumTypeSupport -> PostgresEnumTypeSupport
- Update test class names

* feat(examples): add protocol-specific examples

- Add query category for examples
- Add Postgres window_functions.py (WindowFunctionSupport)
- Add Postgres cte.py (CTESupport)
- Add MySQL fulltext_search.py (MySQLFullTextSearchSupport)

* feat(examples): add Postgres connection quickstart

* refactor(examples): rename array_basic to array_postgres84 for version specificity

* feat(examples): add connection category metadata for Postgres

* feat(examples): add array_postgres84, cte, window_functions metadata

* feat(examples): add Postgres upsert, materialized view examples

* feat(examples): add Postgres FOR UPDATE transaction example

* feat(examples): add Postgres distinct and union examples

* feat(examples): add Postgres CREATE VIEW example

* feat(examples): add Postgres single insert, update, drop_table examples

* fix(examples): correct CreateViewExpression and SetOperationExpression parameter usage

- Replace or_replace=True with replace=True in view.py example
- Replace operation='UNION ALL' with operation='UNION', all_=True in union.py
- Rewrite quickstart.py as self-contained example using Expression API
  instead of raw SQL strings

* fix(examples): correct PostgreSQL example API usage and convert raw SQL to Expression API

Severe fixes:
- query/window_functions.py: rewrite using WindowFunctionCall+WindowSpecification+WindowFrameSpecification
  (was using non-existent WindowFunctionExpression/WindowFrameBounded/WindowFrameRows/ColumnExpression)
- query/cte.py: rewrite using CTEExpression+WithQueryExpression
  (was using non-existent CTEType/CTEClause)
- update/basic.py: replace set_columns/set_values with assignments dict

Config fixes (user→username, PostgresBackend(config)→(connection_config=config)):
- query/window_functions.py, query/cte.py

High-priority fixes:
- insert/upsert.py: rewrite raw SQL using InsertExpression+OnConflictClause
- transaction/for_update.py: rewrite raw SQL using ForUpdateClause+QueryExpression+UpdateExpression
- ddl/materialized_view.py: add comment noting MV is not covered by Expression API

Low-priority fixes:
- query/array_func.py, types/json_basic.py, types/array_postgres84.py:
  use imported helper functions to generate SQL fragments (with usage comments)

* feat(postgres): add PostgresLockingMixin and replace all raw SQL with Expression API in examples

- Create PostgresLockingMixin with supports_for_no_key_update/share/key_share/skip_locked
  and format_postgres_for_update_clause implementation
- Create PostgresLockingSupport Protocol with method declarations
- Move PostgresLockingMixin before LockingMixin in MRO to fix shadowing
- Remove redundant supports_for_* methods from PostgresDialect (now in mixin)
- PostgresForUpdateClause.to_sql() delegates to dialect.format_postgres_for_update_clause
- Replace all backend.execute("raw SQL") in examples with Expression API
  (materialized_view, for_update, view, batch/single insert)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(examples): add PostgreSQL examples for create_table, basic transaction, predicates, pagination, and isolation levels

Add 5 new example files covering DDL, transaction control, complex
predicates, and pagination patterns specific to PostgreSQL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(postgres): add format_on_conflict_clause override for EXCLUDED and remove all RawSQLExpression from examples

- Add format_on_conflict_clause in PostgresDialect to handle EXCLUDED
  pseudo-table without double-quoting (EXCLUDED must not be quoted in PG)
- Add AddTableConstraint/TableConstraint to TYPE_CHECKING imports (F821 fix)
- Replace RawSQLExpression with proper Expression API in all example files:
  - DEFAULT values: use FunctionCall(dialect, 'now') for TIMESTAMP, Python
    bool for BOOLEAN, string '0' for numeric
  - EXCLUDED references: use Column(dialect, 'col', table='EXCLUDED')
  - Text search: use FunctionCall + ComparisonPredicate instead of
    specialized function imports
- Fix IsNullPredicate usage for IS NULL conditions
- Fix transaction examples to use transaction_manager API
- Fix set_values -> assignments in update expressions
- Remove unused imports (F401) and fix f-string issues (F541)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(postgres): update create_table example to use current_timestamp factory

Replace FunctionCall(dialect, 'now') with current_timestamp(dialect)
factory function that generates the SQL:2003 standard niladic form
CURRENT_TIMESTAMP (no parentheses), which PostgreSQL DDL DEFAULT accepts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(postgres): fix E501 line length in example files

Split long SQL string and text search literals across multiple lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(examples): add PostgreSQL examples for DELETE RETURNING, INSERT RETURNING, upsert, unique index, partition, UUID, and niladic functions

Also register existing but unregistered examples (materialized_view, upsert)
in conftest.py metadata.

* fix(examples): distinguish gen_random_uuid (PG13+) from uuid_generate_v4 (PG<13) in UUID example

* feat(examples): add PostgreSQL EXPLAIN Query Plan example

* fix(build): exclude __pycache__ from source distribution

The recursive-include directive used wildcard `*` which overrode
global-exclude rules, causing .pyc files in __pycache__ directories
to be included in the sdist tarball.

* chore: add .DS_Store to gitignore

* fix: exclude .mypy_cache from package data

* ci: update testsuite to release/v1.0.0.dev11

* ci: update activerecord to release/v1.0.0.dev24

* chore: add changelog fragment for PR #30

* test: add DDL expression and protocol tests for PostgreSQL

- Add test_ddl_expressions.py: tests for RefreshMaterializedViewPgExpression,
  CommentExpression, CreatePartitionExpression, DetachPartitionExpression,
  AttachPartitionExpression
- Add test_ddl_protocols.py: tests for PostgresPartitionSupport,
  PostgresIndexSupport, PostgresMaterializedViewSupport protocols

Total: 92 tests

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix(postgres): register requires_inner_join pytest marker

* chore(ci): use PyPI packages instead of git+https

* docs: update CHANGELOG for v1.0.0.dev11

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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