--- /dev/null
+.. change::
+ :tags: bug, mssql, sql
+ :tickets: 9932
+
+ Fixed issue where performing :class:`.Cast` to a string type with an
+ explicit collation would render the COLLATE clause inside the CAST
+ function, which resulted in a syntax error.
return type_coerce.typed_expression._compiler_dispatch(self, **kw)
def visit_cast(self, cast, **kwargs):
- return "CAST(%s AS %s)" % (
+ type_clause = cast.typeclause._compiler_dispatch(self, **kwargs)
+ match = re.match("(.*)( COLLATE .*)", type_clause)
+ return "CAST(%s AS %s)%s" % (
cast.clause._compiler_dispatch(self, **kwargs),
- cast.typeclause._compiler_dispatch(self, **kwargs),
+ match.group(1) if match else type_clause,
+ match.group(2) if match else "",
)
def _format_frame_clause(self, range_, **kw):
dialect=sqlite.dialect(),
)
+ @testing.combinations(
+ (
+ "default",
+ None,
+ "SELECT CAST(t1.txt AS VARCHAR(10)) AS txt FROM t1",
+ None,
+ ),
+ (
+ "explicit_mssql",
+ "Latin1_General_CI_AS",
+ "SELECT CAST(t1.txt AS VARCHAR(10)) COLLATE Latin1_General_CI_AS AS txt FROM t1", # noqa
+ mssql.dialect(),
+ ),
+ (
+ "explicit_mysql",
+ "utf8mb4_unicode_ci",
+ "SELECT CAST(t1.txt AS CHAR(10)) AS txt FROM t1",
+ mysql.dialect(),
+ ),
+ (
+ "explicit_postgresql",
+ "en_US",
+ 'SELECT CAST(t1.txt AS VARCHAR(10)) COLLATE "en_US" AS txt FROM t1', # noqa
+ postgresql.dialect(),
+ ),
+ (
+ "explicit_sqlite",
+ "NOCASE",
+ 'SELECT CAST(t1.txt AS VARCHAR(10)) COLLATE "NOCASE" AS txt FROM t1', # noqa
+ sqlite.dialect(),
+ ),
+ id_="iaaa",
+ )
+ def test_cast_with_collate(self, collation_name, expected_sql, dialect):
+ t1 = Table(
+ "t1",
+ MetaData(),
+ Column("txt", String(10, collation=collation_name)),
+ )
+ stmt = select(func.cast(t1.c.txt, t1.c.txt.type))
+ self.assert_compile(stmt, expected_sql, dialect=dialect)
+
def test_over(self):
self.assert_compile(func.row_number().over(), "row_number() OVER ()")
self.assert_compile(