diff --git a/lib/condition/index.ts b/lib/condition/index.ts index 25a031f..ccabc77 100644 --- a/lib/condition/index.ts +++ b/lib/condition/index.ts @@ -49,6 +49,8 @@ export default class Condition { }, in: (values: Array>): C => { if (values.length === 0) { + // DynamoDB does not support an empty IN condition because it is logically impossible to have any value in an empty array. Therefore, an impossible condition is added to handle this case. + this.operators.push(...OPERATORS.impossibleCondition(key)); return this; } diff --git a/lib/utils/constants.ts b/lib/utils/constants.ts index f0fad36..cae6fdc 100644 --- a/lib/utils/constants.ts +++ b/lib/utils/constants.ts @@ -842,6 +842,14 @@ export const OPERATORS = { BASE_OPERATOR.space, { value, key }, ], + /** attribute_exists(Id) AND attribute_not_exists(Id) */ + impossibleCondition: (key: string): Operators => [ + ...OPERATORS.attributeExists(key), + BASE_OPERATOR.space, + BASE_OPERATOR.and, + BASE_OPERATOR.space, + ...OPERATORS.attributeNotExists(key), + ], }; export const UPDATE_OPERATORS = { diff --git a/tests/e2e/condition.test.ts b/tests/e2e/condition.test.ts index 6c5741f..0398052 100644 --- a/tests/e2e/condition.test.ts +++ b/tests/e2e/condition.test.ts @@ -36,6 +36,7 @@ describe.sequential('EntityManager.condition', () => { MockEntityManager.condition().attribute('string').beginsWith('any'), MockEntityManager.condition().attribute('string').between('a', 'c'), MockEntityManager.condition().attribute('string').in(['anything', 'anything2']), + MockEntityManager.condition().attribute('string').in([]), MockEntityManager.condition().attribute('string').not().in(['string', 'string2']), MockEntityManager.condition().attribute('string').not().eq('string'), MockEntityManager.condition().attribute('string').not().ne('anything'), @@ -100,6 +101,7 @@ describe.sequential('EntityManager.condition', () => { MockEntityManager.condition().attribute('number').between(0, 2), MockEntityManager.condition().attribute('number').in([1]), MockEntityManager.condition().attribute('number').not().in([0]), + MockEntityManager.condition().attribute('string').not().in([]), // boolean MockEntityManager.condition().attribute('boolean').exists(), diff --git a/tests/unit/condition/index.test.ts b/tests/unit/condition/index.test.ts index 9525041..d3370f1 100644 --- a/tests/unit/condition/index.test.ts +++ b/tests/unit/condition/index.test.ts @@ -130,10 +130,10 @@ describe('Condition', () => { }); describe('in', () => { - test('Should not push in expression for en empty array', async () => { + test('Should push an impossible condition for an empty array', async () => { condition.attribute('partitionKey').in([]); - expect(condition['operators']).toEqual([]); + expect(condition['operators']).toEqual([...OPERATORS.impossibleCondition('partitionKey')]); }); test('Should push in expression', async () => { diff --git a/tests/unit/utils/constants.test.ts b/tests/unit/utils/constants.test.ts index b70b2a3..fad6951 100644 --- a/tests/unit/utils/constants.test.ts +++ b/tests/unit/utils/constants.test.ts @@ -363,6 +363,22 @@ describe('Constants', () => { { value: 'value', key: 'key' }, ]); }); + + test('impossibleCondition', async () => { + expect(OPERATORS.impossibleCondition('key')).toEqual([ + { expression: 'attribute_exists' }, + { expression: '(' }, + { key: 'key' }, + { expression: ')' }, + { expression: ' ' }, + { expression: 'AND' }, + { expression: ' ' }, + { expression: 'attribute_not_exists' }, + { expression: '(' }, + { key: 'key' }, + { expression: ')' }, + ]); + }); }); describe('UPDATE_OPERATORS', () => {