sequelize/sequelize — pull request #2518 by janmeier (2014-11-03 20:31:27+00:00)
Title: Upsert

Rejoice, people of #485 , for UPSERT is here!

I finally got to take a stab at doing upsert, which I've been wanting to do for a while.

It is implemented as a single query (possibly with multiple statements, depending on dialect), which should hopefully make it less prone to race conditions.

First of all, upsert will only ever happen if the provided values match either a primary or a unique key, otherwise it's just an insert.

Short explanation of implementation for the 3 dialects:
* MySQL - The simplest of them all, just uses `INSERT ... ON DUPLICATE KEY UPDATE`
* SQLite - uses two separate statements in one query, `INSERT IGNORE ; UPDATE`. The update is always exectued.
* Postgres - Uses `WITH upsert AS (update) insert WHERE NOT EXISTS (SELECT * FROM upsert)`

The row is not returned, because I couldn't find a way to do this consistently across dialects. Specifically, mysql does not return the id of the updated row, even when the ON DUPLICATE clause is triggered. Since upserts should always happen on unique keys I don't think this is a big issue, you could just do a find afterwards if you need the id.

The method returns a boolean, indicating whether the row was created or updated. However, in SQLite it returns undefined, since it is not possible to know if the insert was ignored, when using two separate statements.

The tests are a bit sparse, but i really couldn't come up with more cases - please post them here if you have more :). Also, I was thinking of moving some of the update-related tests from dao-factory.test into the dao-factory/update.test file.