]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Postgresql default to no backslash escaping
authorFederico Caselli <cfederico87@gmail.com>
Wed, 29 Apr 2026 20:11:35 +0000 (22:11 +0200)
committerFederico Caselli <cfederico87@gmail.com>
Wed, 29 Apr 2026 21:16:09 +0000 (23:16 +0200)
Changed the default backslash escape value in the PostgreSQL dialect to
``False`` to align it with the default value of
``standard_conforming_strings=on``. This change should not affect most users
since the value is set at driver initialization on first connect.

Fixes: #13268
Change-Id: I9b7986f1ee466fab3cab88e3f6117e313e3376cd

doc/build/changelog/unreleased_21/11450.rst
doc/build/changelog/unreleased_21/13268.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/postgresql/test_compiler.py
test/dialect/postgresql/test_dialect.py
test/sql/test_operators.py

index 371f86dec18d546af7e850eccde4fed2041899af..3f60d15c3d475ef524eee5a8e28d877471731431 100644 (file)
@@ -4,4 +4,4 @@
 
   Added :paramref:`.selectinload.chunksize` parameter to :func`.selectinload`
   allowing users to configure the number of primary keys sent per IN clause
-  when loading reltaionships. Pull request courtesy bekapono.
+  when loading relationships. Pull request courtesy bekapono.
diff --git a/doc/build/changelog/unreleased_21/13268.rst b/doc/build/changelog/unreleased_21/13268.rst
new file mode 100644 (file)
index 0000000..b55c4da
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+  :tags: postgresql, usecase
+  :tickets: 13268
+
+  Changed the default backslash escape value in the PostgreSQL dialect to
+  ``False`` to align it with the default value of
+  ``standard_conforming_strings=on``. This change should not affect most users
+  since the value is set at driver initialization on first connect.
index 1702bc70c9731f5d5ba827547d5411c4e2d9cb13..58c925d08b29fc12b261e35282d5f2291d6896a0 100644 (file)
@@ -3522,7 +3522,7 @@ class PGDialect(default.DefaultDialect):
 
     reflection_options = ("postgresql_ignore_search_path",)
 
-    _backslash_escapes = True
+    _backslash_escapes = False
     _supports_create_index_concurrently = True
     _supports_drop_index_concurrently = True
     _supports_jsonb_subscripting = True
index 142a7c808f42db5c205cfecc228cde08edfe5dc1..fc460cac18abb2325d45c6bfa86f6083e8425e13 100644 (file)
@@ -3265,7 +3265,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
         dialect = postgresql.dialect()
         self.assert_compile(
             sql.column("foo").ilike("bar", escape="\\"),
-            "foo ILIKE %(foo_1)s::VARCHAR ESCAPE '\\\\'",
+            "foo ILIKE %(foo_1)s::VARCHAR ESCAPE '\\'",
         )
 
         self.assert_compile(
@@ -3276,7 +3276,7 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
 
         self.assert_compile(
             sql.column("foo").notilike("bar", escape="\\"),
-            "foo NOT ILIKE %(foo_1)s::VARCHAR ESCAPE '\\\\'",
+            "foo NOT ILIKE %(foo_1)s::VARCHAR ESCAPE '\\'",
         )
 
         self.assert_compile(
index ce8ff27a2d172b7eaef9d19f654b0057b3826082..e9ee74aac26c82646022855974b51230d562e297 100644 (file)
@@ -989,17 +989,18 @@ class MiscBackendTest(
     def test_backslash_escapes_detection(self, explicit_setting, expected):
         engine = engines.testing_engine()
 
-        if explicit_setting is not None:
-
-            @event.listens_for(engine, "connect", insert=True)
-            @event.listens_for(engine, "first_connect", insert=True)
-            def connect(dbapi_connection, connection_record):
-                cursor = dbapi_connection.cursor()
-                cursor.execute(
-                    "SET SESSION standard_conforming_strings = %s"
-                    % ("off" if not explicit_setting else "on")
-                )
-                dbapi_connection.commit()
+        # check the default value before connect
+        eq_(engine.dialect._backslash_escapes, False)
+
+        @event.listens_for(engine, "connect", insert=True)
+        @event.listens_for(engine, "first_connect", insert=True)
+        def connect(dbapi_connection, connection_record):
+            cursor = dbapi_connection.cursor()
+            cursor.execute(
+                "SET SESSION standard_conforming_strings = %s"
+                % ("off" if not explicit_setting else "on")
+            )
+            dbapi_connection.commit()
 
         with engine.connect():
             eq_(engine.dialect._backslash_escapes, expected)
index d1f2233d94495322e752be81615ed2f18c1de9e8..a815cb63176e7193f735bdacec6d136d02f4a105 100644 (file)
@@ -3219,14 +3219,14 @@ class LikeTest(fixtures.TestBase, testing.AssertsCompiledSQL):
     def test_like_7(self):
         self.assert_compile(
             self.table1.c.myid.ilike("somstr", escape="\\"),
-            "mytable.myid ILIKE %(myid_1)s::VARCHAR ESCAPE '\\\\'",
+            "mytable.myid ILIKE %(myid_1)s::VARCHAR ESCAPE '\\'",
             dialect=postgresql.dialect(),
         )
 
     def test_like_8(self):
         self.assert_compile(
             ~self.table1.c.myid.ilike("somstr", escape="\\"),
-            "mytable.myid NOT ILIKE %(myid_1)s::VARCHAR ESCAPE '\\\\'",
+            "mytable.myid NOT ILIKE %(myid_1)s::VARCHAR ESCAPE '\\'",
             dialect=postgresql.dialect(),
         )