diff --git a/dbms/src/DataStreams/NativeBlockInputStream.cpp b/dbms/src/DataStreams/NativeBlockInputStream.cpp index 07e56c24d96..f5305755863 100644 --- a/dbms/src/DataStreams/NativeBlockInputStream.cpp +++ b/dbms/src/DataStreams/NativeBlockInputStream.cpp @@ -5,7 +5,10 @@ #include #include +#include +#include #include +#include #include #include @@ -21,6 +24,20 @@ namespace ErrorCodes extern const int CANNOT_READ_ALL_DATA; } +namespace +{ + +void deserializeNullValuesByteMap(ColumnNullable & nullable_col, ReadBuffer & istr, size_t limit) +{ + ColumnUInt8 & null_map = static_cast(*(nullable_col.getNullValuesByteMap().get())); + auto & x = null_map.getData(); + + x.resize(limit); + size_t read_count = istr.readBig(reinterpret_cast(&x[0]), limit); + x.resize(read_count); +} + +} NativeBlockInputStream::NativeBlockInputStream( ReadBuffer & istr_, UInt64 server_revision_, @@ -43,10 +60,23 @@ NativeBlockInputStream::NativeBlockInputStream( void NativeBlockInputStream::readData(const IDataType & type, IColumn & column, ReadBuffer & istr, size_t rows) { - /** Для массивов требуется сначала десериализовать смещения, а потом значения. - */ - if (const DataTypeArray * type_arr = typeid_cast(&type)) + if (type.isNullable()) { + const DataTypeNullable & nullable_type = static_cast(type); + const IDataType & nested_type = *(nullable_type.getNestedType().get()); + + ColumnNullable & nullable_col = static_cast(column); + IColumn & nested_col = *(nullable_col.getNestedColumn().get()); + + deserializeNullValuesByteMap(nullable_col, istr, rows); + readData(nested_type, nested_col, istr, rows); + + return; + } + else if (const DataTypeArray * type_arr = typeid_cast(&type)) + { + /** Для массивов требуется сначала десериализовать смещения, а потом значения. + */ IColumn & offsets_column = *typeid_cast(column).getOffsetsColumn(); type_arr->getOffsetsType()->deserializeBinary(offsets_column, istr, rows, 0); diff --git a/dbms/src/DataStreams/NativeBlockOutputStream.cpp b/dbms/src/DataStreams/NativeBlockOutputStream.cpp index 6b93c4dd8d4..64531a59694 100644 --- a/dbms/src/DataStreams/NativeBlockOutputStream.cpp +++ b/dbms/src/DataStreams/NativeBlockOutputStream.cpp @@ -6,8 +6,11 @@ #include #include +#include +#include #include +#include #include #include @@ -16,6 +19,23 @@ namespace DB { +namespace +{ + +void serializeNullValuesByteMap(const ColumnNullable & nullable_col, WriteBuffer & ostr, size_t offset, size_t limit) +{ + const IColumn & nested_col = *(nullable_col.getNestedColumn().get()); + const ColumnUInt8 & content = static_cast(*(nullable_col.getNullValuesByteMap().get())); + const auto & x = content.getData(); + + size_t size = nested_col.size(); + if ((limit == 0) || (offset + limit) > size) + limit = size - offset; + + ostr.write(reinterpret_cast(&x[offset]), limit); +} + +} NativeBlockOutputStream::NativeBlockOutputStream( WriteBuffer & ostr_, UInt64 client_revision_, @@ -44,10 +64,21 @@ void NativeBlockOutputStream::writeData(const IDataType & type, const ColumnPtr else full_column = column; - /** Для массивов требуется сначала сериализовать смещения, а потом значения. - */ - if (const DataTypeArray * type_arr = typeid_cast(&type)) + if (type.isNullable()) { + const DataTypeNullable & nullable_type = static_cast(type); + const IDataType & nested_type = *(nullable_type.getNestedType().get()); + + const ColumnNullable & nullable_col = static_cast(*full_column.get()); + const ColumnPtr & nested_col = nullable_col.getNestedColumn(); + + serializeNullValuesByteMap(nullable_col, ostr, offset, limit); + writeData(nested_type, nested_col, ostr, offset, limit); + } + else if (const DataTypeArray * type_arr = typeid_cast(&type)) + { + /** Для массивов требуется сначала сериализовать смещения, а потом значения. + */ const ColumnArray & column_array = typeid_cast(*full_column); type_arr->getOffsetsType()->serializeBinary(*column_array.getOffsetsColumn(), ostr, offset, limit);