(tableName, insertValues, updateValues, where, model)
| 401 | } |
| 402 | |
| 403 | upsertQuery(tableName, insertValues, updateValues, where, model) { |
| 404 | const targetTableAlias = this.quoteTable(`${tableName}_target`); |
| 405 | const sourceTableAlias = this.quoteTable(`${tableName}_source`); |
| 406 | const primaryKeysAttrs = []; |
| 407 | const identityAttrs = []; |
| 408 | const uniqueAttrs = []; |
| 409 | const tableNameQuoted = this.quoteTable(tableName); |
| 410 | |
| 411 | //Obtain primaryKeys, uniquekeys and identity attrs from rawAttributes as model is not passed |
| 412 | for (const key in model.rawAttributes) { |
| 413 | if (model.rawAttributes[key].primaryKey) { |
| 414 | primaryKeysAttrs.push(model.rawAttributes[key].field || key); |
| 415 | } |
| 416 | if (model.rawAttributes[key].unique) { |
| 417 | uniqueAttrs.push(model.rawAttributes[key].field || key); |
| 418 | } |
| 419 | if (model.rawAttributes[key].autoIncrement) { |
| 420 | identityAttrs.push(model.rawAttributes[key].field || key); |
| 421 | } |
| 422 | } |
| 423 | |
| 424 | //Add unique indexes defined by indexes option to uniqueAttrs |
| 425 | for (const index of model._indexes) { |
| 426 | if (index.unique && index.fields) { |
| 427 | for (const field of index.fields) { |
| 428 | const fieldName = typeof field === 'string' ? field : field.name || field.attribute; |
| 429 | if (uniqueAttrs.indexOf(fieldName) === -1 && model.rawAttributes[fieldName]) { |
| 430 | uniqueAttrs.push(fieldName); |
| 431 | } |
| 432 | } |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | const updateKeys = Object.keys(updateValues); |
| 437 | const insertKeys = Object.keys(insertValues); |
| 438 | const insertKeysQuoted = insertKeys.map(key => this.quoteIdentifier(key)).join(', '); |
| 439 | const insertValuesEscaped = insertKeys.map(key => this.escape(insertValues[key])).join(', '); |
| 440 | const sourceTableQuery = `VALUES(${insertValuesEscaped})`; //Virtual Table |
| 441 | let joinCondition; |
| 442 | |
| 443 | //Filter NULL Clauses |
| 444 | const clauses = where[Op.or].filter(clause => { |
| 445 | let valid = true; |
| 446 | /* |
| 447 | * Exclude NULL Composite PK/UK. Partial Composite clauses should also be excluded as it doesn't guarantee a single row |
| 448 | */ |
| 449 | for (const key in clause) { |
| 450 | if (!clause[key]) { |
| 451 | valid = false; |
| 452 | break; |
| 453 | } |
| 454 | } |
| 455 | return valid; |
| 456 | }); |
| 457 | |
| 458 | /* |
| 459 | * Generate ON condition using PK(s). |
| 460 | * If not, generate using UK(s). Else throw error |
no test coverage detected