Fix BigInt primary key routing (#20744)

Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
This commit is contained in:
Wasim Thoufiq
2023-12-14 22:43:47 +05:30
committed by GitHub
parent 4f3771cc9a
commit 12643385db
3 changed files with 79 additions and 5 deletions

View File

@@ -0,0 +1,5 @@
---
'@directus/api': patch
---
Ensured filter values higher than JavaScript max safe integer work with big integer fields

View File

@@ -76,6 +76,8 @@ const FAKE_SCHEMA: SchemaOverview = {
relations: [],
};
class Client_SQLite3 extends MockClient {}
describe('applySearch', () => {
function mockDatabase() {
const self: Record<string, any> = {
@@ -158,10 +160,7 @@ describe('applyFilter', () => {
for (const { filterOperator, sqlWhereClause } of withReverseOperators) {
for (const filterValue of [true, '', false]) {
test(`${filterOperator} with value ${filterValue}`, async () => {
class Client_SQLite3 extends MockClient {}
const db = vi.mocked(knex.default({ client: Client_SQLite3 }));
const queryBuilder = db.queryBuilder();
const collection = 'test';
@@ -190,4 +189,64 @@ describe('applyFilter', () => {
}
}
});
test(`filter values on bigint fields are correctly passed as such to db query`, async () => {
const collection = 'test';
const field = 'bigInteger';
const BIGINT_FAKE_SCHEMA: SchemaOverview = {
collections: {
[collection]: {
collection: 'test',
primary: 'id',
singleton: false,
sortField: null,
note: null,
accountability: null,
fields: {
[field]: {
field: field,
defaultValue: null,
nullable: false,
generated: false,
type: 'bigInteger',
dbType: null,
precision: null,
scale: null,
special: [],
note: null,
validation: null,
alias: false,
},
},
},
},
relations: [],
};
const db = vi.mocked(knex.default({ client: Client_SQLite3 }));
const queryBuilder = db.queryBuilder();
// testing with value greater than Number.MAX_SAFE_INTEGER
const bigintId = 9007199254740991477n;
const rootFilter = {
[field]: {
_eq: bigintId.toString(),
},
};
const { query } = applyFilter(db, BIGINT_FAKE_SCHEMA, queryBuilder, rootFilter, collection, {});
const tracker = createTracker(db);
tracker.on.select('*').response([]);
await query;
const resultingSelectQuery = tracker.history.select[0];
const expectedSql = `select * where "${collection}"."${field}" = ?`;
expect(resultingSelectQuery?.sql).toEqual(expectedSql);
expect(resultingSelectQuery?.bindings[0]).toEqual(bigintId);
});
});

View File

@@ -644,8 +644,10 @@ export function applyFilter(
const functionName = column!.split('(')[0] as FieldFunction;
const type = getOutputTypeForFunction(functionName);
if (['bigInteger', 'integer', 'float', 'decimal'].includes(type)) {
if (['integer', 'float', 'decimal'].includes(type)) {
compareValue = Number(compareValue);
} else if (type === 'bigInteger') {
compareValue = BigInt(compareValue);
}
}
@@ -664,13 +666,21 @@ export function applyFilter(
}
}
if (['bigInteger', 'integer', 'float', 'decimal'].includes(type)) {
if (['integer', 'float', 'decimal'].includes(type)) {
if (Array.isArray(compareValue)) {
compareValue = compareValue.map((val) => Number(val));
} else {
compareValue = Number(compareValue);
}
}
if (type === 'bigInteger') {
if (Array.isArray(compareValue)) {
compareValue = compareValue.map((val) => BigInt(val));
} else {
compareValue = BigInt(compareValue);
}
}
}
if (operator === '_eq') {