client side column default value processing for special values e.g. JSON.NULL
Issue #3870
resolved
Is this behavior intentional? If I set the default value of a column to be a JSON null
, which should be represented by a Python None
, I'd expect a new object to have that value after flushing. This is especially an issue when using the value e.g. a a dict key since it obviously differs from an actual None
.
from __future__ import print_function
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Test(Base):
__tablename__ = 'test'
id = Column(Integer, primary_key=True)
data = Column(JSON, nullable=False, default=JSON.NULL)
def __repr__(self):
return '<Test({})>'.format(self.id)
e = create_engine('postgresql:///test')
Base.metadata.create_all(e)
s = Session(e)
t = Test()
s.add(t)
print('data before flush', repr(t.data), type(t.data))
s.flush()
print('data after flush', repr(t.data), type(t.data))
foo = {None: 'bar'}
print(foo[None])
print(foo[t.data])
data before flush None <type 'NoneType'>
data after flush symbol('JSON_NULL') <class 'sqlalchemy.util.langhelpers.symbol'>
bar
Traceback (most recent call last):
File "satest2.py", line 31, in <module>
print(foo[t.data])
KeyError: symbol('JSON_NULL')
Comments (3)
-
repo owner -
repo owner - changed title to client side column default value processing for special values e.g. JSON.NULL
- changed milestone to 1.2
- changed component to sql
-
repo owner - changed status to resolved
I put the wrong issue number; here's the changelog:
4d4ea792e7ea7945de9c9b1e005ce09b2feb45b5 Author: Mike Bayer mike_mp@zzzcomputing.com Date: Thu May 18 17:44:10 2017 -0400
- Document the most transparent way to set JSON.NULL for a column default. The JSON.NULL value is special in that while it is a Python-side value, it represents "do this special behavior", and is not at all like any other Python-side value for which normally, that's exactly the type of data we want back. So in this case, encourage the user to use a SQL expression that is exact, so in the ORM context, you get back what was actually persisted in the column. There's some variants of this such as literal(JSON.NULL, JSON) but text("'null'") is simpler. Change-Id: I0339fafdc03e4b2f533d53970b2f74c774f2687b Fixes: #3870
- Log in to comment
I don't even know what to do with that. You set the default as JSON.NULL, so it's potentially ambiguous what someone would want to see as the "value", None is probably the right answer but I can see it going badly either way. Not really sure. It would imply that type deserializers have to run for some client side default values which implies a total crapshow of new plumbing in Core.
Here's how to make it work right now, please feel free to suggest where this might fit in the documentation (e.g. where you would have found it):