On Fri, Nov 17, 2017 at 9:17 AM, Petar <[email protected]> wrote: > I want to override my `Session` such that it performs and `INSERT ON > CONFLICT` whenever I `add` an object. > > `merge` is too slow for my use-case: it has to perform a `SELECT` first, and > I want to reduce my latency as much as I can. > > > Currently this is the standard behaviour: > > user = User(id=1, name='John') # suppose we already have a record with > id=1 > session.add(user) # this tries to INSERT, which will raise an Integrity > error > session.commit() > > > > I want to be able to do something like this: > > user = User(id=1, name='John', update=True) > session.add(user) # this now does INSERT ON CONFLICT DO UPDATE SET ... > session.commit() > > > and if `update=False` then perform `DO NOTHING` > > > I assume I will need to monkey-patch around the Insert class but I am not > 100% sure. Any idea how to achieve this in an elegant way?
it would not happen within the Session as it exists today. the .add() method doesn't emit an INSERT, it just adds the object to a collection. the INSERT occurs within the flush process. The good news is that INSERT/UPDATEs are actually bundled very close together within the flush process, but actually since this object is given as pending, it would only be the INSERT process that needs to change. so it starts first here: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/persistence.py#L167 then objects like this would go into here: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/persistence.py#L799 . it is possible that an _emit_insert_w_merge() type of function could be produced here. However, a lot of the behavioral contracts of the ORM would either be impossible, or be very difficult to maintain, including the "versioning" feature, the ability to correctly invoke Python-side column defaults (because we don't know if this is an INSERT or UPDATE) as well as the ability to receive the values of server-side defaults (same reason). whether insert_w_merge() is called upon could depend upon various factors. We could have a new session.add_for_merge() method that specifies it at that level (probably best), a flag can be added to the instance_state indicating the pending object is of this style. Also, if this were to become a real feature, it would have to work across the various implementations of "merge" for different databases, e.g. postgresql vs. mysql vs. ?. this would not be particularly easy to implement, especially for someone unfamiliar with the codebase (I have 12 years w/ it :) ). So if you just need this to work you might want to stick with your own external function that just calls upon the Core INSERT ON CONFLICT. > > > -- > SQLAlchemy - > The Python SQL Toolkit and Object Relational Mapper > > http://www.sqlalchemy.org/ > > To post example code, please provide an MCVE: Minimal, Complete, and > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > description. > --- > You received this message because you are subscribed to the Google Groups > "sqlalchemy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
