.. changelog::
:version: 1.1.4
+ .. change::
+ :tags: bug, mysql
+ :tickets: 3841
+
+ MySQL's native ENUM type supports any non-valid value being sent, and
+ in response will return a blank string. A hardcoded rule to check for
+ "is returning the blank string" has been added to the MySQL
+ implementation for ENUM so that this blank string is returned to the
+ application rather than being rejected as a non-valid value. Note that
+ if your MySQL enum is linking values to objects, you still get the
+ blank string back.
+
.. changelog::
:version: 1.1.3
:released: October 27, 2016
values, length = self._init_values(values, kw)
return sqltypes.Enum._setup_for_values(self, values, objects, kw)
+ def _object_value_for_elem(self, elem):
+ # mysql sends back a blank string for any value that
+ # was persisted that was not in the enums; that is, it does no
+ # validation on the incoming data, it "truncates" it to be
+ # the blank string. Return it straight.
+ if elem == "":
+ return elem
+ else:
+ return super(ENUM, self)._object_value_for_elem(elem)
+
def __repr__(self):
return util.generic_repr(
self, to_inspect=[ENUM, _StringType, sqltypes.Enum])
eq_(t.c.e6.type.values, ("", "a"))
eq_(t.c.e7.type.values, ("", "'a'", "b'b", "'"))
+ @testing.provide_metadata
+ def test_broken_enum_returns_blanks(self):
+ t = Table(
+ 'enum_missing',
+ self.metadata,
+ Column('id', Integer, primary_key=True),
+ Column('e1', sqltypes.Enum('one', 'two', 'three')),
+ Column('e2', mysql.ENUM('one', 'two', 'three'))
+ )
+ t.create()
+
+ with testing.db.connect() as conn:
+ conn.execute(t.insert(), {"e1": "nonexistent", "e2": "nonexistent"})
+ conn.execute(t.insert(), {"e1": "", "e2": ""})
+ conn.execute(t.insert(), {"e1": "two", "e2": "two"})
+ conn.execute(t.insert(), {"e1": None, "e2": None})
+
+ eq_(
+ conn.execute(
+ select([t.c.e1, t.c.e2]).order_by(t.c.id)
+ ).fetchall(),
+ [("", ""), ("", ""), ("two", "two"), (None, None)]
+ )
+
def colspec(c):
return testing.db.dialect.ddl_compiler(