Skip to content

Commit d0b2aab

Browse files
authored
Attempt to stringify records that are not of the expected upstream type (#63)
* Attempt to stringify records that are not of the expected upstream type * Update version
1 parent 31d41d8 commit d0b2aab

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "shaped-target-clickhouse"
3-
version = "0.1.1"
3+
version = "0.1.2"
44
description = "`target-clickhouse` is a Singer target for clickhouse, built with the Meltano Singer SDK."
55
readme = "README.md"
66
authors = ["Ben Theunissen"]

target_clickhouse/sinks.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from typing import Any, Iterable
66

7+
import jsonschema.exceptions as jsonschema_exceptions
78
import simplejson as json
89
import sqlalchemy
910
from pendulum import now
@@ -133,3 +134,40 @@ def activate_version(self, new_version: int) -> None:
133134
)
134135
with self.connector._connect() as conn, conn.begin(): # noqa: SLF001
135136
conn.execute(query)
137+
138+
139+
# Override record validation implementation to parse objects that can be stringified
140+
# into string fields, ie. numeric or JSON.
141+
def _validate_and_parse(self, record: dict) -> dict:
142+
"""Validate or repair the record, parsing to python-native types as needed.
143+
144+
Args:
145+
record: Individual record in the stream.
146+
147+
Returns:
148+
Validated record.
149+
"""
150+
try:
151+
self._validator.validate(record)
152+
except jsonschema_exceptions.ValidationError as e:
153+
if "is not of type" in e.message and "'string'" in e.message:
154+
self.logger.warning(
155+
"Received non valid record for string type, "
156+
"attempting forced conversion to string",
157+
)
158+
for key, value in record.items():
159+
if isinstance(value, dict):
160+
record[key] = json.dumps(value)
161+
elif not isinstance(value, str):
162+
record[key] = str(value)
163+
self.logger.warning("Validating converted record")
164+
self._validator.validate(record)
165+
else:
166+
raise
167+
168+
self._parse_timestamps_in_record(
169+
record=record,
170+
schema=self.schema,
171+
treatment=self.datetime_error_treatment,
172+
)
173+
return record

0 commit comments

Comments
 (0)