Example #1
0
void ExportCursor::dump (triagens::basics::StringBuffer& buffer) {
  TRI_ASSERT(_ex != nullptr);

  TRI_shaper_t* shaper = _ex->_document->getShaper();
  auto const restrictionType = _ex->_restrictions.type;

  buffer.appendText("\"result\":[");

  size_t const n = batchSize();

  for (size_t i = 0; i < n; ++i) {
    if (! hasNext()) {
      break;
    }

    if (i > 0) {
      buffer.appendChar(',');
    }
    
    auto marker = static_cast<TRI_df_marker_t const*>(_ex->_documents->at(_position++));

    TRI_shaped_json_t shaped;
    TRI_EXTRACT_SHAPED_JSON_MARKER(shaped, marker);
    triagens::basics::Json json(shaper->_memoryZone, TRI_JsonShapedJson(shaper, &shaped));

    // append the internal attributes

    // _id, _key, _rev
    char const* key = TRI_EXTRACT_MARKER_KEY(marker);
    std::string id(_ex->_resolver.getCollectionName(_ex->_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(marker))));
    json(TRI_VOC_ATTRIBUTE_KEY, triagens::basics::Json(key));

    if (TRI_IS_EDGE_MARKER(marker)) {
      // _from
      std::string from(_ex->_resolver.getCollectionNameCluster(TRI_EXTRACT_MARKER_FROM_CID(marker)));
      from.push_back('/');
      from.append(TRI_EXTRACT_MARKER_FROM_KEY(marker));
      json(TRI_VOC_ATTRIBUTE_FROM, triagens::basics::Json(from));
        
      // _to
      std::string to(_ex->_resolver.getCollectionNameCluster(TRI_EXTRACT_MARKER_TO_CID(marker)));
      to.push_back('/');
      to.append(TRI_EXTRACT_MARKER_TO_KEY(marker));
      json(TRI_VOC_ATTRIBUTE_TO, triagens::basics::Json(to));
    }

    if (restrictionType == CollectionExport::Restrictions::RESTRICTION_INCLUDE ||
        restrictionType == CollectionExport::Restrictions::RESTRICTION_EXCLUDE) {
      // only include the specified fields
      // for this we'll modify the JSON that we already have, in place
      // we'll scan through the JSON attributs from left to right and
      // keep all those that we want to keep. we'll overwrite existing
      // other values in the JSON 
      TRI_json_t* obj = json.json();
      TRI_ASSERT(TRI_IsObjectJson(obj));

      size_t const n = TRI_LengthVector(&obj->_value._objects);

      size_t j = 0;
      for (size_t i = 0; i < n; i += 2) {
        auto key = static_cast<TRI_json_t const*>(TRI_AtVector(&obj->_value._objects, i));

        if (! TRI_IsStringJson(key)) {
          continue;
        }

        bool const keyContainedInRestrictions = (_ex->_restrictions.fields.find(key->_value._string.data) != _ex->_restrictions.fields.end());

        if ((restrictionType == CollectionExport::Restrictions::RESTRICTION_INCLUDE && keyContainedInRestrictions) ||
            (restrictionType == CollectionExport::Restrictions::RESTRICTION_EXCLUDE && ! keyContainedInRestrictions)) {
          // include the field
          if (i != j) {
            // steal the key and the value
            void* src = TRI_AddressVector(&obj->_value._objects, i);
            void* dst = TRI_AddressVector(&obj->_value._objects, j);
            memcpy(dst, src, 2 * sizeof(TRI_json_t));
          }
          j += 2;
        }
        else {
          // do not include the field
          // key
          auto src = static_cast<TRI_json_t*>(TRI_AddressVector(&obj->_value._objects, i));
          TRI_DestroyJson(TRI_UNKNOWN_MEM_ZONE, src);
          // value
          TRI_DestroyJson(TRI_UNKNOWN_MEM_ZONE, src + 1);
        }
      }

      // finally adjust the length of the patched JSON so the NULL fields at
      // the end will not be dumped
      TRI_SetLengthVector(&obj->_value._objects, j); 
    }
    else {
      // no restrictions
      TRI_ASSERT(restrictionType == CollectionExport::Restrictions::RESTRICTION_NONE);
    }
        
    int res = TRI_StringifyJson(buffer.stringBuffer(), json.json());

    if (res != TRI_ERROR_NO_ERROR) {
      THROW_ARANGO_EXCEPTION(res);
    }
  }

  buffer.appendText("],\"hasMore\":");
  buffer.appendText(hasNext() ? "true" : "false");

  if (hasNext()) {
    // only return cursor id if there are more documents
    buffer.appendText(",\"id\":\"");
    buffer.appendInteger(id());
    buffer.appendText("\"");
  }

  if (hasCount()) {
    buffer.appendText(",\"count\":");
    buffer.appendInteger(static_cast<uint64_t>(count()));
  }

  if (! hasNext()) {
    delete _ex;
    _ex = nullptr;

    // mark the cursor as deleted
    this->deleted();
  }
}
Example #2
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);
}
Example #3
0
void JsonCursor::dump (triagens::basics::StringBuffer& buffer) {
  buffer.appendText("\"result\":[");

  size_t const n = batchSize();

  // reserve 48 bytes per result document by default, but only
  // if the specified batch size does not get out of hand
  // otherwise specifying a very high batch size would make the allocation fail
  // in every case, even if there were much less documents in the collection
  if (n <= 50000) {
    int res = buffer.reserve(n * 48);

    if (res != TRI_ERROR_NO_ERROR) {
      THROW_ARANGO_EXCEPTION(res);
    }
  }

  for (size_t i = 0; i < n; ++i) {
    if (! hasNext()) {
      break;
    }

    if (i > 0) {
      buffer.appendChar(',');
    }
    
    auto row = next();
    if (row == nullptr) {
      THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
    }

    int res = TRI_StringifyJson(buffer.stringBuffer(), row);

    if (res != TRI_ERROR_NO_ERROR) {
      THROW_ARANGO_EXCEPTION(res);
    }
  }

  buffer.appendText("],\"hasMore\":");
  buffer.appendText(hasNext() ? "true" : "false");

  if (hasNext()) {
    // only return cursor id if there are more documents
    buffer.appendText(",\"id\":\"");
    buffer.appendInteger(id());
    buffer.appendText("\"");
  }

  if (hasCount()) {
    buffer.appendText(",\"count\":");
    buffer.appendInteger(static_cast<uint64_t>(count()));
  }

  TRI_json_t const* extraJson = extra();

  if (TRI_IsObjectJson(extraJson)) {
    buffer.appendText(",\"extra\":");
    TRI_StringifyJson(buffer.stringBuffer(), extraJson);
  }
    
  if (! hasNext()) {
    // mark the cursor as deleted
    this->deleted();
  }
}