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

Commit 7d3172df by LoneWolfPR Committed by Jan Aagaard Meier

cherry-pick: 3168d543

v3: sourceKey feature for hasMany doesn't work if where clause specified in include (#7141) (#7147)

* Initial Commit

* Stops test from removing test/integration/assets/es6project.js

* Fixes impromper syntax when specifying the use of association.sourceIdentifier or left.primaryKeyAttribute for attrLeft. Also includes integration test.

* Updates changelog.

* Adds link to issue in changelog entry.

* Added 'Future' header to changelog entry

* Removed changelog update as requested.

* Updates changelog. Fixes query-generator to properly build queries from hasMany even with an include while respecting a specified sourceKey. Adds an integration test.

* Added back removed whitespace per request.

* Updates test in include altered field name in source key. Fixes were then made to address the test breaking. All tests pass now.

* Adds back removed whitespace.
1 parent 4416eff9
# Future
- [CHANGED] `setIsolationLevelQuery` to skip under MSSQL dialect, added debug listener for tedious [#7130](https://github.com/sequelize/sequelize/pull/7130)
- [FIXED] `sourceKey` FOR `hasMany` now also works if a `where` was specified in an `include` [#7141](https://github.com/sequelize/sequelize/issues/7141)
- [FIXED] `removeColumn` method to support dropping primaryKey column (MSSQL) [#7081](https://github.com/sequelize/sequelize/pull/7081)
- [ADDED] Filtered Indexes support for SQL Server [#7016](https://github.com/sequelize/sequelize/issues/7016)
- [FIXED] Set `timestamps` and `paranoid` options from through model on `belongsToMany` association
......
......@@ -86,6 +86,11 @@ class HasMany extends Association {
this.sourceKeyField = this.sourceKey;
}
if (this.source.fieldRawAttributesMap[this.sourceKey]) {
this.sourceKeyAttribute = this.source.fieldRawAttributesMap[this.sourceKey].fieldName;
} else {
this.sourceKeyAttribute = this.source.primaryKeyAttribute;
}
this.sourceIdentifier = this.sourceKey;
this.associationAccessor = this.as;
......@@ -210,7 +215,7 @@ class HasMany extends Association {
const newAttributes = {};
const constraintOptions = _.clone(this.options); // Create a new options object for use with addForeignKeyConstraints, to avoid polluting this.options in case it is later used for a n:m
newAttributes[this.foreignKey] = _.defaults({}, this.foreignKeyAttribute, {
type: this.options.keyType || this.source.rawAttributes[this.sourceKey].type,
type: this.options.keyType || this.source.rawAttributes[this.sourceKeyAttribute].type,
allowNull : true
});
......
......@@ -293,7 +293,7 @@ const QueryGenerator = {
if (this._dialect.supports['LIMIT ON UPDATE'] && options.limit) {
if (this.dialect !== 'mssql') {
query += ' LIMIT ' + this.escape(options.limit) + ' ';
query += ' LIMIT ' + this.escape(options.limit) + ' ';
}
}
......@@ -1137,7 +1137,7 @@ const QueryGenerator = {
const associationWhere = {};
associationWhere[association.identifierField] = {
$raw: `${this.quoteTable(parentTableName.internalAs)}.${this.quoteIdentifier(association.source.primaryKeyField)}`
$raw: `${this.quoteTable(parentTableName.internalAs)}.${this.quoteIdentifier(association.sourceKeyField || association.source.primaryKeyField)}`
};
if (!topLevelInfo.options.where) {
......@@ -1247,10 +1247,10 @@ const QueryGenerator = {
const left = association.source;
const attrLeft = association instanceof BelongsTo ?
association.identifier :
left.primaryKeyAttribute;
association.sourceKeyAttribute || left.primaryKeyAttribute;
const fieldLeft = association instanceof BelongsTo ?
association.identifierField :
left.rawAttributes[association.sourceIdentifier || left.primaryKeyAttribute].field;
left.rawAttributes[association.sourceKeyAttribute || left.primaryKeyAttribute].field;
let asLeft;
/* Attributes for the right side */
const right = include.model;
......
......@@ -1304,4 +1304,41 @@ describe(Support.getTestDialectTeaser('HasMany'), function() {
});
describe('sourceKey with where clause in include', function() {
beforeEach(function() {
this.User = this.sequelize.define('User',
{ username: Sequelize.STRING, email: { type: Sequelize.STRING, field: 'mail'} },
{ indexes: [ {fields: ['mail'], unique: true} ] }
);
this.Task = this.sequelize.define('Task',
{ title: Sequelize.STRING, userEmail: Sequelize.STRING, taskStatus: Sequelize.STRING });
this.User.hasMany(this.Task, {foreignKey: 'userEmail', sourceKey: 'mail'});
return this.sequelize.sync({ force: true });
});
it('should use the specified sourceKey instead of the primary key', function() {
return this.User.create({ username: 'John', email: 'john@example.com'}).then(() =>
this.Task.bulkCreate([
{title: 'Active Task', userEmail: 'john@example.com', taskStatus: 'Active'},
{title: 'Inactive Task', userEmail: 'john@example.com', taskStatus: 'Inactive'}
])
).then(() =>
this.User.find({
include: [
{
model: this.Task,
where: {taskStatus: 'Active'}
}
],
where: {username: 'John'}
})
).then(user => {
expect(user).to.be.ok;
expect(user.Tasks.length).to.equal(1);
expect(user.Tasks[0].title).to.equal('Active Task');
});
});
});
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!