Skip to content

Commit

Permalink
Merge pull request #366 from Dmitry-k42/master
Browse files Browse the repository at this point in the history
Fix for issue #363: exception raises on insert to a nullable low cardinality columns
  • Loading branch information
xzkostyan committed Apr 1, 2023
2 parents 94f2585 + 6c2cc33 commit 57a60cd
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
16 changes: 15 additions & 1 deletion clickhouse_driver/columns/lowcardinalitycolumn.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,14 @@ def write_state_prefix(self, buf):
def _write_data(self, items, buf):
index, keys = [], []
key_by_index_element = {}
nested_is_nullable = False

if self.nested_column.nullable:
# First element represents NULL if column is nullable.
index.append(self.nested_column.null_value)
# Prevent null map writing. Reset nested column nullable flag.
self.nested_column.nullable = False
nested_is_nullable = True

for x in items:
if x is None:
Expand Down Expand Up @@ -94,7 +96,19 @@ def _write_data(self, items, buf):
write_binary_int64(serialization_type, buf)
write_binary_int64(len(index), buf)

self.nested_column.write_data(index, buf)
if nested_is_nullable:
# Given we reset nested column nullable flag above,
# we need to write null map manually. If to invoke
# write_data method, it will cause an exception,
# because `prepare_data` may not be able to handle
# null value correctly.
self.nested_column.write_items(
[self.nested_column.null_value], buf)
# Remove null map from index, because it is already written.
index_to_write = index[1:]
self.nested_column.write_data(index_to_write, buf)
else:
self.nested_column.write_data(index, buf)
write_binary_int64(len(items), buf)
int_column.write_items(keys, buf)

Expand Down
9 changes: 9 additions & 0 deletions tests/columns/test_low_cardinality.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ def test_date(self):
inserted = self.client.execute(query)
self.assertEqual(inserted, data)

def test_nullable_date(self):
with self.create_table('a LowCardinality(Nullable(Date))'):
data = [(date(2023, 4, 1), ), (None, ), (date(1970, 1, 1), )]
self.client.execute('INSERT INTO test (a) VALUES', data)

query = 'SELECT * FROM test'
inserted = self.client.execute(query)
self.assertEqual(inserted, data)

def test_float(self):
with self.create_table('a LowCardinality(Float)'):
data = [(float(x),) for x in range(300)]
Expand Down

0 comments on commit 57a60cd

Please sign in to comment.