static TRI_json_t* MergeRecursive (TRI_memory_zone_t* zone, const TRI_json_t* const lhs, const TRI_json_t* const rhs, const bool nullMeansRemove) { size_t i, n; TRI_json_t* result = TRI_CopyJson(zone, lhs); if (result == NULL) { return NULL; } n = rhs->_value._objects._length; for (i = 0; i < n; i += 2) { // enumerate all the replacement values TRI_json_t* key = TRI_AtVector(&rhs->_value._objects, i); TRI_json_t* value = TRI_AtVector(&rhs->_value._objects, i + 1); if (value->_type == TRI_JSON_NULL && nullMeansRemove) { // replacement value is a null and we don't want to store nulls => delete attribute from the result TRI_DeleteArrayJson(zone, result, key->_value._string.data); } else { // replacement value is not a null or we want to store nulls TRI_json_t* lhsValue = TRI_LookupArrayJson(lhs, key->_value._string.data); if (lhsValue == NULL) { // 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_Insert3ArrayJson(zone, result, key->_value._string.data, merged); TRI_FreeJson(zone, empty); } else { TRI_Insert3ArrayJson(zone, result, key->_value._string.data, TRI_CopyJson(zone, value)); } } 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); TRI_ReplaceArrayJson(zone, result, key->_value._string.data, merged); TRI_FreeJson(zone, merged); } else { TRI_ReplaceArrayJson(zone, result, key->_value._string.data, value); } } } } return result; }
static TRI_aql_bind_parameter_t* CreateParameter (const char* const name, const size_t nameLength, const TRI_json_t* const value) { TRI_aql_bind_parameter_t* parameter; assert(name); assert(value); parameter = (TRI_aql_bind_parameter_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_bind_parameter_t), false); if (parameter == NULL) { return NULL; } parameter->_name = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, name, nameLength); if (parameter->_name == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter); return NULL; } parameter->_value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (TRI_json_t*) value); if (parameter->_value == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter->_name); TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter); return NULL; } return parameter; }
triagens::basics::Json DocumentAccessor::toJson () { if (_current == nullptr) { // we're still pointing to the original document auto shaper = _document->getShaper(); // fetch document from mptr TRI_shaped_json_t shaped; TRI_EXTRACT_SHAPED_JSON_MARKER(shaped, _mptr->getDataPtr()); triagens::basics::Json json(shaper->memoryZone(), TRI_JsonShapedJson(shaper, &shaped)); // add internal attributes // _id, _key, _rev char const* key = TRI_EXTRACT_MARKER_KEY(_mptr); std::string id(_resolver->getCollectionName(_document->_info._cid)); id.push_back('/'); id.append(key); json(TRI_VOC_ATTRIBUTE_ID, triagens::basics::Json(id)); json(TRI_VOC_ATTRIBUTE_REV, triagens::basics::Json(std::to_string(TRI_EXTRACT_MARKER_RID(_mptr)))); json(TRI_VOC_ATTRIBUTE_KEY, triagens::basics::Json(key)); if (TRI_IS_EDGE_MARKER(_mptr)) { // _from std::string from(_resolver->getCollectionNameCluster(TRI_EXTRACT_MARKER_FROM_CID(_mptr))); from.push_back('/'); from.append(TRI_EXTRACT_MARKER_FROM_KEY(_mptr)); json(TRI_VOC_ATTRIBUTE_FROM, triagens::basics::Json(from)); // _to std::string to(_resolver->getCollectionNameCluster(TRI_EXTRACT_MARKER_TO_CID(_mptr))); to.push_back('/'); to.append(TRI_EXTRACT_MARKER_TO_KEY(_mptr)); json(TRI_VOC_ATTRIBUTE_TO, triagens::basics::Json(to)); } return json; } if (_current == _json.get()) { // _current points at the JSON that we own // steal the JSON TRI_json_t* value = _json.release(); setToNull(); return triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, value); } TRI_json_t* copy = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, _current); if (copy != nullptr) { _json.release(); return triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, copy); } // fall-through intentional return triagens::basics::Json(triagens::basics::Json::Null); }
int TRI_SaveCollectionInfo (char const* path, const TRI_col_info_t* const info) { TRI_json_t* json; char* filename; bool ok; filename = TRI_Concatenate2File(path, TRI_COL_PARAMETER_FILE); // create a json info object json = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE); if (json == NULL) { // out of memory LOG_ERROR("cannot save info block '%s': out of memory", filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_ERROR_OUT_OF_MEMORY; } TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "version", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_version)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "type", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_type)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "cid", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_cid)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "deleted", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, info->_deleted)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "maximalSize", TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, info->_maximalSize)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "name", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, info->_name)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "isVolatile", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, info->_isVolatile)); TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "waitForSync", TRI_CreateBooleanJson(TRI_UNKNOWN_MEM_ZONE, info->_waitForSync)); if (info->_keyOptions) { TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, json, "keyOptions", TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, info->_keyOptions)); } // save json info to file ok = TRI_SaveJson(filename, json); TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json); if (! ok) { LOG_ERROR("cannot save info block '%s': '%s'", filename, TRI_last_error()); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_errno(); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_ERROR_NO_ERROR; }
void TRI_CopyCollectionInfo (TRI_col_info_t* dst, const TRI_col_info_t* const src) { assert(dst); memset(dst, 0, sizeof(TRI_col_info_t)); dst->_version = src->_version; dst->_type = src->_type; dst->_cid = src->_cid; dst->_rid = src->_rid; dst->_deleted = src->_deleted; dst->_isSystem = src->_isSystem; dst->_isVolatile = src->_isVolatile; dst->_maximalSize = src->_maximalSize; TRI_CopyString(dst->_name, src->_name, sizeof(dst->_name)); dst->_waitForSync = src->_waitForSync; if (src->_keyOptions) { dst->_keyOptions = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, src->_keyOptions); } else { dst->_keyOptions = NULL; } }
TRI_index_operator_t* TRI_CopyIndexOperator(TRI_index_operator_t* indexOperator) { TRI_index_operator_t* newOperator; TRI_logical_index_operator_t* newLogicalOperator; TRI_logical_index_operator_t* oldLogicalOperator; TRI_relation_index_operator_t* newRelationOperator; TRI_relation_index_operator_t* oldRelationOperator; newOperator = NULL; if (indexOperator == NULL) { return NULL; } switch (indexOperator->_type) { case TRI_AND_INDEX_OPERATOR: case TRI_NOT_INDEX_OPERATOR: case TRI_OR_INDEX_OPERATOR: { oldLogicalOperator = (TRI_logical_index_operator_t*)(indexOperator); newLogicalOperator = (TRI_logical_index_operator_t*) (TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_logical_index_operator_t), false)); if (newLogicalOperator == NULL) { // out of memory ? break; } newLogicalOperator->_base._type = indexOperator->_type; newLogicalOperator->_base._shaper = indexOperator->_shaper; newLogicalOperator->_left = TRI_CopyIndexOperator(oldLogicalOperator->_left); newLogicalOperator->_right = TRI_CopyIndexOperator(oldLogicalOperator->_right); newOperator = &(newLogicalOperator->_base); break; } case TRI_EQ_INDEX_OPERATOR: case TRI_GE_INDEX_OPERATOR: case TRI_GT_INDEX_OPERATOR: case TRI_NE_INDEX_OPERATOR: case TRI_LE_INDEX_OPERATOR: case TRI_LT_INDEX_OPERATOR: case TRI_IN_INDEX_OPERATOR: { oldRelationOperator = (TRI_relation_index_operator_t*)(indexOperator); newRelationOperator = (TRI_relation_index_operator_t*) (TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_relation_index_operator_t), false)); if (newRelationOperator == NULL) { // out of memory? break; } newRelationOperator->_base._type = indexOperator->_type; newRelationOperator->_base._shaper = indexOperator->_shaper; if (oldRelationOperator->_parameters != NULL) { newRelationOperator->_parameters = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, oldRelationOperator->_parameters); } else { newRelationOperator->_parameters = NULL; } if (oldRelationOperator->_fields != NULL) { newRelationOperator->_fields = TRI_CopyShapedJson(oldRelationOperator->_base._shaper, oldRelationOperator->_fields); } else { newRelationOperator->_fields = NULL; } newRelationOperator->_numFields = oldRelationOperator->_numFields; newRelationOperator->_collection = oldRelationOperator->_collection; newOperator = &(newRelationOperator->_base); break; } } return newOperator; }
int TRI_LoadCollectionInfo (char const* path, TRI_col_info_t* parameter) { TRI_json_t* json; char* filename; char* error = NULL; size_t i; size_t n; memset(parameter, 0, sizeof(TRI_col_info_t)); // find parameter file filename = TRI_Concatenate2File(path, TRI_COL_PARAMETER_FILE); if (filename == NULL) { LOG_ERROR("cannot load parameter info for collection '%s', out of memory", path); return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); } if (! TRI_ExistsFile(filename)) { TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE); } json = TRI_JsonFile(TRI_UNKNOWN_MEM_ZONE, filename, &error); if (json == NULL) { if (error != NULL) { LOG_ERROR("cannot open '%s', parameter block not readable: %s", filename, error); TRI_FreeString(TRI_CORE_MEM_ZONE, error); } else { LOG_ERROR("cannot open '%s', parameter block not readable", filename); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE); } if (json->_type != TRI_JSON_ARRAY) { LOG_ERROR("cannot open '%s', file does not contain a json array", filename); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE); } TRI_FreeString(TRI_CORE_MEM_ZONE, filename); // convert json n = json->_value._objects._length; for (i = 0; i < n; i += 2) { TRI_json_t* key; TRI_json_t* value; key = TRI_AtVector(&json->_value._objects, i); value = TRI_AtVector(&json->_value._objects, i + 1); if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_NUMBER) { if (TRI_EqualString(key->_value._string.data, "version")) { parameter->_version = value->_value._number; } else if (TRI_EqualString(key->_value._string.data, "type")) { parameter->_type = value->_value._number; } else if (TRI_EqualString(key->_value._string.data, "cid")) { parameter->_cid = value->_value._number; } else if (TRI_EqualString(key->_value._string.data, "maximalSize")) { parameter->_maximalSize = value->_value._number; } } else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_STRING) { if (TRI_EqualString(key->_value._string.data, "name")) { TRI_CopyString(parameter->_name, value->_value._string.data, sizeof(parameter->_name)); parameter->_isSystem = TRI_IsSystemCollectionName(parameter->_name); } } else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_BOOLEAN) { if (TRI_EqualString(key->_value._string.data, "deleted")) { parameter->_deleted = value->_value._boolean; } else if (TRI_EqualString(key->_value._string.data, "isVolatile")) { parameter->_isVolatile = value->_value._boolean; } else if (TRI_EqualString(key->_value._string.data, "waitForSync")) { parameter->_waitForSync = value->_value._boolean; } } else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_ARRAY) { if (TRI_EqualString(key->_value._string.data, "keyOptions")) { parameter->_keyOptions = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, value); } } } TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json); return TRI_ERROR_NO_ERROR; }
TRI_json_t* TRI_UnionizeListsJson (const TRI_json_t* const list1, const TRI_json_t* const list2, const bool unique) { TRI_json_t* last = NULL; TRI_json_t* result; size_t i1, i2; size_t n1, n2; assert(list1); assert(list1->_type == TRI_JSON_LIST); assert(list2); assert(list2->_type == TRI_JSON_LIST); n1 = list1->_value._objects._length; n2 = list2->_value._objects._length; // special cases for empty lists if (n1 == 0 && !unique) { return TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (TRI_json_t*) list2); } if (n2 == 0 && !unique) { return TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (TRI_json_t*) list1); } // create result list result = TRI_CreateListJson(TRI_UNKNOWN_MEM_ZONE); if (!result) { return NULL; } // reset positions i1 = 0; i2 = 0; // iterate over lists while (true) { // pointers to elements in both lists TRI_json_t* p1; TRI_json_t* p2; if (i1 < n1 && i2 < n2) { int compareResult; // both lists not yet exhausted p1 = TRI_AtVector(&list1->_value._objects, i1); p2 = TRI_AtVector(&list2->_value._objects, i2); compareResult = TRI_CompareValuesJson(p1, p2); if (compareResult < 0) { // left element is smaller if (!unique || !last || TRI_CompareValuesJson(p1, last) > 0) { TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p1); last = p1; } ++i1; } else if (compareResult > 0) { // right element is smaller if (!unique || !last || TRI_CompareValuesJson(p2, last) > 0) { TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p2); last = p2; } ++i2; } else { // both elements are equal if (!unique || !last || TRI_CompareValuesJson(p1, last) > 0) { TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p1); last = p1; if (!unique) { TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p2); } } ++i1; ++i2; } } else if (i1 < n1 && i2 >= n2) { // only right list is exhausted p1 = TRI_AtVector(&list1->_value._objects, i1); if (!unique || !last || TRI_CompareValuesJson(p1, last) > 0) { TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p1); last = p1; } ++i1; } else if (i1 >= n1 && i2 < n2) { // only left list is exhausted p2 = TRI_AtVector(&list2->_value._objects, i2); if (!unique || !last || TRI_CompareValuesJson(p2, last) > 0) { TRI_PushBackListJson(TRI_UNKNOWN_MEM_ZONE, result, p2); last = p2; } ++i2; } else { // both lists exhausted, stop! break; } } return result; }
static TRI_json_t* MergeRecursive (TRI_memory_zone_t* zone, TRI_json_t const* lhs, TRI_json_t const* rhs, bool nullMeansRemove, bool mergeObjects) { TRI_ASSERT(lhs != nullptr); std::unique_ptr<TRI_json_t> result(TRI_CopyJson(zone, lhs)); if (result == nullptr) { return nullptr; } auto r = result.get(); // shortcut variable size_t const n = TRI_LengthVector(&rhs->_value._objects); for (size_t i = 0; i < n; i += 2) { // enumerate all the replacement values auto key = static_cast<TRI_json_t const*>(TRI_AtVector(&rhs->_value._objects, i)); auto value = static_cast<TRI_json_t const*>(TRI_AtVector(&rhs->_value._objects, i + 1)); if (value->_type == TRI_JSON_NULL && nullMeansRemove) { // replacement value is a null and we don't want to store nulls => delete attribute from the result TRI_DeleteObjectJson(zone, r, key->_value._string.data); } else { // replacement value is not a null or we want to store nulls TRI_json_t const* lhsValue = TRI_LookupObjectJson(lhs, key->_value._string.data); if (lhsValue == nullptr) { // existing array does not have the attribute => append new attribute if (value->_type == TRI_JSON_OBJECT && nullMeansRemove) { TRI_json_t empty; TRI_InitObjectJson(TRI_UNKNOWN_MEM_ZONE, &empty); TRI_json_t* merged = MergeRecursive(zone, &empty, value, nullMeansRemove, mergeObjects); if (merged == nullptr) { return nullptr; } TRI_json_t* copy = TRI_CopyJson(zone, value); if (copy == nullptr) { return nullptr; } TRI_Insert3ObjectJson(zone, r, key->_value._string.data, copy); } else { TRI_Insert3ObjectJson(zone, r, key->_value._string.data, TRI_CopyJson(zone, value)); } } else { // existing array already has the attribute => replace attribute if (lhsValue->_type == TRI_JSON_OBJECT && value->_type == TRI_JSON_OBJECT && mergeObjects) { TRI_json_t* merged = MergeRecursive(zone, lhsValue, value, nullMeansRemove, mergeObjects); if (merged == nullptr) { return nullptr; } TRI_ReplaceObjectJson(zone, r, key->_value._string.data, merged); TRI_FreeJson(zone, merged); } else { TRI_ReplaceObjectJson(zone, r, key->_value._string.data, value); } } } } return result.release(); }