diff --git a/dbms/src/Columns/ColumnArray.cpp b/dbms/src/Columns/ColumnArray.cpp index b4382755ba3..b825342ee5f 100644 --- a/dbms/src/Columns/ColumnArray.cpp +++ b/dbms/src/Columns/ColumnArray.cpp @@ -178,11 +178,16 @@ StringRef ColumnArray::serializeValueIntoArena(size_t n, Arena & arena, char con char * pos = arena.allocContinue(sizeof(array_size), begin); memcpy(pos, &array_size, sizeof(array_size)); - size_t values_size = 0; - for (size_t i = 0; i < array_size; ++i) - values_size += getData().serializeValueIntoArena(offset + i, arena, begin).size; + StringRef res(pos, sizeof(array_size)); - return StringRef(begin, sizeof(array_size) + values_size); + for (size_t i = 0; i < array_size; ++i) + { + auto value_ref = getData().serializeValueIntoArena(offset + i, arena, begin); + res.data = value_ref.data - res.size; + res.size += value_ref.size; + } + + return res; } diff --git a/dbms/src/Columns/ColumnNullable.cpp b/dbms/src/Columns/ColumnNullable.cpp index 3ae692552e8..c5cdffba84d 100644 --- a/dbms/src/Columns/ColumnNullable.cpp +++ b/dbms/src/Columns/ColumnNullable.cpp @@ -103,12 +103,13 @@ StringRef ColumnNullable::serializeValueIntoArena(size_t n, Arena & arena, char auto pos = arena.allocContinue(s, begin); memcpy(pos, &arr[n], s); - size_t nested_size = 0; + if (arr[n]) + return StringRef(pos, s); - if (arr[n] == 0) - nested_size = getNestedColumn().serializeValueIntoArena(n, arena, begin).size; + auto nested_ref = getNestedColumn().serializeValueIntoArena(n, arena, begin); - return StringRef{begin, s + nested_size}; + /// serializeValueIntoArena may reallocate memory. Have to use ptr from nested_ref.data and move it back. + return StringRef(nested_ref.data - s, nested_ref.size + s); } const char * ColumnNullable::deserializeAndInsertFromArena(const char * pos) diff --git a/dbms/src/Columns/ColumnTuple.cpp b/dbms/src/Columns/ColumnTuple.cpp index f7a95c1ac9f..3ad7f007edf 100644 --- a/dbms/src/Columns/ColumnTuple.cpp +++ b/dbms/src/Columns/ColumnTuple.cpp @@ -142,11 +142,15 @@ void ColumnTuple::popBack(size_t n) StringRef ColumnTuple::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const { - size_t values_size = 0; + StringRef res(begin, 0); for (auto & column : columns) - values_size += column->serializeValueIntoArena(n, arena, begin).size; + { + auto value_ref = column->serializeValueIntoArena(n, arena, begin); + res.data = value_ref.data - res.size; + res.size += value_ref.size; + } - return StringRef(begin, values_size); + return res; } const char * ColumnTuple::deserializeAndInsertFromArena(const char * pos) diff --git a/dbms/src/Columns/ColumnUnique.h b/dbms/src/Columns/ColumnUnique.h index febdeaafa95..0c5efd8058d 100644 --- a/dbms/src/Columns/ColumnUnique.h +++ b/dbms/src/Columns/ColumnUnique.h @@ -300,19 +300,19 @@ StringRef ColumnUnique::serializeValueIntoArena(size_t n, Arena & ar { if (is_nullable) { - const UInt8 null_flag = 1; - const UInt8 not_null_flag = 0; + static constexpr auto s = sizeof(UInt8); - auto pos = arena.allocContinue(sizeof(null_flag), begin); - auto & flag = (n == getNullValueIndex() ? null_flag : not_null_flag); - memcpy(pos, &flag, sizeof(flag)); + auto pos = arena.allocContinue(s, begin); + UInt8 flag = (n == getNullValueIndex() ? 1 : 0); + unalignedStore(pos, flag); - size_t nested_size = 0; + if (n == getNullValueIndex()) + return StringRef(pos, s); - if (n != getNullValueIndex()) - nested_size = column_holder->serializeValueIntoArena(n, arena, begin).size; + auto nested_ref = column_holder->serializeValueIntoArena(n, arena, begin); - return StringRef(pos, sizeof(null_flag) + nested_size); + /// serializeValueIntoArena may reallocate memory. Have to use ptr from nested_ref.data and move it back. + return StringRef(nested_ref.data - s, nested_ref.size + s); } return column_holder->serializeValueIntoArena(n, arena, begin);