Repository navigation
feat: SQL Server SQL Graph support and statement-level NOSCAN option - #3
Merged
Merged
Conversation
…e format_method - Backend types carry sqlserver_-prefixed generic names; dispatch by naming convention (format_data_type_<name>); @DDLTypeMixin.handles registration removed. - Formatting functions take (self, expr); CAST is a CastExpression node. - CI installs rhosocial-activerecord and the testsuite from their active branches. - Renamed private format functions to remove backend name suffix.
- Remove extra filter_predicate param from format_function_call - Update format_json_table_expression to accept single expr param
… method - Updated import in dialect.py from JoinExpression to JoinClause - Renamed format_grouping_expression to format_grouping_clause with correct signature (self, expr) instead of (self, operation, _expressions) - Updated example code import in examples/query/join.py - Updated test_expressions.py imports and class name - Updated test_dialect_version_branches.py to use new method name and signature
Driver 17 is one generation too old for SQL Server 2025's protocol/TLS defaults; parallel test workers failed connections at suite start.
…ion contracts - 9 type classes declare dialect_options explicitly; unified _type_params based equality/hash - 29 supports_data_type_* added (1:1 with format family) - suggested_data_types(): uuid/interval/array/enum/jsonb/timestamptz/timetz -> honest cross-backend suggestions; keys disjoint from supported - Precision validation: decimal 1-38/0-precision, float 1-53, temporal 0-7 - _register_type_formatters() copies supports methods + regex attrs - New test_sqlserver_type_protocol.py (30 tests)
Update ColumnDefinition, DataType subclasses, and CreateTableExpression to use dialect-first constructor signatures: - ColumnDefinition(dialect, name, type, ...) - IntegerType(dialect), VarCharType(dialect, length=...), etc. This aligns tests with the parameter-inline refactor in core library where expressions bind the dialect at construction time. Fixes CI failures in: - test_auto_increment_ddl (ColumnDefinition/DataType signatures) - test_data_type_parsing (DataType dialect-first) - test_dialect_comprehensive (CreateTableExpression) - test_dialect_version_branches (DDL rendering snapshots) - test_create_table_like (ColumnDefinition signatures) - test_niladic_functions (DataType dialect-first) - test_p2_coverage_features (DataType dialect-first) - test_schema_diff, test_sqlserver_partition (providers/fixtures) - test_connection_management, test_parallel_crud (providers/fixtures)
Root cause:
_prepare_read_committed_snapshot was a session-scoped autouse fixture
that executed ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON.
This requires an exclusive database lock. With pytest-xdist -n 8,
each of the 8 workers runs its own session and executes this fixture
simultaneously — all trying to acquire the exclusive lock at once,
causing a deadlock where every worker waits for the others.
Fix:
1. Add tests/enable_read_committed_snapshot.py — a standalone script
that enables READ_COMMITTED_SNAPSHOT using pyodbc, meant to run
BEFORE pytest in the CI workflow step.
2. In the workflow, insert 'python tests/enable_read_committed_snapshot.py'
before every 'python -m pytest' invocation (10 jobs).
3. In conftest.py, change the fixture to verify-only mode: it checks
whether the option is already on (it should be, from step 1),
and only attempts ALTER DATABASE as a lightweight fallback with
a short 3s timeout and 2 retries (instead of 5s × 5 retries).
…ures ColumnConstraint.__init__ requires dialect as first argument (parameter-inline convention), but SQL Server fixtures were calling ColumnConstraint(ColumnConstraintType.XXX) without dialect. Fixed in: basic.py, events.py, mixins.py, query.py
…tion col_def.data_type.to_sql(self) was passing dialect as an argument, but parameter-inline refactored to_sql() to take no arguments (dialect is bound at construction time). Change to to_sql(). Also addresses the locking.py to_sql() -> str question: SQLServerTableHint is a standalone dataclass (not BaseExpression), its to_sql() returning a hint name string is intentional.
Same parameter-inline migration as ClickHouse/Oracle: the method now takes a single expr argument, extracting left/right/operation/all_/ alias/order_by_clause/limit_offset_clause from it.
Add the dialect first argument to all remaining ColumnDefinition, ColumnConstraint, and DataType constructor calls across test files: - test_alter_table_if_exists_backend.py - test_auto_increment_ddl.py (_pk helper now takes dialect) - test_create_table_like.py - test_dialect_comprehensive.py - test_dialect_version_branches.py (use local 'd' variable) - test_niladic_functions.py - test_p2_coverage_features.py (_create_table uses its 'd' param) - test_schema_diff.py (add local SQLServerDialect) - test_sqlserver_partition.py (use local 'd' variable)
…ative) New test_sqlserver_protocol_conformance.py complements the SQLServer-specific test_protocol_support.py by covering the generic dialect protocols: - SQLSERVER_PROTOCOLS (35 implemented generic protocols) - SQLSERVER_NOT_IMPLEMENTED (10: SQL/XML*, GraphTable, ILIKE, FunctionSupport intentional; GeneratedColumnSupport known gap — naming mismatch, TODO) - negative isinstance test + partition completeness test
SQL Server supports computed columns but only exposed the singular supports_generated_column(). Add the plural supports_generated_columns() (protocol-compliant) and promote GeneratedColumnSupport from SQLSERVER_NOT_IMPLEMENTED to SQLSERVER_PROTOCOLS.
…tion - SetOperation tests: construct SetOperationExpression instead of passing individual keyword args to format_set_operation_expression() - MergeAction: add missing dialect= argument - IndexDefinition/ForeignKeyConstraint/TableConstraint: add missing dialect positional argument in fixtures and test_p2_coverage_features.py
- test_dialect_version_branches.py: 3 MergeAction calls - test_protocol_support.py: 2 MergeAction calls (also positional→keyword)
…ion-based signature Core protocol changed from scatter args to (self, expr). Update backend overrides and tests to construct expression objects.
SQL Server prohibits ORDER BY in CTEs unless TOP/OFFSET/FOR XML is also specified. This is a known SQL Server limitation.
…ional_cte_order_by
…ssion TypeCastingMixin.cast() now returns a CastExpression AST node. The old cast_types attribute no longer exists on JSONExpression. This was causing AttributeError in derived field tests.
- Add backend reserved words and wire format_identifier(need_quote=...) through SQLDialectBase, warning when a reserved word is left unquoted - Rename supports_table_like_syntax to supports_create_table_like - Add identifier quoting tests
…methods Add FilterClauseMixin, TransactionControlMixin, AutoIncrementMixin, GeneratedColumnMixin, TriggerMixin, PartitionMixin, ILIKEMixin, FunctionMixin to inheritance chain (P0 fix: these were missing, causing support methods to return None via Protocol stubs). Remove 29 supports_* methods that are now redundant with the newly added mixins or existing global mixin defaults: - ArrayMixin, GraphMixin, QualifyClauseMixin, OrderedSetAggregationMixin - ViewMixin, SchemaMixin, IndexMixin, SequenceMixin, TableMixin - ConstraintMixin, DDLColumnMixin, SetOperationMixin dialect.py: 1970 → 1900 lines (-70)
The dialect now composes FunctionMixin/ILIKEMixin, so it satisfies FunctionSupport/ILikesupport; the negative-contract list was stale and failed. Note their semantics remain backend-specific.
Move 90 methods from dialect.py into 25 mixin files: - datetime.py, collation.py, cte.py, returning.py, constraint.py, window.py, json.py, grouping.py, locking.py, merge.py, temporal.py, upsert.py, lateral.py, explain.py, dql.py, dml.py, view.py, schema.py, index.py, generated_column.py, set_operation.py, table.py, identifier.py, transaction.py, function.py (new) - Extended: trigger.py, sequence.py - New shared constants: version_constants.py dialect.py: 1900 → 1062 lines.
Expression nodes for format_* signature compliance (mirrors the MySQL/ MariaDB expression-object convention).
Drop the redundant _support suffix from the protocol module name.
SQLDialectBase precedes the feature mixins in the MRO, so the bracket formatter in SQLServerIdentifierMixin was shadowed and identifiers were rendered with double quotes. Re-declare it on the dialect.
Tests were calling dialect formatters with raw strings/lists, bypassing the expression layer. Construct the corresponding expression classes and call to_sql() so the tests exercise the real expression<->formatter integration: - NEXT VALUE FOR -> SQLServerNextValueForExpression - CONTAINS / FREETEXT -> SQLServerContainsPredicate / SQLServerFreetextPredicate - TRY_CAST / TRY_CONVERT -> SQLServerTryCastExpression / SQLServerTryConvertExpression - table hints -> SQLServerTableHintClause - OPENJSON -> SQLServerOpenJsonExpression - temporal period -> SQLServerTemporalPeriodDefinition - FULLTEXT CATALOG -> SQLServerCreateFullTextCatalogExpression - OPTION hints -> SQLServerOptionHintClause
CollationMixin was imported but not in the bases, so format_collate_ expression resolved to the CollationSupport protocol stub (None).
…sion
- remove the inline dialect_options['like_table'] guard from
format_create_table_statement; SQL Server inherits
supports_create_table_like() == False, so the gated generic
format_create_table_like_statement raises UnsupportedFeatureError
- tests migrate to CreateTableLikeExpression and assert the raise
BREAKING CHANGE: CREATE TABLE ... LIKE is no longer expressed through
CreateTableExpression(dialect_options={'like_table': ...}); use
CreateTableLikeExpression, which raises UnsupportedFeatureError on
SQL Server.
Renderer now reads memory_optimized/durability from typed CreateTableOptions fields first, falling back to dialect_options.
- Add supports_drop_table_cascade() → False - Add supports_drop_table_restrict() → False - Remove format_drop_table_statement override (use generic impl)
SQL Server requires one action per ALTER TABLE statement.
- Add SQLServerDatabaseMixin for CREATE/DROP/ALTER DATABASE support - Add SQLServerViewMixin with capability gating - Add test_sqlserver_ddl_improvements.py with 5 tests - Rename view.py -> ddl_view.py
- Per-expression virtual-table prefix (Column(table='DELETED'|'INSERTED')) - ReturningClause.output_into renders OUTPUT ... INTO <target> - Raise UnsupportedFeatureError for non-column expressions, wildcards, aliases - supports_returning_alias/wildcard False, supports_returning_into True - Fix stale .mixins.view import (renamed to ddl_view) - Add OUTPUT tests
- format_limit_offset_clause: FETCH NEXT ... ROWS WITH TIES - supports_fetch_with_ties True; supports_nulls_first_last False - locking: gate strength (no silent ignore) - set_operation: raise on unsupported FOR UPDATE
…LMixin/ExpressionMixin)
…CH predicate) SQL Server SQL Graph is independent from SQL/PGQ (different data model and query shape), so it lives in the SQL Server backend, not the core GraphMixin. - expression/graph.py: SQLServerGraphDirection, SQLServerGraphPseudoColumn, SQLServerGraphNodeRef, SQLServerGraphEdgeRef, SQLServerGraphPattern, SQLServerMatchPredicate, SQLServerShortestPathExpression, SQLServerGraphPathAggregate, SQLServerForPathTable - expression/ddl/graph.py: SQLServerGraphTableKind, SQLServerAsGraphTableExpression, SQLServerEdgeConstraint - protocols/graph.py: SQLServerGraphSupport (6 switches + 9 formatters) - mixins/graph.py: SQLServerGraphMixin with version gating (SQL Graph 2017+, SHORTEST_PATH / path aggregates 2019+) - dialect: compose mixin + protocol; integrate AS NODE/AS EDGE and CONNECTION edge constraints into format_create_table_statement - version_constants: add SQL_SERVER_2025 - keep core SQL/PGQ MatchClause rejection; clarify suggestion text - tests: 30 cases (switches, pattern/MATCH/SHORTEST_PATH/path aggregate, pseudo-column validation, DDL, version-gating negatives)
Store 'pattern'/'extra_patterns' so the introspection-based get_params() serialization round-trip can reconstruct the expression; expose 'patterns' as a derived property.
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## release/v1.0.0.dev3 #3 +/- ##
=======================================================
+ Coverage 72.14% 73.98% +1.84%
=======================================================
Files 86 124 +38
Lines 5783 6715 +932
Branches 934 1019 +85
=======================================================
+ Hits 4172 4968 +796
- Misses 1325 1432 +107
- Partials 286 315 +29
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
vistart
added a commit
that referenced
this pull request
Sep 24, 2026
) * feat(sqlserver): adapt to node-based expression system and declarative format_method - Backend types carry sqlserver_-prefixed generic names; dispatch by naming convention (format_data_type_<name>); @DDLTypeMixin.handles registration removed. - Formatting functions take (self, expr); CAST is a CastExpression node. - CI installs rhosocial-activerecord and the testsuite from their active branches. - Renamed private format functions to remove backend name suffix. * refactor: enforce (self, expr) signature on format_* methods - Remove extra filter_predicate param from format_function_call - Update format_json_table_expression to accept single expr param * fix: Rename JoinExpression→JoinClause, fix format_grouping_expression method - Updated import in dialect.py from JoinExpression to JoinClause - Renamed format_grouping_expression to format_grouping_clause with correct signature (self, expr) instead of (self, operation, _expressions) - Updated example code import in examples/query/join.py - Updated test_expressions.py imports and class name - Updated test_dialect_version_branches.py to use new method name and signature * ci: upgrade to ODBC Driver 18 for SQL Server 2025 jobs Driver 17 is one generation too old for SQL Server 2025's protocol/TLS defaults; parallel test workers failed connections at suite start. * feat(dialect-protocol): formalize SQL Server type support and suggestion contracts - 9 type classes declare dialect_options explicitly; unified _type_params based equality/hash - 29 supports_data_type_* added (1:1 with format family) - suggested_data_types(): uuid/interval/array/enum/jsonb/timestamptz/timetz -> honest cross-backend suggestions; keys disjoint from supported - Precision validation: decimal 1-38/0-precision, float 1-53, temporal 0-7 - _register_type_formatters() copies supports methods + regex attrs - New test_sqlserver_type_protocol.py (30 tests) * fix(test): adapt all tests to dialect-first parameter-inline convention Update ColumnDefinition, DataType subclasses, and CreateTableExpression to use dialect-first constructor signatures: - ColumnDefinition(dialect, name, type, ...) - IntegerType(dialect), VarCharType(dialect, length=...), etc. This aligns tests with the parameter-inline refactor in core library where expressions bind the dialect at construction time. Fixes CI failures in: - test_auto_increment_ddl (ColumnDefinition/DataType signatures) - test_data_type_parsing (DataType dialect-first) - test_dialect_comprehensive (CreateTableExpression) - test_dialect_version_branches (DDL rendering snapshots) - test_create_table_like (ColumnDefinition signatures) - test_niladic_functions (DataType dialect-first) - test_p2_coverage_features (DataType dialect-first) - test_schema_diff, test_sqlserver_partition (providers/fixtures) - test_connection_management, test_parallel_crud (providers/fixtures) * fix(ci): prevent xdist worker deadlock on READ_COMMITTED_SNAPSHOT Root cause: _prepare_read_committed_snapshot was a session-scoped autouse fixture that executed ALTER DATABASE ... SET READ_COMMITTED_SNAPSHOT ON. This requires an exclusive database lock. With pytest-xdist -n 8, each of the 8 workers runs its own session and executes this fixture simultaneously — all trying to acquire the exclusive lock at once, causing a deadlock where every worker waits for the others. Fix: 1. Add tests/enable_read_committed_snapshot.py — a standalone script that enables READ_COMMITTED_SNAPSHOT using pyodbc, meant to run BEFORE pytest in the CI workflow step. 2. In the workflow, insert 'python tests/enable_read_committed_snapshot.py' before every 'python -m pytest' invocation (10 jobs). 3. In conftest.py, change the fixture to verify-only mode: it checks whether the option is already on (it should be, from step 1), and only attempts ALTER DATABASE as a lightweight fallback with a short 3s timeout and 2 retries (instead of 5s × 5 retries). * fix(fixtures): add dialect to ColumnConstraint in all SQL Server fixtures ColumnConstraint.__init__ requires dialect as first argument (parameter-inline convention), but SQL Server fixtures were calling ColumnConstraint(ColumnConstraintType.XXX) without dialect. Fixed in: basic.py, events.py, mixins.py, query.py * fix(dialect): use to_sql() without arguments in _format_column_definition col_def.data_type.to_sql(self) was passing dialect as an argument, but parameter-inline refactored to_sql() to take no arguments (dialect is bound at construction time). Change to to_sql(). Also addresses the locking.py to_sql() -> str question: SQLServerTableHint is a standalone dataclass (not BaseExpression), its to_sql() returning a hint name string is intentional. * fix(dialect): migrate format_set_operation_expression to (self, expr) Same parameter-inline migration as ClickHouse/Oracle: the method now takes a single expr argument, extracting left/right/operation/all_/ alias/order_by_clause/limit_offset_clause from it. * fix(test): complete dialect-first migration in SQL Server tests Add the dialect first argument to all remaining ColumnDefinition, ColumnConstraint, and DataType constructor calls across test files: - test_alter_table_if_exists_backend.py - test_auto_increment_ddl.py (_pk helper now takes dialect) - test_create_table_like.py - test_dialect_comprehensive.py - test_dialect_version_branches.py (use local 'd' variable) - test_niladic_functions.py - test_p2_coverage_features.py (_create_table uses its 'd' param) - test_schema_diff.py (add local SQLServerDialect) - test_sqlserver_partition.py (use local 'd' variable) * test(protocol): add generic protocol conformance test (positive + negative) New test_sqlserver_protocol_conformance.py complements the SQLServer-specific test_protocol_support.py by covering the generic dialect protocols: - SQLSERVER_PROTOCOLS (35 implemented generic protocols) - SQLSERVER_NOT_IMPLEMENTED (10: SQL/XML*, GraphTable, ILIKE, FunctionSupport intentional; GeneratedColumnSupport known gap — naming mismatch, TODO) - negative isinstance test + partition completeness test * feat(dialect): declare GeneratedColumn protocol support SQL Server supports computed columns but only exposed the singular supports_generated_column(). Add the plural supports_generated_columns() (protocol-compliant) and promote GeneratedColumnSupport from SQLSERVER_NOT_IMPLEMENTED to SQLSERVER_PROTOCOLS. * fix(test): migrate remaining tests to parameter-inline calling convention - SetOperation tests: construct SetOperationExpression instead of passing individual keyword args to format_set_operation_expression() - MergeAction: add missing dialect= argument - IndexDefinition/ForeignKeyConstraint/TableConstraint: add missing dialect positional argument in fixtures and test_p2_coverage_features.py * fix(test): add missing dialect= to MergeAction in remaining test files - test_dialect_version_branches.py: 3 MergeAction calls - test_protocol_support.py: 2 MergeAction calls (also positional→keyword) * fix(dialect): adapt format_fulltext_match/array_expression to expression-based signature Core protocol changed from scatter args to (self, expr). Update backend overrides and tests to construct expression objects. * feat(protocol): override supports_cte_order_by to False SQL Server prohibits ORDER BY in CTEs unless TOP/OFFSET/FOR XML is also specified. This is a known SQL Server limitation. * refactor(protocol): rename supports_cte_order_by to supports_unconditional_cte_order_by * fix(dialect): remove stale cast_types handling from format_json_expression TypeCastingMixin.cast() now returns a CastExpression AST node. The old cast_types attribute no longer exists on JSONExpression. This was causing AttributeError in derived field tests. * feat(identifier): add reserved words and opt-out identifier quoting - Add backend reserved words and wire format_identifier(need_quote=...) through SQLDialectBase, warning when a reserved word is left unquoted - Rename supports_table_like_syntax to supports_create_table_like - Add identifier quoting tests * refactor(identifier): remove IdentifierMixin and fix method signatures * refactor(sqlserver): add missing global mixins + remove 29 duplicate methods Add FilterClauseMixin, TransactionControlMixin, AutoIncrementMixin, GeneratedColumnMixin, TriggerMixin, PartitionMixin, ILIKEMixin, FunctionMixin to inheritance chain (P0 fix: these were missing, causing support methods to return None via Protocol stubs). Remove 29 supports_* methods that are now redundant with the newly added mixins or existing global mixin defaults: - ArrayMixin, GraphMixin, QualifyClauseMixin, OrderedSetAggregationMixin - ViewMixin, SchemaMixin, IndexMixin, SequenceMixin, TableMixin - ConstraintMixin, DDLColumnMixin, SetOperationMixin dialect.py: 1970 → 1900 lines (-70) * test(protocol): move Function/ILIKE to positive protocol list The dialect now composes FunctionMixin/ILIKEMixin, so it satisfies FunctionSupport/ILikesupport; the negative-contract list was stale and failed. Note their semantics remain backend-specific. * refactor(sqlserver): split dialect methods into 25 feature mixins Move 90 methods from dialect.py into 25 mixin files: - datetime.py, collation.py, cte.py, returning.py, constraint.py, window.py, json.py, grouping.py, locking.py, merge.py, temporal.py, upsert.py, lateral.py, explain.py, dql.py, dml.py, view.py, schema.py, index.py, generated_column.py, set_operation.py, table.py, identifier.py, transaction.py, function.py (new) - Extended: trigger.py, sequence.py - New shared constants: version_constants.py dialect.py: 1900 → 1062 lines. * feat(sqlserver): add JSON/SET/spatial expression classes Expression nodes for format_* signature compliance (mirrors the MySQL/ MariaDB expression-object convention). * refactor(sqlserver): rename protocols/json_support.py to json.py Drop the redundant _support suffix from the protocol module name. * fix(sqlserver): declare format_identifier on the dialect SQLDialectBase precedes the feature mixins in the MRO, so the bracket formatter in SQLServerIdentifierMixin was shadowed and identifiers were rendered with double quotes. Re-declare it on the dialect. * test(sqlserver): route direct formatter calls through expression nodes Tests were calling dialect formatters with raw strings/lists, bypassing the expression layer. Construct the corresponding expression classes and call to_sql() so the tests exercise the real expression<->formatter integration: - NEXT VALUE FOR -> SQLServerNextValueForExpression - CONTAINS / FREETEXT -> SQLServerContainsPredicate / SQLServerFreetextPredicate - TRY_CAST / TRY_CONVERT -> SQLServerTryCastExpression / SQLServerTryConvertExpression - table hints -> SQLServerTableHintClause - OPENJSON -> SQLServerOpenJsonExpression - temporal period -> SQLServerTemporalPeriodDefinition - FULLTEXT CATALOG -> SQLServerCreateFullTextCatalogExpression - OPTION hints -> SQLServerOptionHintClause * fix(sqlserver): compose CollationMixin for format_collate_expression CollationMixin was imported but not in the bases, so format_collate_ expression resolved to the CollationSupport protocol stub (None). * refactor(sqlserver): emit bind placeholders via dialect accessor * fix: replace hardcoded ? placeholder with dialect.p() in async_backend * refactor: normalize format_* return types to Tuple[str, tuple] and eliminate isinstance - Global: Tuple[str, Tuple] → Tuple[str, tuple] across all format_* methods - format_auto_increment: str → Tuple[str, tuple] - format_top_n_clause: str → Tuple[str, tuple] - format_inline_index: str → Tuple[str, tuple] - format_limit_offset: Tuple[Optional[str], List[Any]] → Tuple[str, tuple] - format_next_value_for: str → Tuple[str, tuple] - format_set_identity_insert: str → Tuple[str, tuple] - format_temporal_period_definition: str → Tuple[str, tuple] - format_table_hint / format_table_hint_locking: str → Tuple[str, tuple] - format_tablesample_clause: str → Tuple[str, tuple] - format_*_fulltext_*: str → Tuple[str, tuple] - Eliminated isinstance checks: - format_column_definition: data_type always DataType, default_value uses inline_sql_literal - format_create_index_statement: columns unified to expression objects - format_fulltext_match: columns unified to expression objects - format_json_function_expression: column unified to expression objects - format_sqlserver_partition_function: values use inline_sql_literal - format_openjson_schema: schema unified to expression objects - Added type hints to ~40% of methods previously lacking them - Updated all protocol definitions to match new signatures * chore: fix .gitignore for .claude/plan*/ * fix: update tests and dialect for signature normalization - format_limit_offset returns (str, tuple) not (None, []); fix test assertions - format_top_n_clause returns Tuple[str, tuple] not str; fix test assertions - format_table_hint_locking/format_set_identity_insert return Tuple[str, tuple] - format_create_index_statement: handle string columns via isinstance check - Import ToSQLProtocol from expression.bases for column type checking * fix: update tests to unpack (sql, params) tuple from format_tablesample_clause * fix: handle BaseExpression default values in format_column_definition When DEFAULT value is a FunctionCall or other BaseExpression, call to_sql() instead of inline_sql_literal() which cannot handle expression objects. * refactor(ddl)!: SQL Server LIKE unsupported via CreateTableLikeExpression - remove the inline dialect_options['like_table'] guard from format_create_table_statement; SQL Server inherits supports_create_table_like() == False, so the gated generic format_create_table_like_statement raises UnsupportedFeatureError - tests migrate to CreateTableLikeExpression and assert the raise BREAKING CHANGE: CREATE TABLE ... LIKE is no longer expressed through CreateTableExpression(dialect_options={'like_table': ...}); use CreateTableLikeExpression, which raises UnsupportedFeatureError on SQL Server. * feat(ddl): prefer typed table_options for memory_optimized/durability Renderer now reads memory_optimized/durability from typed CreateTableOptions fields first, falling back to dialect_options. * fix(ddl): fix DROP TABLE CASCADE/RESTRICT and remove override - Add supports_drop_table_cascade() → False - Add supports_drop_table_restrict() → False - Remove format_drop_table_statement override (use generic impl) * feat(ddl): add supports_multi_action_alter_table(False) SQL Server requires one action per ALTER TABLE statement. * refactor(ddl): rename table.py → ddl_table.py in mixins * feat: add SQL Server DDL improvements with capability gating - Add SQLServerDatabaseMixin for CREATE/DROP/ALTER DATABASE support - Add SQLServerViewMixin with capability gating - Add test_sqlserver_ddl_improvements.py with 5 tests - Rename view.py -> ddl_view.py * refactor: remove ReturningMixin import (merged into DMLMixin in core) * feat: improve OUTPUT clause (per-expression prefix, INTO, validation) - Per-expression virtual-table prefix (Column(table='DELETED'|'INSERTED')) - ReturningClause.output_into renders OUTPUT ... INTO <target> - Raise UnsupportedFeatureError for non-column expressions, wildcards, aliases - supports_returning_alias/wildcard False, supports_returning_into True - Fix stale .mixins.view import (renamed to ddl_view) - Add OUTPUT tests * test: classify DatabaseSupport in SQL Server protocol conformance * test: pass SQL Server version in DDL capability tests to satisfy version gating * feat(dql): WITH TIES + typed lock strength + set-op FOR UPDATE gate - format_limit_offset_clause: FETCH NEXT ... ROWS WITH TIES - supports_fetch_with_ties True; supports_nulls_first_last False - locking: gate strength (no silent ignore) - set_operation: raise on unsupported FOR UPDATE * refactor: remove core DQL/Expression mixin references (merged into DQLMixin/ExpressionMixin) * feat(ddl): render generated columns via core GeneratedColumnExpression * chore: add scripts/preflight.sh and optional git hook installer * feat(graph): add SQL Server SQL Graph support (node/edge tables + MATCH predicate) SQL Server SQL Graph is independent from SQL/PGQ (different data model and query shape), so it lives in the SQL Server backend, not the core GraphMixin. - expression/graph.py: SQLServerGraphDirection, SQLServerGraphPseudoColumn, SQLServerGraphNodeRef, SQLServerGraphEdgeRef, SQLServerGraphPattern, SQLServerMatchPredicate, SQLServerShortestPathExpression, SQLServerGraphPathAggregate, SQLServerForPathTable - expression/ddl/graph.py: SQLServerGraphTableKind, SQLServerAsGraphTableExpression, SQLServerEdgeConstraint - protocols/graph.py: SQLServerGraphSupport (6 switches + 9 formatters) - mixins/graph.py: SQLServerGraphMixin with version gating (SQL Graph 2017+, SHORTEST_PATH / path aggregates 2019+) - dialect: compose mixin + protocol; integrate AS NODE/AS EDGE and CONNECTION edge constraints into format_create_table_statement - version_constants: add SQL_SERVER_2025 - keep core SQL/PGQ MatchClause rejection; clarify suggestion text - tests: 30 cases (switches, pattern/MATCH/SHORTEST_PATH/path aggregate, pseudo-column validation, DDL, version-gating negatives) * fix(graph): align SQLServerShortestPathExpression attrs with ctor params Store 'pattern'/'extra_patterns' so the introspection-based get_params() serialization round-trip can reconstruct the expression; expose 'patterns' as a derived property. * chore(ci): update rhosocial-activerecord install source to release/v1.0.0.dev30 * fix(sqlserver): correct pagination, database ownership and temporal formatting * fix(graph): correct shortest path grouping and edge constraint gating * test(graph): reuse scenario fixtures and protocol capability checks * feat(sqlserver): add statement-level NOSCAN execution option * chore: add changelog fragment for graph support and NOSCAN option
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
This PR introduces significant improvements to the SQL Server backend:
(self, expr)signature pattern for consistency with core libraryAdds # (issue)
Type of change
feat: A new featuredocs: 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 commitBreaking Change
Impact on End-Users:
No backward-incompatible changes are expected for typical end-user applications.
Impact on Backend Developers (Custom Implementations):
The parameter-inline convention changes the signature of all
format_*methods from(column, ...)to(self, expr). Backend developers with custom implementations will need to update their method signatures to match the new pattern.Related Repositories/Packages
rhosocial-activerecord(core): Uses the same parameter-inline conventionpython-activerecord-testsuite: May need protocol conformance test updatesTesting
test_execution_options.pycovers sync/async NOSCAN regression (temporary solution, subject to change)Test Plan:
Checklist
README.md, etc.).changelog.d/<issue_number>.<type>.md).Additional Notes
Key commits:
feat(graph): add SQL Server SQL Graph support (node/edge tables + MATCH predicate)feat(dialect): declare GeneratedColumn protocol supportrefactor(sqlserver): split dialect methods into 25 feature mixinsfix(sqlserver): correct pagination, database ownership and temporal formattingtest(protocol): add generic protocol conformance testThis is a substantial refactor that formalizes the SQL Server dialect architecture while adding new features. The parameter-inline convention is now consistently applied across all format methods.