Let's start by defining my mapped class
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.types import JSON
from sqlalchemy.ext.mutable import MutableDict
from sqlalchemy import Column, Integer
base = declarative_base()
class MinimalExample(Base):
__tablename__ = 'users'
id = Column(Integer)
data = Column(MutableDict.as_mutable(JSON))
Let's say I have in my table a row with id=1
and data={'key_0': 1}
I can request it through a session
object quite easily
first_row = session.query(MinimalExample)\
.filter(MinimalExample.id==1)\
.first()
And from there I can modify the JSON field any way I want and update the database:
first_row.data['key_2'] = 1
session.commit()
The code above works (because we marked the JSON field as a mutable dict we don't have to mark it as dirty by hand)
session.query(MinimalExample.data)\
.filter(MinimalExample.id==1)\
.first()
>>> {'key_0': 1, 'key_2': 1}
However it means that I have to query all the rows I want to modify on my local computer, which is just too slow/I have not enough memory.
I am looking for a way to use the sqlalchemy.update
function to get the same result
Here is what I have already tried:
from sqlalchemy import update
stmt = update(MinimalExample)
.where(MinimalExample.id=1)\
.values(MinimalExample.data={'key_1': 1})
session.execute(stmt)
session.commit()
which is just going to replace the data
field in my row by the dictionary {'key_1': 1}
Something similar to this seems like the way to go:
(EDIT: found a way to correct my previous code so it does not raise an error anymore, simply by putting the object into a dictionary)
stmt = update(MinimalExample)
.where(MinimalExample.id=1)\
.values({MinimalExample.data['key_1']:1})
looking at the string of this statement seems quite good
str(stmt)
>>> 'UPDATE users SET data[:data_1]=:param_1 WHERE users.id = :id_1'
However executing this statement lead to a ProgrammingError: (MySQLdb._exceptions.ProgrammingError) (1064, 'You have an error in your SQL syntax
...
Any thought on that ? Bonus points if I can update several rows at the same time