Skip to content

Commit

Permalink
fix(search): searching for a big int value should not break if there …
Browse files Browse the repository at this point in the history
…is a regular integer field (#694)
  • Loading branch information
adriguy authored Apr 22, 2021
1 parent f384b9b commit af076ad
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 6 deletions.
19 changes: 13 additions & 6 deletions src/services/search-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,22 @@ function SearchBuilder(model, opts, params, fieldNamesRequested) {
pushCondition(condition, field.field);
}
} else if (field.type === 'Number') {
let value = Number(params.search);

if (!Number.isNaN(value)) {
if (Number.isInteger(value) && !Number.isSafeInteger(value)) {
// NOTE: Numbers higher than MAX_SAFE_INTEGER need to be handled as
// strings to circumvent precision problems
const searchAsNumber = Number(params.search);
let value;

if (!Number.isNaN(searchAsNumber)) {
if (Number.isInteger(searchAsNumber)
&& !Number.isSafeInteger(searchAsNumber)
&& model.rawAttributes[field.field].type instanceof DataTypes.BIGINT) {
// Numbers higher than MAX_SAFE_INTEGER need to be handled as strings to circumvent
// precision problems only if the field type is a big int.
value = params.search;
} else {
value = searchAsNumber;
}
}

if (value !== undefined) {
condition[field.field] = value;
pushCondition(condition, field.field);
}
Expand Down
30 changes: 30 additions & 0 deletions test/databases.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const HasManyDissociator = require('../src/services/has-many-dissociator');

models.counter = sequelize.define('counter', {
clicks: { type: Sequelize.BIGINT },
quantity: { type: Sequelize.INTEGER },
});

models.customer = sequelize.define('customer', {
Expand Down Expand Up @@ -383,6 +384,7 @@ const HasManyDissociator = require('../src/services/has-many-dissociator');
fields: [
{ field: 'id', type: 'Number' },
{ field: 'clicks', type: 'Number' },
{ field: 'quantity', type: 'Number' },
],
},
customer: {
Expand Down Expand Up @@ -1187,6 +1189,34 @@ const HasManyDissociator = require('../src/services/has-many-dissociator');
connectionManager.closeConnection();
}
});

it('should handle numbers over MAX_SAFE_INTEGER even if there are fields that are not big int', async () => {
expect.assertions(2);
const { models, sequelizeOptions } = initializeSequelize();

// HACK: sequelize-fixtures does not support BigInt in json files,
// so we need to update the clicks value manually
const counter = await models.counter.findByPk(10);
counter.clicks = BigInt('9013084467599484828'); // eslint-disable-line no-undef
await counter.save();

const params = {
fields: {
counter: 'id,clicks,quantity',
},
page: { number: '1', size: '30' },
search: '9013084467599484828',
timezone: 'Europe/Paris',
};
try {
const result = await new ResourcesGetter(models.counter, sequelizeOptions, params)
.perform();
expect(result[0]).toHaveLength(1);
expect(result[0][0].id).toBe(10);
} finally {
connectionManager.closeConnection();
}
});
});

describe('with a "string" search on a smart field', () => {
Expand Down

0 comments on commit af076ad

Please sign in to comment.