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