diff options
Diffstat (limited to 'src/mongo/bson')
-rw-r--r-- | src/mongo/bson/util/bsoncolumn_test.cpp | 31 | ||||
-rw-r--r-- | src/mongo/bson/util/bsoncolumnbuilder.cpp | 12 |
2 files changed, 42 insertions, 1 deletions
diff --git a/src/mongo/bson/util/bsoncolumn_test.cpp b/src/mongo/bson/util/bsoncolumn_test.cpp index 6ab45991fb2..17572486ea0 100644 --- a/src/mongo/bson/util/bsoncolumn_test.cpp +++ b/src/mongo/bson/util/bsoncolumn_test.cpp @@ -3577,6 +3577,37 @@ TEST_F(BSONColumnTest, InterleavedIncompatibleAfterDeterminedReference) { verifyDecompression(binData, elems); } +TEST_F(BSONColumnTest, InterleavedSkipAfterEmptySubObj) { + BSONColumnBuilder cb("test"_sd); + + std::vector<BSONElement> elems = { + createElementObj(BSON("x" << 1 << "y" << 2 << "z" << BSON("z1" << BSONObjBuilder().obj()))), + BSONElement()}; + + for (auto elem : elems) { + if (!elem.eoo()) + cb.append(elem); + else + cb.skip(); + } + + BufBuilder expected; + appendInterleavedStart(expected, elems.front().Obj()); + appendSimple8bControl(expected, 0b1000, 0b0000); + appendSimple8bBlocks64(expected, {kDeltaForBinaryEqualValues}, 1); + appendSimple8bControl(expected, 0b1000, 0b0000); + appendSimple8bBlocks64(expected, {kDeltaForBinaryEqualValues}, 1); + appendEOO(expected); + + appendSimple8bControl(expected, 0b1000, 0b0000); + appendSimple8bBlock64(expected, boost::none); + appendEOO(expected); + + auto binData = cb.finalize(); + verifyBinary(binData, expected); + verifyDecompression(binData, elems); +} + TEST_F(BSONColumnTest, ObjectEmpty) { BSONColumnBuilder cb("test"_sd); diff --git a/src/mongo/bson/util/bsoncolumnbuilder.cpp b/src/mongo/bson/util/bsoncolumnbuilder.cpp index 3a77fdbd83c..9156b56a5f4 100644 --- a/src/mongo/bson/util/bsoncolumnbuilder.cpp +++ b/src/mongo/bson/util/bsoncolumnbuilder.cpp @@ -360,7 +360,17 @@ BSONColumnBuilder& BSONColumnBuilder::append(BSONElement elem) { BSONColumnBuilder& BSONColumnBuilder::skip() { if (_mode == Mode::kRegular) { _state.skip(); - } else if (_mode == Mode::kSubObjDeterminingReference) { + return *this; + } + + // If the reference object contain any empty subobjects we need to end interleaved mode as + // skipping in all substreams would not be encoded as skipped root object. + if (_hasEmptyObj(_referenceSubObj)) { + _flushSubObjMode(); + return skip(); + } + + if (_mode == Mode::kSubObjDeterminingReference) { _bufferedObjElements.push_back(BSONObj()); } else { for (auto&& state : _subobjStates) { |