aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorInnokentii Mokin <innokentii@ydb.tech>2024-07-16 00:54:36 +0700
committerGitHub <noreply@github.com>2024-07-15 20:54:36 +0300
commitd0c6dfb408e65296029d06fbbfb68f37f8865fde (patch)
tree3cc8eaab7030fe54b36e3bf522499bbaf1b8b97d
parente1cde29891b6df64b6cd2ef3dff66ce675f32160 (diff)
downloadydb-d0c6dfb408e65296029d06fbbfb68f37f8865fde.tar.gz
add unsafe append to tablecell (#6696)
-rw-r--r--ydb/core/scheme/scheme_tablecell.cpp39
-rw-r--r--ydb/core/scheme/scheme_tablecell.h3
-rw-r--r--ydb/core/scheme/scheme_tablecell_ut.cpp33
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));
+ }
}