Skip to content

Commit ec6ab89

Browse files
authored
fix(search): handle large numbers in search queries (#621)
2 parents d515c64 + b981441 commit ec6ab89

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

src/services/search-builder.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,15 @@ function SearchBuilder(model, opts, params, fieldNamesRequested) {
148148
pushCondition(condition, columnName);
149149
}
150150
} else if (field.type === 'Number') {
151-
const value = Number(params.search);
151+
let value = Number(params.search);
152+
152153
if (!Number.isNaN(value)) {
154+
if (Number.isInteger(value) && !Number.isSafeInteger(value)) {
155+
// NOTE: Numbers higher than MAX_SAFE_INTEGER need to be handled as
156+
// strings to circumvent precision problems
157+
value = params.search;
158+
}
159+
153160
condition[field.field] = value;
154161
pushCondition(condition, field.field);
155162
}

test/databases.test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ const HasManyDissociator = require('../src/services/has-many-dissociator');
124124
ownerId: { type: Sequelize.INTEGER },
125125
});
126126

127+
models.counter = sequelize.define('counter', {
128+
clicks: { type: Sequelize.BIGINT },
129+
});
130+
127131
models.address.belongsTo(models.user);
128132
models.addressWithUserAlias.belongsTo(models.user, { as: 'userAlias' });
129133
models.user.hasMany(models.address);
@@ -316,6 +320,16 @@ const HasManyDissociator = require('../src/services/has-many-dissociator');
316320
{ field: 'ownerId', type: 'Number', reference: 'owner.ownerId' },
317321
],
318322
},
323+
counter: {
324+
name: 'counter',
325+
idField: 'id',
326+
primaryKeys: ['id'],
327+
isCompositePrimary: false,
328+
fields: [
329+
{ field: 'id', type: 'Number' },
330+
{ field: 'clicks', type: 'Number' },
331+
],
332+
},
319333
},
320334
};
321335

@@ -1010,6 +1024,34 @@ const HasManyDissociator = require('../src/services/has-many-dissociator');
10101024
connectionManager.closeConnection();
10111025
}
10121026
});
1027+
1028+
it('should handle numbers over MAX_SAFE_INTEGER', async () => {
1029+
expect.assertions(2);
1030+
const { models, sequelizeOptions } = initializeSequelize();
1031+
1032+
// HACK: sequelize-fixtures does not support BigInt in json files,
1033+
// so we need to update the clicks value manually
1034+
const counter = await models.counter.findByPk(10);
1035+
counter.clicks = BigInt('9013084467599484828'); // eslint-disable-line no-undef
1036+
await counter.save();
1037+
1038+
const params = {
1039+
fields: {
1040+
counter: 'id,clicks',
1041+
},
1042+
page: { number: '1', size: '30' },
1043+
search: '9013084467599484828',
1044+
timezone: 'Europe/Paris',
1045+
};
1046+
try {
1047+
const result = await new ResourcesGetter(models.counter, sequelizeOptions, params)
1048+
.perform();
1049+
expect(result[0]).toHaveLength(1);
1050+
expect(result[0][0].id).toBe(10);
1051+
} finally {
1052+
connectionManager.closeConnection();
1053+
}
1054+
});
10131055
});
10141056
});
10151057

test/fixtures/db.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
[
2+
{
3+
"model": "counter",
4+
"data": {
5+
"id": 10,
6+
"clicks": 9013084467599484828
7+
}
8+
},
29
{
310
"model": "user",
411
"data": {

0 commit comments

Comments
 (0)