Repository navigation
chore: Release v1.0.0.dev12 - #34
Merged
Merged
Conversation
Adds support for executing named queries via CLI using the shared named_query module from core library. Features: - --describe: show function signature - --dry-run: preview SQL without execution - --list: list queries in a module - --param: pass parameters - --force: allow DML/DDL execution
- Register named-procedure parser and handler - Add async support for named-query and named-procedure
This adds test coverage for PostgreSQL backend CLI: - TestCLINamedQueryArgs: 6 tests for named-query args parsing - TestCLINamedProcedureArgs: 9 tests for named-procedure args parsing These tests mirror the MySQL CLI tests for consistency.
Provide PostgreSQL-specific connection parameter examples in help text instead of SQLite's --db-file examples.
- Add PostgresConcurrencyMixin in base.py - Uses connection pool size as concurrency limit - Both sync and async backends implement ConcurrencyAware protocol
- Replace pytest_asyncio.mark.asyncio with pytest.mark.asyncio - This fixes test collection error in pytest-asyncio 1.3.0
- Add CreateExtensionExpression for CREATE EXTENSION SQL generation - Add DropExtensionExpression for DROP EXTENSION SQL generation - Update PostgresExtensionSupport protocol with format methods - Add format_create_extension and format_drop_extension to mixin - Add comprehensive tests for extension DDL expressions - Auto-quote extension names containing hyphens or underscores
- Add Dockerfile for PostgreSQL 14-18 with postgis, pgvector, earthdistance - Add docker-compose.yml for easy deployment - Add build.sh for multi-version builds - Add init-extensions.sh for automatic extension creation - Add comprehensive README documentation Supports: amd64, arm64, ppc64le, s390x
- Add test_postgres_protocol_conformance.py with tests for: - PostgresDialect implements all declared protocols - All protocols have at least one member - No overlap between protocols - Skip non-runtime_checkable protocols in isinstance tests
AsyncIntrospectionSupport was removed from python-activerecord, so the test exclusion is no longer needed.
PostgresBackendMixin now provides threadsafety property (returns 2). Removed duplicate implementation from sync.py and async_backend.py.
…ests Refactor handle_info() to use _resolve_postgres_config() instead of inline named connection logic, ensuring consistency across all subcommands. Add test suite with PostgreSQL 18 example connections. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pytest does not allow __init__.py in test directories. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ility status - Add 'available' field to PostgresExtensionInfo to track installable extensions - Add is_extension_available() method to protocol and mixin - Expand KNOWN_EXTENSIONS from 11 to 35+ extensions - Query pg_available_extensions for complete extension status - Add 'extensions' introspection command for CLI - Update info command to display installed vs available extensions
…ions Previously _detect_extensions() only queried pg_extension for installed extensions and used hardcoded KNOWN_EXTENSIONS as fallback. This missed pre-installed extensions that are available but not enabled. Now the method: 1. Queries pg_extension for installed extensions (installed=True, available=True) 2. Queries pg_available_extensions for all available extensions 3. Marks installed extensions as available 4. Marks not-installed-but-available extensions as available=True
- Sort extensions alphabetically by name
…ions Implemented support for the following extensions: - pg_cron: job scheduling - citext: case-insensitive text - bloom: bloom filter index - pg_partman: partition management - orafce: Oracle compatibility - pglogical: logical replication - pgaudit: audit logging - pg_repack: online rebuild - hypopg: hypothetical indexes - address_standardizer: address parsing - pg_surgery: data repair - pg_walinspect: WAL inspection - fuzzystrmatch: fuzzy string matching - cube: multidimensional cube - pgcrypto: cryptographic functions - btree_gin: GIN index for btree types - btree_gist: GiST index for btree types - uuid-ossp: UUID generation
- Follow the examples README structure (Setup/Business Logic/Execution/Teardown) - Use expressions (CreateTableExpression, InsertExpression, QueryExpression) - Check extension availability before execution - Auto-create extension if needed
- Use CreateExtensionExpression for extension creation - Follow examples README structure (Setup/Business Logic/Execution/Teardown) - Check extension availability before execution
- Use CreateExtensionExpression for extension creation - Re-detect extensions after creation with introspect_and_adapt() - Follow examples README structure
- Remove backend_cls parameter requirement from named connection factories - Update CLI config resolution to use new API - Add CLI parameter priority tests (5 tests pass)
- Add named-connection subcommand for managing named connections - Support --list, --show, --describe options - Allows users to list and inspect named connection configs
Add examples for development and production PostgreSQL connections: - local_dev(): local development database - local_dev_no_password(): local database without password - test_db(): test database - prod_db(): production database with SSL - prod_db_ssl(): production with full SSL verification - prod_replica(): read replica for read-heavy workloads
- Remove erroneous reset_pg_stat_statements() from pg_stat_statements Protocol (violates Dialect layer "generate SQL, don't execute" principle) - Add supports_pg_cron_run capability to pg_cron Protocol/Mixin - Add format_auto_partition_config to pg_partman Mixin/Protocol (aligns with existing supports_pg_partman_auto_partition declaration) - Add format_pglogical_show_subscription_status and format_pglogical_alter_subscription_synchronize to pglogical Mixin/Protocol (aligns with existing supports_pglogical_replication declaration) - Update KNOWN_EXTENSIONS: add 'cancel' and 'run' features for pg_cron
… for 29 extensions Add missing format_* methods to Mixins where supports_* declared a capability but no SQL generation method existed: - hstore: format_hstore_delete_key, format_hstore_each, format_hstore_keys/values - ltree: format_ltree_concat, format_ltree_lca - intarray: format_intarray_index_statement - citext: format_citext_literal - cube: format_cube_contains, format_cube_distance, format_cube_size - pgcrypto: format_digest, format_pgp_encrypt, format_pgp_decrypt - postgis: format_geography_literal, format_st_area/transform/as_geojson/buffer - pgvector: format_create_hnsw_index_statement, format_vector_l2_distance/inner_product - fuzzystrmatch: format_difference, format_metaphone - btree_gin/gist: format_btree_gin/gist_operator_class - hypopg: format_hypopg_estimate_size - orafce: format_instr, format_substr Add format_* method signatures to all 29 Protocol files (previously only supports_* was declared). Register new Mixins in PostgresDialect inheritance. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…sions Add requires_extension() and requires_extension_available() decorators to conftest.py for skipping integration tests when extensions are not installed on the test database. Add unit tests for all 20 extensions that previously lacked test coverage: citext, pgcrypto, fuzzystrmatch, cube, uuid-ossp, bloom, btree_gin, btree_gist, tablefunc, pg_stat_statements, pg_cron, orafce, pg_partman, hypopg, pglogical, pgaudit, pg_repack, address_standardizer, pg_surgery, pg_walinspect. All tests are pure in-memory (no database connection required).
Integration tests that connect to real PostgreSQL database: - hstore: CRUD, operators (@>/?/||), functions (each/akeys/avals) - pg_trgm: similarity, % operator, GIN index, show_trgm - uuid-ossp: uuid_generate_v1/v4, UUID column default - citext: case-insensitive comparison, unique constraint, LIKE, JOIN - ltree: path operators (@>/<@/~), ancestor/descendant, GiST index - pgcrypto: crypt+gen_salt, digest, hmac, pgp_sym_encrypt/decrypt - intarray: @>/&&/<@ operators, idx() function, GIN index - fuzzystrmatch: levenshtein, soundex, difference, metaphone/dmetaphone All tests use requires_extension() guard to skip when not installed.
- postgis: spatial data (geometry), ST_Distance/Contains, GIST index - pgvector: vector column, cosine similarity search, HNSW index - ltree: hierarchical paths, ancestor/descendant queries, GiST index - pgcrypto: crypt+gen_salt password hashing, digest, hmac - pg_trgm: similarity fuzzy search, % operator, GIN index - intarray: @>/&& operators, idx/sort/uniq functions - earthdistance: earth_distance calculation, range queries - cube: @> contains, <-> distance, nearest-neighbor search All examples follow Setup → Business Logic → Execution → Teardown structure with CreateExtensionExpression and introspect_and_adapt().
…date KNOWN_EXTENSIONS - Add PostgresPostgisRasterSupport protocol and PostgresPostgisRasterMixin for PostGIS raster type operations (ST_AsRaster, ST_RastFromText, etc.) - Add PostgresPgRoutingSupport protocol and PostgresPgRoutingMixin for pgRouting path finding operations (pgr_dijkstra, pgr_astar, etc.) - Update KNOWN_EXTENSIONS: add raster_type feature for postgis_raster, dijkstra feature for pgrouting, cancel/run features for pg_cron - Mark 8 extensions as requires_dialect: False that don't need Protocol/Mixin adaptation (postgis_topology, postgis_sfcgal, postgis_tiger_geocoder, amcheck, pageinspect, pgtap, pg_logicalinspect, address_standardizer_data_us)
…/ subpackage Split the 1779-line __main__.py into a thin entry point and 9 focused modules under cli/, following the same pattern as SQLite and MySQL: - __init__.py: subcommand registration and dynamic dispatch - output.py: provider factory and RICH_AVAILABLE - connection.py: connection args, config resolution, backend creation - info.py: info subcommand with protocol display (26 Postgres Protocols) - query.py: query subcommand (sync + async) - introspect.py: introspect subcommand with 'extensions' type - status.py: status subcommand with WAL/Replication/Archive/Security sections - named_query.py: named-query adapter using closures - named_procedure.py: named-procedure adapter using closures - named_connection.py: named-connection adapter with empty parent parser Key changes: - Remove global _default_backend variable, use closure-based approach - Move -v/--verbose from main parser to info/status subcommands only - Each subcommand independently decides its own arguments - Rename test_cli.py to test_named_connection_cli.py for clarity - Update mock paths from __main__ to cli.connection module
…YTHONPATH, and enable autocommit 1. Remove `tests.` prefix from module paths in integration tests. The `tests.rhosocial...` import paths only worked with `python -m pytest` (CWD in sys.path makes `tests` an implicit namespace package). Direct `pytest` does not add CWD to sys.path, causing ModuleNotFoundError. Fix by using `rhosocial.xxx` paths that work via PYTHONPATH entry. 2. Add `tests` to PYTHONPATH in CI to ensure `tests/rhosocial/` is searched as part of the namespace package path. 3. Enable autocommit on psycopg connections to prevent psycopg 3 from auto-managing transactions (which conflicts with manual BEGIN/COMMIT statements in the ActiveRecord layer).
…rinciples - Derive 5 PG protocols from generic counterparts: PostgresTableSupport(TableSupport), PostgresIndexSupport(IndexSupport), PostgresLockingSupport(LockingSupport), PostgresTriggerSupport(TriggerSupport), PostgresConstraintSupport(ConstraintSupport) - Remove 4 duplicate generic protocols from PostgresDialect base class list - Rename 22 PG expression classes with Postgres prefix: AdvisoryLockExpression → PostgresAdvisoryLockExpression, RefreshMaterializedViewPgExpression → PostgresRefreshMaterializedViewExpression, CreateEnumTypeExpression → PostgresCreateEnumTypeExpression, etc. - Fix Expression-Dialect separation for 3 expression classes: PostgresAlterEnumTypeAddValueExpression, PostgresAlterEnumTypeRenameValueExpression, PostgresCreateRangeTypeExpression - Make PostgresRefreshMaterializedViewExpression derive from RefreshMaterializedViewExpression with schema/name/concurrently aliases - Rename format_postgres_for_update_clause → format_for_update_clause in PostgresLockingMixin and PostgresLockingSupport protocol - Add TestPostgresProtocolDerivation and TestPostgresExpressionDialectSeparation test classes for protocol coverage validation - Update test_postgres_protocol_conformance.py excluded_overlaps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…2 format
The third segment of UUID v1 was incorrectly matched with {3} hex chars
instead of {4}, causing test_uuid_generate_v1 to always fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PostgresIndexSupport, PostgresTableSupport, and PostgresConstraintSupport now derive from their generic counterparts, so method overlap is expected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… and PostgresMultirangeSupport These two protocols were missing the decorator, causing them to be skipped in protocol conformance isinstance() checks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…l_and_params
ActiveQuery layer uses ? as parameter placeholders (e.g. where("name = ?",
params)), but psycopg v3 requires %s format. Previously the conversion
was not performed, causing "the query has N placeholders but M parameters
were passed" errors for any query using RawSQLPredicate/RawSQLExpression.
The new _convert_qmark_to_format() method handles the conversion while
preserving PostgreSQL's hstore/jsonb operators (?, ?|, ?&) by:
- Keeping ? followed by | or & as-is (operator context)
- Keeping ? preceded by alphanumeric/underscore as-is (identifier context)
- Replacing all other ? with %s (parameter placeholder context)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…greSQL backend Placeholder conversion is now handled by the ActiveRecord layer via convert_qmark_placeholder(). The backend no longer needs to do any ? → %s conversion in _prepare_sql_and_params. Remove _convert_qmark_to_format static method and _prepare_sql_and_params override, restoring base class pass-through behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…in format_for_update_clause PostgreSQL dialect's format_for_update_clause assumed clause.strength always exists, but the base ForUpdateClause class (used by Query.for_update()) does not have this attribute — only PostgresForUpdateClause does. Use getattr() with a default of LockStrength.UPDATE for compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch from PyPI package to git+https source for rhosocial-activerecord-testsuite to track the new dev12 branch.
…nsaction_manager access Replace direct `_transaction_manager.is_active` checks with the `in_transaction` property in both sync and async backends. The property already handles the None case for `_transaction_manager`, making the code simpler and consistent with the project's abstraction conventions.
Add a second PostgreSQL service using vistart/postgres-exts image alongside the official postgres container, allowing tests against databases with additional extensions installed. - postgres service: port 5432 (official image) - postgres-exts service: port 5433 (vistart/postgres-exts image) - Both use same version tag from matrix, same credentials - Added postgres_exts scenario to CI config - Wait step now checks both services are ready Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…c/async parity Move identical non-I/O methods from sync and async implementations into shared mixin classes to enforce proper sync/async parity: - PostgresBackendMixin: log, _register_postgres_adapters, _is_connection_error, _is_connection_error_message, _parse_explain_result, CONNECTION_ERROR_SQLSTATES - PostgresTransactionMixin (new): _ISOLATION_LEVELS, _build_begin_sql, set_deferrable, get_deferred_constraints, get_active_savepoint Also fix AsyncPostgresTransactionManager.set_deferrable being incorrectly marked async (no I/O in method body), and fix member order inconsistency in async_backend.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…atibility Changes: - Fix MRO ordering: PostgresBackendMixin must come before ExplainBackendMixin to ensure _parse_explain_result returns PostgresExplainResult instead of BaseExplainResult - Add WindowsSelectorEventLoopPolicy setup in tests/conftest.py for Windows compatibility with async tests - Fix test: set_deferrable() is sync, not async (PostgresTransactionManager)
- Updated PostgreSQL CLI to match new runner.run(backend) signature - Removed execute_query, get_dialect parameters from handle_named_procedure - Updated docs examples to use new API
- Add F401 fixes to __all__ in named_connections/__init__.py, mixins/__init__.py, protocols/__init__.py - Fix unused imports in various files (from ruff --fix) - Update extension examples to use 4-section format consistently
) * test(schema): add schema namespace tests for PostgresBackend Add test_schema_namespace.py covering: - Dialect layer: schema capability declarations, Column/TableExpression/ WildcardExpression with schema_name, CreateSchemaExpression/ DropSchemaExpression SQL generation (including IF NOT EXISTS/IF EXISTS CASCADE) - Backend layer: get_default_schema(), CREATE/DROP schema, CRUD in custom schema, information_schema introspection with schema - Async Backend layer: async equivalents of backend operations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(schema): add get_default_schema() and schema config to PostgresBackend - PostgresBackendMixin.get_default_schema(): returns configured default_schema or 'public' as PostgreSQL standard default - PostgresConnectionConfig: add search_path and default_schema fields - Pass search_path to psycopg connection params Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(postgres): add UUID type adapter and gen_random_uuid function factory Add PostgresUUIDAdapter for bidirectional conversion between Python UUID objects and database values. Add gen_random_uuid() and uuid-ossp extension function factories that return Expression objects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(postgres): add pgvector type, adapter, and function factories Add PostgresVector dataclass, PostgresVectorAdapter, and pgvector function factories (l2_distance, cosine_distance, inner_product, cosine_similarity, literal) that return Expression objects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(postgres): add PostGIS type, adapter, and function factories Add PostgresGeometry dataclass, PostgresGeometryAdapter, and PostGIS function factories (ST_MakePoint, ST_Contains, ST_Distance, etc.) that return Expression objects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(postgres): rewrite hstore module with Expression/Dialect architecture Replace raw string returns with Expression objects (FunctionCall, BinaryExpression) in hstore function factories. Add PostgresHstore dataclass, PostgresHstoreAdapter, and simplify hstore extension mixin to only keep supports_*() methods. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(postgres): add extension-aware function version system Replace flat _POSTGRES_FUNCTION_VERSIONS dict with categorized FunctionVersionRequirement definitions in function_versions.py. Functions from extensions (hstore, uuid-ossp, pgvector, PostGIS) now require extension installation check via introspect_and_adapt(). Key changes: - FunctionVersionRequirement: structured version req with extension awareness - FunctionSupportInfo: detailed support status with reason for unavailability - supports_functions() returns Dict[str, FunctionSupportInfo] - Extension functions return False when _extensions not probed (no guessing) - _POSTGRES_FUNCTION_VERSIONS moved to function_versions.py, 15 categories Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(tests): move transaction tests into transaction/ subdirectory Reorganize transaction-related test files into a dedicated transaction/ subdirectory under feature/backend/ for better test structure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(postgres): align Expression-Dialect architecture across all function modules Implement all 6 phases of the expression-dialect alignment plan: Phase 1: Rewrite core native type function factories (geometric, bit_string, enum, array, json, text_search, xml, network) to return Expression objects instead of raw SQL strings. Phase 2-3: Create new function factory modules for all extension types (pgcrypto, ltree, pg_trgm, fuzzystrmatch, earthdistance, intarray, cube, citext, pg_stat_statements, postgis_raster, pglogical, pgrouting, tablefunc, pg_cron, pgaudit, hypopg, pg_surgery, pg_walinspect, address_standardizer, pg_partman, pg_repack, orafce) and add data_type function factories (xid8_literal, array_literal). Phase 4: Migrate multirange/data_type format_* methods from mixins to function factories, retaining only supports_* and DDL methods in mixins. Phase 5: Update all tests to use Expression-based assertions (to_sql(), isinstance checks) instead of raw string comparison. Phase 6: Add 4 new protocol definitions (PostgresFullTextSearchSupport, PostgresRangeTypeSupport, PostgresJSONBEnhancedSupport, PostgresArrayEnhancedSupport) with corresponding supports_* methods in PostgresDialect. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(backend): add protocol implementation completeness tests for PostgreSQL Add three test classes to verify bidirectional consistency between Protocol declarations and Mixin/Dialect implementations: - TestProtocolMethodSignatureConformance: verifies method signatures on PostgresDialect match Protocol declarations - TestProtocolMixinForwardCoverage: verifies Protocol-declared methods exist in corresponding Mixins (42 Protocol-Mixin pairs) - TestProtocolMixinReverseCoverage: verifies Mixin-implemented methods are declared in corresponding Protocols Also fix protocol implementation gaps discovered by the tests: New Mixins (5): - PostgresFullTextSearchMixin: 4 methods migrated from Dialect - PostgresRangeTypeMixin: 4 methods migrated from Dialect - PostgresJSONBEnhancedMixin: 5 methods migrated + 1 new (supports_jsonb_subscript) - PostgresArrayEnhancedMixin: 5 methods migrated + 1 new (supports_domain_arrays) - PostgresParallelQueryMixin: 6 new methods (all previously missing) Protocol declarations completed (8): - PostgresExtensionSupport: +2 methods - PostgresPartitionSupport: +1 method - PostgresIndexSupport: +6 methods - PostgresDataTypeSupport: +1 method - PostgresMultirangeSupport: +2 methods - PostgresEnumTypeSupport: +10 methods - PostgresQueryOptimizationSupport: +6 methods - PostgresSQLSyntaxSupport: +9 methods Upgrade get_all_protocol_methods() to walk MRO for Python < 3.12, and add get_own_protocol_methods() for forward coverage testing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve all ruff lint errors across postgres backend - Rename PostgresGeometryAdapter (postgis) to PostgresPostGISAdapter to avoid name collision with geometric adapter (F811) - Rename orafce trunc/round to orafce_trunc/orafce_round to avoid collision with math_enhanced module (F811) - Add TYPE_CHECKING imports for FunctionSupportInfo and FunctionVersionRequirement in dialect.py (F821) - Remove unused imports: List, Optional, Dict, re, field (F401) - Remove unused variable assignment for provider in cli/info.py (F841) - Add `from None` to raise inside except in types/postgis.py (B904) - Fix f-string without placeholders in examples/types/uuid.py (F541) - Break long lines across adapters, cli, introspection, functions, mixins, and protocols modules (E501) - Configure ruff per-file-ignores for examples/ (E402, E501) and migrate select/ignore to [tool.ruff.lint] section Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: restore quoted type annotations and update test references - Add quotes back around FunctionSupportInfo and FunctionVersionRequirement in dialect.py type annotations, since they are imported under TYPE_CHECKING and not available at runtime (Python 3.8+ evaluates annotations eagerly) - Update test_postgis_types.py to use PostgresPostGISAdapter instead of the old PostgresGeometryAdapter name Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(tests): update function support tests for FunctionSupportInfo return type supports_functions() returns Dict[str, FunctionSupportInfo] (not bool), so tests must check .supported attribute instead of using `is True`/`is False`. - Replace `result[func] is True` with `result[func].supported` - Replace `result[func] is False` with `not result[func].supported` - Update hstore extension tests: without database connection, extension functions return extension_not_probed instead of True - Add FunctionSupportInfo import and type check test Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(postgres): override format_column() with alias-aware schema handling PostgreSQL rejects three-segment column references (schema.table.column) when the table has an alias in the FROM/JOIN clause. Override format_column() to implement PostgreSQL-specific rules: - When table has an alias, use alias.column (ignore schema_name) - When table has no alias but has schema, use schema.table.column - Otherwise use standard table.column or column form This fixes the JOIN bug where ON conditions generated "public"."users"."id" instead of "users"."id" when tables had aliases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(postgres): add async integration tests and expression-based fixtures for all 29 extensions Add async integration tests matching existing sync tests for all 29 extension test files, including async fixtures using async_postgres_backend_single. Convert raw SQL strings in fixtures and test methods to expression objects (CreateTableExpression, InsertExpression, QueryExpression, FunctionCall, etc.). Key changes: - Add async_ensure_extension_installed to test utils - Add async_postgres_backend_single fixture to conftest - Add 29 async test classes with _async table suffix convention - Replace raw SQL with expression objects across all integration tests - Use Literal.cast("type") for PostgreSQL type casts (cube, hstore, ltree, vector, uuid, integer[], geography) instead of RawSQLExpression - Use Subquery wrapper for ComparisonPredicate aliasing - Use specific exception types (IntegrityError, DatabaseError) instead of bare Exception in pytest.raises - Fix earth_distance() assertion (returns meters, not miles) - Fix hypopg_estimate_size assertion (maps to hypopg_relation_size) Remaining RawSQLExpression usage (with TODO comments): - COUNT(*) where Literal("*") gets parameterized - PostgreSQL operators with aliases where ComparisonPredicate lacks .as_() - Index opclass specifications (no structural expression support) All 316 tests pass, 13 skipped (extensions not available/permissions). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(tests): skip pg_stat_statements and pg_walinspect tests on CI env constraints - pg_stat_statements: skip when extension requires shared_preload_libraries - pg_walinspect: skip when LSN is rejected as future start LSN (Postgres 15) Both failures are environment configuration issues, not code bugs. * chore: add changelog fragment for PR #33 --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add comprehensive SQL injection protection for the PostgreSQL backend: - Add validation for EXCLUDE constraint index methods (using allowlist) - Add validation for EXCLUDE constraint operators (using allowlist) - Add _escape_sql_string() for DEFAULT constraint values - Add _validate_data_type() for column data types - Add security unit tests for constraint validation - Add integration tests with real PostgreSQL database execution Security fixes prevent SQL injection through: - Index method allowlist validation (gist, btree, spgist, etc.) - Operator allowlist validation (&&, =, @>, etc.) - String escaping for DEFAULT values - Type validation for column definitions Fixes: #sql-injection-audit-remediation
PostgreSQL array types like TEXT[] and INTEGER[] were rejected because the base dialect's allowlist pattern didn't include brackets []. Override _validate_data_type in PostgresDialect to support array types, with a note that this can be removed once rhosocial-activerecord base dialect includes this change in a future release.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #34 +/- ##
==========================================
- Coverage 73.12% 68.66% -4.47%
==========================================
Files 136 230 +94
Lines 7365 10049 +2684
Branches 1218 1598 +380
==========================================
+ Hits 5386 6900 +1514
- Misses 1546 2628 +1082
- Partials 433 521 +88
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Description
Release v1.0.0.dev12 for python-activerecord-postgres. This release includes named query/procedure CLI support, schema namespace support, 29 new PostgreSQL extension protocols/mixins, and various bug fixes and refactoring.
Release/Hotfix Details
v1.0.0.dev12Development ReleaseRelated Issues/PRs
Breaking Change
Testing
release/v1.0.0.dev12).Test Plan:
PYTHONPATH=src .venv3.8/bin/pytest tests/ -v --tb=shortChecklist
Additional Notes
This is a development release (dev12) leading up to v1.0.0.
Commits included since v1.0.0.dev11 (55 commits):