The PostgreSQL ON CONFLICT
clause in INSERT
statements provides "upsert" functionality (i.e. update an existing record, or insert a new one if no such record exists). This functionality is supported in SQLAlchemy via the on_conflict_do_nothing
and on_conflict_do_update
methods on the PostgreSQL dialect's Insert
object (as described here):
from sqlalchemy.dialects.postgresql import insert
insert_stmt = insert(my_table).values(
id='some_existing_id',
data='inserted value'
)
do_nothing_stmt = insert_stmt.on_conflict_do_nothing(
index_elements=['id']
)
conn.execute(do_nothing_stmt)
do_update_stmt = insert_stmt.on_conflict_do_update(
constraint='pk_my_table',
set_=dict(data='updated value')
)
conn.execute(do_update_stmt)
I am using flask_sqlalchemy
, which manages SQLAlchemy's engine, session, and connections for you. To add an element to the database, I create an instance of my model, add it to the database session, and then call commit, something like this:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
class MyTable(db.Model):
id = db.Column(UUID, primary_key=True)
data = db.Column(db.String)
relation = MyTable(id=1, data='foo')
db.session.add(relation)
db.session.commit()
So the Insert
object is completely wrapped and obscured by flask_sqlalchemy
.
How can I access the PostgreSQL-specific dialect methods to perform an upsert? Do I need to bypass flask_sqlalchemy
and create my own session? If I do this, how can I ensure no conflicts?