Skip to content

Commit

Permalink
DynamoDB: Apply rough type evaluation and dispatching\
Browse files Browse the repository at this point in the history
... when computing values for `UPDATE` statements.
  • Loading branch information
Andreas Motl authored and amotl committed Aug 20, 2024
1 parent 23452c6 commit 97940c1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Changelog

## Unreleased
- DynamoDB: Apply rough type evaluation and dispatching when computing
values for `UPDATE` statements

## 2024/08/17 v0.0.7
- DynamoDB: Fixed a syntax issue with `text` data type in `UPDATE` statements
Expand Down
6 changes: 4 additions & 2 deletions src/commons_codec/transform/dynamodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import simplejson as json
import toolz

from commons_codec.util.data import is_container, is_number
from commons_codec.vendor.boto3.dynamodb.types import TypeDeserializer

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -145,8 +146,9 @@ def values_to_update(self, keys: t.Dict[str, t.Dict[str, str]]) -> str:

constraints: t.List[str] = []
for key_name, key_value in values_clause.items():
key_value = str(key_value).replace("'", "''")
constraint = f"{self.DATA_COLUMN}['{key_name}'] = '{key_value}'"
if not is_container(key_value) and not is_number(key_value):
key_value = "'" + str(key_value).replace("'", "''") + "'"
constraint = f"{self.DATA_COLUMN}['{key_name}'] = {key_value}"
constraints.append(constraint)

return ", ".join(constraints)
Expand Down
4 changes: 4 additions & 0 deletions src/commons_codec/util/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ def is_number(s):
pass

return False


def is_container(value):
return isinstance(value, (dict, list, set))
45 changes: 41 additions & 4 deletions tests/transform/test_dynamodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
},
"eventSource": "aws:dynamodb",
}
MSG_MODIFY = {
MSG_MODIFY_BASIC = {
"awsRegion": "us-east-1",
"eventID": "24757579-ebfd-480a-956d-a1287d2ef707",
"eventName": "MODIFY",
Expand Down Expand Up @@ -84,6 +84,35 @@
},
"eventSource": "aws:dynamodb",
}
MSG_MODIFY_NESTED = {
"awsRegion": "us-east-1",
"eventID": "24757579-ebfd-480a-956d-a1287d2ef707",
"eventName": "MODIFY",
"userIdentity": None,
"recordFormat": "application/json",
"tableName": "foo",
"dynamodb": {
"ApproximateCreationDateTime": 1720742302233719,
"Keys": {"device": {"S": "foo"}, "timestamp": {"S": "2024-07-12T01:17:42"}},
"NewImage": {
"device": {"M": {"id": {"S": "bar"}, "serial": {"N": 12345}}},
"tags": {"L": [{"S": "foo"}, {"S": "bar"}]},
"empty_map": {"M": {}},
"empty_list": {"L": []},
"timestamp": {"S": "2024-07-12T01:17:42"},
},
"OldImage": {
"humidity": {"N": "84.84"},
"temperature": {"N": "42.42"},
"device": {"S": "foo"},
"location": {"S": "Sydney"},
"timestamp": {"S": "2024-07-12T01:17:42"},
},
"SizeBytes": 161,
"ApproximateCreationDateTimePrecision": "MICROSECOND",
},
"eventSource": "aws:dynamodb",
}
MSG_REMOVE = {
"awsRegion": "us-east-1",
"eventID": "ff4e68ab-0820-4a0c-80b2-38753e8e00e5",
Expand Down Expand Up @@ -145,10 +174,18 @@ def test_decode_cdc_insert_nested():
)


def test_decode_cdc_modify():
def test_decode_cdc_modify_basic():
assert (
DynamoCDCTranslatorCrateDB(table_name="foo").to_sql(MSG_MODIFY_BASIC) == 'UPDATE "foo" '
"SET data['humidity'] = 84.84, data['temperature'] = 55.66, data['location'] = 'Sydney' "
"WHERE data['device'] = 'foo' AND data['timestamp'] = '2024-07-12T01:17:42';"
)


def test_decode_cdc_modify_nested():
assert (
DynamoCDCTranslatorCrateDB(table_name="foo").to_sql(MSG_MODIFY) == 'UPDATE "foo" '
"SET data['humidity'] = '84.84', data['temperature'] = '55.66', data['location'] = 'Sydney' "
DynamoCDCTranslatorCrateDB(table_name="foo").to_sql(MSG_MODIFY_NESTED) == 'UPDATE "foo" '
"SET data['tags'] = ['foo', 'bar'], data['empty_map'] = {}, data['empty_list'] = [] "
"WHERE data['device'] = 'foo' AND data['timestamp'] = '2024-07-12T01:17:42';"
)

Expand Down

0 comments on commit 97940c1

Please sign in to comment.