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

Commit 37087559 by Jan Aagaard Meier

Rebase and Merge pull request #1024 from durango/newindex

2 parents 4845800a 8a81de1e
......@@ -115,10 +115,24 @@ module.exports = (function() {
})()
DAOFactory.prototype.init = function(daoFactoryManager) {
var self = this;
var self = this
this.daoFactoryManager = daoFactoryManager
this.primaryKeys = {};
this.primaryKeys = {}
self.options.uniqueKeys = {}
Utils._.each(this.rawAttributes, function(columnValues, columnName) {
if (columnValues.hasOwnProperty('unique') && columnValues.unique !== true) {
var idxName = columnValues.unique
if (typeof columnValues.unique === "object") {
idxName = columnValues.unique.name
}
self.options.uniqueKeys[idxName] = self.options.uniqueKeys[idxName] || {fields: [], msg: null}
self.options.uniqueKeys[idxName].fields.push(columnName)
self.options.uniqueKeys[idxName].msg = self.options.uniqueKeys[idxName].msg || columnValues.unique.msg || null
}
})
Utils._.each(this.attributes, function(dataTypeString, attributeName) {
if (dataTypeString.indexOf('PRIMARY KEY') !== -1) {
......
......@@ -396,7 +396,23 @@ module.exports = (function() {
args[2] = values
self.QueryInterface[query].apply(self.QueryInterface, args)
.proxy(emitter, {events: ['sql', 'error']})
.proxy(emitter, {events: ['sql']})
.error(function(err) {
if (!!self.__options.uniqueKeys && err.code && self.QueryInterface.QueryGenerator.uniqueConstraintMapping.code === err.code) {
var fields = self.QueryInterface.QueryGenerator.uniqueConstraintMapping.map(err.toString())
if (fields !== false) {
fields = fields.filter(function(f) { return f !== self.daoFactory.tableName; })
Utils._.each(self.__options.uniqueKeys, function(value, key) {
if (Utils._.isEqual(value.fields, fields) && !!value.msg) {
err = value.msg
}
})
}
}
emitter.emit('error', err)
})
.success(function(result) {
// Transfer database generated values (defaults, autoincrement, etc)
values = _.extend(values, result.dataValues)
......
......@@ -2,7 +2,19 @@ var Utils = require("../../utils")
module.exports = (function() {
var QueryGenerator = {
dialect: 'mariadb'
dialect: 'mariadb',
uniqueConstraintMapping: {
code: 1062,
map: function(str) {
// we're manually remvoving uniq_ here for a future capability of defining column names explicitly
var match = str.replace('uniq_', '').match(/Duplicate entry .* for key '(.*?)'$/)
if (match === null || match.length < 2) {
return false
}
return match[1].split('_')
}
},
}
// "MariaDB is a drop-in replacement for MySQL." - so thats exactly what we do, drop in the mysql query generator
......
......@@ -76,6 +76,12 @@ module.exports = (function() {
}
, pkString = primaryKeys.map(function(pk) { return this.quoteIdentifier(pk) }.bind(this)).join(", ")
if (!!options.uniqueKeys) {
Utils._.each(options.uniqueKeys, function(columns) {
values.attributes += ", UNIQUE uniq_" + tableName + '_' + columns.fields.join('_') + " (" + columns.fields.join(', ') + ")"
})
}
if (pkString.length > 0) {
values.attributes += ", PRIMARY KEY (" + pkString + ")"
}
......@@ -103,6 +109,19 @@ module.exports = (function() {
return 'SHOW TABLES;'
},
uniqueConstraintMapping: {
code: 'ER_DUP_ENTRY',
map: function(str) {
// we're manually remvoving uniq_ here for a future capability of defining column names explicitly
var match = str.replace('uniq_', '').match(/Duplicate entry .* for key '(.*?)'$/)
if (match === null || match.length < 2) {
return false
}
return match[1].split('_')
}
},
addColumnQuery: function(tableName, attributes) {
var query = "ALTER TABLE `<%= tableName %>` ADD <%= attributes %>;"
, attrString = []
......@@ -317,7 +336,7 @@ module.exports = (function() {
template += " DEFAULT " + this.escape(dataType.defaultValue)
}
if (dataType.unique) {
if (dataType.unique === true) {
template += " UNIQUE"
}
......
......@@ -44,6 +44,8 @@ module.exports = (function() {
},
createTableQuery: function(tableName, attributes, options) {
var self = this
options = Utils._.extend({
}, options || {})
......@@ -76,6 +78,12 @@ module.exports = (function() {
comments: Utils._.template(comments, { table: this.quoteIdentifiers(tableName)})
}
if (!!options.uniqueKeys) {
Utils._.each(options.uniqueKeys, function(columns) {
values.attributes += ", UNIQUE (" + columns.fields.map(function(f) { return self.quoteIdentifiers(f) }).join(', ') + ")"
})
}
var pks = primaryKeys[tableName].map(function(pk){
return this.quoteIdentifier(pk)
}.bind(this)).join(",")
......@@ -114,6 +122,18 @@ module.exports = (function() {
})
},
uniqueConstraintMapping: {
code: '23505',
map: function(str) {
var match = str.match(/duplicate key value violates unique constraint "(.*?)_key"/)
if (match === null || match.length < 2) {
return false
}
return match[1].split('_').splice(1)
}
},
addColumnQuery: function(tableName, attributes) {
var query = "ALTER TABLE <%= tableName %> ADD COLUMN <%= attributes %>;"
, attrString = []
......@@ -448,7 +468,7 @@ module.exports = (function() {
replacements.defaultValue = this.escape(dataType.defaultValue)
}
if (dataType.unique) {
if (dataType.unique === true) {
template += " UNIQUE"
}
......
......@@ -109,6 +109,12 @@ module.exports = (function() {
}
, pkString = primaryKeys.map(function(pk) { return this.quoteIdentifier(pk) }.bind(this)).join(", ")
if (!!options.uniqueKeys) {
Utils._.each(options.uniqueKeys, function(columns) {
values.attributes += ", UNIQUE (" + columns.fields.join(', ') + ")"
})
}
if (pkString.length > 0) {
values.attributes += ", PRIMARY KEY (" + pkString + ")"
}
......@@ -131,6 +137,18 @@ module.exports = (function() {
})
},
uniqueConstraintMapping: {
code: 'SQLITE_CONSTRAINT',
map: function(str) {
var match = str.match(/columns (.*?) are/)
if (match === null || match.length < 2) {
return false
}
return match[1].split(', ')
}
},
addLimitAndOffset: function(options, query){
query = query || ""
if (options.offset && !options.limit) {
......@@ -184,6 +202,26 @@ module.exports = (function() {
return Utils._.template(query)(replacements)
},
updateQuery: function(tableName, attrValueHash, where, options) {
attrValueHash = Utils.removeNullValuesFromHash(attrValueHash, this.options.omitNull, options)
var query = "UPDATE <%= table %> SET <%= values %> WHERE <%= where %>"
, values = []
for (var key in attrValueHash) {
var value = attrValueHash[key]
values.push(this.quoteIdentifier(key) + "=" + this.escape(value))
}
var replacements = {
table: this.quoteIdentifier(tableName),
values: values.join(","),
where: this.getWhereConditions(where)
}
return Utils._.template(query)(replacements)
},
deleteQuery: function(tableName, where, options) {
options = options || {}
......@@ -226,7 +264,7 @@ module.exports = (function() {
replacements.defaultValue = this.escape(dataType.defaultValue)
}
if (dataType.unique) {
if (dataType.unique === true) {
template += " UNIQUE"
}
......
......@@ -246,6 +246,39 @@ describe(Support.getTestDialectTeaser("DAOFactory"), function () {
})
})
})
it('allows multiple column unique keys to be defined', function(done) {
var User = this.sequelize.define('UserWithUniqueUsername', {
username: { type: Sequelize.STRING, unique: 'user_and_email' },
email: { type: Sequelize.STRING, unique: 'user_and_email' },
aCol: { type: Sequelize.STRING, unique: 'a_and_b' },
bCol: { type: Sequelize.STRING, unique: 'a_and_b' }
})
User.sync({ force: true }).on('sql', function(sql) {
expect(sql).to.match(/UNIQUE\s*(uniq_UserWithUniqueUsernames_username_email)?\s*\([`"]?username[`"]?, [`"]?email[`"]?\)/)
expect(sql).to.match(/UNIQUE\s*(uniq_UserWithUniqueUsernames_aCol_bCol)?\s*\([`"]?aCol[`"]?, [`"]?bCol[`"]?\)/)
done()
})
})
it('allows us to customize the error message for unique constraint', function(done) {
var User = this.sequelize.define('UserWithUniqueUsername', {
username: { type: Sequelize.STRING, unique: { name: 'user_and_email', msg: 'User and email must be unique' }},
email: { type: Sequelize.STRING, unique: 'user_and_email' },
aCol: { type: Sequelize.STRING, unique: 'a_and_b' },
bCol: { type: Sequelize.STRING, unique: 'a_and_b' }
})
User.sync({ force: true }).success(function() {
User.create({username: 'tobi', email: 'tobi@tobi.me'}).success(function() {
User.create({username: 'tobi', email: 'tobi@tobi.me'}).error(function(err) {
expect(err).to.equal('User and email must be unique')
done()
})
})
})
})
})
describe('build', function() {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!