Skip to content

Commit e6d0d3e

Browse files
fix(putRequest): add support for composite partition key when using the ifNotExists
1 parent fdf6f85 commit e6d0d3e

File tree

6 files changed

+69
-19
lines changed

6 files changed

+69
-19
lines changed

src/dynamo/request/delete/delete.request.spec.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import moment from 'moment-es6'
22
import { getTableName } from '../../../../test/helper/get-table-name.function'
33
import { ComplexModel } from '../../../../test/models/complex.model'
4-
import { SimpleWithIdModel } from '../../../../test/models/simple-with-id.model'
4+
import { SimpleWithPartitionKeyModel } from '../../../../test/models/simple-with-partition-key.model'
55
import { MetadataHelper } from '../../../decorator/metadata/metadata-helper'
66
import { ModelConstructor } from '../../../model/model-constructor'
77
import { DeleteRequest } from './delete.request'
@@ -26,7 +26,12 @@ describe('delete request', () => {
2626
})
2727

2828
it('should create request with key (simple) expression', () => {
29-
const request = new DeleteRequest(<any>null, SimpleWithIdModel, getTableName(SimpleWithIdModel), 'myId')
29+
const request = new DeleteRequest(
30+
<any>null,
31+
SimpleWithPartitionKeyModel,
32+
getTableName(SimpleWithPartitionKeyModel),
33+
'myId'
34+
)
3035
const key = request.params.Key
3136
expect(key).toBeDefined()
3237
expect(Object.keys(key).length).toBe(1)

src/dynamo/request/get/get.request.spec.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
import { GetItemInput } from 'aws-sdk/clients/dynamodb'
22
import { getTableName } from '../../../../test/helper/get-table-name.function'
3-
import { SimpleWithIdModel } from '../../../../test/models/simple-with-id.model'
3+
import { SimpleWithPartitionKeyModel } from '../../../../test/models/simple-with-partition-key.model'
44
import { GetRequest } from './get.request'
55

66
describe('get requst', () => {
7-
let request: GetRequest<SimpleWithIdModel>
7+
let request: GetRequest<SimpleWithPartitionKeyModel>
88

99
beforeEach(() => {
10-
request = new GetRequest(null, SimpleWithIdModel, getTableName(SimpleWithIdModel), 'partitionKeyValue')
10+
request = new GetRequest(
11+
null,
12+
SimpleWithPartitionKeyModel,
13+
getTableName(SimpleWithPartitionKeyModel),
14+
'partitionKeyValue'
15+
)
1116
})
1217

1318
it('default params', () => {
1419
const params: GetItemInput = request.params
15-
expect(params.TableName).toBe('simple-with-id-models')
20+
expect(params.TableName).toBe('simple-with-partition-key-models')
1621
expect(params.Key).toEqual({ id: { S: 'partitionKeyValue' } })
1722
expect(Object.keys(params).length).toBe(2)
1823
})

src/dynamo/request/put/put.request.spec.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,53 @@
11
import { PutItemInput } from 'aws-sdk/clients/dynamodb'
2+
import moment from 'moment-es6'
23
import { getTableName } from '../../../../test/helper/get-table-name.function'
3-
import { SimpleWithIdModel } from '../../../../test/models/simple-with-id.model'
4+
import { SimpleWithCompositePartitionKeyModel } from '../../../../test/models/simple-with-composite-partition-key.model'
5+
import { SimpleWithPartitionKeyModel } from '../../../../test/models/simple-with-partition-key.model'
46
import { PutRequest } from './put.request'
57

68
describe('put request', () => {
79
it('default params', () => {
8-
const item: SimpleWithIdModel = { id: 'myId', age: 45 }
9-
const request = new PutRequest(null, SimpleWithIdModel, getTableName(SimpleWithIdModel), item)
10+
const item: SimpleWithPartitionKeyModel = { id: 'myId', age: 45 }
11+
const request = new PutRequest(null, SimpleWithPartitionKeyModel, getTableName(SimpleWithPartitionKeyModel), item)
1012
const params: PutItemInput = request.params
1113

12-
expect(params.TableName).toBe('simple-with-id-models')
14+
expect(params.TableName).toBe('simple-with-partition-key-models')
1315
expect(params.Item).toEqual({ id: { S: 'myId' }, age: { N: '45' } })
1416
expect(Object.keys(params).length).toBe(2)
1517
})
1618

1719
describe('if exists condition', () => {
18-
it('simple', () => {
19-
const item: SimpleWithIdModel = { id: 'myId', age: 45 }
20-
const request = new PutRequest(null, SimpleWithIdModel, getTableName(SimpleWithIdModel), item)
20+
it('simple partition key', () => {
21+
const item: SimpleWithPartitionKeyModel = { id: 'myId', age: 45 }
22+
const request = new PutRequest(null, SimpleWithPartitionKeyModel, getTableName(SimpleWithPartitionKeyModel), item)
2123
request.ifNotExists()
2224

2325
const params: PutItemInput = request.params
24-
expect(params.ConditionExpression).toBe('attribute_not_exists (#id)')
26+
expect(params.ConditionExpression).toBe('(attribute_not_exists (#id))')
2527
expect(params.ExpressionAttributeNames).toEqual({ '#id': 'id' })
2628
expect(params.ExpressionAttributeValues).toBeUndefined()
2729
})
2830

31+
it('composite partition key', () => {
32+
const now = moment()
33+
const item: SimpleWithCompositePartitionKeyModel = { id: 'myId', creationDate: now, age: 45 }
34+
const request = new PutRequest(
35+
null,
36+
SimpleWithCompositePartitionKeyModel,
37+
getTableName(SimpleWithCompositePartitionKeyModel),
38+
item
39+
)
40+
request.ifNotExists()
41+
42+
const params: PutItemInput = request.params
43+
expect(params.ConditionExpression).toBe('(attribute_not_exists (#id) AND attribute_not_exists (#creationDate))')
44+
expect(params.ExpressionAttributeNames).toEqual({ '#id': 'id', '#creationDate': 'creationDate' })
45+
expect(params.ExpressionAttributeValues).toBeUndefined()
46+
})
47+
2948
it('predicate', () => {
30-
const item: SimpleWithIdModel = { id: 'myId', age: 45 }
31-
const request = new PutRequest(null, SimpleWithIdModel, getTableName(SimpleWithIdModel), item)
49+
const item: SimpleWithPartitionKeyModel = { id: 'myId', age: 45 }
50+
const request = new PutRequest(null, SimpleWithPartitionKeyModel, getTableName(SimpleWithPartitionKeyModel), item)
3251
request.ifNotExists(25 + 20 === 40)
3352

3453
const params: PutItemInput = request.params

src/dynamo/request/put/put.request.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { Mapper } from '../../../mapper/mapper'
44
import { ModelConstructor } from '../../../model/model-constructor'
55
import { DynamoRx } from '../../dynamo-rx'
66
import { and } from '../../expression/logical-operator/and.function'
7+
import { attribute } from '../../expression/logical-operator/attribute.function'
78
import { ParamUtil } from '../../expression/param-util'
89
import { RequestExpressionBuilder } from '../../expression/request-expression-builder'
910
import { ConditionExpressionDefinitionFunction } from '../../expression/type/condition-expression-definition-function'
10-
import { Expression } from '../../expression/type/expression.type'
1111
import { RequestConditionFunction } from '../../expression/type/request-condition-function'
1212
import { BaseRequest } from '../base.request'
1313

@@ -23,8 +23,16 @@ export class PutRequest<T> extends BaseRequest<T, any> {
2323
*/
2424
ifNotExists(predicate?: boolean): PutRequest<T> {
2525
// FIXME should we check for sort key too?
26+
const conditionDefFns = []
2627
if (predicate === undefined || (predicate !== undefined && predicate === true)) {
27-
this.whereAttribute(this.metaData.getPartitionKey()).null()
28+
conditionDefFns.push(attribute<T>(this.metaData.getPartitionKey()).null())
29+
30+
const sortKey = this.metaData.getSortKey()
31+
if (sortKey !== null) {
32+
conditionDefFns.push(attribute<T>(sortKey).null())
33+
}
34+
35+
this.where(...conditionDefFns)
2836
}
2937

3038
return this
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as moment from 'moment-es6'
2+
import { PartitionKey } from '../../src/decorator/impl/key/partition-key.decorator'
3+
import { SortKey } from '../../src/decorator/impl/key/sort-key.decorator'
4+
import { Model } from '../../src/decorator/impl/model/model.decorator'
5+
6+
@Model()
7+
export class SimpleWithCompositePartitionKeyModel {
8+
@PartitionKey() id: string
9+
10+
@SortKey() creationDate: moment.Moment
11+
12+
age: number
13+
}

test/models/simple-with-id.model.ts renamed to test/models/simple-with-partition-key.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { PartitionKey } from '../../src/decorator/impl/key/partition-key.decorat
22
import { Model } from '../../src/decorator/impl/model/model.decorator'
33

44
@Model()
5-
export class SimpleWithIdModel {
5+
export class SimpleWithPartitionKeyModel {
66
@PartitionKey() id: string
77

88
age: number

0 commit comments

Comments
 (0)