Reputation: 323
In SQLalchemy, I use this declared attribute in a mixin:
@declared_attr
def updated_seq(cls): return db.Column(db.BigInteger(), server_default=0)
and I would like to do an onupdate where the sql server (and not python) auto-increments by 1 the value. How can it be done? Tx
I am for instance looking for the following sql equivalent statement during onupdate:
UPDATE updated_seq=updated_seq+1
Upvotes: 1
Views: 1228
Reputation: 4793
Sounds like a job for triggers. First the mixin somewhere:
class Mixin(object):
@declared_attr
def updated_seq(cls):
return Column(BigInteger, server_default='0')
Then on either a startup file or a script, wherever you prefer (I can't think of anything really elegant). Here is one solution in PSQL
# import Mixin
# import sqlalchemy engine
for class_ in Mixin.__subclasses__:
engine.execute('''
CREATE OR REPLACE FUNCTION %{tablename}s_increment() RETURNS TRIGGER AS $$
BEGIN
NEW.updated_seq := OLD.updated_seq + 1 WHERE id = OLD.id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER %{tablename}s_increment_trigger BEFORE UPDATE ON %{tablename}s
FOR EACH ROW EXECUTE PROCEDURE %{tablename}s_increment();
``` % {tablename: class_.__tablename__}
You may need to check my SQL on this, as it's been a while and this is untested. But regardless, it will create triggers in your database that detect and autoincrement that row. The downside is you'll need to manually delete any trigger that loses the updated_seq column
Edit: Looks like OP found a way easier solution than mine. Oops.
Upvotes: 0
Reputation: 323
Actually the correct is simply:
@declared_attr
def updated_seq(cls): return db.Column(db.BigInteger(), server_default=0, onupdate=text('updated_seq + 1'))
Upvotes: 2
Reputation: 4137
You can handle this situation with an event listener that increments updated_seq
.
class Mixin(object):
@declared_attr
def updated_seq(cls):
return Column(BigInteger, server_default='0')
class Person(Base, Mixin):
__tablename__ = 'person'
id = Column(Integer, primary_key=True)
name = Column(Text)
@event.listens_for(Person, 'before_update')
def increment_seq(mapper, connection, target):
target.updated_seq += 1
>>> p = Person(name="foo")
>>> session.add(p)
>>> session.commit()
>>> p = session.query(Person).first()
>>> p.updated_seq
0
>>> p.name = "bar"
>>> session.commit()
>>> p = session.query(Person).first()
>>> p.updated_seq
1
Upvotes: 0