[Sqlalchemy-tickets] Issue #3427: SQLAlchemy 1.0 behavior difference regarding column default handl
Brought to you by:
zzzeek
|
From: Raphaël S. <iss...@bi...> - 2015-05-21 13:26:34
|
New issue 3427: SQLAlchemy 1.0 behavior difference regarding column default handling https://bitbucket.org/zzzeek/sqlalchemy/issue/3427/sqlalchemy-10-behavior-difference Raphaël Slinckx: Here is a test case yielding different results between sqlalchemy 0.9.9 and 1.0+ ```python import json from sqlalchemy import create_engine, Column from sqlalchemy.types import TypeDecorator, UnicodeText, Integer from sqlalchemy.ext.mutable import MutableDict from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import Session class JSONDictType(TypeDecorator): impl = UnicodeText def process_bind_param(self, value, dialect): if value is not None: value = unicode(json.dumps(value)) return value def process_result_value(self, value, dialect): if value is not None: value = json.loads(value) return value def JSON(): return MutableDict.as_mutable(JSONDictType) Base = declarative_base() class MyDataClass(Base): __tablename__ = 'my_data' id = Column(Integer, primary_key=True) data = Column(JSON(), default={}, nullable=False) session = Session(create_engine("sqlite:///:memory:", echo=True)) Base.metadata.create_all(session.bind) m1 = MyDataClass() session.add(m1) session.flush() # Note: without this, the m1.data is None on sqlalchemy 1.0 m1.data["test"] = 1 session.commit() m2 = MyDataClass() session.add(m2) session.commit() assert m1.data == {'test': 1} assert m2.data == {} # With sqlalchemy 1.0 this results in # m1.data == {} # m2.data == {'test': 1} ``` As you can see the default={} seemed to work previously (also the m1.data['test'] = 1 worked without the session.flush() just above) With the latest version, the dict provided as default seems to be used and re-used resulting in a process-wide globally shared default dict which can lead to catastrophic leaks in a webapp for example. Also the object needs to be flushed before m1.data is populated. Maybe this usage was not expected or even discouraged, but I didn't find anything in the docs about this. The closest thing I identified is the change discussed here: http://docs.sqlalchemy.org/en/latest/changelog/migration_10.html#changes-to-attribute-events-and-other-operations-regarding-attributes-that-have-no-pre-existing-value and possibly the new default handling. What is the expected behavior as of 1.0 ? And how do I get the old behavior using the latest version ? Responsible: zzzeek |