* Upsert * * @param {string} tableName table to upsert on * @param {object} insertValues values to be inserted, mapped to field name * @param {object} updateValues values to be updated, mapped to field name * @param {object} where where conditions, which can be used for UPDA
(tableName, insertValues, updateValues, where, options)
| 787 | * @returns {Promise<boolean,?number>} Resolves an array with <created, primaryKey> |
| 788 | */ |
| 789 | async upsert(tableName, insertValues, updateValues, where, options) { |
| 790 | options = { ...options }; |
| 791 | |
| 792 | const model = options.model; |
| 793 | |
| 794 | options.type = QueryTypes.UPSERT; |
| 795 | options.updateOnDuplicate = Object.keys(updateValues); |
| 796 | options.upsertKeys = options.conflictFields || []; |
| 797 | |
| 798 | if (options.upsertKeys.length === 0) { |
| 799 | const primaryKeys = Object.values(model.primaryKeys).map(item => item.field); |
| 800 | const uniqueKeys = Object.values(model.uniqueKeys).filter(c => c.fields.length > 0).map(c => c.fields); |
| 801 | const indexKeys = Object.values(model._indexes).filter(c => c.unique && c.fields.length > 0).map(c => c.fields); |
| 802 | // For fields in updateValues, try to find a constraint or unique index |
| 803 | // that includes given field. Only first matching upsert key is used. |
| 804 | for (const field of options.updateOnDuplicate) { |
| 805 | const uniqueKey = uniqueKeys.find(fields => fields.includes(field)); |
| 806 | if (uniqueKey) { |
| 807 | options.upsertKeys = uniqueKey; |
| 808 | break; |
| 809 | } |
| 810 | |
| 811 | const indexKey = indexKeys.find(fields => fields.includes(field)); |
| 812 | if (indexKey) { |
| 813 | options.upsertKeys = indexKey; |
| 814 | break; |
| 815 | } |
| 816 | } |
| 817 | |
| 818 | // Always use PK, if no constraint available OR update data contains PK |
| 819 | if ( |
| 820 | options.upsertKeys.length === 0 |
| 821 | || _.intersection(options.updateOnDuplicate, primaryKeys).length |
| 822 | ) { |
| 823 | options.upsertKeys = primaryKeys; |
| 824 | } |
| 825 | |
| 826 | options.upsertKeys = _.uniq(options.upsertKeys); |
| 827 | } |
| 828 | |
| 829 | const sql = this.queryGenerator.insertQuery(tableName, insertValues, model.rawAttributes, options); |
| 830 | return await this.sequelize.query(sql, options); |
| 831 | } |
| 832 | |
| 833 | /** |
| 834 | * Insert multiple records into a table |
nothing calls this directly
no test coverage detected