dynamodb-toolbox
dynamodb-toolbox copied to clipboard
Update issue with default
If you have an entity defined with a field which defaults to some value whenever you call update the default overwrites whatever value was there. This was surprising to me. I would have expected the default value only to write if there was no previous value
e.g.
const Group = new Entity({
name: 'Group',
attributes: {
pk: {
type: 'string',
partitionKey: true,
required: true,
},
foo: { type: string },
enabled: {
type: 'boolean',
default: false,
}
},
table: MainTable,
})
const pk = 'asdf'
await Group.put({ pk, enabled: true }) // enabled is true
await Group.update({pk, foo: 'asdf'}) // enabled is now false
side bug is that you can't have a required boolean field set to false
Hmm, let me look into this.
The library is generating the following parameters:
{
TableName: 'test-table',
Key: { pk: 'asdf' },
UpdateExpression: 'SET #enabled = if_not_exists(#enabled,:enabled), #_ct = if_not_exists(#_ct,:_ct), #_md = :_md, #_et = if_not_exists(#_et,:_et), #foo = :foo',
ExpressionAttributeNames: {
'#enabled': 'enabled',
'#_ct': '_ct',
'#_md': '_md',
'#_et': '_et',
'#foo': 'foo'
},
ExpressionAttributeValues: {
':enabled': false,
':_ct': '2020-11-19T21:19:12.952Z',
':_md': '2020-11-19T21:19:12.952Z',
':_et': 'Group',
':foo': 'asdf'
}
}
This should be working correctly, but I'll try it out on a live table.
Can you use updateParams or add the execute: false flag to your update and post that here? I'm getting the correct parameters for both v0.2 and v0.3.
await Group.put({ pk, enabled: true })
{
TableName: 'Group',
Key: {
pk: 'asdf',
},
UpdateExpression: 'SET #createdAt = if_not_exists(#createdAt,:createdAt), #updatedAt = if_not_exists(#updatedAt,:updatedAt), #enabled = :enabled',
ExpressionAttributeNames: {
'#createdAt': 'createdAt',
'#updatedAt': 'updatedAt',
'#enabled': 'enabled'
},
ExpressionAttributeValues: {
':createdAt': 1605888916731,
':updatedAt': 1605888916731,
':enabled': true
}
}
await Group.update({pk, foo: 'asdf'})
{
TableName: 'Group',
Key: {
pk: 'asdf',
},
UpdateExpression: 'SET #createdAt = if_not_exists(#createdAt,:createdAt), #updatedAt = if_not_exists(#updatedAt,:updatedAt), #enabled = :enabled, #foo = :foo',
ExpressionAttributeNames: {
'#createdAt': 'createdAt',
'#updatedAt': 'updatedAt',
'#enabled': 'enabled',
'#foo': 'foo'
},
ExpressionAttributeValues: {
':createdAt': 1605888916733,
':updatedAt': 1605888916733,
':enabled': false,
':foo': 'asdf'
}
}
Interestingly using enabled: () => false works instead of enabled: false
using the former:
{
TableName: 'Group',
Key: {
key: 'asdf',
},
UpdateExpression: 'SET #createdAt = if_not_exists(#createdAt,:createdAt), #updatedAt = if_not_exists(#updatedAt,:updatedAt), #enabled = if_not_exists(#enabled,:enabled), #foo = :foo',
ExpressionAttributeNames: {
'#createdAt': 'createdAt',
'#updatedAt': 'updatedAt',
'#enabled': 'enabled',
'#foo': 'foo'
},
ExpressionAttributeValues: {
':createdAt': 1605889046135,
':updatedAt': 1605889046135,
':enabled': false,
':foo': 'asdf'
}
}
note the if_not_exists is missing
Thanks for this. I'll take another look.
Using version 0.2.0-beta.1 FYI 💁♂️
What is the default behaviour or default?
Should it only populate on first go? Or should default be calculated each time?
I still can't duplicate this. Unless onUpdate is set to true, then any default value generates the "if_not_exists" in the UpdateExpression like this: #enabled = if_not_exists(#enabled,:enabled).
Can anyone else replicate this behavior?
Can anyone else replicate this behavior?
I can't.
I have done negative testing using 0.3.1 (updating an entity where onUpdate is false) and this is working as intended for me (I.e. the default is not recalculated).
I think this can be closed.
Hey @mfbx9da4, thanks for opening this issue, I've also tried to re-create this without success.
I'll be closing this issue, feel free to ping me or open a new issue if this issue still persists for you.