不要怂,就是干,撸起袖子干!

Commit f8cf8dcd by Jan Aagaard Meier

Merge pull request #2692 from jcombes/master

Support of ON DUPLICATE KEY for 'bulkCreate' method (only supported by mysql & mariadb)
2 parents 9e9cfb04 686ff708
...@@ -179,9 +179,10 @@ module.exports = (function() { ...@@ -179,9 +179,10 @@ module.exports = (function() {
}, },
bulkInsertQuery: function(tableName, attrValueHashes, options) { bulkInsertQuery: function(tableName, attrValueHashes, options) {
var query = 'INSERT<%= ignoreDuplicates %> INTO <%= table %> (<%= attributes %>) VALUES <%= tuples %>;' var query = 'INSERT<%= ignoreDuplicates %> INTO <%= table %> (<%= attributes %>) VALUES <%= tuples %><%= onDuplicateKeyUpdate %>;'
, tuples = [] , tuples = []
, allAttributes = []; , allAttributes = []
, onDuplicateKeyUpdate = '';
Utils._.forEach(attrValueHashes, function(attrValueHash, i) { Utils._.forEach(attrValueHashes, function(attrValueHash, i) {
Utils._.forOwn(attrValueHash, function(value, key, hash) { Utils._.forOwn(attrValueHash, function(value, key, hash) {
...@@ -197,13 +198,21 @@ module.exports = (function() { ...@@ -197,13 +198,21 @@ module.exports = (function() {
')'); ')');
}.bind(this)); }.bind(this));
if (options && options.updateOnDuplicate) {
onDuplicateKeyUpdate += ' ON DUPLICATE KEY UPDATE ' + options.updateOnDuplicate.map(function(attr) {
var key = this.quoteIdentifier(attr);
return key + '=VALUES(' + key + ')';
}.bind(this)).join(',');
}
var replacements = { var replacements = {
ignoreDuplicates: options && options.ignoreDuplicates ? ' IGNORE' : '', ignoreDuplicates: options && options.ignoreDuplicates ? ' IGNORE' : '',
table: this.quoteTable(tableName), table: this.quoteTable(tableName),
attributes: allAttributes.map(function(attr) { attributes: allAttributes.map(function(attr) {
return this.quoteIdentifier(attr); return this.quoteIdentifier(attr);
}.bind(this)).join(','), }.bind(this)).join(','),
tuples: tuples tuples: tuples,
onDuplicateKeyUpdate: onDuplicateKeyUpdate
}; };
return Utils._.template(query)(replacements); return Utils._.template(query)(replacements);
......
...@@ -1232,6 +1232,7 @@ module.exports = (function() { ...@@ -1232,6 +1232,7 @@ module.exports = (function() {
* @param {Boolean} [options.hooks=true] Run before / after bulk create hooks? * @param {Boolean} [options.hooks=true] Run before / after bulk create hooks?
* @param {Boolean} [options.individualHooks=false] Run before / after create hooks for each individual Instance? BulkCreate hooks will still be run if options.hooks is true. * @param {Boolean} [options.individualHooks=false] Run before / after create hooks for each individual Instance? BulkCreate hooks will still be run if options.hooks is true.
* @param {Boolean} [options.ignoreDuplicates=false] Ignore duplicate values for primary keys? (not supported by postgres) * @param {Boolean} [options.ignoreDuplicates=false] Ignore duplicate values for primary keys? (not supported by postgres)
* @param {Array} [options.updateOnDuplicate] Fields to update if row key already exists (on duplicate key update)? (only supported by mysql & mariadb). By default, all fields are updated.
* *
* @return {Promise<Array<Instance>>} * @return {Promise<Array<Instance>>}
*/ */
...@@ -1257,9 +1258,22 @@ module.exports = (function() { ...@@ -1257,9 +1258,22 @@ module.exports = (function() {
options = Utils._.extend(options, fieldsOrOptions); options = Utils._.extend(options, fieldsOrOptions);
} }
if (this.sequelize.options.dialect === 'postgres' && options.ignoreDuplicates) { var dialect = this.sequelize.options.dialect;
if (options.ignoreDuplicates && dialect === 'postgres') {
return Promise.reject(new Error('Postgres does not support the \'ignoreDuplicates\' option.')); return Promise.reject(new Error('Postgres does not support the \'ignoreDuplicates\' option.'));
} }
if (options.updateOnDuplicate && ['mysql', 'mariadb'].indexOf(dialect) === -1) {
return Promise.reject(new Error(dialect + ' does not support the \'updateOnDuplicate\' option.'));
}
if (options.updateOnDuplicate) {
// By default, all attributes except 'createdAt' can be updated
var updatableFields = Utils._.pull(Object.keys(this.tableAttributes), 'createdAt');
if (Utils._.isArray(options.updateOnDuplicate) && !Utils._.isEmpty(options.updateOnDuplicate)) {
updatableFields = Utils._.intersection(updatableFields, options.updateOnDuplicate);
}
options.updateOnDuplicate = updatableFields;
}
var self = this var self = this
, createdAtAttr = this._timestampAttributes.createdAt , createdAtAttr = this._timestampAttributes.createdAt
......
...@@ -424,6 +424,9 @@ if (Support.dialectIsMySQL()) { ...@@ -424,6 +424,9 @@ if (Support.dialectIsMySQL()) {
}, { }, {
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}], {ignoreDuplicates: true}], arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}], {ignoreDuplicates: true}],
expectation: "INSERT IGNORE INTO `myTable` (`name`) VALUES ('foo'),('bar');" expectation: "INSERT IGNORE INTO `myTable` (`name`) VALUES ('foo'),('bar');"
}, {
arguments: ['myTable', [{name: 'foo'}, {name: 'bar'}], {updateOnDuplicate: ['name']}],
expectation: "INSERT INTO `myTable` (`name`) VALUES ('foo'),('bar') ON DUPLICATE KEY UPDATE `name`=VALUES(`name`);"
} }
], ],
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!