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

Commit 17b19d9c by Maks Nemisj Committed by Sushant

fix(abstract-query): properly hash primaryKey for buffers (#8174)

1 parent 06779e55
...@@ -479,6 +479,7 @@ class AbstractQuery { ...@@ -479,6 +479,7 @@ class AbstractQuery {
return uniqueKeyAttributes; return uniqueKeyAttributes;
}; };
const stringify = obj => obj instanceof Buffer ? obj.toString('hex') : obj;
let primaryKeyAttributes; let primaryKeyAttributes;
let uniqueKeyAttributes; let uniqueKeyAttributes;
let prefix; let prefix;
...@@ -499,11 +500,11 @@ class AbstractQuery { ...@@ -499,11 +500,11 @@ class AbstractQuery {
$length = includeOptions.model.primaryKeyAttributes.length; $length = includeOptions.model.primaryKeyAttributes.length;
topHash = ''; topHash = '';
if ($length === 1) { if ($length === 1) {
topHash = row[includeOptions.model.primaryKeyAttributes[0]]; topHash = stringify(row[includeOptions.model.primaryKeyAttributes[0]]);
} }
else if ($length > 1) { else if ($length > 1) {
for ($i = 0; $i < $length; $i++) { for ($i = 0; $i < $length; $i++) {
topHash += row[includeOptions.model.primaryKeyAttributes[$i]]; topHash += stringify(row[includeOptions.model.primaryKeyAttributes[$i]]);
} }
} }
else if (!_.isEmpty(includeOptions.model.uniqueKeys)) { else if (!_.isEmpty(includeOptions.model.uniqueKeys)) {
...@@ -551,11 +552,11 @@ class AbstractQuery { ...@@ -551,11 +552,11 @@ class AbstractQuery {
$length = primaryKeyAttributes.length; $length = primaryKeyAttributes.length;
itemHash = prefix; itemHash = prefix;
if ($length === 1) { if ($length === 1) {
itemHash += row[prefix+'.'+primaryKeyAttributes[0]]; itemHash += stringify(row[prefix+'.'+primaryKeyAttributes[0]]);
} }
else if ($length > 1) { else if ($length > 1) {
for ($i = 0; $i < $length; $i++) { for ($i = 0; $i < $length; $i++) {
itemHash += row[prefix+'.'+primaryKeyAttributes[$i]]; itemHash += stringify(row[prefix+'.'+primaryKeyAttributes[$i]]);
} }
} }
else if (!_.isEmpty(includeMap[prefix].model.uniqueKeys)) { else if (!_.isEmpty(includeMap[prefix].model.uniqueKeys)) {
...@@ -640,11 +641,11 @@ class AbstractQuery { ...@@ -640,11 +641,11 @@ class AbstractQuery {
$length = primaryKeyAttributes.length; $length = primaryKeyAttributes.length;
itemHash = prefix; itemHash = prefix;
if ($length === 1) { if ($length === 1) {
itemHash += row[prefix+'.'+primaryKeyAttributes[0]]; itemHash += stringify(row[prefix+'.'+primaryKeyAttributes[0]]);
} }
else if ($length > 0) { else if ($length > 0) {
for ($i = 0; $i < $length; $i++) { for ($i = 0; $i < $length; $i++) {
itemHash += row[prefix+'.'+primaryKeyAttributes[$i]]; itemHash += stringify(row[prefix+'.'+primaryKeyAttributes[$i]]);
} }
} }
else if (!_.isEmpty(includeMap[prefix].model.uniqueKeys)) { else if (!_.isEmpty(includeMap[prefix].model.uniqueKeys)) {
......
'use strict';
const path = require('path');
const Query = require(path.resolve('./lib/dialects/abstract/query.js'));
const Support = require(path.join(__dirname, './../../support'));
const chai = require('chai');
const current = Support.sequelize;
const expect = chai.expect;
describe('[ABSTRACT]', () => {
describe('_groupJoinData', () => {
it('should hash second nested set correctly, when has multiple primary keys and one is a Buffer', () => {
const Team = current.define('team', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const Player = current.define('player', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const Agent = current.define('agent', {
uuid: {
primaryKey: true,
type: 'BINARY(16)'
},
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
Team.Player = Team.hasMany(Player, { foreignKey: 'teamId' });
Team.Agent = Team.hasMany(Agent, { foreignKey: 'teamId' });
const includeOptions = {
model: Team,
includeMap: {
'players': {
model: Player,
association: Team.Player
},
'agents': {
model: Agent,
association: Team.Agent
}
}
};
const agentOneUuid = Buffer.from('966ea4c3028c11e7bc99a99d4c0d78cf', 'hex');
const agentTwoUuid = Buffer.from('966ecbd0028c11e7bc99a99d4c0d78cf', 'hex');
const data = [
{
id: 'a',
'players.id': '1-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-03-06T15:47:30.000Z'),
'agents.uuid': agentOneUuid,
'agents.id': 'p',
'agents.name': 'One'
},
{
id: 'a',
'players.id': '2-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-22T11:16:44.000Z'),
'agents.uuid': agentTwoUuid,
'agents.id': 'z',
'agents.name': 'Two'
}
];
const result = Query._groupJoinData(data, includeOptions, { checkExisting: true });
expect(result.length).to.be.equal(1);
expect(result[0]).to.have.property('id').and.be.equal('a');
expect(result[0].agents).to.be.deep.equal([
{
id: 'p',
uuid: agentOneUuid,
name: 'One'
},
{
id: 'z',
uuid: agentTwoUuid,
name: 'Two'
}
]);
});
it('should hash second nested set correctly, when primary is a Buffer', () => {
const Team = current.define('team', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const Player = current.define('player', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const Agent = current.define('agent', {
uuid: {
primaryKey: true,
type: 'BINARY(16)'
}
});
Team.Player = Team.hasMany(Player, { foreignKey: 'teamId' });
Team.Agent = Team.hasMany(Agent, { foreignKey: 'teamId' });
const includeOptions = {
model: Team,
includeMap: {
'players': {
model: Player,
association: Team.Player
},
'agents': {
model: Agent,
association: Team.Agent
}
}
};
const agentOneUuid = Buffer.from('966ea4c3028c11e7bc99a99d4c0d78cf', 'hex');
const agentTwoUuid = Buffer.from('966ecbd0028c11e7bc99a99d4c0d78cf', 'hex');
const data = [
{
id: 'a',
'players.id': '1-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-03-06T15:47:30.000Z'),
'agents.uuid': agentOneUuid,
'agents.name': 'One'
},
{
id: 'a',
'players.id': '2-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-22T11:16:44.000Z'),
'agents.uuid': agentTwoUuid,
'agents.name': 'Two'
}
];
const result = Query._groupJoinData(data, includeOptions, { checkExisting: true });
expect(result.length).to.be.equal(1);
expect(result[0]).to.have.property('id').and.be.equal('a');
expect(result[0].agents).to.be.deep.equal([
{
uuid: agentOneUuid,
name: 'One'
},
{
uuid: agentTwoUuid,
name: 'Two'
}
]);
});
it('should hash parents correctly, when has multiple primary keys and one is a Buffer', () => {
const Team = current.define('team', {
uuid: {
primaryKey: true,
type: 'BINARY(16)'
},
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const Player = current.define('player', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const association = Team.hasMany(Player, { foreignKey: 'teamId' });
const includeOptions = {
model: Team,
includeMap: {
'players': {
model: Player,
association
}
}
};
const teamOneUuid = Buffer.from('966ea4c3028c11e7bc99a99d4c0d78cf', 'hex');
const teamTwoUuid = Buffer.from('966ecbd0028c11e7bc99a99d4c0d78cf', 'hex');
const data = [
{
uuid: teamOneUuid,
id: 'x',
'players.id': '1-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
uuid: teamTwoUuid,
id: 'y',
'players.id': '2-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-22T11:16:44.000Z'),
},
{
uuid: teamOneUuid,
id: 'x',
'players.id': '1-2',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-24T11:16:44.000Z'),
}
];
const result = Query._groupJoinData(data, includeOptions, { checkExisting: true });
expect(result.length).to.be.equal(2);
expect(result[0]).to.have.property('uuid').and.be.equal(teamOneUuid);
expect(result[0].players).to.be.deep.equal([
{
'id': '1-1',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
'id': '1-2',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-08-24T11:16:44.000Z'),
}
]);
expect(result[1]).to.have.property('uuid').and.be.equal(teamTwoUuid);
expect(result[1].players).to.be.deep.equal([{
'id': '2-1',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-08-22T11:16:44.000Z'),
}]);
});
it('should hash parents correctly, when primary key is a Buffer', () => {
const Team = current.define('team', {
uuid: {
primaryKey: true,
type: 'BINARY(16)'
}
});
const Player = current.define('player', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const association = Team.hasMany(Player, { foreignKey: 'teamId' });
const includeOptions = {
model: Team,
includeMap: {
'players': {
model: Player,
association
}
}
};
const teamOneUuid = Buffer.from('966ea4c3028c11e7bc99a99d4c0d78cf', 'hex');
const teamTwoUuid = Buffer.from('966ecbd0028c11e7bc99a99d4c0d78cf', 'hex');
const data = [
{
uuid: teamOneUuid,
'players.id': '1-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
uuid: teamTwoUuid,
'players.id': '2-1',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-22T11:16:44.000Z'),
},
{
uuid: teamOneUuid,
'players.id': '1-2',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-24T11:16:44.000Z'),
}
];
const result = Query._groupJoinData(data, includeOptions, { checkExisting: true });
expect(result.length).to.be.equal(2);
expect(result[0]).to.have.property('uuid').and.be.equal(teamOneUuid);
expect(result[0].players).to.be.deep.equal([
{
'id': '1-1',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
'id': '1-2',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-08-24T11:16:44.000Z'),
}
]);
expect(result[1]).to.have.property('uuid').and.be.equal(teamTwoUuid);
expect(result[1].players).to.be.deep.equal([{
'id': '2-1',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-08-22T11:16:44.000Z'),
}]);
});
it('should hash nested correctly, when primary key is a Buffer', () => {
const Team = current.define('team', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const Player = current.define('player', {
uuid: {
primaryKey: true,
type: 'BINARY(16)'
}
});
const association = Team.hasMany(Player, { foreignKey: 'teamId' });
const includeOptions = {
model: Team,
includeMap: {
'players': {
model: Player,
association
}
}
};
const playerOneUuid = Buffer.from('966ea4c3028c11e7bc99a99d4c0d78cf', 'hex');
const playerTwoUuid = Buffer.from('966ecbd0028c11e7bc99a99d4c0d78cf', 'hex');
const data = [
{
id: '1',
'players.uuid': playerOneUuid,
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
id: '1',
'players.uuid': playerTwoUuid,
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-22T11:16:44.000Z'),
}
];
const result = Query._groupJoinData(data, includeOptions, { checkExisting: true });
expect(result.length).to.be.equal(1);
expect(result[0]).to.have.property('id').and.be.equal('1');
expect(result[0].players).to.be.deep.equal([
{
'uuid': playerOneUuid,
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
'uuid': playerTwoUuid,
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-08-22T11:16:44.000Z'),
}
]);
});
it('should hash nested correctly, when has multiple primary keys and one is a Buffer', () => {
const Team = current.define('team', {
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const Player = current.define('player', {
uuid: {
primaryKey: true,
type: 'BINARY(16)'
},
id: {
primaryKey: true,
type: current.Sequelize.STRING(1)
}
});
const association = Team.hasMany(Player, { foreignKey: 'teamId' });
const includeOptions = {
model: Team,
includeMap: {
'players': {
model: Player,
association
}
}
};
const playerOneUuid = Buffer.from('966ea4c3028c11e7bc99a99d4c0d78cf', 'hex');
const playerTwoUuid = Buffer.from('966ecbd0028c11e7bc99a99d4c0d78cf', 'hex');
const data = [
{
id: '1',
'players.uuid': playerOneUuid,
'players.id': 'x',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
id: '1',
'players.uuid': playerTwoUuid,
'players.id': 'y',
'players.created': new Date('2017-03-06T15:47:30.000Z'),
'players.lastModified': new Date('2017-08-22T11:16:44.000Z'),
}
];
const result = Query._groupJoinData(data, includeOptions, { checkExisting: true });
expect(result.length).to.be.equal(1);
expect(result[0]).to.have.property('id').and.be.equal('1');
expect(result[0].players).to.be.deep.equal([
{
'uuid': playerOneUuid,
'id': 'x',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-03-06T15:47:30.000Z'),
},
{
'uuid': playerTwoUuid,
'id': 'y',
'created': new Date('2017-03-06T15:47:30.000Z'),
'lastModified': new Date('2017-08-22T11:16:44.000Z'),
}
]);
});
});
});
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!