Skip to content

Commit 9a49425

Browse files
vistartclaude
andcommitted
refactor(sqlserver): accept collation expression in validation
Adapt COLLATE validation to consume the full CollateExpression while preserving SQL Server DATABASE_DEFAULT keyword handling. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent f1129b9 commit 9a49425

2 files changed

Lines changed: 14 additions & 10 deletions

File tree

‎src/rhosocial/activerecord/backend/impl/sqlserver/dialect.py‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787

8888
if TYPE_CHECKING:
8989
from rhosocial.activerecord.backend.expression import bases
90-
from rhosocial.activerecord.backend.expression.collation import CollationName
90+
from rhosocial.activerecord.backend.expression.collation import CollateExpression
9191
from rhosocial.activerecord.backend.expression.advanced_functions import ArrayExpression, OrderedSetAggregation, JSONExpression
9292
from rhosocial.activerecord.backend.expression.graph import MatchClause
9393
from rhosocial.activerecord.backend.expression.query_parts import (
@@ -278,13 +278,18 @@ def supports_collate_expression(self) -> bool:
278278
"""SQL Server supports expression-level COLLATE."""
279279
return True
280280

281-
def validate_collation_name(self, collation: "CollationName") -> str:
281+
def validate_collation_name(self, expr: "CollateExpression") -> str:
282282
"""Validate SQL Server collation names and return their SQL representation."""
283-
if collation.schema is not None:
283+
if "schema" in expr.collation_options:
284284
raise UnsupportedFeatureError(self.name, "schema-qualified COLLATE")
285-
if collation.keyword is not None and collation.keyword != "DATABASE_DEFAULT":
286-
raise ValueError(f"Unsupported SQL Server collation keyword: {collation.keyword!r}")
287-
return validate_sqlserver_collation_name(collation.keyword or collation.name, getattr(self, "version", None))
285+
keyword = expr.collation_options.get("keyword", False)
286+
unsupported = set(expr.collation_options) - {"keyword", "schema"}
287+
if unsupported:
288+
options = ", ".join(sorted(unsupported))
289+
raise UnsupportedFeatureError(self.name, f"COLLATE options: {options}")
290+
if keyword and expr.collation_name != "DATABASE_DEFAULT":
291+
raise ValueError(f"Unsupported SQL Server collation keyword: {expr.collation_name!r}")
292+
return validate_sqlserver_collation_name(expr.collation_name, getattr(self, "version", None))
288293

289294
def format_identifier(self, identifier: str) -> str:
290295
"""

‎tests/rhosocial/activerecord_sqlserver_test/feature/query/test_collation_expression.py‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import pytest
77

88
from rhosocial.activerecord.backend.expression import Column, Literal
9-
from rhosocial.activerecord.backend.expression.collation import CollationName
109
from rhosocial.activerecord.backend.impl.sqlserver import SQLServerCollation, SQLServerDialect
1110

1211

@@ -52,7 +51,7 @@ def test_literal_collate_preserves_parameter_binding(self, dialect):
5251
assert params == ("Alice",)
5352

5453
def test_database_default_keyword_generates_sql(self, dialect):
55-
expr = Column(dialect, "name").collate(CollationName.as_keyword("DATABASE_DEFAULT"))
54+
expr = Column(dialect, "name").collate("DATABASE_DEFAULT", keyword=True)
5655

5756
sql, params = expr.to_sql()
5857

@@ -61,14 +60,14 @@ def test_database_default_keyword_generates_sql(self, dialect):
6160

6261
def test_rejects_schema_qualified_collation(self, dialect):
6362
expr = Column(dialect, "name").collate(
64-
CollationName(SQLServerCollation.LATIN1_GENERAL_CI_AS.value, schema="dbo")
63+
SQLServerCollation.LATIN1_GENERAL_CI_AS.value, schema="dbo"
6564
)
6665

6766
with pytest.raises(Exception, match="schema-qualified COLLATE"):
6867
expr.to_sql()
6968

7069
def test_rejects_unsupported_keyword(self, dialect):
71-
expr = Column(dialect, "name").collate(CollationName.as_keyword("CATALOG_DEFAULT"))
70+
expr = Column(dialect, "name").collate("CATALOG_DEFAULT", keyword=True)
7271

7372
with pytest.raises(ValueError, match="Unsupported SQL Server collation keyword"):
7473
expr.to_sql()

0 commit comments

Comments
 (0)