// hit a put, merge the put value with operands and store the
// final result in saved_value_. We are done!
const Slice val = iter_.value();
- Status s = Merge(&val, ikey.user_key);
- if (!s.ok()) {
+ if (!Merge(&val, ikey.user_key)) {
return false;
}
// iter_ is positioned after put
return false;
}
valid_ = true;
- Status s = Merge(&blob_value_, ikey.user_key);
- if (!s.ok()) {
+ if (!Merge(&blob_value_, ikey.user_key)) {
return false;
}
}
return true;
} else if (kTypeWideColumnEntity == ikey.type) {
- // TODO: support wide-column entities
- status_ = Status::NotSupported(
- "Merge currently not supported for wide-column entities");
- valid_ = false;
- return false;
+ if (!MergeEntity(iter_.value(), ikey.user_key)) {
+ return false;
+ }
+
+ // iter_ is positioned after put
+ iter_.Next();
+ if (!iter_.status().ok()) {
+ valid_ = false;
+ return false;
+ }
+
+ return true;
} else {
valid_ = false;
status_ = Status::Corruption(
// a deletion marker.
// feed null as the existing value to the merge operator, such that
// client can differentiate this scenario and do things accordingly.
- Status s = Merge(nullptr, saved_key_.GetUserKey());
- if (!s.ok()) {
+ if (!Merge(nullptr, saved_key_.GetUserKey())) {
return false;
}
assert(status_.ok());
if (last_not_merge_type == kTypeDeletion ||
last_not_merge_type == kTypeSingleDeletion ||
last_not_merge_type == kTypeDeletionWithTimestamp) {
- s = Merge(nullptr, saved_key_.GetUserKey());
- if (!s.ok()) {
+ if (!Merge(nullptr, saved_key_.GetUserKey())) {
return false;
}
return true;
return false;
}
valid_ = true;
- s = Merge(&blob_value_, saved_key_.GetUserKey());
- if (!s.ok()) {
+ if (!Merge(&blob_value_, saved_key_.GetUserKey())) {
return false;
}
return true;
} else if (last_not_merge_type == kTypeWideColumnEntity) {
- // TODO: support wide-column entities
- status_ = Status::NotSupported(
- "Merge currently not supported for wide-column entities");
- valid_ = false;
- return false;
+ if (!MergeEntity(pinned_value_, saved_key_.GetUserKey())) {
+ return false;
+ }
+
+ return true;
} else {
assert(last_not_merge_type == kTypeValue);
- s = Merge(&pinned_value_, saved_key_.GetUserKey());
- if (!s.ok()) {
+ if (!Merge(&pinned_value_, saved_key_.GetUserKey())) {
return false;
}
return true;
if (ikey.type == kTypeValue) {
const Slice val = iter_.value();
- Status s = Merge(&val, saved_key_.GetUserKey());
- if (!s.ok()) {
+ if (!Merge(&val, saved_key_.GetUserKey())) {
return false;
}
return true;
return false;
}
valid_ = true;
- Status s = Merge(&blob_value_, saved_key_.GetUserKey());
- if (!s.ok()) {
+ if (!Merge(&blob_value_, saved_key_.GetUserKey())) {
return false;
}
return true;
} else if (ikey.type == kTypeWideColumnEntity) {
- // TODO: support wide-column entities
- status_ = Status::NotSupported(
- "Merge currently not supported for wide-column entities");
- valid_ = false;
- return false;
+ if (!MergeEntity(iter_.value(), saved_key_.GetUserKey())) {
+ return false;
+ }
+
+ return true;
} else {
valid_ = false;
status_ = Status::Corruption(
}
}
- Status s = Merge(nullptr, saved_key_.GetUserKey());
- if (!s.ok()) {
+ if (!Merge(nullptr, saved_key_.GetUserKey())) {
return false;
}
return true;
}
-Status DBIter::Merge(const Slice* val, const Slice& user_key) {
+bool DBIter::Merge(const Slice* val, const Slice& user_key) {
Status s = MergeHelper::TimedFullMerge(
merge_operator_, user_key, val, merge_context_.GetOperands(),
&saved_value_, logger_, statistics_, clock_, &pinned_value_,
if (!s.ok()) {
valid_ = false;
status_ = s;
- return s;
+ return false;
}
SetValueAndColumnsFromPlain(pinned_value_.data() ? pinned_value_
: saved_value_);
valid_ = true;
- return s;
+ return true;
+}
+
+bool DBIter::MergeEntity(const Slice& entity, const Slice& user_key) {
+ Status s = MergeHelper::TimedFullMergeWithEntity(
+ merge_operator_, user_key, entity, merge_context_.GetOperands(),
+ &saved_value_, logger_, statistics_, clock_,
+ /* update_num_ops_stats */ true);
+ if (!s.ok()) {
+ valid_ = false;
+ status_ = s;
+ return false;
+ }
+
+ if (!SetValueAndColumnsFromEntity(saved_value_)) {
+ return false;
+ }
+
+ valid_ = true;
+ return true;
}
// Move backwards until the key smaller than saved_key_.
auto verify = [&]() {
const std::string first_expected_default(
first_columns[0].value().ToString() + delim + first_merge_operand);
+ WideColumns first_expected_columns{
+ {kDefaultWideColumnName, first_expected_default},
+ first_columns[1],
+ first_columns[2]};
+
+ const std::string second_expected_default(delim + second_merge_operand);
+ WideColumns second_expected_columns{
+ {kDefaultWideColumnName, second_expected_default},
+ second_columns[0],
+ second_columns[1]};
{
PinnableSlice result;
PinnableWideColumns result;
ASSERT_OK(db_->GetEntity(ReadOptions(), db_->DefaultColumnFamily(),
first_key, &result));
-
- WideColumns expected_columns{
- {kDefaultWideColumnName, first_expected_default},
- first_columns[1],
- first_columns[2]};
-
- ASSERT_EQ(result.columns(), expected_columns);
+ ASSERT_EQ(result.columns(), first_expected_columns);
}
{
ASSERT_EQ(merge_operands[1], first_merge_operand);
}
- const std::string second_expected_default(delim + second_merge_operand);
-
{
PinnableSlice result;
ASSERT_OK(db_->Get(ReadOptions(), db_->DefaultColumnFamily(), second_key,
PinnableWideColumns result;
ASSERT_OK(db_->GetEntity(ReadOptions(), db_->DefaultColumnFamily(),
second_key, &result));
-
- WideColumns expected_columns{
- {kDefaultWideColumnName, second_expected_default},
- second_columns[0],
- second_columns[1]};
-
- ASSERT_EQ(result.columns(), expected_columns);
+ ASSERT_EQ(result.columns(), second_expected_columns);
}
{
ASSERT_OK(statuses[1]);
}
- // Note: Merge is currently not supported for wide-column entities in
- // iterator
{
std::unique_ptr<Iterator> iter(db_->NewIterator(ReadOptions()));
iter->SeekToFirst();
+ ASSERT_TRUE(iter->Valid());
+ ASSERT_OK(iter->status());
+ ASSERT_EQ(iter->key(), first_key);
+ ASSERT_EQ(iter->value(), first_expected_default);
+ ASSERT_EQ(iter->columns(), first_expected_columns);
+
+ iter->Next();
+ ASSERT_TRUE(iter->Valid());
+ ASSERT_OK(iter->status());
+ ASSERT_EQ(iter->key(), second_key);
+ ASSERT_EQ(iter->value(), second_expected_default);
+ ASSERT_EQ(iter->columns(), second_expected_columns);
+
+ iter->Next();
ASSERT_FALSE(iter->Valid());
- ASSERT_TRUE(iter->status().IsNotSupported());
+ ASSERT_OK(iter->status());
iter->SeekToLast();
+ ASSERT_TRUE(iter->Valid());
+ ASSERT_OK(iter->status());
+ ASSERT_EQ(iter->key(), second_key);
+ ASSERT_EQ(iter->value(), second_expected_default);
+ ASSERT_EQ(iter->columns(), second_expected_columns);
+
+ iter->Prev();
+ ASSERT_TRUE(iter->Valid());
+ ASSERT_OK(iter->status());
+ ASSERT_EQ(iter->key(), first_key);
+ ASSERT_EQ(iter->value(), first_expected_default);
+ ASSERT_EQ(iter->columns(), first_expected_columns);
+
+ iter->Prev();
ASSERT_FALSE(iter->Valid());
- ASSERT_TRUE(iter->status().IsNotSupported());
+ ASSERT_OK(iter->status());
}
};