Example:
- Column('myenum', MSEnum("'foo'", "'bar'", "'baz'"))
+ Column('myenum', MSEnum("foo", "bar", "baz"))
Arguments are:
enums
- The range of valid values for this ENUM. Values will be used
- exactly as they appear when generating schemas. Strings must
- be quoted, as in the example above. Single-quotes are suggested
- for ANSI compatability and are required for portability to servers
- with ANSI_QUOTES enabled.
+ The range of valid values for this ENUM. Values will be quoted
+ when generating the schema according to the quoting flag (see
+ below).
strict
Defaults to False: ensure that a given value is in this ENUM's
that matches the column's character set. Generates BINARY in
schema. This does not affect the type of data stored, only the
collation of character data.
- """
- self.__ddl_values = enums
+ quoting
+ Defaults to 'auto': automatically determine enum value quoting. If
+ all enum values are surrounded by the same quoting character, then
+ use 'quoted' mode. Otherwise, use 'unquoted' mode.
- strip_enums = []
- for a in enums:
- if a[0:1] == '"' or a[0:1] == "'":
- # strip enclosing quotes and unquote interior
- a = a[1:-1].replace(a[0] * 2, a[0])
- strip_enums.append(a)
+ 'quoted': values in enums are already quoted, they will be used
+ directly when generating the schema.
+
+ 'unquoted': values in enums are not quoted, they will be escaped and
+ surrounded by single quotes when generating the schema.
+
+ Previous versions of this type always required manually quoted
+ values to be supplied; future versions will always quote the string
+ literals for you. This is a transitional option.
+
+ """
+ self.quoting = kw.pop('quoting', 'auto')
+
+ if self.quoting == 'auto':
+ # What quoting character are we using?
+ q = None
+ for e in enums:
+ if len(e) == 0:
+ self.quoting = 'unquoted'
+ break
+ elif q is None:
+ q = e[0]
+
+ if e[0] != q or e[-1] != q:
+ self.quoting = 'unquoted'
+ break
+ else:
+ self.quoting = 'quoted'
+
+ if self.quoting == 'quoted':
+ util.warn_pending_deprecation(
+ 'Manually quoting ENUM value literals is deprecated. Supply '
+ 'unquoted values and use the quoting= option in cases of '
+ 'ambiguity.')
+ strip_enums = []
+ for a in enums:
+ if a[0:1] == '"' or a[0:1] == "'":
+ # strip enclosing quotes and unquote interior
+ a = a[1:-1].replace(a[0] * 2, a[0])
+ strip_enums.append(a)
+ self.enums = strip_enums
+ else:
+ self.enums = list(enums)
- self.enums = strip_enums
self.strict = kw.pop('strict', False)
- length = max([len(v) for v in strip_enums] + [0])
+ length = max([len(v) for v in self.enums] + [0])
super(MSEnum, self).__init__(length, **kw)
def bind_processor(self, dialect):
return process
def get_col_spec(self):
- return self._extend("ENUM(%s)" % ",".join(self.__ddl_values))
-
+ quoted_enums = []
+ for e in self.enums:
+ quoted_enums.append("'%s'" % e.replace("'", "''"))
+ return self._extend("ENUM(%s)" % ",".join(quoted_enums))
class MSSet(MSString):
"""MySQL SET type."""
if spec.get(kw, False):
type_kw[kw] = spec[kw]
+ if type_ == 'enum':
+ type_kw['quoting'] = 'quoted'
+
type_instance = col_type(*type_args, **type_kw)
col_args, col_kw = [], {}
from sqlalchemy import *
from sqlalchemy import sql, exc
from sqlalchemy.databases import mysql
+from testlib.testing import eq_
from testlib import *
Column('num4', mysql.MSDouble),
Column('num5', mysql.MSDouble()),
Column('enum1', mysql.MSEnum("'black'", "'white'")),
+ Column('enum2', mysql.MSEnum("dog", "cat")),
)
try:
table.drop(checkfirst=True)
assert isinstance(t2.c.num4.type, mysql.MSDouble)
assert isinstance(t2.c.num5.type, mysql.MSDouble)
assert isinstance(t2.c.enum1.type, mysql.MSEnum)
+ assert isinstance(t2.c.enum2.type, mysql.MSEnum)
t2.drop()
t2.create()
finally:
(mysql.MSLongText, [], {'ascii':True},
'LONGTEXT ASCII'),
- (mysql.MSEnum, ["'foo'", "'bar'"], {'unicode':True},
+ (mysql.MSEnum, ["foo", "bar"], {'unicode':True},
'''ENUM('foo','bar') UNICODE''')
]
nullable=False),
Column('e3', mysql.MSEnum("'a'", "'b'", strict=True)),
Column('e4', mysql.MSEnum("'a'", "'b'", strict=True),
- nullable=False))
+ nullable=False),
+ Column('e5', mysql.MSEnum("a", "b")),
+ Column('e6', mysql.MSEnum("'a'", "b")),
+ )
self.assert_eq(colspec(enum_table.c.e1),
"e1 ENUM('a','b')")
"e3 ENUM('a','b')")
self.assert_eq(colspec(enum_table.c.e4),
"e4 ENUM('a','b') NOT NULL")
+ self.assert_eq(colspec(enum_table.c.e5),
+ "e5 ENUM('a','b')")
+ self.assert_eq(colspec(enum_table.c.e6),
+ "e6 ENUM('''a''','b')")
enum_table.drop(checkfirst=True)
enum_table.create()
self.assert_(True)
try:
- enum_table.insert().execute(e1='c', e2='c', e3='c', e4='c')
+ enum_table.insert().execute(e1='c', e2='c', e3='c',
+ e4='c', e5='c', e6='c')
self.assert_(False)
except exc.InvalidRequestError:
self.assert_(True)
enum_table.insert().execute()
- enum_table.insert().execute(e1='a', e2='a', e3='a', e4='a')
- enum_table.insert().execute(e1='b', e2='b', e3='b', e4='b')
+ enum_table.insert().execute(e1='a', e2='a', e3='a',
+ e4='a', e5='a', e6="'a'")
+ enum_table.insert().execute(e1='b', e2='b', e3='b',
+ e4='b', e5='b', e6='b')
res = enum_table.select().execute().fetchall()
- expected = [(None, 'a', None, 'a'),
- ('a', 'a', 'a', 'a'),
- ('b', 'b', 'b', 'b')]
+ expected = [(None, 'a', None, 'a', None, None),
+ ('a', 'a', 'a', 'a', 'a', "'a'"),
+ ('b', 'b', 'b', 'b', 'b', 'b')]
# This is known to fail with MySQLDB 1.2.2 beta versions
# which return these as sets.Set(['a']), sets.Set(['b'])
enum_table = Table('mysql_enum', MetaData(testing.db),
Column('e1', mysql.MSEnum("'a'")),
Column('e2', mysql.MSEnum("''")),
- Column('e3', mysql.MSEnum("'a'", "''")),
- Column('e4', mysql.MSEnum("''", "'a'")),
- Column('e5', mysql.MSEnum("''", "'''a'''", "'b''b'", "''''")))
+ Column('e3', mysql.MSEnum('a')),
+ Column('e4', mysql.MSEnum('')),
+ Column('e5', mysql.MSEnum("'a'", "''")),
+ Column('e6', mysql.MSEnum("''", "'a'")),
+ Column('e7', mysql.MSEnum("''", "'''a'''", "'b''b'", "''''")))
for col in enum_table.c:
self.assert_(repr(col))
reflected = Table('mysql_enum', MetaData(testing.db),
autoload=True)
for t in enum_table, reflected:
- assert t.c.e1.type.enums == ["a"]
- assert t.c.e2.type.enums == [""]
- assert t.c.e3.type.enums == ["a", ""]
- assert t.c.e4.type.enums == ["", "a"]
- assert t.c.e5.type.enums == ["", "'a'", "b'b", "'"]
+ eq_(t.c.e1.type.enums, ["a"])
+ eq_(t.c.e2.type.enums, [""])
+ eq_(t.c.e3.type.enums, ["a"])
+ eq_(t.c.e4.type.enums, [""])
+ eq_(t.c.e5.type.enums, ["a", ""])
+ eq_(t.c.e6.type.enums, ["", "a"])
+ eq_(t.c.e7.type.enums, ["", "'a'", "b'b", "'"])
finally:
enum_table.drop()