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

Commit 162ef09e by Mick Hansen

Merge branch 'additional-include-tests'

2 parents 6b9aa0c4 8fe7a681
...@@ -1378,6 +1378,12 @@ module.exports = (function() { ...@@ -1378,6 +1378,12 @@ module.exports = (function() {
include = includes[index] = validateIncludedElement.call(this, include, tableNames) include = includes[index] = validateIncludedElement.call(this, include, tableNames)
include.parent = options
// associations that are required or have a required child as is not a ?:M association are candidates for the subquery
include.subQuery = !include.association.isMultiAssociation && (include.hasIncludeRequired || include.required)
include.hasParentWhere = options.hasParentWhere || !!options.where
include.hasParentRequired = options.hasParentRequired || !!options.required
options.includeMap[include.as] = include options.includeMap[include.as] = include
options.includeNames.push(include.as) options.includeNames.push(include.as)
options.includeNames.push(include.as.substr(0,1).toLowerCase() + include.as.substr(1)) options.includeNames.push(include.as.substr(0,1).toLowerCase() + include.as.substr(1))
......
...@@ -587,10 +587,14 @@ module.exports = (function() { ...@@ -587,10 +587,14 @@ module.exports = (function() {
} }
if (options.include) { if (options.include) {
var generateJoinQuery = function(include, parentTable) { var generateJoinQueries = function(include, parentTable) {
var table = include.daoFactory.tableName var table = include.daoFactory.tableName
, as = include.as , as = include.as
, joinQueryItem = "" , joinQueryItem = ""
, joinQueries = {
mainQuery: [],
subQuery: []
}
, attributes , attributes
, association = include.association , association = include.association
, through = include.through , through = include.through
...@@ -610,8 +614,7 @@ module.exports = (function() { ...@@ -610,8 +614,7 @@ module.exports = (function() {
return self.quoteIdentifier(as) + "." + self.quoteIdentifier(attr) + " AS " + self.quoteIdentifier(as + "." + attr) return self.quoteIdentifier(as) + "." + self.quoteIdentifier(attr) + " AS " + self.quoteIdentifier(as + "." + attr)
}) })
// If not many to many, and we're doing a subquery, add attributes to the subquery if (include.subQuery && subQuery) {
if (!include.association.isMultiAssociation && subQuery && (include.hasIncludeRequired || include.required)) {
subQueryAttributes = subQueryAttributes.concat(attributes) subQueryAttributes = subQueryAttributes.concat(attributes)
} else { } else {
mainAttributes = mainAttributes.concat(attributes) mainAttributes = mainAttributes.concat(attributes)
...@@ -690,7 +693,12 @@ module.exports = (function() { ...@@ -690,7 +693,12 @@ module.exports = (function() {
// Filter statement // Filter statement
// Used by both join and subquery where // Used by both join and subquery where
if (subQuery && !include.subQuery && include.parent.subQuery) {
where = self.quoteIdentifier(tableLeft + "." + attrLeft) + " = "
} else {
where = self.quoteIdentifier(tableLeft) + "." + self.quoteIdentifier(attrLeft) + " = " where = self.quoteIdentifier(tableLeft) + "." + self.quoteIdentifier(attrLeft) + " = "
}
where += self.quoteIdentifier(tableRight) + "." + self.quoteIdentifier(attrRight) where += self.quoteIdentifier(tableRight) + "." + self.quoteIdentifier(attrRight)
// Generate join SQL // Generate join SQL
...@@ -709,26 +717,33 @@ module.exports = (function() { ...@@ -709,26 +717,33 @@ module.exports = (function() {
} }
} }
if (include.subQuery && subQuery) {
joinQueries.subQuery.push(joinQueryItem);
} else {
joinQueries.mainQuery.push(joinQueryItem);
}
if (include.include) { if (include.include) {
include.include.forEach(function(childInclude) { include.include.forEach(function(childInclude) {
if (childInclude._pseudo) return if (childInclude._pseudo) return
joinQueryItem += generateJoinQuery(childInclude, as) var childJoinQueries = generateJoinQueries(childInclude, as)
if (childInclude.subQuery && subQuery) {
joinQueries.subQuery = joinQueries.subQuery.concat(childJoinQueries.subQuery)
} else {
joinQueries.mainQuery = joinQueries.mainQuery.concat(childJoinQueries.mainQuery)
}
}.bind(this)) }.bind(this))
} }
return joinQueries
return joinQueryItem
} }
// Loop through includes and generate subqueries // Loop through includes and generate subqueries
options.include.forEach(function(include) { options.include.forEach(function(include) {
var joinQueryItem = generateJoinQuery(include, tableName) var joinQueries = generateJoinQueries(include, tableName)
// If not many to many, and we're doing a subquery, add joinQuery to subQueries subJoinQueries = subJoinQueries.concat(joinQueries.subQuery)
if (!include.association.isMultiAssociation && (subQuery && (include.hasIncludeRequired || include.required))) { mainJoinQueries = mainJoinQueries.concat(joinQueries.mainQuery)
subJoinQueries.push(joinQueryItem)
} else {
mainJoinQueries.push(joinQueryItem)
}
}.bind(this)) }.bind(this))
} }
......
...@@ -780,7 +780,7 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -780,7 +780,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
}) })
}) })
it('should be possible to define a belongsTo include as required with limit', function (done) { it('should be possible to extend the on clause with a where option on a belongsTo include', function (done) {
var User = this.sequelize.define('User', {}) var User = this.sequelize.define('User', {})
, Group = this.sequelize.define('Group', { , Group = this.sequelize.define('Group', {
name: DataTypes.STRING name: DataTypes.STRING
...@@ -815,6 +815,213 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -815,6 +815,213 @@ describe(Support.getTestDialectTeaser("Include"), function () {
User.findAll({ User.findAll({
include: [ include: [
{model: Group, required: true} {model: Group, required: true}
]
}).done(function (err, users) {
expect(err).not.to.be.ok
users.forEach(function (user) {
expect(user.group).to.be.ok
})
done()
})
})
})
})
it('should be possible to define a belongsTo include as required with child hasMany with limit', function (done) {
var User = this.sequelize.define('User', {})
, Group = this.sequelize.define('Group', {
name: DataTypes.STRING
})
, Category = this.sequelize.define('Category', {
category: DataTypes.STRING
})
User.belongsTo(Group)
Group.hasMany(Category)
this.sequelize.sync({force: true}).done(function () {
async.auto({
groups: function (callback) {
Group.bulkCreate([
{name: 'A'},
{name: 'B'}
]).done(function () {
Group.findAll().done(callback)
})
},
users: function (callback) {
User.bulkCreate([{}, {}]).done(function () {
User.findAll().done(callback)
})
},
categories: function (callback) {
Category.bulkCreate([{}, {}]).done(function () {
Category.findAll().done(callback)
})
},
userGroups: ['users', 'groups', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
chainer.add(results.users[0].setGroup(results.groups[1]))
chainer.add(results.users[1].setGroup(results.groups[0]))
chainer.run().done(callback)
}],
groupCategories: ['groups', 'categories', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
results.groups.forEach(function (group) {
chainer.add(group.setCategories(results.categories))
})
chainer.run().done(callback)
}]
}, function (err, results) {
expect(err).not.to.be.ok
User.findAll({
include: [
{model: Group, required: true, include: [
{model: Category}
]}
],
limit: 1
}).done(function (err, users) {
expect(err).not.to.be.ok
expect(users.length).to.equal(1)
users.forEach(function (user) {
expect(user.group).to.be.ok
expect(user.group.categories).to.be.ok
})
done()
})
})
})
})
it('should be possible to define a belongsTo include as required with child hasMany with limit and aliases', function (done) {
var User = this.sequelize.define('User', {})
, Group = this.sequelize.define('Group', {
name: DataTypes.STRING
})
, Category = this.sequelize.define('Category', {
category: DataTypes.STRING
})
User.belongsTo(Group, {as: 'Team'})
Group.hasMany(Category, {as: 'Tags'})
this.sequelize.sync({force: true}).done(function () {
async.auto({
groups: function (callback) {
Group.bulkCreate([
{name: 'A'},
{name: 'B'}
]).done(function () {
Group.findAll().done(callback)
})
},
users: function (callback) {
User.bulkCreate([{}, {}]).done(function () {
User.findAll().done(callback)
})
},
categories: function (callback) {
Category.bulkCreate([{}, {}]).done(function () {
Category.findAll().done(callback)
})
},
userGroups: ['users', 'groups', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
chainer.add(results.users[0].setTeam(results.groups[1]))
chainer.add(results.users[1].setTeam(results.groups[0]))
chainer.run().done(callback)
}],
groupCategories: ['groups', 'categories', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
results.groups.forEach(function (group) {
chainer.add(group.setTags(results.categories))
})
chainer.run().done(callback)
}]
}, function (err, results) {
expect(err).not.to.be.ok
User.findAll({
include: [
{model: Group, required: true, as: 'Team', include: [
{model: Category, as: 'Tags'}
]}
],
limit: 1
}).done(function (err, users) {
expect(err).not.to.be.ok
expect(users.length).to.equal(1)
users.forEach(function (user) {
expect(user.team).to.be.ok
expect(user.team.tags).to.be.ok
})
done()
})
})
})
})
it('should be possible to define a belongsTo include as required with child hasMany which is not required with limit', function (done) {
var User = this.sequelize.define('User', {})
, Group = this.sequelize.define('Group', {
name: DataTypes.STRING
})
, Category = this.sequelize.define('Category', {
category: DataTypes.STRING
})
User.belongsTo(Group)
Group.hasMany(Category)
this.sequelize.sync({force: true}).done(function () {
async.auto({
groups: function (callback) {
Group.bulkCreate([
{name: 'A'},
{name: 'B'}
]).done(function () {
Group.findAll().done(callback)
})
},
users: function (callback) {
User.bulkCreate([{}, {}]).done(function () {
User.findAll().done(callback)
})
},
categories: function (callback) {
Category.bulkCreate([{}, {}]).done(function () {
Category.findAll().done(callback)
})
},
userGroups: ['users', 'groups', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
chainer.add(results.users[0].setGroup(results.groups[1]))
chainer.add(results.users[1].setGroup(results.groups[0]))
chainer.run().done(callback)
}],
groupCategories: ['groups', 'categories', function (callback, results) {
var chainer = new Sequelize.Utils.QueryChainer()
results.groups.forEach(function (group) {
chainer.add(group.setCategories(results.categories))
})
chainer.run().done(callback)
}]
}, function (err, results) {
expect(err).not.to.be.ok
User.findAll({
include: [
{model: Group, required: true, include: [
{model: Category, required: false}
]}
], ],
limit: 1 limit: 1
}).done(function (err, users) { }).done(function (err, users) {
...@@ -822,6 +1029,7 @@ describe(Support.getTestDialectTeaser("Include"), function () { ...@@ -822,6 +1029,7 @@ describe(Support.getTestDialectTeaser("Include"), function () {
expect(users.length).to.equal(1) expect(users.length).to.equal(1)
users.forEach(function (user) { users.forEach(function (user) {
expect(user.group).to.be.ok expect(user.group).to.be.ok
expect(user.group.categories).to.be.ok
}) })
done() done()
}) })
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!