Skip to content

Commit

Permalink
Merge pull request #19 from blazejkustra/fix/empty-in-operator
Browse files Browse the repository at this point in the history
Handle in operator with empty array with an impossible condition
  • Loading branch information
blazejkustra authored Jan 23, 2024
2 parents 283e76f + fc03824 commit 84aaf86
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/condition/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export default class Condition<E extends typeof Entity> {
},
in: (values: Array<EntityValue<E, K>>): 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;
}

Expand Down
8 changes: 8 additions & 0 deletions lib/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
2 changes: 2 additions & 0 deletions tests/e2e/condition.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down Expand Up @@ -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(),
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/condition/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
16 changes: 16 additions & 0 deletions tests/unit/utils/constants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down

0 comments on commit 84aaf86

Please sign in to comment.