diff options
author | Innokentii Mokin <innokentii@ydb.tech> | 2024-07-16 00:54:36 +0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-15 20:54:36 +0300 |
commit | d0c6dfb408e65296029d06fbbfb68f37f8865fde (patch) | |
tree | 3cc8eaab7030fe54b36e3bf522499bbaf1b8b97d | |
parent | e1cde29891b6df64b6cd2ef3dff66ce675f32160 (diff) | |
download | ydb-d0c6dfb408e65296029d06fbbfb68f37f8865fde.tar.gz |
add unsafe append to tablecell (#6696)
-rw-r--r-- | ydb/core/scheme/scheme_tablecell.cpp | 39 | ||||
-rw-r--r-- | ydb/core/scheme/scheme_tablecell.h | 3 | ||||
-rw-r--r-- | ydb/core/scheme/scheme_tablecell_ut.cpp | 33 |
3 files changed, 75 insertions, 0 deletions
diff --git a/ydb/core/scheme/scheme_tablecell.cpp b/ydb/core/scheme/scheme_tablecell.cpp index 77c0e331919..1cb11cb1b9d 100644 --- a/ydb/core/scheme/scheme_tablecell.cpp +++ b/ydb/core/scheme/scheme_tablecell.cpp @@ -258,6 +258,45 @@ bool TSerializedCellVec::DoTryParse(const TString& data) { return TryDeserializeCellVec(data, Buf, Cells); } +bool TSerializedCellVec::UnsafeAppendCells(TConstArrayRef<TCell> cells, TString& serializedCellVec) { + if (Y_UNLIKELY(cells.size() == 0)) { + return true; + } + + if (!serializedCellVec) { + TSerializedCellVec::Serialize(serializedCellVec, cells); + return true; + } + + const char* buf = serializedCellVec.data(); + const char* bufEnd = serializedCellVec.data() + serializedCellVec.size(); + const size_t bufSize = bufEnd - buf; + + if (Y_UNLIKELY(bufSize < static_cast<ptrdiff_t>(sizeof(ui16)))) { + return false; + } + + ui16 cellCount = ReadUnaligned<ui16>(buf); + cellCount += cells.size(); + + size_t newSize = serializedCellVec.size(); + + for (auto& cell : cells) { + newSize += sizeof(TCellHeader) + cell.Size(); + } + + serializedCellVec.ReserveAndResize(newSize); + + char* mutableBuf = serializedCellVec.Detach(); + char* oldBufEnd = mutableBuf + bufSize; + + WriteUnaligned<ui16>(mutableBuf, cellCount); + + SerializeCellVecBody(cells, oldBufEnd, nullptr); + + return true; +} + TSerializedCellMatrix::TSerializedCellMatrix(TConstArrayRef<TCell> cells, ui32 rowCount, ui16 colCount) : RowCount(rowCount), ColCount(colCount) { diff --git a/ydb/core/scheme/scheme_tablecell.h b/ydb/core/scheme/scheme_tablecell.h index 752be860abc..5ce8d5515cc 100644 --- a/ydb/core/scheme/scheme_tablecell.h +++ b/ydb/core/scheme/scheme_tablecell.h @@ -555,6 +555,9 @@ public: return Cells; } + // read headers, assuming the buf is correct and append additional cells at the end + static bool UnsafeAppendCells(TConstArrayRef<TCell> cells, TString& serializedCellVec); + static void Serialize(TString& res, TConstArrayRef<TCell> cells); static TString Serialize(TConstArrayRef<TCell> cells); diff --git a/ydb/core/scheme/scheme_tablecell_ut.cpp b/ydb/core/scheme/scheme_tablecell_ut.cpp index ae780b8cfc5..e842cf5268e 100644 --- a/ydb/core/scheme/scheme_tablecell_ut.cpp +++ b/ydb/core/scheme/scheme_tablecell_ut.cpp @@ -507,4 +507,37 @@ Y_UNIT_TEST_SUITE(Scheme) { } } } + + Y_UNIT_TEST(UnsafeAppend) { + TString appended = TSerializedCellVec::Serialize({}); + + UNIT_ASSERT(TSerializedCellVec::UnsafeAppendCells({}, appended)); + + UNIT_ASSERT_EQUAL(appended.size(), 0); + + ui64 intVal = 42; + char bigStrVal[] = "This is a large string value that shouldn't be inlined"; + + TVector<TCell> cells; + cells.emplace_back(TCell::Make(intVal)); + cells.emplace_back(bigStrVal, sizeof(bigStrVal)); + + UNIT_ASSERT(TSerializedCellVec::UnsafeAppendCells(cells, appended)); + TString serialized = TSerializedCellVec::Serialize(cells); + + UNIT_ASSERT_VALUES_EQUAL(appended, serialized); + + UNIT_ASSERT(TSerializedCellVec::UnsafeAppendCells(cells, appended)); + + cells.emplace_back(TCell::Make(intVal)); + cells.emplace_back(bigStrVal, sizeof(bigStrVal)); + + serialized = TSerializedCellVec::Serialize(cells); + + UNIT_ASSERT_VALUES_EQUAL(appended, serialized); + + appended.resize(1); + + UNIT_ASSERT(!TSerializedCellVec::UnsafeAppendCells(cells, appended)); + } } |