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

Commit 4244ac8d by Mick Hansen

fix(model): support custom fields in aggregate methods, closes #4935

1 parent bdb1c731
# Next]
- [FIXED] Model.aggregate methods now support attributes and where conditions with fields. [#4935](https://github.com/sequelize/sequelize/issues/4935)
# 3.14.1 # 3.14.1
- [FIXED] Issue with transaction options leaking and certain queries running outside of the transaction connection. - [FIXED] Issue with transaction options leaking and certain queries running outside of the transaction connection.
......
...@@ -1504,20 +1504,23 @@ Model.prototype.find = Model.prototype.findOne; ...@@ -1504,20 +1504,23 @@ Model.prototype.find = Model.prototype.findOne;
* *
* @return {Promise<options.dataType|object>} Returns the aggregate result cast to `options.dataType`, unless `options.plain` is false, in which case the complete data result is returned. * @return {Promise<options.dataType|object>} Returns the aggregate result cast to `options.dataType`, unless `options.plain` is false, in which case the complete data result is returned.
*/ */
Model.prototype.aggregate = function(field, aggregateFunction, options) { Model.prototype.aggregate = function(attribute, aggregateFunction, options) {
options = Utils._.extend({ attributes: [] }, options || {}); options = Utils._.extend({ attributes: [] }, options || {});
conformOptions(options, this); conformOptions(options, this);
Model.$injectScope(this.$scope, options); Model.$injectScope(this.$scope, options);
var aggregateColumn = this.sequelize.col(field); var attrOptions = this.rawAttributes[attribute]
, field = attrOptions && attrOptions.field || attribute
, aggregateColumn = this.sequelize.col(field);
if (options.distinct) { if (options.distinct) {
aggregateColumn = this.sequelize.fn('DISTINCT', aggregateColumn); aggregateColumn = this.sequelize.fn('DISTINCT', aggregateColumn);
} }
options.attributes.push([this.sequelize.fn(aggregateFunction, aggregateColumn), aggregateFunction]); options.attributes.push([this.sequelize.fn(aggregateFunction, aggregateColumn), aggregateFunction]);
if (!options.dataType) { if (!options.dataType) {
if (this.rawAttributes[field]) { if (attrOptions) {
options.dataType = this.rawAttributes[field].type; options.dataType = attrOptions.type;
} else { } else {
// Use FLOAT as fallback // Use FLOAT as fallback
options.dataType = new DataTypes.FLOAT(); options.dataType = new DataTypes.FLOAT();
...@@ -1526,6 +1529,7 @@ Model.prototype.aggregate = function(field, aggregateFunction, options) { ...@@ -1526,6 +1529,7 @@ Model.prototype.aggregate = function(field, aggregateFunction, options) {
options.dataType = this.sequelize.normalizeDataType(options.dataType); options.dataType = this.sequelize.normalizeDataType(options.dataType);
} }
Utils.mapOptionFieldNames(options, this);
options = paranoidClause(this, options); options = paranoidClause(this, options);
return this.QueryInterface.rawSelect(this.getTableName(options), options, aggregateFunction, this); return this.QueryInterface.rawSelect(this.getTableName(options), options, aggregateFunction, this);
......
...@@ -11,6 +11,7 @@ var chai = require('chai') ...@@ -11,6 +11,7 @@ var chai = require('chai')
, sinon = require('sinon') , sinon = require('sinon')
, _ = require('lodash') , _ = require('lodash')
, moment = require('moment') , moment = require('moment')
, Promise = require('bluebird')
, current = Support.sequelize; , current = Support.sequelize;
describe(Support.getTestDialectTeaser('Model'), function() { describe(Support.getTestDialectTeaser('Model'), function() {
...@@ -1997,9 +1998,23 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -1997,9 +1998,23 @@ describe(Support.getTestDialectTeaser('Model'), function() {
value: Sequelize.DECIMAL(10, 3) value: Sequelize.DECIMAL(10, 3)
}); });
return this.UserWithAge.sync({ force: true }).then(function() { this.UserWithFields = this.sequelize.define('UserWithFields', {
return self.UserWithDec.sync({ force: true }); age: {
type: Sequelize.INTEGER,
field: 'user_age'
},
order: Sequelize.INTEGER,
gender: {
type: Sequelize.ENUM('male', 'female'),
field: 'male_female'
}
}); });
return Promise.join(
this.UserWithAge.sync({ force: true }),
this.UserWithDec.sync({ force: true }),
this.UserWithFields.sync({ force: true })
);
}); });
it('should return the sum of the values for a field named the same as an SQL reserved keyword', function() { it('should return the sum of the values for a field named the same as an SQL reserved keyword', function() {
...@@ -2040,6 +2055,19 @@ describe(Support.getTestDialectTeaser('Model'), function() { ...@@ -2040,6 +2055,19 @@ describe(Support.getTestDialectTeaser('Model'), function() {
}); });
}); });
it('should accept a where clause with custom fields', function() {
return this.UserWithFields.bulkCreate([
{age: 2, gender: 'male'},
{age: 3, gender: 'female'}
], {
logging: console.log
}).bind(this).then(function() {
return expect(this.UserWithFields.sum('age', {
where: { 'gender': 'male' }
})).to.eventually.equal(2);
});
});
it('allows sql logging', function() { it('allows sql logging', function() {
var logged = false; var logged = false;
return this.UserWithAge.sum('age', { return this.UserWithAge.sum('age', {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!