.. 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
: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
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)
__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(
"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')))
"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(