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

Commit 592099dd by Pedro Augusto de Paula Barbosa Committed by Sushant

fix(count): fix null count with includes (#11295)

1 parent 80d36257
Showing with 125 additions and 118 deletions
...@@ -2017,7 +2017,9 @@ class Model { ...@@ -2017,7 +2017,9 @@ class Model {
*/ */
static count(options) { static count(options) {
return Promise.try(() => { return Promise.try(() => {
options = _.defaults(Utils.cloneDeep(options), { hooks: true }); options = Utils.cloneDeep(options);
options = _.defaults(options, { hooks: true });
options.raw = true;
if (options.hooks) { if (options.hooks) {
return this.runHooks('beforeCount', options); return this.runHooks('beforeCount', options);
} }
......
...@@ -6,119 +6,97 @@ const chai = require('chai'), ...@@ -6,119 +6,97 @@ const chai = require('chai'),
DataTypes = require('../../../lib/data-types'); DataTypes = require('../../../lib/data-types');
describe(Support.getTestDialectTeaser('Model'), () => { describe(Support.getTestDialectTeaser('Model'), () => {
beforeEach(function() {
this.User = this.sequelize.define('User', {
username: DataTypes.STRING,
age: DataTypes.INTEGER
});
this.Project = this.sequelize.define('Project', {
name: DataTypes.STRING
});
this.User.hasMany(this.Project);
this.Project.belongsTo(this.User);
return this.sequelize.sync({ force: true });
});
describe('count', () => { describe('count', () => {
beforeEach(function() { beforeEach(function() {
return this.User.bulkCreate([ this.User = this.sequelize.define('User', {
{ username: 'boo' }, username: DataTypes.STRING,
{ username: 'boo2' } age: DataTypes.INTEGER
]).then(() => { });
return this.User.findOne(); this.Project = this.sequelize.define('Project', {
}).then(user => { name: DataTypes.STRING
return user.createProject({
name: 'project1'
});
}); });
this.User.hasMany(this.Project);
this.Project.belongsTo(this.User);
return this.sequelize.sync({ force: true });
}); });
it('should count rows', function() { it('should count rows', function() {
return expect(this.User.count()).to.eventually.equal(2); return this.User.bulkCreate([
{ username: 'foo' },
{ username: 'bar' }
]).then(() => {
return expect(this.User.count()).to.eventually.equal(2);
});
}); });
it('should support include', function() { it('should support include', function() {
return expect(this.User.count({ return this.User.bulkCreate([
include: [{ { username: 'foo' },
model: this.Project, { username: 'bar' }
where: { ]).then(() => this.User.findOne())
name: 'project1' .then(user => user.createProject({ name: 'project1' }))
} .then(() => {
}] return expect(this.User.count({
})).to.eventually.equal(1); include: [{
model: this.Project,
where: { name: 'project1' }
}]
})).to.eventually.equal(1);
});
}); });
it('should return attributes', function() { it('should count groups correctly and return attributes', function() {
return this.User.create({ return this.User.bulkCreate([
username: 'valak', { username: 'foo' },
createdAt: (new Date()).setFullYear(2015) { username: 'bar' },
}) {
.then(() => username: 'valak',
this.User.count({ createdAt: (new Date()).setFullYear(2015)
attributes: ['createdAt'], }
group: ['createdAt'] ]).then(() => this.User.count({
}) attributes: ['createdAt'],
) group: ['createdAt']
.then(users => { })).then(users => {
expect(users.length).to.be.eql(2); expect(users.length).to.be.eql(2);
expect(users[0].createdAt).to.exist;
// have attributes expect(users[1].createdAt).to.exist;
expect(users[0].createdAt).to.exist; });
expect(users[1].createdAt).to.exist;
});
}); });
it('should not return NaN', function() { it('should not return NaN', function() {
return this.sequelize.sync({ force: true }) return this.User.bulkCreate([
.then(() => { username: 'valak', age: 10 },
this.User.bulkCreate([ { username: 'conjuring', age: 20 },
{ username: 'valak', age: 10 }, { username: 'scary', age: 10 }
{ username: 'conjuring', age: 20 }, ]).then(() => this.User.count({
{ username: 'scary', age: 10 } where: { age: 10 },
]) group: ['age'],
) order: ['age']
.then(() => })).then(result => {
this.User.count({ // TODO: `parseInt` should not be needed, see #10533
where: { age: 10 }, expect(parseInt(result[0].count, 10)).to.be.eql(2);
group: ['age'], return this.User.count({
order: ['age'] where: { username: 'fire' }
})
)
.then(result => {
// TODO: `parseInt` should not be needed, see #10533
expect(parseInt(result[0].count, 10)).to.be.eql(2);
return this.User.count({
where: { username: 'fire' }
});
})
.then(count => {
expect(count).to.be.eql(0);
return this.User.count({
where: { username: 'fire' },
group: 'age'
});
})
.then(count => {
expect(count).to.be.eql([]);
}); });
}).then(count => {
expect(count).to.be.eql(0);
return this.User.count({
where: { username: 'fire' },
group: 'age'
});
}).then(count => {
expect(count).to.be.eql([]);
});
}); });
it('should be able to specify column for COUNT()', function() { it('should be able to specify column for COUNT()', function() {
return this.sequelize.sync({ force: true }) return this.User.bulkCreate([
.then(() => { username: 'ember', age: 10 },
this.User.bulkCreate([ { username: 'angular', age: 20 },
{ username: 'ember', age: 10 }, { username: 'mithril', age: 10 }
{ username: 'angular', age: 20 }, ]).then(() => this.User.count({ col: 'username' }))
{ username: 'mithril', age: 10 }
])
)
.then(() =>
this.User.count({
col: 'username'
})
)
.then(count => { .then(count => {
expect(count).to.be.eql(3); expect(count).to.be.eql(3);
return this.User.count({ return this.User.count({
...@@ -132,43 +110,70 @@ describe(Support.getTestDialectTeaser('Model'), () => { ...@@ -132,43 +110,70 @@ describe(Support.getTestDialectTeaser('Model'), () => {
}); });
it('should be able to use where clause on included models', function() { it('should be able to use where clause on included models', function() {
const queryObject = { const countOptions = {
col: 'username', col: 'username',
include: [this.Project], include: [this.Project],
where: { where: {
'$Projects.name$': 'project1' '$Projects.name$': 'project1'
} }
}; };
return this.User.count(queryObject).then(count => { return this.User.bulkCreate([
expect(count).to.be.eql(1); { username: 'foo' },
queryObject.where['$Projects.name$'] = 'project2'; { username: 'bar' }
return this.User.count(queryObject); ]).then(() => this.User.findOne())
}).then(count => { .then(user => user.createProject({ name: 'project1' }))
expect(count).to.be.eql(0); .then(() => {
}); return this.User.count(countOptions).then(count => {
expect(count).to.be.eql(1);
countOptions.where['$Projects.name$'] = 'project2';
return this.User.count(countOptions);
});
})
.then(count => {
expect(count).to.be.eql(0);
});
}); });
it('should be able to specify column for COUNT() with includes', function() { it('should be able to specify column for COUNT() with includes', function() {
return this.sequelize.sync({ force: true }).then(() => return this.User.bulkCreate([
this.User.bulkCreate([ { username: 'ember', age: 10 },
{ username: 'ember', age: 10 }, { username: 'angular', age: 20 },
{ username: 'angular', age: 20 }, { username: 'mithril', age: 10 }
{ username: 'mithril', age: 10 } ]).then(() => this.User.count({
]) col: 'username',
).then(() => distinct: true,
this.User.count({ include: [this.Project]
col: 'username', })).then(count => {
distinct: true,
include: [this.Project]
})
).then(count => {
expect(count).to.be.eql(3); expect(count).to.be.eql(3);
return this.User.count({ return this.User.count({
col: 'age', col: 'age',
distinct: true, distinct: true,
include: [this.Project] include: [this.Project]
}); });
}).then(count => expect(count).to.be.eql(2)); }).then(count => {
expect(count).to.be.eql(2);
});
});
it('should work correctly with include and whichever raw option', function() {
const Post = this.sequelize.define('Post', {});
this.User.hasMany(Post);
return Post.sync({ force: true })
.then(() => Promise.all([this.User.create({}), Post.create({})]))
.then(([user, post]) => user.addPost(post))
.then(() => Promise.all([
this.User.count(),
this.User.count({ raw: undefined }),
this.User.count({ raw: false }),
this.User.count({ raw: true }),
this.User.count({ include: Post }),
this.User.count({ include: Post, raw: undefined }),
this.User.count({ include: Post, raw: false }),
this.User.count({ include: Post, raw: true })
]))
.then(counts => {
expect(counts).to.deep.equal([1, 1, 1, 1, 1, 1, 1, 1]);
});
}); });
}); });
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!