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

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

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

1 parent 80d36257
...@@ -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,6 +6,7 @@ const chai = require('chai'), ...@@ -6,6 +6,7 @@ const chai = require('chai'),
DataTypes = require('../../../lib/data-types'); DataTypes = require('../../../lib/data-types');
describe(Support.getTestDialectTeaser('Model'), () => { describe(Support.getTestDialectTeaser('Model'), () => {
describe('count', () => {
beforeEach(function() { beforeEach(function() {
this.User = this.sequelize.define('User', { this.User = this.sequelize.define('User', {
username: DataTypes.STRING, username: DataTypes.STRING,
...@@ -21,104 +22,81 @@ describe(Support.getTestDialectTeaser('Model'), () => { ...@@ -21,104 +22,81 @@ describe(Support.getTestDialectTeaser('Model'), () => {
return this.sequelize.sync({ force: true }); return this.sequelize.sync({ force: true });
}); });
describe('count', () => { it('should count rows', function() {
beforeEach(function() {
return this.User.bulkCreate([ return this.User.bulkCreate([
{ username: 'boo' }, { username: 'foo' },
{ username: 'boo2' } { username: 'bar' }
]).then(() => { ]).then(() => {
return this.User.findOne();
}).then(user => {
return user.createProject({
name: 'project1'
});
});
});
it('should count rows', function() {
return expect(this.User.count()).to.eventually.equal(2); return expect(this.User.count()).to.eventually.equal(2);
}); });
});
it('should support include', function() { it('should support include', function() {
return this.User.bulkCreate([
{ username: 'foo' },
{ username: 'bar' }
]).then(() => this.User.findOne())
.then(user => user.createProject({ name: 'project1' }))
.then(() => {
return expect(this.User.count({ return expect(this.User.count({
include: [{ include: [{
model: this.Project, model: this.Project,
where: { where: { name: 'project1' }
name: 'project1'
}
}] }]
})).to.eventually.equal(1); })).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: 'foo' },
{ username: 'bar' },
{
username: 'valak', username: 'valak',
createdAt: (new Date()).setFullYear(2015) createdAt: (new Date()).setFullYear(2015)
}) }
.then(() => ]).then(() => this.User.count({
this.User.count({
attributes: ['createdAt'], attributes: ['createdAt'],
group: ['createdAt'] group: ['createdAt']
}) })).then(users => {
)
.then(users => {
expect(users.length).to.be.eql(2); expect(users.length).to.be.eql(2);
// have attributes
expect(users[0].createdAt).to.exist; expect(users[0].createdAt).to.exist;
expect(users[1].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(() =>
this.User.bulkCreate([
{ username: 'valak', age: 10 }, { username: 'valak', age: 10 },
{ username: 'conjuring', age: 20 }, { username: 'conjuring', age: 20 },
{ username: 'scary', age: 10 } { username: 'scary', age: 10 }
]) ]).then(() => this.User.count({
)
.then(() =>
this.User.count({
where: { age: 10 }, where: { age: 10 },
group: ['age'], group: ['age'],
order: ['age'] order: ['age']
}) })).then(result => {
)
.then(result => {
// TODO: `parseInt` should not be needed, see #10533 // TODO: `parseInt` should not be needed, see #10533
expect(parseInt(result[0].count, 10)).to.be.eql(2); expect(parseInt(result[0].count, 10)).to.be.eql(2);
return this.User.count({ return this.User.count({
where: { username: 'fire' } where: { username: 'fire' }
}); });
}) }).then(count => {
.then(count => {
expect(count).to.be.eql(0); expect(count).to.be.eql(0);
return this.User.count({ return this.User.count({
where: { username: 'fire' }, where: { username: 'fire' },
group: 'age' group: 'age'
}); });
}) }).then(count => {
.then(count => {
expect(count).to.be.eql([]); 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(() =>
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(() =>
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([
{ username: 'foo' },
{ username: 'bar' }
]).then(() => this.User.findOne())
.then(user => user.createProject({ name: 'project1' }))
.then(() => {
return this.User.count(countOptions).then(count => {
expect(count).to.be.eql(1); expect(count).to.be.eql(1);
queryObject.where['$Projects.name$'] = 'project2'; countOptions.where['$Projects.name$'] = 'project2';
return this.User.count(queryObject); return this.User.count(countOptions);
}).then(count => { });
})
.then(count => {
expect(count).to.be.eql(0); 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({
).then(() =>
this.User.count({
col: 'username', col: 'username',
distinct: true, distinct: true,
include: [this.Project] include: [this.Project]
}) })).then(count => {
).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!