1
0
Fork 0

added mergeArrays

This commit is contained in:
Jan Steemann 2014-11-28 14:07:36 +01:00
parent a1892e0c7a
commit 7ef8097fe1
17 changed files with 89 additions and 16 deletions

View File

@ -3369,7 +3369,7 @@ void UpdateBlock::work (std::vector<AqlItemBlock*>& blocks) {
TRI_json_t* old = TRI_JsonShapedJson(_collection->documentCollection()->getShaper(), &shapedJson);
if (old != nullptr) {
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json.json(), ep->_options.nullMeansRemove);
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json.json(), ep->_options.nullMeansRemove, ep->_options.mergeArrays);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, old);
if (patchedJson != nullptr) {

View File

@ -251,6 +251,9 @@ ModificationOptions ExecutionPlan::createOptions (AstNode const* node) {
// nullMeansRemove is the opposite of keepNull
options.nullMeansRemove = value->isFalse();
}
else if (strcmp(name, "mergeArrays") == 0) {
options.mergeArrays = value->isTrue();
}
}
}
}

View File

@ -36,6 +36,7 @@ ModificationOptions::ModificationOptions (Json const& json) {
ignoreErrors = JsonHelper::getBooleanValue(array.json(), "ignoreErrors", false);
waitForSync = JsonHelper::getBooleanValue(array.json(), "waitForSync", false);
nullMeansRemove = JsonHelper::getBooleanValue(array.json(), "nullMeansRemove", false);
mergeArrays = JsonHelper::getBooleanValue(array.json(), "mergeArrays", false);
}
void ModificationOptions::toJson (triagens::basics::Json& json,
@ -44,7 +45,8 @@ void ModificationOptions::toJson (triagens::basics::Json& json,
flags = Json(Json::Array, 3)
("ignoreErrors", Json(ignoreErrors))
("waitForSync", Json(waitForSync))
("nullMeansRemove", Json(nullMeansRemove));
("nullMeansRemove", Json(nullMeansRemove))
("mergeArrays", Json(mergeArrays));
json ("modificationFlags", flags);
}

View File

@ -53,7 +53,8 @@ namespace triagens {
ModificationOptions ()
: ignoreErrors(false),
waitForSync(false),
nullMeansRemove(false) {
nullMeansRemove(false),
mergeArrays(false) {
}
void toJson (triagens::basics::Json& json, TRI_memory_zone_t* zone) const;
@ -65,6 +66,7 @@ namespace triagens {
bool ignoreErrors;
bool waitForSync;
bool nullMeansRemove;
bool mergeArrays;
};

View File

@ -1051,6 +1051,7 @@ int modifyDocumentOnCoordinator (
bool waitForSync,
bool isPatch,
bool keepNull, // only counts for isPatch == true
bool mergeArrays, // only counts for isPatch == true
TRI_json_t* json,
map<string, string> const& headers,
triagens::rest::HttpResponse::HttpResponseCode& responseCode,
@ -1115,6 +1116,12 @@ int modifyDocumentOnCoordinator (
if (! keepNull) {
revstr += "&keepNull=false";
}
if (mergeArrays) {
revstr += "&mergeArrays=true";
}
else {
revstr += "&mergeArrays=false";
}
}
else {
reqType = triagens::rest::HttpRequest::HTTP_REQUEST_PUT;

View File

@ -177,6 +177,7 @@ namespace triagens {
bool waitForSync,
bool isPatch,
bool keepNull, // only counts for isPatch == true
bool mergeArrays, // only counts for isPatch == true
TRI_json_t* json,
std::map<std::string, std::string> const& headers,
triagens::rest::HttpResponse::HttpResponseCode& responseCode,

View File

@ -1202,6 +1202,12 @@ bool RestDocumentHandler::replaceDocument () {
/// from the existing document that are contained in the patch document with an
/// attribute value of *null*.
///
/// @RESTQUERYPARAM{mergeArrays,boolean,optional}
/// Controls whether arrays (not lists) will be merged if present in both the
/// existing and the patch document. If set to *false*, the value in the
/// patch document will overwrite the existing document's value. If set to
/// *true*, arrays will be merged. The default is *true*.
///
/// @RESTQUERYPARAM{waitForSync,boolean,optional}
/// Wait until document has been synced to disk.
///
@ -1410,6 +1416,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
if (isPatch) {
// patching an existing document
bool nullMeansRemove;
bool mergeArrays;
bool found;
char const* valueStr = _request->value("keepNull", found);
if (! found || StringUtils::boolean(valueStr)) {
@ -1421,6 +1428,15 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
nullMeansRemove = true;
}
valueStr = _request->value("mergeArrays", found);
if (! found || StringUtils::boolean(valueStr)) {
// the default is true
mergeArrays = true;
}
else {
mergeArrays = false;
}
// read the existing document
TRI_doc_mptr_copy_t oldDocument;
@ -1471,7 +1487,7 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
}
}
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json, nullMeansRemove);
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json, nullMeansRemove, mergeArrays);
TRI_FreeJson(shaper->_memoryZone, old);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
@ -1574,13 +1590,17 @@ bool RestDocumentHandler::modifyDocumentCoordinator (
string resultBody;
bool keepNull = true;
if (! strcmp(_request->value("keepNull"),"false")) {
if (! strcmp(_request->value("keepNull"), "false")) {
keepNull = false;
}
bool mergeArrays = true;
if (TRI_EqualString(_request->value("mergeArrays"), "false")) {
mergeArrays = false;
}
int error = triagens::arango::modifyDocumentOnCoordinator(
dbname, collname, key, rev, policy, waitForSync, isPatch,
keepNull, json, headers, responseCode, resultHeaders, resultBody);
keepNull, mergeArrays, json, headers, responseCode, resultHeaders, resultBody);
if (error != TRI_ERROR_NO_ERROR) {
generateTransactionError(collname, error);

View File

@ -91,6 +91,7 @@ struct InsertOptions {
struct UpdateOptions {
bool overwrite = false;
bool keepNull = true;
bool mergeArrays = true;
bool waitForSync = false;
bool silent = false;
};
@ -701,6 +702,7 @@ static v8::Handle<v8::Value> ModifyVocbaseColCoordinator (
bool waitForSync,
bool isPatch,
bool keepNull, // only counts if isPatch==true
bool mergeArrays, // only counts if isPatch==true
bool silent,
v8::Arguments const& argv) {
v8::HandleScope scope;
@ -734,7 +736,7 @@ static v8::Handle<v8::Value> ModifyVocbaseColCoordinator (
error = triagens::arango::modifyDocumentOnCoordinator(
dbname, collname, key, rev, policy, waitForSync, isPatch,
keepNull, json, headers, responseCode, resultHeaders, resultBody);
keepNull, mergeArrays, json, headers, responseCode, resultHeaders, resultBody);
// Note that the json has been freed inside!
if (error != TRI_ERROR_NO_ERROR) {
@ -875,6 +877,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (bool useCollection,
options.waitForSync,
false, // isPatch
true, // keepNull, does not matter
false, // mergeArrays, does not matter
options.silent,
argv));
}
@ -1081,7 +1084,7 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (bool useCollection,
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
if (argLength < 2 || argLength > 5) {
TRI_V8_EXCEPTION_USAGE(scope, "update(<document>, <data>, {overwrite: booleanValue, keepNull: booleanValue, waitForSync: booleanValue})");
TRI_V8_EXCEPTION_USAGE(scope, "update(<document>, <data>, {overwrite: booleanValue, keepNull: booleanValue, mergeArrays: booleanValue, waitForSync: booleanValue})");
}
if (argLength > 2) {
@ -1094,6 +1097,9 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (bool useCollection,
if (optionsObject->Has(v8g->KeepNullKey)) {
options.keepNull = TRI_ObjectToBoolean(optionsObject->Get(v8g->KeepNullKey));
}
if (optionsObject->Has(v8g->MergeArraysKey)) {
options.mergeArrays = TRI_ObjectToBoolean(optionsObject->Get(v8g->MergeArraysKey));
}
if (optionsObject->Has(v8g->WaitForSyncKey)) {
options.waitForSync = TRI_ObjectToBoolean(optionsObject->Get(v8g->WaitForSyncKey));
}
@ -1160,6 +1166,7 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (bool useCollection,
options.waitForSync,
true, // isPatch
options.keepNull,
options.mergeArrays,
options.silent,
argv));
}
@ -1226,7 +1233,7 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (bool useCollection,
}
}
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json, ! options.keepNull);
TRI_json_t* patchedJson = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, old, json, ! options.keepNull, options.mergeArrays);
TRI_FreeJson(zone, old);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);

View File

@ -786,7 +786,7 @@ class KeySpace {
TRI_V8_EXCEPTION(scope, TRI_ERROR_OUT_OF_MEMORY);
}
TRI_json_t* merged = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, found->json, other, nullMeansRemove);
TRI_json_t* merged = TRI_MergeJson(TRI_UNKNOWN_MEM_ZONE, found->json, other, nullMeansRemove, false);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, other);
if (merged == nullptr) {

View File

@ -1174,6 +1174,7 @@ ArangoCollection.prototype.replace = function (id, data, overwrite, waitForSync)
/// @param id the id of the document
/// @param overwrite (optional) a boolean value or a json object
/// @param keepNull (optional) determines if null values should saved or not
/// @param mergeArrays (optional) whether or not array values should be merged
/// @param waitForSync (optional) a boolean value .
/// @example update("example/996280832675", { a : 1, c : 2} )
/// @example update("example/996280832675", { a : 1, c : 2, x: null}, true, true, true)
@ -1212,6 +1213,11 @@ ArangoCollection.prototype.update = function (id, data, overwrite, keepNull, wai
}
params = "?keepNull=" + options.keepNull;
if (! options.hasOwnProperty("mergeArrays")) {
options.mergeArrays = true;
}
params += "&mergeArrays=" + options.mergeArrays;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "&policy=last";
}

View File

@ -758,6 +758,10 @@ ArangoDatabase.prototype._update = function (id, data, overwrite, keepNull, wait
options.keepNull = true;
}
params = "?keepNull=" + options.keepNull;
if (! options.hasOwnProperty("mergeArrays")) {
options.mergeArrays = true;
}
params += "&mergeArrays=" + options.mergeArrays;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "&policy=last";

View File

@ -1173,6 +1173,7 @@ ArangoCollection.prototype.replace = function (id, data, overwrite, waitForSync)
/// @param id the id of the document
/// @param overwrite (optional) a boolean value or a json object
/// @param keepNull (optional) determines if null values should saved or not
/// @param mergeArrays (optional) whether or not array values should be merged
/// @param waitForSync (optional) a boolean value .
/// @example update("example/996280832675", { a : 1, c : 2} )
/// @example update("example/996280832675", { a : 1, c : 2, x: null}, true, true, true)
@ -1211,6 +1212,11 @@ ArangoCollection.prototype.update = function (id, data, overwrite, keepNull, wai
}
params = "?keepNull=" + options.keepNull;
if (! options.hasOwnProperty("mergeArrays")) {
options.mergeArrays = true;
}
params += "&mergeArrays=" + options.mergeArrays;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "&policy=last";
}

View File

@ -757,6 +757,10 @@ ArangoDatabase.prototype._update = function (id, data, overwrite, keepNull, wait
options.keepNull = true;
}
params = "?keepNull=" + options.keepNull;
if (! options.hasOwnProperty("mergeArrays")) {
options.mergeArrays = true;
}
params += "&mergeArrays=" + options.mergeArrays;
if (options.hasOwnProperty("overwrite") && options.overwrite) {
params += "&policy=last";

View File

@ -40,7 +40,8 @@
static TRI_json_t* MergeRecursive (TRI_memory_zone_t* zone,
TRI_json_t const* lhs,
TRI_json_t const* rhs,
bool nullMeansRemove) {
bool nullMeansRemove,
bool mergeArrays) {
TRI_json_t* result = TRI_CopyJson(zone, lhs);
if (result == nullptr) {
@ -65,7 +66,7 @@ static TRI_json_t* MergeRecursive (TRI_memory_zone_t* zone,
// existing array does not have the attribute => append new attribute
if (value->_type == TRI_JSON_ARRAY) {
TRI_json_t* empty = TRI_CreateArrayJson(zone);
TRI_json_t* merged = MergeRecursive(zone, empty, value, nullMeansRemove);
TRI_json_t* merged = MergeRecursive(zone, empty, value, nullMeansRemove, mergeArrays);
TRI_Insert3ArrayJson(zone, result, key->_value._string.data, merged);
TRI_FreeJson(zone, empty);
@ -76,8 +77,8 @@ static TRI_json_t* MergeRecursive (TRI_memory_zone_t* zone,
}
else {
// existing array already has the attribute => replace attribute
if (lhsValue->_type == TRI_JSON_ARRAY && value->_type == TRI_JSON_ARRAY) {
TRI_json_t* merged = MergeRecursive(zone, lhsValue, value, nullMeansRemove);
if (lhsValue->_type == TRI_JSON_ARRAY && value->_type == TRI_JSON_ARRAY && mergeArrays) {
TRI_json_t* merged = MergeRecursive(zone, lhsValue, value, nullMeansRemove, mergeArrays);
TRI_ReplaceArrayJson(zone, result, key->_value._string.data, merged);
TRI_FreeJson(zone, merged);
}
@ -732,13 +733,14 @@ bool TRI_HasDuplicateKeyJson (TRI_json_t const* object) {
TRI_json_t* TRI_MergeJson (TRI_memory_zone_t* zone,
TRI_json_t const* lhs,
TRI_json_t const* rhs,
bool nullMeansRemove) {
bool nullMeansRemove,
bool mergeArrays) {
TRI_json_t* result;
TRI_ASSERT(lhs->_type == TRI_JSON_ARRAY);
TRI_ASSERT(rhs->_type == TRI_JSON_ARRAY);
result = MergeRecursive(zone, lhs, rhs, nullMeansRemove);
result = MergeRecursive(zone, lhs, rhs, nullMeansRemove, mergeArrays);
return result;
}

View File

@ -137,6 +137,7 @@ bool TRI_HasDuplicateKeyJson (TRI_json_t const*);
TRI_json_t* TRI_MergeJson (TRI_memory_zone_t*,
TRI_json_t const*,
TRI_json_t const*,
bool,
bool);
////////////////////////////////////////////////////////////////////////////////

View File

@ -92,6 +92,7 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
KeyOptionsKey(),
LengthKey(),
LifeTimeKey(),
MergeArraysKey(),
NameKey(),
OperationIDKey(),
ParametersKey(),
@ -176,6 +177,7 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
KeyOptionsKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("keyOptions"));
LengthKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("length"));
LifeTimeKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("lifeTime"));
MergeArraysKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("mergeArrays"));
NameKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("name"));
OperationIDKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("operationID"));
OverwriteKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("overwrite"));

View File

@ -555,6 +555,12 @@ typedef struct TRI_v8_global_s {
v8::Persistent<v8::String> LifeTimeKey;
////////////////////////////////////////////////////////////////////////////////
/// @brief "mergeArrays" key name
////////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::String> MergeArraysKey;
////////////////////////////////////////////////////////////////////////////////
/// @brief "name" key
////////////////////////////////////////////////////////////////////////////////