Skip to content

chore: Release v1.0.0.dev2 - #1

Merged
vistart merged 91 commits into
mainfrom
release/v1.0.0.dev2
Aug 15, 2026
Merged

vistart merged 91 commits into
mainfrom
release/v1.0.0.dev2

Conversation

@vistart

@vistart vistart commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Description

This is the first development release (v1.0.0.dev2) of the SQL Server backend implementation for rhosocial-activerecord. It provides a complete SQL Server backend, including dialect mappings, T-SQL-specific DDL support, expression-level COLLATE, datetime2 handling, and comprehensive test infrastructure bridges.

Release/Hotfix Details

  • Target Version: v1.0.0.dev2
  • Type: Development Release
  • Key Changes:
    • New Features
    • Bug Fixes
    • Breaking Changes
    • Security Fixes

New Features

  • Complete SQL Server backend implementation (dialect, adapters, connection, transaction manager, async support)
  • SQL Server dialect protocols, expressions, and comprehensive tests
  • SQL Server function factories and datetime interval expression formatting
  • T-SQL-specific DDL: partition DDL (SQLServerPartitionMixin), in-memory OLTP options, indexed views, full-text catalog, columnstore, SELECT INTO, PIVOT/UNPIVOT, TABLESAMPLE, OPTION hints, NEXT VALUE FOR, MERGE OUTPUT/HOLDLOCK, IF EXISTS for DROP COLUMN/CONSTRAINT
  • SQLServerSchemaDiffer for schema snapshot diff/comparison
  • named-migration CLI subcommand with sync and --async support
  • Expression-level COLLATE support with dialect hook validation
  • DataType #108 parsing support and server-version-gaited protocol conformance
  • Modular CLI with info, query, introspect, status, named-query/procedure/connection subcommands

Bug Fixes

  • Handle datetime2 7-digit fractional strings in adapters; normalize fractional seconds to 6 digits and introspect server version on connect
  • Enable READ_COMMITTED_SNAPSHOT at session start to prevent CI hang
  • Terminate MERGE statements with required trailing semicolon
  • Fix transaction level tracking, cursor await, and execute options
  • Fix async backend fetch operations and transaction manager
  • Fix CLI import paths and config __repr__ for core ConnectionConfig protocol compatibility
  • Fix parse_type VARCHAR/NCHAR detection
  • Remove hardcoded credentials from examples and CLI docs
  • Drop Python 3.8 support (pyodbc 5.x requires Python >= 3.9)

Test Infrastructure

  • Integrate new testsuite with Sync/Async dual providers and bridge files for basic/query/relation/derived_field/interface features
  • Add provider registry (TESTSUITE_PROVIDER_REGISTRY) and TESTSUITE_ACTIVE_SCENARIOS filtering support
  • Add SQL Server Python 3.9 + SQL Server 2017 CI test job; allow free-threaded 3.13t job to fail without blocking
  • Publish only via manual workflow_dispatch; install core 1.0.0.dev29 and testsuite 1.0.0.dev16 from PyPI in CI

Related Issues/PRs

Initial development release for the SQL Server backend; no prior release exists.

Breaking Change

  • Yes
  • No

Applicable rhosocial-activerecord Version Range: >=1.0.0,<2.0.0

Testing

  • All CI checks passed on the source branch (release/v1.0.0.dev2) — pending verification
  • Specific tests have been run and passed

Test Plan: Full test suite execution (covered by CI on the release branch)

Checklist

  • My changes follow the project's version control guidelines
  • I have updated the CHANGELOG.md using towncrier build (will be done after PR approval)
  • All necessary documentation has been prepared or updated
  • I have confirmed all CI checks have passed on the target branch after merging (post-merge verification)

Additional Notes

This is the first development release (dev2) of the SQL Server backend. The changelog will be built using towncrier after this PR is approved and CI checks pass.

vistart and others added 30 commits April 13, 2026 00:59
Implement comprehensive SQL Server backend for rhosocial-activerecord:

Core Components:
- config.py: Connection configuration with Windows/SQL authentication
- dialect.py: SQL Server dialect with T-SQL specific syntax
- backend.py: Synchronous backend using pyodbc
- async_backend.py: Asynchronous backend using aioodbc
- transaction.py: Transaction management with savepoint support
- async_transaction.py: Async transaction manager

Type System:
- adapters.py: Type adapters for UUID, DateTime, JSON, XML, Spatial types

SQL Server Features:
- OUTPUT clause (similar to RETURNING)
- OFFSET FETCH pagination (SQL Server 2012+)
- MERGE statement for upsert
- CROSS APPLY/OUTER APPLY instead of LATERAL
- SNAPSHOT isolation level
- IDENTITY columns

Additional:
- explain/: EXPLAIN result types
- introspection/: Schema introspector
- examples/: Usage examples (connection, query, transaction, DDL)
- protocols.py: SQL Server specific protocols
- mixins.py: SQL Server backend mixins
Update all example files to:
- Load connection configuration from environment variables
- Provide sensible default values for all settings
- Be self-contained without external config file dependencies
- Follow the style of sqlite examples

Environment variables (with defaults):
- SQLSERVER_HOST (localhost)
- SQLSERVER_PORT (1433)
- SQLSERVER_DATABASE (test_db)
- SQLSERVER_USERNAME (sa)
- SQLSERVER_PASSWORD (Password123!)
- SQLSERVER_DRIVER (ODBC Driver 17 for SQL Server)
- SQLSERVER_ENCRYPT (false)
- SQLSERVER_TRUST_SERVER_CERTIFICATE (true)
Update all example files to:
- Add clear SECTION comments (Setup, Business Logic, Execution, Teardown)
- Use expression-based SQL instead of raw SQL strings
- Follow the SQLite examples structure and style
- All SQL is generated via expressions (CreateTableExpression, QueryExpression, etc.)

New files added:
- examples/README.md: Directory structure and usage guide
- examples/ddl/create_index.py: Index creation example
- examples/insert/batch.py: Batch insert example
- examples/insert/with_output.py: OUTPUT clause example (SQL Server's RETURNING)
- examples/query/join.py: JOIN examples
- examples/types/json_basic.py: JSON operations

Key principles:
- Self-contained: Each file runs independently
- Clear sections: Setup/Teardown marked as reference only
- Pure business logic: Core expression usage is copyable
- Expression-based: All SQL via Expression-Dialect architecture
…lect methods

- Add get_default_adapter_suggestions() to backend for type adapter support
- Add format_limit_offset_clause() for OFFSET FETCH syntax (SQL Server 2012+)
- Fix OUTPUT clause position in INSERT statements (before VALUES)
- Add format_create_index_statement() for SQL Server CREATE INDEX syntax
- Update config.py to support legacy 'SQL Server' ODBC driver
- Fix all example files to use correct driver and port defaults
- Fix join.py example to use JoinExpression correctly
- Add Python 3.8, 3.9, 3.13, 3.14 and free-threaded versions (3.13t, 3.14t)
- Distribute Python versions across SQL Server 2019, 2022, 2025
- Fix healthcheck command path: /opt/mssql-tools18/bin/sqlcmd
- Add explicit ODBC Driver 17 installation step
- Use autocommit=True for database creation
- Update pyodbc dependency to >=5.3.0
- Add test suite structure following MySQL/SQLite patterns
- test_dialect.py: Test dialect formatting methods (OFFSET FETCH, identifiers)
- test_config.py: Test connection configuration and validation
- test_backend.py: Test backend functionality with real database (sync/async)
- test_expressions.py: Test SQL Server-specific expression formatting
- Add conftest.py with fixtures for backend setup and scenario loading
- Update pytest.ini with test configuration and markers
- Add aioodbc>=0.5.0 to requirements.txt for async support
- Fix dialect tests to use correct method names (supports_returning_clause, etc.)
- Fix OFFSET FETCH tests - SQL Server requires LIMIT with OFFSET
- Fix async backend tests to use transaction_manager.begin()/commit()
- Remove is_connected() assertion (method not available in backend)
- All 45 tests now passing
…d-query/procedure/connection subcommands

Refactor SQL Server backend CLI to match the modular subcommand architecture
used by postgres/sqlite backends. Add ODBC driver compatibility fixes for
nvarchar(max) columns and SERVERPROPERTY() with legacy drivers.
- Add execute_many tests for batch operations
- Add transaction savepoint tests
- Add transaction isolation level tests
- Add async CRUD tests
- Add JSON expression tests (SQL Server 2016+)
- Add DDL features tests (SELECT INTO)

These tests close the feature gap with MySQL and PostgreSQL backends.
- Fix execute_many empty param list handling (return 0 affected rows)
- Fix async execute_many empty param list handling
- Fix JSON adapter method names (to_database/from_database)
- Update test assertions to not rely on affected_rows
- Add JSON functions (json_value, json_query, is_json, json_object, json_array)
- Add string functions (string_agg, concat_ws, trim, format, string_split)
- Add datetime functions (eomonth, datefromparts, datetime2fromparts, timefromparts)
- Add utility functions (iif, choose, try_cast, try_convert, try_parse, coalesce, nullif)
- Add tests and examples
…omprehensive tests

- Add 10+ SQL Server-specific protocol extensions (TableSupport, LockingSupport,
  JSONSupport, TemporalTable, Sequence, FullTextSearch, Pagination, Merge, etc.)
- Add 6 expression modules: output (INSERTED/DELETED), locking (table hints),
  openjson (OPENJSON with schema), temporal (SYSTEM_VERSIONING), functions
  (TRY_CAST, TRY_CONVERT, CONTAINS, FREETEXT)
- Add 16 format_* method overrides to SQLServerDialect for SQL Server-specific
  syntax (SEQUENCE, SCHEMA, TRUNCATE, MERGE, LATERAL→CROSS/OUTER APPLY,
  FOR UPDATE→table hints, set operations, ALTER TABLE, full-text, TOP n)
- Add 78 comprehensive dialect unit tests
- Fix format_update_statement (assignments→values) and format_delete_statement
  (table→tables) API compatibility
…dencies

- Change dialect __init__ default version from (16,0,0) to None, call
  super().__init__() first to enforce version adaptation via
  introspect_and_adapt()
- Replace supports_returning_clause() with DML-specific
  supports_returning_insert/update/delete() (all True, OUTPUT clause)
- Fix DEFAULT value escaping: use _escape_sql_string() instead of
  manual inline replace
- Add constraint capability overrides: supports_constraint_enforced()
  (False), supports_fk_match() (False), supports_deferrable_constraint()
  (False)
- Bump CI: activerecord to release/v1.0.0.dev27, testsuite to
  release/v1.0.0.dev14

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Fix savepoint() to return name (str) instead of None, matching base
  class TransactionManager signature
- Change savepoints from property to method, matching test expectations
- Fix isolation level handling: separate SQLServerIsolationLevel from
  base IsolationLevel, resolve from base class property in begin()
- Fix test_supports_isolation_level to use
  supports_isolation_level_in_begin() (correct method name)
- Fix all SQLServerDialect() instantiations in tests to pass
  version=(16,0,0) to avoid DialectNotAdaptedException

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…nager

- Add AsyncSQLOperationsMixin to async backend class hierarchy so
  fetch_one/fetch_all are async and properly await execute()
- Add AsyncTransactionManagementMixin for async transaction context
  manager support
- Fix AsyncSQLServerTransactionManager.savepoint() to return name (str)
  instead of None, matching base class signature
- Change savepoints from property to method for API consistency
- Add isolation_level property to async transaction manager with proper
  SQLServerIsolationLevel resolution
- Add @asynccontextmanager decorator to transaction() method
- Separate _sqlserver_isolation_level from base IsolationLevel to
  prevent enum value being used as SQL string

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…efaults

- Remove db-dev-1-n.rho.im and hardcoded passwords from test_connection.py
- Fix all 10 examples to use empty default password instead of Password123!
- Fix examples/README.md documented default password
- Remove hardcoded --password secret from CLI docstrings
- Add test_connection.py to .gitignore to prevent future leakage
- Replace Password123! default with empty string in all 10 examples
- Fix examples/README.md documented default password
- Remove --password secret from CLI docstrings (use env vars instead)
…lect compat

- Add bridge test files for basic/connection/worker, events, mixins, query
- Add native backend tests: dialect_function_support, cli, explain,
  async_error_handling, transaction_backend, connection_resilience
- Add SQL Server test providers with FK-safe DROP TABLE and DropTableExpression
- Add pytest.ini with markers and SQLAlchemy-style scenario markers
- Convert SQLServerConnectionConfig to @DataClass inheriting ConnectionConfig
- Add encrypt_connection ↔ encrypt bridge via __post_init__
- Override _build_query_result to handle cursor.rowcount = -1 with OUTPUT INSERTED
- Override format_update_statement/format_delete_statement (remove double WHERE)
- Override format_returning_clause with default_table param (INSERTED/DELETED)
- Override format_query_statement to append ORDER BY (SELECT NULL) for OFFSET
- Add version-gated supports_* methods for sequences, IF EXISTS (2012/2016+)
- Fix all SQLServer*Adapter.to_database/from_database to accept target_type/options
- Fix SQLServerDateTimeAdapter.from_database string path to add UTC tzinfo
- Register Python-type-to-Python-type mappings in _register_sqlserver_adapters
- Add (dict,str)/(list,str) to get_default_adapter_suggestions for JSON support
…nc execute pipeline

- Move get_default_adapter_suggestions to SQLServerBackendMixin so both
  sync and async backends share the implementation
- Rewrite AsyncSQLServerBackend.execute to use parameter preparation
  (to_database via adapter suggestions) and result processing
  (_adapt_row_types via column_adapters/column_mapping)
- Use _build_query_result from mixin to handle cursor.rowcount = -1
  with OUTPUT clause by computing len(data) instead
- Fix test_dialect_comprehensive.py: assert DELETED instead of INSERTED
  for DELETE OUTPUT clause
- Create bridge files for all 26 query test files (sync + async)
- Create bridge files for connection/ subpackage (3 test files)
- Create bridge files for worker/ subpackage (2 test files)
- Add conftest.py bridge files for query/, connection/, worker/
- Register requires_protocol, requires_functions, requires_inner_join
  markers in root conftest (testsuite markers not auto-loaded from pkg)
- Fix query provider FK drop issue: add _drop_table_safely with
  _FK_DEPENDENCY_MAP to safely drop FK-referenced tables before
  target table (prevents SQL Server error 3726)
- Fix comments.sql FK cascade: change ON DELETE CASCADE to
  ON DELETE NO ACTION on both FKs (prevents error 1785)
…ting

SQL Server uses bracket quoting []. Tests verify:
- Normal, embedded-bracket, and injection payload cases
- Naive vs proper bracket escaping for safe and malicious input
- Bracket counts are balanced and breakout is prevented
vistart added 17 commits August 8, 2026 21:03
…nd feature tests

- dialect: map LENGTH/CHAR_LENGTH to LEN, JSON_EXTRACT/JSON_UNQUOTE to
  JSON_VALUE via _clone_with_func_name and format_json_function_expression
- backend_mixin: SQL Server version string parsing and connection logging
- backend/async_backend: MERGE trailing semicolon, connection stability and
  async pool initialization fixes
- functions: add aggregate/bitwise/math/spatial factories, SHOW functionality
  module, JSON/string function adaptations
- tests: replace testsuite bridge skip-helper with proper SQL Server
  expectations (trailing-space trim, READ_COMMITTED_SNAPSHOT pool behavior,
  OBJECT_ID existence checks, table-like DDL)
- relation derived/integration bridges no longer skip testsuite coverage
- add pytest-benchmark to dev requirements for benchmark test infra
…event CI hang

The previous per-module autouse fixture ran ALTER DATABASE ... SET
READ_COMMITTED_SNAPSHOT when the connection tests began, by which point
earlier worker/concurrency tests had opened connections against the
database. Because this ALTER requires an exclusive database lock, the
fixture blocked forever (CI observed >50 minutes with no progress) and the
missing MVCC semantics also caused parallel-CRUD worker tests to fail.

Move the enabling logic to a session-level autouse fixture in the root
tests conftest, which runs before any test opens a connection, uses a
LOCK_TIMEOUT and retries, and skips databases already configured.
ODBC and older Python runtimes deliver datetime2 values as strings with
seven fractional digits (100ns precision). datetime.fromisoformat capped
at 6 digits on Python < 3.13, raising ValueError during row adaption.

Normalize the string before parsing: map 'Z' to +00:00, restore the T
separator, and drop fractional digits beyond 6.
…ise core dependency

- Scenario filtering reads generic TESTSUITE_ACTIVE_SCENARIOS env var
  (fallback from backend-local SQLSERVER_ACTIVE_SCENARIOS) so --scenarios
  works when running tests from either the testsuite dir or this repo
- Raise rhosocial-activerecord dependency floor to >=1.0.0.dev0
- Fix relation/derived bridge imports to correctly named testsuite modules
- Add changelog fragment
…emaDiffer

The core migrated schema-diff resolution to the dependency-inversion hook
SQLDialectBase.create_schema_differ() and no longer imports concrete
backend differs. Override the hook so SQL Server keeps its ordinal-position-aware
column comparison in migration snapshot diffs.

- Implement SQLServerDialect.create_schema_differ() returning SQLServerSchemaDiffer
- Add changelog fragment
@vistart vistart self-assigned this Aug 15, 2026
@codecov

codecov Bot commented Aug 15, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@vistart
vistart marked this pull request as ready for review August 15, 2026 10:28
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
3.7% Duplication on New Code (required ≤ 3%)
C Security Rating on New Code (required ≥ A)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@vistart
vistart merged commit 42ba89f into main Aug 15, 2026
21 of 22 checks passed
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