Example #1
0
Json AqlValue::extractObjectMember (triagens::arango::AqlTransaction* trx,
                                    TRI_document_collection_t const* document,
                                    char const* name,
                                    bool copy,
                                    triagens::basics::StringBuffer& buffer) const {
  switch (_type) {
    case JSON: {
      TRI_ASSERT(_json != nullptr);
      TRI_json_t const* json = _json->json();

      if (TRI_IsObjectJson(json)) {
        TRI_json_t const* found = TRI_LookupObjectJson(json, name);

        if (found != nullptr) {
          if (copy) {
            // return a copy of the value
            auto c = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, found);

            if (c == nullptr) {
              THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
            }

            return Json(TRI_UNKNOWN_MEM_ZONE, c, triagens::basics::Json::AUTOFREE);
          }

          // return a pointer to the original value, without asking for its ownership
          return Json(TRI_UNKNOWN_MEM_ZONE, found, triagens::basics::Json::NOFREE);
        }
      }
      
      // attribute does not exist or something went wrong - fall-through to returning null below
      return Json(Json::Null);
    }

    case SHAPED: {
      TRI_ASSERT(document != nullptr);
      TRI_ASSERT(_marker != nullptr);

      // look for the attribute name in the shape
      if (*name == '_' && name[1] != '\0') {
        if (name[1] == 'k' && strcmp(name, TRI_VOC_ATTRIBUTE_KEY) == 0) {
          // _key value is copied into JSON
          return Json(TRI_UNKNOWN_MEM_ZONE, TRI_EXTRACT_MARKER_KEY(_marker));
        }
        if (name[1] == 'i' && strcmp(name, TRI_VOC_ATTRIBUTE_ID) == 0) {
          // _id
          buffer.reset();
          trx->resolver()->getCollectionName(document->_info._cid, buffer);
          buffer.appendChar('/');
          buffer.appendText(TRI_EXTRACT_MARKER_KEY(_marker));
          return Json(TRI_UNKNOWN_MEM_ZONE, buffer.c_str(), buffer.length());
        }
        if (name[1] == 'r' && strcmp(name, TRI_VOC_ATTRIBUTE_REV) == 0) {
          // _rev
          TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_marker);
          buffer.reset();
          buffer.appendInteger(rid);
          return Json(TRI_UNKNOWN_MEM_ZONE, buffer.c_str(), buffer.length());
        }
        if (name[1] == 'f' && 
            strcmp(name, TRI_VOC_ATTRIBUTE_FROM) == 0 &&
            (_marker->_type == TRI_DOC_MARKER_KEY_EDGE ||
             _marker->_type == TRI_WAL_MARKER_EDGE)) {
          buffer.reset();
          trx->resolver()->getCollectionNameCluster(TRI_EXTRACT_MARKER_FROM_CID(_marker), buffer);
          buffer.appendChar('/');
          buffer.appendText(TRI_EXTRACT_MARKER_FROM_KEY(_marker));
          return Json(TRI_UNKNOWN_MEM_ZONE, buffer.c_str(), buffer.length());
        }
        if (name[1] == 't' && 
            strcmp(name, TRI_VOC_ATTRIBUTE_TO) == 0 &&
            (_marker->_type == TRI_DOC_MARKER_KEY_EDGE ||
            _marker->_type == TRI_WAL_MARKER_EDGE)) {
          buffer.reset();
          trx->resolver()->getCollectionNameCluster(TRI_EXTRACT_MARKER_TO_CID(_marker), buffer);
          buffer.appendChar('/');
          buffer.appendText(TRI_EXTRACT_MARKER_TO_KEY(_marker));
          return Json(TRI_UNKNOWN_MEM_ZONE, buffer.c_str(), buffer.length());
        }
      }

      auto shaper = document->getShaper();

      TRI_shape_pid_t pid = shaper->lookupAttributePathByName(name);

      if (pid != 0) {
        // attribute exists
        TRI_shaped_json_t document;
        TRI_EXTRACT_SHAPED_JSON_MARKER(document, _marker);

        TRI_shaped_json_t json;
        TRI_shape_t const* shape;

        bool ok = shaper->extractShapedJson(&document, 0, pid, &json, &shape);

        if (ok && shape != nullptr) {
          auto v = TRI_JsonShapedJson(shaper, &json);

          if (v == nullptr) {
            THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
          }

          return Json(TRI_UNKNOWN_MEM_ZONE, v);
        }
      }

      // attribute does not exist or something went wrong - fall-through to returning null
      break;
    }

    case DOCVEC:
    case RANGE:
    case EMPTY: {
      break;
    }
  }

  return Json(Json::Null);
}