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

Commit c8d49662 by Sascha Depold

removeColum is working for sqlite + describeTable was unified

1 parent c541ddc9
...@@ -72,12 +72,13 @@ module.exports = (function() { ...@@ -72,12 +72,13 @@ module.exports = (function() {
result = data result = data
if (this.sql.toLowerCase().indexOf('describe') === 0) { if (this.sql.toLowerCase().indexOf('describe') === 0) {
result = result.map(function(result) { result = {}
return {
attribute: result.Field, data.forEach(function(_result) {
type: result.Type.toUpperCase(), result[_result.Field] = {
allowNull: (result.Null === 'YES'), type: _result.Type.toUpperCase(),
defaultValue: result.Default allowNull: (_result.Null === 'YES'),
defaultValue: _result.Default
} }
}) })
} else if (this.sql.toLowerCase().indexOf('show index from') === 0) { } else if (this.sql.toLowerCase().indexOf('show index from') === 0) {
......
...@@ -74,16 +74,25 @@ module.exports = (function() { ...@@ -74,16 +74,25 @@ module.exports = (function() {
if (this.send('isSelectQuery')) { if (this.send('isSelectQuery')) {
if (this.sql.toLowerCase().indexOf('select column_name') === 0) { if (this.sql.toLowerCase().indexOf('select column_name') === 0) {
rows = rows.map(function(result) { var result = {}
return {
attribute: result.Field, rows.forEach(function(_result) {
type: result.Type.toUpperCase(), result[_result.Field] = {
allowNull: (result.Null === 'YES'), type: _result.Type.toUpperCase(),
defaultValue: result.Default allowNull: (_result.Null === 'YES'),
defaultValue: _result.Default
}
if (result[_result.Field].type === 'BOOLEAN') {
result[_result.Field].defaultValue = { 'false': false, 'true': true }[result[_result.Field].defaultValue]
if (result[_result.Field].defaultValue === undefined) {
result[_result.Field].defaultValue = null
}
} }
}) })
this.emit('success', rows) this.emit('success', result)
} else { } else {
this.emit('success', this.send('handleSelectQuery', rows)) this.emit('success', this.send('handleSelectQuery', rows))
} }
......
...@@ -58,7 +58,13 @@ module.exports = (function() { ...@@ -58,7 +58,13 @@ module.exports = (function() {
values.attributes += ", PRIMARY KEY (" + pkString + ")" values.attributes += ", PRIMARY KEY (" + pkString + ")"
} }
return Utils._.template(query)(values).trim() + ";" var sql = Utils._.template(query, values).trim() + ";"
return QueryGenerator.replaceBooleanDefaults(sql)
},
addColumnQuery: function() {
var sql = MySqlQueryGenerator.addColumnQuery.apply(null, arguments)
return QueryGenerator.replaceBooleanDefaults(sql)
}, },
showTablesQuery: function() { showTablesQuery: function() {
...@@ -145,7 +151,7 @@ module.exports = (function() { ...@@ -145,7 +151,7 @@ module.exports = (function() {
, replacements = { type: dataType.type } , replacements = { type: dataType.type }
if (dataType.type === DataTypes.ENUM) { if (dataType.type === DataTypes.ENUM) {
replacements.type = "INTEGER" replacements.type = "INTEGER"
} }
if (dataType.hasOwnProperty('allowNull') && !dataType.allowNull && !dataType.primaryKey) { if (dataType.hasOwnProperty('allowNull') && !dataType.allowNull && !dataType.primaryKey) {
...@@ -227,15 +233,38 @@ module.exports = (function() { ...@@ -227,15 +233,38 @@ module.exports = (function() {
}, },
describeTableQuery: function(tableName) { describeTableQuery: function(tableName) {
var sql = "PRAGMA TABLE_INFO('<%= tableName %>')" var sql = "PRAGMA TABLE_INFO('<%= tableName %>');"
return Utils._.template(sql, { tableName: tableName }) return Utils._.template(sql, { tableName: tableName })
}, },
renameTableQuery: function(before, after) { renameTableQuery: function(before, after) {
var query = "ALTER TABLE `<%= before %>` RENAME TO `<%= after %>`;" var query = "ALTER TABLE `<%= before %>` RENAME TO `<%= after %>`;"
return Utils._.template(query, { before: before, after: after }) return Utils._.template(query, { before: before, after: after })
},
removeColumnQuery: function(tableName, attributes) {
attributes = QueryGenerator.attributesToSQL(attributes)
var backupTableName = tableName + "_backup"
var query = [
QueryGenerator.createTableQuery(backupTableName, attributes).replace('CREATE TABLE', 'CREATE TEMPORARY TABLE'),
"INSERT INTO <%= tableName %>_backup SELECT <%= attributeNames %> FROM <%= tableName %>;",
"DROP TABLE <%= tableName %>;",
QueryGenerator.createTableQuery(tableName, attributes),
"INSERT INTO <%= tableName %> SELECT <%= attributeNames %> FROM <%= tableName %>_backup;",
"DROP TABLE <%= tableName %>_backup;",
].join("")
return Utils._.template(query, {
tableName: tableName,
attributeNames: Utils._.keys(attributes)
})
},
replaceBooleanDefaults: function(sql) {
return sql.replace(/DEFAULT '?false'?/g, "DEFAULT 0").replace(/DEFAULT '?true'?/g, "DEFAULT 1")
} }
} }
return Utils._.extend(MySqlQueryGenerator, QueryGenerator) return Utils._.extend({}, MySqlQueryGenerator, QueryGenerator)
})() })()
...@@ -67,7 +67,7 @@ module.exports = (function() { ...@@ -67,7 +67,7 @@ module.exports = (function() {
//private //private
var getDatabaseMethod = function() { var getDatabaseMethod = function() {
if (this.send('isInsertQuery') || this.send('isUpdateQuery')) { if (this.send('isInsertQuery') || this.send('isUpdateQuery') || (this.sql.toLowerCase().indexOf('CREATE TEMPORARY TABLE'.toLowerCase()) !== -1)) {
return 'run' return 'run'
} else { } else {
return 'all' return 'all'
...@@ -112,12 +112,21 @@ module.exports = (function() { ...@@ -112,12 +112,21 @@ module.exports = (function() {
}) })
} else if (this.sql.indexOf('PRAGMA TABLE_INFO') !== -1) { } else if (this.sql.indexOf('PRAGMA TABLE_INFO') !== -1) {
// this is the sqlite way of getting the metadata of a table // this is the sqlite way of getting the metadata of a table
result = results.map(function(result) { result = {}
return {
attribute: result.name, results.forEach(function(_result) {
type: result.type, result[_result.name] = {
allowNull: (result.notnull === 0), type: _result.type,
defaultValue: result.dflt_value allowNull: (_result.notnull === 0),
defaultValue: _result.dflt_value
}
if (result[_result.name].type === 'TINYINT(1)') {
result[_result.name].defaultValue = { '0': false, '1': true }[result[_result.name].defaultValue]
}
if (result[_result.name].defaultValue === undefined) {
result[_result.name].defaultValue = null
} }
}) })
} }
......
...@@ -3,9 +3,9 @@ var Utils = require('./utils') ...@@ -3,9 +3,9 @@ var Utils = require('./utils')
module.exports = (function() { module.exports = (function() {
var QueryInterface = function(sequelize) { var QueryInterface = function(sequelize) {
this.sequelize = sequelize this.sequelize = sequelize
this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator') this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
this.QueryGenerator.options = this.sequelize.options; this.QueryGenerator.options = this.sequelize.options;
} }
Utils.addEventEmitter(QueryInterface) Utils.addEventEmitter(QueryInterface)
...@@ -102,7 +102,7 @@ module.exports = (function() { ...@@ -102,7 +102,7 @@ module.exports = (function() {
var attributes = {} var attributes = {}
if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) { if (Utils._.values(DataTypes).indexOf(dataTypeOrOptions) > -1) {
attributes[attributeName] = { type: dataTypeOrOptions, allowNull: false } attributes[attributeName] = { type: dataTypeOrOptions, allowNull: true }
} else { } else {
attributes[attributeName] = dataTypeOrOptions attributes[attributeName] = dataTypeOrOptions
} }
...@@ -114,8 +114,40 @@ module.exports = (function() { ...@@ -114,8 +114,40 @@ module.exports = (function() {
} }
QueryInterface.prototype.removeColumn = function(tableName, attributeName) { QueryInterface.prototype.removeColumn = function(tableName, attributeName) {
var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName) if (this.sequelize.options.dialect === 'sqlite') {
return queryAndEmit.call(this, sql, 'removeColumn') // sqlite needs some special treatment as it cannot drop a column
return new Utils.CustomEventEmitter(function(emitter) {
this.describeTable(tableName).complete(function(err, fields) {
if (err) {
emitter.emit('error', err)
} else {
delete fields[attributeName]
var sql = this.QueryGenerator.removeColumnQuery(tableName, fields)
, chainer = new Utils.QueryChainer()
, subQueries = sql.split(';').filter(function(q) { return q !== '' })
subQueries.splice(0, subQueries.length - 1).forEach(function(subQuery) {
chainer.add(this.sequelize, 'query', [subQuery + ";", null, { raw: true }])
}.bind(this))
chainer
.runSerially()
.complete(function(err) {
if (err) {
emitter.emit('removeColumn', err)
emitter.emit('error', err)
} else {
queryAndEmit.call(this, subQueries.splice(subQueries.length - 1)[0], 'removeColumn')
}
}.bind(this))
}
}.bind(this))
}.bind(this)).run()
} else {
var sql = this.QueryGenerator.removeColumnQuery(tableName, attributeName)
return queryAndEmit.call(this, sql, 'removeColumn')
}
} }
QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) { QueryInterface.prototype.changeColumn = function(tableName, attributeName, dataTypeOrOptions) {
...@@ -138,12 +170,12 @@ module.exports = (function() { ...@@ -138,12 +170,12 @@ module.exports = (function() {
return new Utils.CustomEventEmitter(function(emitter) { return new Utils.CustomEventEmitter(function(emitter) {
self.describeTable(tableName).success(function(data) { self.describeTable(tableName).success(function(data) {
data = data.filter(function(h) { return h.attribute == attrNameBefore })[0] || {} data = data[attrNameBefore] || {}
var options = {} var options = {}
options[attrNameAfter] = { options[attrNameAfter] = {
attribute: data.attribute, attribute: attrNameAfter,
type: data.type, type: data.type,
allowNull: data.allowNull, allowNull: data.allowNull,
defaultValue: data.defaultValue defaultValue: data.defaultValue
...@@ -247,15 +279,13 @@ module.exports = (function() { ...@@ -247,15 +279,13 @@ module.exports = (function() {
// private // private
var queryAndEmit = function(sqlOrQueryParams, methodName, options) { var queryAndEmit = function(sqlOrQueryParams, methodName, options, emitter) {
var self = this
options = Utils._.extend({ options = Utils._.extend({
success: function(){}, success: function(){},
error: function(){} error: function(){}
}, options || {}) }, options || {})
return new Utils.CustomEventEmitter(function(emitter) { var execQuery = function(emitter) {
var query = null var query = null
if (Array.isArray(sqlOrQueryParams)) { if (Array.isArray(sqlOrQueryParams)) {
...@@ -267,9 +297,9 @@ module.exports = (function() { ...@@ -267,9 +297,9 @@ module.exports = (function() {
sqlOrQueryParams.push({}) sqlOrQueryParams.push({})
} }
query = self.sequelize.query.apply(self.sequelize, sqlOrQueryParams) query = this.sequelize.query.apply(this.sequelize, sqlOrQueryParams)
} else { } else {
query = self.sequelize.query(sqlOrQueryParams, null, {}) query = this.sequelize.query(sqlOrQueryParams, null, {})
} }
// append the query for better testing // append the query for better testing
...@@ -277,17 +307,24 @@ module.exports = (function() { ...@@ -277,17 +307,24 @@ module.exports = (function() {
query.success(function(obj) { query.success(function(obj) {
options.success && options.success(obj) options.success && options.success(obj)
self.emit(methodName, null) this.emit(methodName, null)
emitter.emit('success', obj) emitter.emit('success', obj)
}).error(function(err) { }.bind(this)).error(function(err) {
options.error && options.error(err) options.error && options.error(err)
self.emit(methodName, err) this.emit(methodName, err)
emitter.emit('error', err) emitter.emit('error', err)
}) }.bind(this))
query.on('sql', function(sql) { query.on('sql', function(sql) {
emitter.emit('sql', sql) emitter.emit('sql', sql)
}); })
}).run() }.bind(this)
if (!!emitter) {
execQuery(emitter)
} else {
return new Utils.CustomEventEmitter(execQuery).run()
}
} }
return QueryInterface return QueryInterface
......
...@@ -123,7 +123,7 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() { ...@@ -123,7 +123,7 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() {
it("executes migration #20111117063700 and correctly adds isBetaMember", function(done) { it("executes migration #20111117063700 and correctly adds isBetaMember", function(done) {
this.sequelize.getQueryInterface().describeTable('Person').success(function(data) { this.sequelize.getQueryInterface().describeTable('Person').success(function(data) {
var fields = data.map(function(d) { return d.attribute }).sort() var fields = Helpers.Sequelize.Utils._.keys(data).sort()
expect(fields).toEqual([ 'isBetaMember', 'name' ]) expect(fields).toEqual([ 'isBetaMember', 'name' ])
done() done()
}) })
...@@ -190,9 +190,9 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() { ...@@ -190,9 +190,9 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() {
this.init({ from: 20111117063700, to: 20111205162700 }, function(migrator) { this.init({ from: 20111117063700, to: 20111205162700 }, function(migrator) {
migrator.migrate().success(function() { migrator.migrate().success(function() {
this.sequelize.getQueryInterface().describeTable('User').success(function(data) { this.sequelize.getQueryInterface().describeTable('User').success(function(data) {
var signature = data.filter(function(hash){ return hash.Field == 'signature' })[0] var signature = data.signature
, isAdmin = data.filter(function(hash){ return hash.Field == 'isAdmin' })[0] , isAdmin = data.isAdmin
, shopId = data.filter(function(hash){ return hash.Field == 'shopId' })[0] , shopId = data.shopId
expect(signature.Field).toEqual('signature') expect(signature.Field).toEqual('signature')
expect(signature.Null).toEqual('NO') expect(signature.Null).toEqual('NO')
...@@ -212,20 +212,17 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() { ...@@ -212,20 +212,17 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() {
}) })
describe('removeColumn', function() { describe('removeColumn', function() {
(dialect === 'mysql' ? it : itEventually)('removes the shopId column from user', function(done) { it('removes the shopId column from user', function(done) {
this.init({ to: 20111206061400 }, function(migrator) { this.init({ to: 20111206061400 }, function(migrator) {
migrator.migrate().success(function(){ migrator.migrate().success(function(){
this.sequelize.getQueryInterface().describeTable('User').success(function(data) { this.sequelize.getQueryInterface().describeTable('User').success(function(data) {
var signature = data.filter(function(hash){ return hash.attribute == 'signature' })[0] var signature = data.signature
, isAdmin = data.filter(function(hash){ return hash.attribute == 'isAdmin' })[0] , isAdmin = data.isAdmin
, shopId = data.filter(function(hash){ return hash.attribute == 'shopId' })[0] , shopId = data.shopId
expect(signature.attribute).toEqual('signature') expect(signature.allowNull).toEqual(true)
expect(signature.allowNull).toEqual(false)
expect(isAdmin.attribute).toEqual('isAdmin')
expect(isAdmin.allowNull).toEqual(false) expect(isAdmin.allowNull).toEqual(false)
expect(isAdmin.defaultValue).toEqual('0') expect(isAdmin.defaultValue).toEqual(false)
expect(shopId).toBeFalsy() expect(shopId).toBeFalsy()
...@@ -241,9 +238,8 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() { ...@@ -241,9 +238,8 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() {
this.init({ to: 20111206063000 }, function(migrator) { this.init({ to: 20111206063000 }, function(migrator) {
migrator.migrate().success(function() { migrator.migrate().success(function() {
this.sequelize.getQueryInterface().describeTable('User').success(function(data) { this.sequelize.getQueryInterface().describeTable('User').success(function(data) {
var signature = data.filter(function(hash){ return hash.attribute == 'signature' })[0] var signature = data.signature
expect(signature.attribute).toEqual('signature')
expect(signature.type).toEqual('VARCHAR(255)') expect(signature.type).toEqual('VARCHAR(255)')
expect(signature.allowNull).toEqual(false) expect(signature.allowNull).toEqual(false)
expect(signature.defaultValue).toEqual('Signature') expect(signature.defaultValue).toEqual('Signature')
...@@ -261,8 +257,8 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() { ...@@ -261,8 +257,8 @@ describe(Helpers.getTestDialectTeaser("Migrator"), function() {
this.init({ to: 20111206163300 }, function(migrator) { this.init({ to: 20111206163300 }, function(migrator) {
migrator.migrate().success(function(){ migrator.migrate().success(function(){
this.sequelize.getQueryInterface().describeTable('User').success(function(data) { this.sequelize.getQueryInterface().describeTable('User').success(function(data) {
var signature = data.filter(function(hash){ return hash.attribute === 'signature' })[0] var signature = data.signature
, sig = data.filter(function(hash){ return hash.attribute === 'sig' })[0] , sig = data.sig
expect(signature).toBeFalsy() expect(signature).toBeFalsy()
expect(sig).toBeTruthy() expect(sig).toBeTruthy()
......
...@@ -101,15 +101,13 @@ describe(Helpers.getTestDialectTeaser("QueryInterface"), function() { ...@@ -101,15 +101,13 @@ describe(Helpers.getTestDialectTeaser("QueryInterface"), function() {
this.interface.describeTable('User').complete(function(err, metadata) { this.interface.describeTable('User').complete(function(err, metadata) {
expect(err).toBeNull() expect(err).toBeNull()
var username = metadata.filter(function(m) { return m.attribute === 'username' })[0] var username = metadata.username
var isAdmin = metadata.filter(function(m) { return m.attribute === 'isAdmin' })[0] var isAdmin = metadata.isAdmin
expect(username.attribute).toEqual('username')
expect(username.type).toEqual(dialect === 'postgres' ? 'CHARACTER VARYING' : 'VARCHAR(255)') expect(username.type).toEqual(dialect === 'postgres' ? 'CHARACTER VARYING' : 'VARCHAR(255)')
expect(username.allowNull).toBeTrue() expect(username.allowNull).toBeTrue()
expect(username.defaultValue).toBeNull() expect(username.defaultValue).toBeNull()
expect(isAdmin.attribute).toEqual('isAdmin')
expect(isAdmin.type).toEqual(dialect === 'postgres' ? 'BOOLEAN' : 'TINYINT(1)') expect(isAdmin.type).toEqual(dialect === 'postgres' ? 'BOOLEAN' : 'TINYINT(1)')
expect(isAdmin.allowNull).toBeTrue() expect(isAdmin.allowNull).toBeTrue()
expect(isAdmin.defaultValue).toBeNull() expect(isAdmin.defaultValue).toBeNull()
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!