summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/unreleased_13/5467.rst6
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py5
-rw-r--r--test/dialect/mssql/test_compiler.py19
3 files changed, 26 insertions, 4 deletions
diff --git a/doc/build/changelog/unreleased_13/5467.rst b/doc/build/changelog/unreleased_13/5467.rst
new file mode 100644
index 000000000..241bdb7ff
--- /dev/null
+++ b/doc/build/changelog/unreleased_13/5467.rst
@@ -0,0 +1,6 @@
+.. change::
+ :tags: bug, mssql, sql
+ :tickets: 5467
+
+ Fixed bug where the mssql dialect incorrectly escaped object names that
+ contained ']' character(s).
diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py
index c3cc4e425..0ec6cf8a3 100644
--- a/lib/sqlalchemy/dialects/mssql/base.py
+++ b/lib/sqlalchemy/dialects/mssql/base.py
@@ -2244,7 +2244,10 @@ class MSIdentifierPreparer(compiler.IdentifierPreparer):
)
def _escape_identifier(self, value):
- return value
+ return value.replace("]", "]]")
+
+ def _unescape_identifier(self, value):
+ return value.replace("]]", "]")
def quote_schema(self, schema, force=None):
"""Prepare a quoted table and schema name."""
diff --git a/test/dialect/mssql/test_compiler.py b/test/dialect/mssql/test_compiler.py
index 732ff1f55..83a610888 100644
--- a/test/dialect/mssql/test_compiler.py
+++ b/test/dialect/mssql/test_compiler.py
@@ -40,10 +40,23 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
self.assert_compile(sql.false(), "0")
self.assert_compile(sql.true(), "1")
- def test_select(self):
- t = table("sometable", column("somecolumn"))
+ @testing.combinations(
+ ("plain", "sometable", "sometable"),
+ ("matched_square_brackets", "colo[u]r", "[colo[u]]r]"),
+ ("unmatched_left_square_bracket", "colo[ur", "[colo[ur]"),
+ ("unmatched_right_square_bracket", "colou]r", "[colou]]r]"),
+ ("double quotes", 'Edwin "Buzz" Aldrin', '[Edwin "Buzz" Aldrin]'),
+ ("dash", "Dash-8", "[Dash-8]"),
+ ("slash", "tl/dr", "[tl/dr]"),
+ ("space", "Red Deer", "[Red Deer]"),
+ ("question mark", "OK?", "[OK?]"),
+ ("percent", "GST%", "[GST%]"),
+ id_="iaa",
+ )
+ def test_identifier_rendering(self, table_name, rendered_name):
+ t = table(table_name, column("somecolumn"))
self.assert_compile(
- t.select(), "SELECT sometable.somecolumn FROM sometable"
+ t.select(), "SELECT {0}.somecolumn FROM {0}".format(rendered_name)
)
def test_select_with_nolock(self):