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

Commit e7a89ad0 by Mick Hansen

merge

2 parents cf37311c fea739d8
Notice: All 1.7.x changed are present in 2.0.x aswell
Notice: All 1.7.x changes are present in 2.0.x aswell
# v1.7.0-rc2
- fixes unixSocket connections for mariadb [#1248](https://github.com/sequelize/sequelize/pull/1248)
- fixes a hangup issue for mysql [#1244](https://github.com/sequelize/sequelize/pull/1244)
- improves handling of uncaught errors in eventemitter [#1245](https://github.com/sequelize/sequelize/pull/1245)
- fixes bug with mysql replication and pool settings [#1251](https://github.com/sequelize/sequelize/pull/1251)
# v2.0.0 (alpha1) #
- [FEATURE] async validations. [#580](https://github.com/sequelize/sequelize/pull/580). thanks to Interlock
......@@ -11,6 +17,7 @@ Notice: All 1.7.x changed are present in 2.0.x aswell
- fix bug where `{where: {ne: null}}` would result in `!= NULL` instead of `IS NOT NULL` [#1231](https://github.com/sequelize/sequelize/pull/1059)
- fixes a bug with validation skipping using the `fields` options. [#1233](https://github.com/sequelize/sequelize/pull/1233)
- fixes a bug with postgres and setters [#1234](https://github.com/sequelize/sequelize/issues/1234)
- fixes it so `field: {type: Sequelize.ENUM(value1, value2)}` works
#### Backwards compatability changes
- Hooks are no longer passing value hashes. Instead, they are now passing instances of the model.
......
......@@ -269,6 +269,11 @@ module.exports = (function() {
})
}
if (connectionConfig.unixSocket) {
delete connectionConfig.host;
delete connectionConfig.port;
}
client = new mariadb()
client.connect(connectionConfig)
client
......
......@@ -5,7 +5,7 @@ var MariaDialect = function(sequelize) {
this.sequelize = sequelize
}
MariaDialect.prototype = _.extend({
MariaDialect.prototype = _.defaults({
}, MySQL.prototype)
......
......@@ -225,9 +225,7 @@ module.exports = (function() {
var disconnect = function(client) {
var self = this;
if (!this.useQueue) {
this.client = null;
}
this.client = null;
client.end(function() {
if (!self.useQueue) {
......@@ -238,14 +236,11 @@ module.exports = (function() {
var cleanup = function () {
var retryCt = 0
// make sure to let client finish before calling destroy
if (self && self.hasQueuedItems) {
if (client._queue && (client._queue.length > 0)) {
return
}
// needed to prevent mysql connection leak
client.destroy()
if (self && self.client) {
self.client = null
}
clearInterval(intervalObj)
}
intervalObj = setInterval(cleanup, 10)
......@@ -294,7 +289,7 @@ module.exports = (function() {
connection.query("SET time_zone = '+0:00'");
// client.setMaxListeners(self.maxConcurrentQueries)
this.isConnecting = false
if (config.pool.handleDisconnects) {
if (config.pool != null && config.pool.handleDisconnects) {
handleDisconnect(this.pool, connection)
}
done(null, connection)
......
......@@ -5,8 +5,8 @@ var MysqlDialect = function(sequelize) {
this.sequelize = sequelize
}
MysqlDialect.prototype.supports = _.extend(Abstract.prototype.supports, {
MysqlDialect.prototype.supports = _.defaults({
'VALUES ()': true
})
}, Abstract.prototype.supports)
module.exports = MysqlDialect
......@@ -5,9 +5,9 @@ var PostgresDialect = function(sequelize) {
this.sequelize = sequelize
}
PostgresDialect.prototype.supports = _.extend(Abstract.prototype.supports, {
PostgresDialect.prototype.supports = _.defaults({
'RETURNING': true,
'DEFAULT VALUES': true
})
}, Abstract.prototype.supports)
module.exports = PostgresDialect
......@@ -5,9 +5,9 @@ var SqliteDialect = function(sequelize) {
this.sequelize = sequelize
}
SqliteDialect.prototype.supports = _.extend(Abstract.prototype.supports, {
SqliteDialect.prototype.supports = _.defaults({
'DEFAULT': false,
'DEFAULT VALUES': true
})
}, Abstract.prototype.supports)
module.exports = SqliteDialect
......@@ -28,6 +28,39 @@ module.exports = (function() {
return this
}
CustomEventEmitter.prototype.emit = function(type) {
this._events = this._events || {};
// Override default 'error' event logic
if (type === 'error' && !this._events.error) {
// No error listener
var er = arguments[1];
// If error argument is an object but no error,
// boil it down to the value of the first key
// (probably an Array in most cases)
if (Utils._.isObject(er) && !(er instanceof Error)) {
er = er[Object.keys(er)[0]]
}
// If error argument is an array, make sure we
// pass only the first error to the original
// .emit() function of EventEmitter
if (er instanceof Array) {
er = Utils._.flatten(er)[0]
}
// We don't want to throw strings. Make them Errors!
if (typeof er === "string") {
er = new Error(er)
}
arguments[1] = er
}
EventEmitter.prototype.emit.apply(this, arguments);
};
/**
Shortcut methods (success, ok) for listening for success events.
......
......@@ -50,12 +50,17 @@ module.exports = (function() {
}).run()
}
QueryInterface.prototype.showAllSchemas = function() {
QueryInterface.prototype.showAllSchemas = function(options) {
var self = this
options = Utils._.extend({
transaction: null,
raw: true
}, options || {})
return new Utils.CustomEventEmitter(function(emitter) {
var showSchemasSql = self.QueryGenerator.showSchemasQuery()
self.sequelize.query(showSchemasSql, null, { raw: true }).success(function(schemaNames) {
self.sequelize.query(showSchemasSql, null, options).success(function(schemaNames) {
self.emit('showAllSchemas', null)
emitter.emit('success', Utils._.flatten(Utils._.map(schemaNames, function(value){ return (!!value.schema_name ? value.schema_name : value) })))
}).error(function(err) {
......@@ -278,13 +283,18 @@ module.exports = (function() {
return queryAndEmit.call(this, sql, 'renameTable')
}
QueryInterface.prototype.showAllTables = function() {
QueryInterface.prototype.showAllTables = function(options) {
var self = this
options = Utils._.extend({
transaction: null,
raw: true
}, options || {})
return new Utils.CustomEventEmitter(function(emitter) {
var showTablesSql = self.QueryGenerator.showTablesQuery()
self.sequelize.query(showTablesSql, null, { raw: true }).success(function(tableNames) {
self.sequelize.query(showTablesSql, null, options).success(function(tableNames) {
self.emit('showAllTables', null)
emitter.emit('success', Utils._.flatten(tableNames))
}).error(function(err) {
......
......@@ -710,7 +710,7 @@ describe(Support.getTestDialectTeaser("DAO"), function () {
})
})
it("gets triggered if everything was ok", function(done) {
it("gets triggered if everything was ok", function(done) {
this.User.count().complete(function(err, result) {
expect(err).to.be.null
expect(result).to.exist
......@@ -795,7 +795,7 @@ describe(Support.getTestDialectTeaser("DAO"), function () {
// timeout is needed, in order to check the update of the timestamp
var build = function(callback) {
user = User.build({ username: 'user' })
var save = user.save()
save.success(function() {
......
......@@ -60,4 +60,64 @@ describe(Support.getTestDialectTeaser("CustomEventEmitter"), function () {
proxy.emit('success')
})
})
describe("when emitting an error event with an array of errors", function() {
describe("if no error handler is given", function() {
it("should throw the first error", function(done) {
var emitter = new CustomEventEmitter()
expect(function () {
emitter.emit("error", [
[
new Error("First error"),
new Error("Second error")
], [
new Error("Third error")
]
])
}).to.throw("First error")
done()
})
})
describe("if an error handler is given", function() {
it("should return the whole array", function(done) {
var emitter = new CustomEventEmitter()
var errors = [
[
new Error("First error"),
new Error("Second error")
], [
new Error("Third error")
]
]
emitter.error(function (err) {
expect(err).to.equal(errors)
done()
})
emitter.emit("error", errors)
})
})
})
describe("when emitting an error event with a hash containing arrays of error strings", function() {
describe("if no error handler is given", function() {
it("should throw an error with the first error string", function(done) {
var emitter = new CustomEventEmitter()
var errors = {
myValidation: [ "Invalid Length" ],
someOtherValidation: [ "Naah don't like that value!", "It's weird, u know?" ]
}
expect(function () {
emitter.emit("error", errors)
}).to.throw(errors.myValidation[0])
done()
})
})
})
})
......@@ -32,5 +32,26 @@ if (Support.dialectIsMySQL()) {
})
})
})
it('accepts new queries after shutting down a connection', function(done) {
// Create a sequelize instance with pooling disabled
var sequelize = Support.createSequelizeInstance({ pool: false })
var User = sequelize.define('User', { username: DataTypes.STRING })
User.sync({force: true}).on('success', function() {
User.create({username: 'user1'}).on('success', function() {
// After 100 ms the DB connection will be disconnected for inactivity
setTimeout(function() {
// This query will be queued just after the `client.end` is executed and before its callback is called
sequelize.query('SELECT COUNT(*) AS count FROM Users').on('success', function(count) {
expect(count[0].count).to.equal(1)
done()
}).error(function(error) {
expect(error).to.not.exist
})
}, 100)
})
})
})
})
}
......@@ -18,6 +18,65 @@ describe(Support.getTestDialectTeaser("Sequelize#transaction"), function () {
.transaction(function(t) { t.rollback() })
.success(function() { done() })
})
it('works for long running transactions', function(done) {
Support.prepareTransactionTest(this.sequelize, function(sequelize) {
var User = sequelize.define('User', {
name: Support.Sequelize.STRING
}, { timestamps: false })
sequelize.sync({ force: true }).success(function() {
sequelize
.transaction(function(t) {
var query = 'select sleep(2);'
switch(Support.getTestDialect()) {
case 'postgres':
query = 'select pg_sleep(2);'
break
case 'sqlite':
query = 'select sqlite3_sleep(2);'
break
default:
break
}
sequelize.query(query, null, {
raw: true,
plain: true,
transaction: t
}).done(function() {
var dao = User.build({ name: 'foo' })
// this.QueryGenerator.insertQuery(tableName, values, dao.daoFactory.rawAttributes)
query = sequelize
.getQueryInterface()
.QueryGenerator
.insertQuery(User.tableName, dao.values, User.rawAttributes)
setTimeout(function() {
sequelize.query(query, null, {
raw: true,
plain: true,
transaction: t
}).done(function(err, res) {
t.commit()
})
}, 2000)
})
})
.success(function() {
User.all().success(function(users) {
expect(users.length).to.equal(1)
expect(users[0].name).to.equal('foo')
done()
})
})
})
})
})
})
describe('error', function() {
......
......@@ -45,7 +45,7 @@ var Support = {
var config = Config[options.dialect]
options.logging = (options.hasOwnProperty('logging') ? options.logging : false)
options.pool = options.pool || config.pool
options.pool = options.pool !== undefined ? options.pool : config.pool
var sequelizeOptions = {
host: options.host || config.host,
......
......@@ -49,5 +49,25 @@ describe(Support.getTestDialectTeaser("Transaction"), function () {
transaction.commit()
})
})
it('works for long running transactions', function(done) {
var transaction = new Transaction(this.sequelize)
, self = this
transaction.done(done)
transaction.prepareEnvironment(function() {
setTimeout(function() {
self.sequelize.query('select 1+1 as sum', null, {
raw: true,
plain: true,
transaction: transaction
}).done(function(err, result) {
expect(err).to.be.null
expect(result.sum).to.equal(2)
transaction.commit()
})
}, 2000)
})
})
})
})
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!