From 949124cbfaabe5b81db56883e2106b71b7be0a52 Mon Sep 17 00:00:00 2001 From: tada5hi Date: Sun, 27 Nov 2022 10:27:52 +0100 Subject: [PATCH] feat: allow null value in query filter list --- package-lock.json | 14 +++++++------- package.json | 2 +- src/query/parameter/filters/module.ts | 23 +++++++++++++++++++++++ test/unit/query/filters.spec.ts | 12 ++++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index dad4b64d..c4f432b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@faker-js/faker": "^7.6.0", "locter": "^0.3.2", - "rapiq": "^0.4.1", + "rapiq": "^0.5.0", "reflect-metadata": "^0.1.13", "yargs": "^17.6.2" }, @@ -12601,9 +12601,9 @@ } }, "node_modules/rapiq": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/rapiq/-/rapiq-0.4.1.tgz", - "integrity": "sha512-0U9uDbBitAyUEnm0ZS+8nwIB137hth0aVAMUXMn1KxRCs8edelehmhpdes360sNk9AEMTx9AZaBLLlsywKS8lQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/rapiq/-/rapiq-0.5.0.tgz", + "integrity": "sha512-eklnAf4rKY3bAcUhTSmHOehrnD5Bm6YWIuItmG6YUrUpBDskQ3lhNFCTkbwfEQrJTnSjZdhiwB2wq9IVEF2/WA==", "dependencies": { "minimatch": "^5.1.0", "smob": "^0.0.6" @@ -24389,9 +24389,9 @@ "dev": true }, "rapiq": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/rapiq/-/rapiq-0.4.1.tgz", - "integrity": "sha512-0U9uDbBitAyUEnm0ZS+8nwIB137hth0aVAMUXMn1KxRCs8edelehmhpdes360sNk9AEMTx9AZaBLLlsywKS8lQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/rapiq/-/rapiq-0.5.0.tgz", + "integrity": "sha512-eklnAf4rKY3bAcUhTSmHOehrnD5Bm6YWIuItmG6YUrUpBDskQ3lhNFCTkbwfEQrJTnSjZdhiwB2wq9IVEF2/WA==", "requires": { "minimatch": "^5.1.0", "smob": "^0.0.6" diff --git a/package.json b/package.json index 8d7a60be..30681cab 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "dependencies": { "@faker-js/faker": "^7.6.0", "locter": "^0.3.2", - "rapiq": "^0.4.1", + "rapiq": "^0.5.0", "reflect-metadata": "^0.1.13", "yargs": "^17.6.2" }, diff --git a/src/query/parameter/filters/module.ts b/src/query/parameter/filters/module.ts index e8ccb40d..9490bd8b 100644 --- a/src/query/parameter/filters/module.ts +++ b/src/query/parameter/filters/module.ts @@ -91,6 +91,29 @@ export function transformParsedFilters( statement.push('IN'); statement.push(`(:...${bindingKey})`); + + if (Array.isArray(filter.value)) { + const nullIndex = (filter.value as unknown[]).indexOf(null); + if (nullIndex !== -1) { + filter.value.splice(nullIndex, 1); + + statement.unshift('('); + if (filter.operator === FilterComparisonOperator.NOT_IN) { + statement.push('AND'); + } else { + statement.push('OR'); + } + statement.push(fullKey); + statement.push('IS'); + + if (filter.operator === FilterComparisonOperator.NOT_IN) { + statement.push('NOT'); + } + + statement.push('NULL'); + statement.push(')'); + } + } break; } case FilterComparisonOperator.LESS_THAN: diff --git a/test/unit/query/filters.spec.ts b/test/unit/query/filters.spec.ts index f59b1b08..b435d8c5 100644 --- a/test/unit/query/filters.spec.ts +++ b/test/unit/query/filters.spec.ts @@ -92,12 +92,24 @@ describe('src/api/filters.ts', () => { {statement: 'id IN (:...filter_id)', binding: {'filter_id': [1,2,3]}} ] as QueryFiltersOutput); + // in operator with null + data = parseAndTransformFilters({id: 'null,1,2,3'}, {allowed: ['id']}); + expect(data).toEqual([ + {statement: '( id IN (:...filter_id) OR id IS NULL )', binding: {'filter_id': [1,2,3]}} + ] as QueryFiltersOutput); + // negation with in operator data = parseAndTransformFilters({id: '!1,2,3'}, {allowed: ['id']}); expect(data).toEqual([ {statement: 'id NOT IN (:...filter_id)', binding: {'filter_id': [1,2,3]}} ] as QueryFiltersOutput); + // negation with in operator and null + data = parseAndTransformFilters({id: '!null,1,2,3'}, {allowed: ['id']}); + expect(data).toEqual([ + {statement: '( id NOT IN (:...filter_id) AND id IS NOT NULL )', binding: {'filter_id': [1,2,3]}} + ] as QueryFiltersOutput); + // like operator data = parseAndTransformFilters({name: '~name'}, {allowed: ['name']}); expect(data).toEqual([