diff --git a/arangod/Aql/Expression.cpp b/arangod/Aql/Expression.cpp index ab88852c10..8c4bc3546f 100644 --- a/arangod/Aql/Expression.cpp +++ b/arangod/Aql/Expression.cpp @@ -188,18 +188,33 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node, auto shaper = myCollection->getShaper(); // look for the attribute name in the shape - if (strcmp(name, "_key") == 0) { - return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, TRI_EXTRACT_MARKER_KEY(result._marker))); - } - else if (strcmp(name, "_id") == 0) { - std::string id(myCollection->_info._name); - id.push_back('/'); - id.append(TRI_EXTRACT_MARKER_KEY(result._marker)); - return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, id)); - } - else if (strcmp(name, "_rev") == 0) { - TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(result._marker); - return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, JsonHelper::uint64String(TRI_UNKNOWN_MEM_ZONE, rid))); + if (*name == '_') { + if (strcmp(name, "_key") == 0) { + // _key value is copied into JSON + return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, TRI_EXTRACT_MARKER_KEY(result._marker))); + } + else if (strcmp(name, "_id") == 0) { + std::string id(trx->resolver()->getCollectionName(myCollection->_info._cid)); + id.push_back('/'); + id.append(TRI_EXTRACT_MARKER_KEY(result._marker)); + return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, id)); + } + else if (strcmp(name, "_rev") == 0) { + TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(result._marker); + return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, JsonHelper::uint64String(TRI_UNKNOWN_MEM_ZONE, rid))); + } + else if (strcmp(name, "_from") == 0) { + std::string id(trx->resolver()->getCollectionName(TRI_EXTRACT_MARKER_FROM_CID(result._marker))); + id.push_back('/'); + id.append(TRI_EXTRACT_MARKER_FROM_KEY(result._marker)); + return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, id)); + } + else if (strcmp(name, "_to") == 0) { + std::string id(trx->resolver()->getCollectionName(TRI_EXTRACT_MARKER_TO_CID(result._marker))); + id.push_back('/'); + id.append(TRI_EXTRACT_MARKER_TO_KEY(result._marker)); + return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, id)); + } } TRI_shape_pid_t pid = shaper->lookupAttributePathByName(shaper, name); @@ -257,7 +272,6 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node, } } - else if (node->type == NODE_TYPE_REFERENCE) { auto v = static_cast(node->getData()); diff --git a/arangod/VocBase/document-collection.h b/arangod/VocBase/document-collection.h index 4e75aeaa57..d7553d36db 100644 --- a/arangod/VocBase/document-collection.h +++ b/arangod/VocBase/document-collection.h @@ -508,6 +508,86 @@ size_t TRI_DocumentIteratorDocumentCollection (triagens::arango::TransactionBase #define TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(a) \ TRI_UnlockCondition(&(a)->_journalsCondition) +//////////////////////////////////////////////////////////////////////////////// +/// @brief extracts the pointer to the _from key from a marker +//////////////////////////////////////////////////////////////////////////////// + +static inline char const* TRI_EXTRACT_MARKER_FROM_KEY (TRI_df_marker_t const* marker) { + if (marker->_type == TRI_DOC_MARKER_KEY_EDGE) { + return ((char const*) marker) + ((TRI_doc_edge_key_marker_t const*) marker)->_offsetFromKey; + } + else if (marker->_type == TRI_WAL_MARKER_EDGE) { + return ((char const*) marker) + ((triagens::wal::edge_marker_t const*) marker)->_offsetFromKey; + } + +#ifdef TRI_ENABLE_MAINTAINER_MODE + // invalid marker type + TRI_ASSERT(false); +#endif + + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief extracts the pointer to the _to key from a marker +//////////////////////////////////////////////////////////////////////////////// + +static inline char const* TRI_EXTRACT_MARKER_TO_KEY (TRI_df_marker_t const* marker) { + if (marker->_type == TRI_DOC_MARKER_KEY_EDGE) { + return ((char const*) marker) + ((TRI_doc_edge_key_marker_t const*) marker)->_offsetToKey; + } + else if (marker->_type == TRI_WAL_MARKER_EDGE) { + return ((char const*) marker) + ((triagens::wal::edge_marker_t const*) marker)->_offsetToKey; + } + +#ifdef TRI_ENABLE_MAINTAINER_MODE + // invalid marker type + TRI_ASSERT(false); +#endif + + return nullptr; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief extracts the _from cid from a marker +//////////////////////////////////////////////////////////////////////////////// + +static inline TRI_voc_cid_t TRI_EXTRACT_MARKER_FROM_CID (TRI_df_marker_t const* marker) { + if (marker->_type == TRI_DOC_MARKER_KEY_EDGE) { + return ((TRI_doc_edge_key_marker_t const*) marker)->_fromCid; + } + else if (marker->_type == TRI_WAL_MARKER_EDGE) { + return ((triagens::wal::edge_marker_t const*) marker)->_fromCid; + } + +#ifdef TRI_ENABLE_MAINTAINER_MODE + // invalid marker type + TRI_ASSERT(false); +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief extracts the _to cid from a marker +//////////////////////////////////////////////////////////////////////////////// + +static inline TRI_voc_cid_t TRI_EXTRACT_MARKER_TO_CID (TRI_df_marker_t const* marker) { + if (marker->_type == TRI_DOC_MARKER_KEY_EDGE) { + return ((TRI_doc_edge_key_marker_t const*) marker)->_toCid; + } + else if (marker->_type == TRI_WAL_MARKER_EDGE) { + return ((triagens::wal::edge_marker_t const*) marker)->_toCid; + } + +#ifdef TRI_ENABLE_MAINTAINER_MODE + // invalid marker type + TRI_ASSERT(false); +#endif + + return 0; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief extracts the revision id from a marker ////////////////////////////////////////////////////////////////////////////////