]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Escape literal string values passed to server_default
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 30 Sep 2016 13:23:50 +0000 (09:23 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 30 Sep 2016 13:23:50 +0000 (09:23 -0400)
A string sent as a column default via the
:paramref:`.Column.server_default` parameter is now escaped for quotes.

This change is backwards compatible with code that may have been
working around this previously.

Change-Id: I341298a76cc67bc0a53df4ab51ab9379f2294cdd
Fixes: #3809
doc/build/changelog/changelog_11.rst
doc/build/changelog/migration_11.rst
lib/sqlalchemy/sql/compiler.py
test/sql/test_defaults.py

index af22fd6bc82adfe7b212988999b35b54adeaaea8..af217170795967c5bd665ab5fd7bba830b7fe17d 100644 (file)
 .. changelog::
     :version: 1.1.0
 
+    .. change::
+        :tags: bug, sql
+        :tickets: 3809
+
+        A string sent as a column default via the
+        :paramref:`.Column.server_default` parameter is now escaped for quotes.
+
+        .. seealso::
+
+            :ref:`change_3809`
+
     .. change::
         :tags: bug, postgresql
         :tickets: 3807
index c85f1bf1f94862cfeec7cfcdf4702d3d583d2122..e514f4dbbd310efd6eed3bead8002391bc9fef56 100644 (file)
@@ -1180,6 +1180,31 @@ statement::
 
 :ticket:`2551`
 
+.. _change_3809:
+
+String server_default now literal quoted
+----------------------------------------
+
+A server default passed to :paramref:`.Column.server_default` as a plain
+Python string that has quotes embedded is now
+passed through the literal quoting system::
+
+    >>> from sqlalchemy.schema import MetaData, Table, Column, CreateTable
+    >>> from sqlalchemy.types import String
+    >>> t = Table('t', MetaData(), Column('x', String(), server_default="hi ' there"))
+    >>> print CreateTable(t)
+
+    CREATE TABLE t (
+        x VARCHAR DEFAULT 'hi '' there'
+    )
+
+Previously the quote would render directly.     This change may be backwards
+incompatible for applications with such a use case who were working around
+the issue.
+
+
+:ticket:`3809`
+
 .. _change_3049:
 
 Support for RANGE and ROWS specification within window functions
index a7954f10a297da1530bb032297350a2c99a431c6..a2dbcee5c3a207fbe8ea024071d6ace1ad4ff243 100644 (file)
@@ -2494,7 +2494,8 @@ class DDLCompiler(Compiled):
     def get_column_default_string(self, column):
         if isinstance(column.server_default, schema.DefaultClause):
             if isinstance(column.server_default.arg, util.string_types):
-                return "'%s'" % column.server_default.arg
+                return self.sql_compiler.render_literal_value(
+                    column.server_default.arg, sqltypes.STRINGTYPE)
             else:
                 return self.sql_compiler.process(
                     column.server_default.arg, literal_binds=True)
index 57af1e536e06f8b3ea3a5acabd44865ecf1b34f1..1b033fce8f8b9b6fc54a8a2577ce11a372cd6484 100644 (file)
@@ -24,6 +24,9 @@ class DDLTest(fixtures.TestBase, AssertsCompiledSQL):
     __dialect__ = 'default'
 
     def test_string(self):
+        # note: that the datatype is an Integer here doesn't matter,
+        # the server_default is interpreted independently of the
+        # column's datatype.
         m = MetaData()
         t = Table('t', m, Column('x', Integer, server_default='5'))
         self.assert_compile(
@@ -31,6 +34,14 @@ class DDLTest(fixtures.TestBase, AssertsCompiledSQL):
             "CREATE TABLE t (x INTEGER DEFAULT '5')"
         )
 
+    def test_string_w_quotes(self):
+        m = MetaData()
+        t = Table('t', m, Column('x', Integer, server_default="5'6"))
+        self.assert_compile(
+            CreateTable(t),
+            "CREATE TABLE t (x INTEGER DEFAULT '5''6')"
+        )
+
     def test_text(self):
         m = MetaData()
         t = Table('t', m, Column('x', Integer, server_default=text('5 + 8')))
@@ -39,6 +50,23 @@ class DDLTest(fixtures.TestBase, AssertsCompiledSQL):
             "CREATE TABLE t (x INTEGER DEFAULT 5 + 8)"
         )
 
+    def test_text_w_quotes(self):
+        m = MetaData()
+        t = Table('t', m, Column('x', Integer, server_default=text("5 ' 8")))
+        self.assert_compile(
+            CreateTable(t),
+            "CREATE TABLE t (x INTEGER DEFAULT 5 ' 8)"
+        )
+
+    def test_literal_binds_w_quotes(self):
+        m = MetaData()
+        t = Table('t', m, Column('x', Integer,
+                  server_default=literal("5 ' 8")))
+        self.assert_compile(
+            CreateTable(t),
+            """CREATE TABLE t (x INTEGER DEFAULT '5 '' 8')"""
+        )
+
     def test_text_literal_binds(self):
         m = MetaData()
         t = Table(