mirror of https://gitee.com/bigwinds/arangodb
Fix creation of millions of VPackBuilders in edge import - part 1 - #194
This commit is contained in:
parent
d402ea62cb
commit
0669e517ed
|
@ -199,6 +199,7 @@ class Collection {
|
||||||
bool mergeValues, bool nullMeansRemove = false) {
|
bool mergeValues, bool nullMeansRemove = false) {
|
||||||
return merge(*left, *right, mergeValues, nullMeansRemove);
|
return merge(*left, *right, mergeValues, nullMeansRemove);
|
||||||
}
|
}
|
||||||
|
static Builder& merge(Builder& builder, Slice const& left, Slice const& right, bool mergeValues, bool nullMeansRemove = false);
|
||||||
|
|
||||||
static void visitRecursive(
|
static void visitRecursive(
|
||||||
Slice const& slice, VisitationOrder order,
|
Slice const& slice, VisitationOrder order,
|
||||||
|
|
|
@ -403,6 +403,71 @@ Builder Collection::merge(Slice const& left, Slice const& right,
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Builder& Collection::merge(Builder& builder, Slice const& left, Slice const& right,
|
||||||
|
bool mergeValues, bool nullMeansRemove) {
|
||||||
|
if (!left.isObject() || !right.isObject()) {
|
||||||
|
throw Exception(Exception::InvalidValueType, "Expecting type Object");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.add(Value(ValueType::Object));
|
||||||
|
|
||||||
|
std::unordered_map<std::string, Slice> rightValues;
|
||||||
|
{
|
||||||
|
ObjectIterator it(right);
|
||||||
|
while (it.valid()) {
|
||||||
|
rightValues.emplace(it.key(true).copyString(), it.value());
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ObjectIterator it(left);
|
||||||
|
|
||||||
|
while (it.valid()) {
|
||||||
|
auto key = it.key(true).copyString();
|
||||||
|
auto found = rightValues.find(key);
|
||||||
|
|
||||||
|
if (found == rightValues.end()) {
|
||||||
|
// use left value
|
||||||
|
builder.add(key, it.value());
|
||||||
|
} else if (mergeValues && it.value().isObject() &&
|
||||||
|
(*found).second.isObject()) {
|
||||||
|
// merge both values
|
||||||
|
auto& value = (*found).second;
|
||||||
|
if (!nullMeansRemove || (!value.isNone() && !value.isNull())) {
|
||||||
|
Collection::merge(builder, it.value(), value, true, nullMeansRemove);
|
||||||
|
}
|
||||||
|
// clear the value in the map so its not added again
|
||||||
|
(*found).second = Slice();
|
||||||
|
} else {
|
||||||
|
// use right value
|
||||||
|
auto& value = (*found).second;
|
||||||
|
if (!nullMeansRemove || (!value.isNone() && !value.isNull())) {
|
||||||
|
builder.add(key, value);
|
||||||
|
}
|
||||||
|
// clear the value in the map so its not added again
|
||||||
|
(*found).second = Slice();
|
||||||
|
}
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add remaining values that were only in right
|
||||||
|
for (auto& it : rightValues) {
|
||||||
|
auto& s = it.second;
|
||||||
|
if (s.isNone()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nullMeansRemove && s.isNull()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
builder.add(std::move(it.first), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.close();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
template <Collection::VisitationOrder order>
|
template <Collection::VisitationOrder order>
|
||||||
static bool doVisit(
|
static bool doVisit(
|
||||||
Slice const& slice,
|
Slice const& slice,
|
||||||
|
|
|
@ -201,7 +201,7 @@ int RestImportHandler::handleSingleDocument(SingleCollectionTransaction& trx,
|
||||||
|
|
||||||
|
|
||||||
// document ok, now import it
|
// document ok, now import it
|
||||||
VPackBuilder newBuilder;
|
transaction::BuilderLeaser newBuilder(&trx);
|
||||||
|
|
||||||
// add prefixes to _from and _to
|
// add prefixes to _from and _to
|
||||||
if (!_fromPrefix.empty() || !_toPrefix.empty()) {
|
if (!_fromPrefix.empty() || !_toPrefix.empty()) {
|
||||||
|
@ -239,9 +239,8 @@ int RestImportHandler::handleSingleDocument(SingleCollectionTransaction& trx,
|
||||||
tempBuilder->close();
|
tempBuilder->close();
|
||||||
|
|
||||||
if (tempBuilder->slice().length() > 0) {
|
if (tempBuilder->slice().length() > 0) {
|
||||||
newBuilder =
|
VPackCollection::merge(*(newBuilder.builder()), slice, tempBuilder->slice(), false, false);
|
||||||
VPackCollection::merge(slice, tempBuilder->slice(), false, false);
|
slice = newBuilder->slice();
|
||||||
slice = newBuilder.slice();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue