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

Commit 7625843d by Sascha Depold

Merge branch 'master' of github.com:sequelize/sequelize

2 parents 5895f964 582b9aff
......@@ -432,16 +432,19 @@ module.exports = (function() {
* Delete multiple instances
*
* @param {Object} where Options to describe the scope of the search.
* @param {Object} options Possible options are:
- limit: How many rows to delete
- truncate: If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is truncated the where and limit options are ignored
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
*/
DAOFactory.prototype.destroy = function(where) {
DAOFactory.prototype.destroy = function(where, options) {
if (this.options.timestamps && this.options.paranoid) {
var attr = this.options.underscored ? 'deleted_at' : 'deletedAt'
var attrValueHash = {}
attrValueHash[attr] = Utils.now()
return this.QueryInterface.bulkUpdate(this.tableName, attrValueHash, where)
} else {
return this.QueryInterface.bulkDelete(this.tableName, where)
return this.QueryInterface.bulkDelete(this.tableName, where, options)
}
}
......
......@@ -291,6 +291,11 @@ module.exports = (function() {
options = options || {}
var table = QueryGenerator.addQuotes(tableName)
if (options.truncate === true) {
// Truncate does not allow LIMIT and WHERE
return "TRUNCATE " + table
}
where = QueryGenerator.getWhereConditions(where)
var limit = ""
......@@ -302,9 +307,7 @@ module.exports = (function() {
limit = " LIMIT " + Utils.escape(options.limit)
}
var query = "DELETE FROM " + table + " WHERE " + where + limit
return query
return "DELETE FROM " + table + " WHERE " + where + limit
},
bulkDeleteQuery: function(tableName, where, options) {
......
......@@ -98,7 +98,7 @@ module.exports = (function() {
},
describeTableQuery: function(tableName) {
var query = 'SELECT column_name as "Field", column_default as "Default", is_nullable as "Null", data_type as "Type" FROM information_schema.columns WHERE table_name = <%= table %>;'
var query = 'SELECT c.column_name as "Field", c.column_default as "Default", c.is_nullable as "Null", c.data_type as "Type", (SELECT array_agg(e.enumlabel) FROM pg_catalog.pg_type t JOIN pg_catalog.pg_enum e ON t.oid=e.enumtypid WHERE t.typname=c.udt_name) AS special FROM information_schema.columns c WHERE table_name = <%= table %>;'
return Utils._.template(query)({
table: QueryGenerator.addQuotes(tableName, "'")
})
......@@ -363,6 +363,10 @@ module.exports = (function() {
deleteQuery: function(tableName, where, options) {
options = options || {}
if (options.truncate === true) {
return "TRUNCATE " + QueryGenerator.addQuotes(tableName)
}
if(Utils._.isUndefined(options.limit)) {
options.limit = 1;
}
......@@ -686,6 +690,21 @@ module.exports = (function() {
return "DROP TYPE IF EXISTS " + enumName + "; CREATE TYPE " + enumName + " AS " + dataType.match(/^ENUM\(.+\)/)[0] + "; "
},
fromArray: function(text) {
text = text.replace(/^{/, '').replace(/}$/, '')
var matches = text.match(/("(?:\\.|[^"\\\\])*"|[^,]*)(?:\s*,\s*|\s*$)/ig)
if (matches.length < 1) {
return []
}
matches = matches.map(function(m){
return m.replace(/",$/, '').replace(/,$/, '').replace(/(^"|"$)/, '')
})
return matches.slice(0, -1)
},
toHstore: function(text) {
var obj = {}
, pattern = '("\\\\.|[^"\\\\]*"\s*=|[^=]*)\s*=\s*>\s*("(?:\\.|[^"\\\\])*"|[^,]*)(?:\s*,\s*|$)'
......
......@@ -56,6 +56,7 @@ module.exports = (function() {
var onSuccess = function(rows) {
var results = []
, self = this
, isTableNameQuery = (this.sql.indexOf('SELECT table_name FROM information_schema.tables') === 0)
, isRelNameQuery = (this.sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0)
......@@ -74,14 +75,15 @@ module.exports = (function() {
}
if (this.send('isSelectQuery')) {
if (this.sql.toLowerCase().indexOf('select column_name') === 0) {
if (this.sql.toLowerCase().indexOf('select c.column_name') === 0) {
var result = {}
rows.forEach(function(_result) {
result[_result.Field] = {
type: _result.Type.toUpperCase(),
allowNull: (_result.Null === 'YES'),
defaultValue: _result.Default
defaultValue: _result.Default,
special: (!!_result.special ? self.sequelize.queryInterface.QueryGenerator.fromArray(_result.special) : [])
}
if (result[_result.Field].type === 'BOOLEAN') {
......@@ -96,7 +98,10 @@ module.exports = (function() {
result[_result.Field].defaultValue = result[_result.Field].defaultValue.replace(/'/g, "")
if (result[_result.Field].defaultValue.indexOf('::') > -1) {
result[_result.Field].defaultValue = result[_result.Field].defaultValue.split('::')[0]
var split = result[_result.Field].defaultValue.split('::');
if (split[1].toLowerCase() !== "regclass)") {
result[_result.Field].defaultValue = split[0]
}
}
}
})
......
......@@ -150,6 +150,11 @@ module.exports = (function() {
If you use a string, you have to escape it on your own.
Options:
- limit -> Maximaum count of lines to delete
- truncate -> boolean - whether to use an 'optimized' mechanism (i.e. TRUNCATE) if available,
note that this should not be the default behaviour because TRUNCATE does not
always play nicely (e.g. InnoDB tables with FK constraints)
(@see http://dev.mysql.com/doc/refman/5.6/en/truncate-table.html).
Note that truncate must ignore limit and where
*/
deleteQuery: function(tableName, where, options) {
throwMethodUndefined('deleteQuery')
......
......@@ -280,8 +280,8 @@ module.exports = (function() {
return queryAndEmit.call(this, [sql, dao], 'delete')
}
QueryInterface.prototype.bulkDelete = function(tableName, identifier) {
var sql = this.QueryGenerator.deleteQuery(tableName, identifier, {limit: null})
QueryInterface.prototype.bulkDelete = function(tableName, identifier, options) {
var sql = this.QueryGenerator.deleteQuery(tableName, identifier, Utils._.defaults(options || {}, {limit: null}))
return queryAndEmit.call(this, sql, 'bulkDelete')
}
......
......@@ -300,6 +300,12 @@ describe('QueryGenerator', function() {
}, {
arguments: ['myTable', 1],
expectation: "DELETE FROM `myTable` WHERE `id`=1 LIMIT 1"
},{
arguments: ['myTable', undefined, {truncate: true}],
expectation: "TRUNCATE `myTable`"
},{
arguments: ['myTable', 1, {limit: 10, truncate: true}],
expectation: "TRUNCATE `myTable`"
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `id`=1 LIMIT 10"
......
......@@ -293,6 +293,12 @@ describe('QueryGenerator', function() {
arguments: ['myTable', 1],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"id\"=1 LIMIT 1)"
}, {
arguments: ['myTable', undefined, {truncate: true}],
expectation: "TRUNCATE \"myTable\""
}, {
arguments: ['myTable', 1, {limit: 10, truncate: true}],
expectation: "TRUNCATE \"myTable\""
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM \"myTable\" WHERE \"id\" IN (SELECT \"id\" FROM \"myTable\" WHERE \"id\"=1 LIMIT 10)"
}, {
......
......@@ -199,6 +199,9 @@ describe('QueryGenerator', function() {
arguments: ['myTable', 1],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', 1, {truncate: true}],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
arguments: ['myTable', 1, {limit: 10}],
expectation: "DELETE FROM `myTable` WHERE `id`=1"
}, {
......
......@@ -93,7 +93,8 @@ describe(Helpers.getTestDialectTeaser("QueryInterface"), function() {
before(function(done) {
this.interface.createTable('User', {
username: Helpers.Sequelize.STRING,
isAdmin: Helpers.Sequelize.BOOLEAN
isAdmin: Helpers.Sequelize.BOOLEAN,
enumVals: Helpers.Sequelize.ENUM('hello', 'world')
}).success(done)
})
......@@ -103,6 +104,7 @@ describe(Helpers.getTestDialectTeaser("QueryInterface"), function() {
var username = metadata.username
var isAdmin = metadata.isAdmin
var enumVals = metadata.enumVals
expect(username.type).toEqual(dialect === 'postgres' ? 'CHARACTER VARYING' : 'VARCHAR(255)')
expect(username.allowNull).toBeTrue()
......@@ -112,6 +114,11 @@ describe(Helpers.getTestDialectTeaser("QueryInterface"), function() {
expect(isAdmin.allowNull).toBeTrue()
expect(isAdmin.defaultValue).toBeNull()
if (dialect === 'postgres') {
expect(enumVals.special).toBeArray();
expect(enumVals.special.length).toEqual(2);
}
done()
})
})
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!