* Insert or update a single row. An update will be executed if a row which matches the supplied values on either the primary key or a unique key is found. Note that the unique index must be defined in your sequelize model and not just in the table. Otherwise you may experience a unique constraint vi
(values, options)
| 2539 | * @returns {Promise<Array<Model, boolean | null>>} returns an array with two elements, the first being the new record and the second being `true` if it was just created or `false` if it already existed (except on Postgres and SQLite, which can't detect this and will always return `null` instead of a boolean). |
| 2540 | */ |
| 2541 | static async upsert(values, options) { |
| 2542 | options = { |
| 2543 | hooks: true, |
| 2544 | returning: true, |
| 2545 | validate: true, |
| 2546 | ...Utils.cloneDeep(options) |
| 2547 | }; |
| 2548 | |
| 2549 | // Add CLS transaction |
| 2550 | if (options.transaction === undefined && this.sequelize.constructor._cls) { |
| 2551 | const t = this.sequelize.constructor._cls.get('transaction'); |
| 2552 | if (t) { |
| 2553 | options.transaction = t; |
| 2554 | } |
| 2555 | } |
| 2556 | |
| 2557 | const createdAtAttr = this._timestampAttributes.createdAt; |
| 2558 | const updatedAtAttr = this._timestampAttributes.updatedAt; |
| 2559 | const hasPrimary = this.primaryKeyField in values || this.primaryKeyAttribute in values; |
| 2560 | const instance = this.build(values); |
| 2561 | |
| 2562 | options.model = this; |
| 2563 | options.instance = instance; |
| 2564 | |
| 2565 | const changed = Array.from(instance._changed); |
| 2566 | if (!options.fields) { |
| 2567 | options.fields = changed; |
| 2568 | } |
| 2569 | |
| 2570 | if (options.validate) { |
| 2571 | await instance.validate(options); |
| 2572 | } |
| 2573 | // Map field names |
| 2574 | const updatedDataValues = _.pick(instance.dataValues, changed); |
| 2575 | const insertValues = Utils.mapValueFieldNames(instance.dataValues, Object.keys(instance.rawAttributes), this); |
| 2576 | const updateValues = Utils.mapValueFieldNames(updatedDataValues, options.fields, this); |
| 2577 | const now = Utils.now(this.sequelize.options.dialect); |
| 2578 | |
| 2579 | // Attach createdAt |
| 2580 | if (createdAtAttr && !insertValues[createdAtAttr]) { |
| 2581 | const field = this.rawAttributes[createdAtAttr].field || createdAtAttr; |
| 2582 | insertValues[field] = this._getDefaultTimestamp(createdAtAttr) || now; |
| 2583 | } |
| 2584 | if (updatedAtAttr && !insertValues[updatedAtAttr]) { |
| 2585 | const field = this.rawAttributes[updatedAtAttr].field || updatedAtAttr; |
| 2586 | insertValues[field] = updateValues[field] = this._getDefaultTimestamp(updatedAtAttr) || now; |
| 2587 | } |
| 2588 | |
| 2589 | // Db2 does not allow NULL values for unique columns. |
| 2590 | // Add dummy values if not provided by test case or user. |
| 2591 | if (this.sequelize.options.dialect === 'db2') { |
| 2592 | this.uniqno = this.sequelize.dialect.queryGenerator.addUniqueFields( |
| 2593 | insertValues, this.rawAttributes, this.uniqno); |
| 2594 | } |
| 2595 | |
| 2596 | // Build adds a null value for the primary key, if none was given by the user. |
| 2597 | // We need to remove that because of some Postgres technicalities. |
| 2598 | if (!hasPrimary && this.primaryKeyAttribute && !this.rawAttributes[this.primaryKeyAttribute].defaultValue) { |