Ejemplo n.º 1
0
static int TraditionalGenerate (TRI_key_generator_t* const generator,
                                const size_t maxLength,
                                const TRI_voc_tick_t tick,
                                const char* const userKey,
                                char* const outBuffer,
                                size_t* const outLength,
                                bool isRestore) {
  traditional_keygen_t* data;
  char* current;

  data = (traditional_keygen_t*) generator->_data;
  assert(data != NULL);

  current = outBuffer;

  if (userKey != NULL) {
    size_t userKeyLength;

    // user has specified a key
    if (! data->_allowUserKeys && ! isRestore) {
      // we do not allow user-generated keys
      return TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED;
    }

    userKeyLength = strlen(userKey);
    if (userKeyLength > maxLength) {
      // user key is too long
      return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
    }
    else if (userKeyLength == 0) {
      // user key is empty
      return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
    }

    // validate user-supplied key
    if (! ValidateKey(userKey)) {
      return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
    }

    memcpy(outBuffer, userKey, userKeyLength);
    current += userKeyLength;
  }
  else {
    // user has not specified a key, generate one based on tick
    current += TRI_StringUInt64InPlace(tick, outBuffer);
  }

  // add 0 byte
  *current = '\0';

  if (current - outBuffer > (int) maxLength) {
    return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
  }

  *outLength = (current - outBuffer);

  return TRI_ERROR_NO_ERROR;
}
Ejemplo n.º 2
0
int TRI_AppendUInt64StringBuffer (TRI_string_buffer_t * self, uint64_t attr) {
  int res;
  size_t len;

  res = Reserve(self, 21);

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

  len = TRI_StringUInt64InPlace(attr, self->_current);
  self->_current += len;

  return TRI_ERROR_NO_ERROR;
}
Ejemplo n.º 3
0
static int AutoIncrementGenerate (TRI_key_generator_t* const generator,
                                  const size_t maxLength,
                                  const TRI_voc_tick_t tick,
                                  const char* const userKey,
                                  char* const outBuffer,
                                  size_t* const outLength,
                                  bool isRestore) {
  autoincrement_keygen_t* data;
  char* current;

  data = (autoincrement_keygen_t*) generator->_data;
  assert(data != NULL);

  current = outBuffer;

  if (userKey != NULL) {
    uint64_t userKeyValue;
    size_t userKeyLength;

    // user has specified a key
    if (! data->_allowUserKeys && ! isRestore) {
      // we do not allow user-generated keys
      return TRI_ERROR_ARANGO_DOCUMENT_KEY_UNEXPECTED;
    }

    userKeyLength = strlen(userKey);
    if (userKeyLength > maxLength) {
      // user key is too long
      return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
    }

    // validate user-supplied key
    if (! ValidateNumericKey(userKey)) {
      return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
    }

    memcpy(outBuffer, userKey, userKeyLength);
    current += userKeyLength;

    userKeyValue = TRI_UInt64String2(userKey, userKeyLength);
    if (userKeyValue > data->_lastValue) {
      // update our last value
      data->_lastValue = userKeyValue;
    }
  }
  else {
    // user has not specified a key, generate one based on algorithm
    uint64_t keyValue = AutoIncrementNext(data->_lastValue, data->_increment, data->_offset);

    // bounds and sanity checks
    if (keyValue == UINT64_MAX || keyValue < data->_lastValue) {
      return TRI_ERROR_ARANGO_OUT_OF_KEYS;
    }

    assert(keyValue > data->_lastValue);
    // update our last value
    data->_lastValue = keyValue;

    current += TRI_StringUInt64InPlace(keyValue, outBuffer);
  }

  // add 0 byte
  *current = '\0';

  if (current - outBuffer > (int) maxLength) {
    return TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD;
  }

  *outLength = (current - outBuffer);

  return TRI_ERROR_NO_ERROR;
}
Ejemplo n.º 4
0
void DocumentAccessor::lookupDocumentAttribute (char const* name, size_t nameLength) {
  if (*name == '_' && name[1] != '\0') {
    if (name[1] == 'k' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_KEY, nameLength) == 0) {
      // _key value is copied into JSON
      char const* key = TRI_EXTRACT_MARKER_KEY(_mptr);
      if (key == nullptr) {
        setToNull();
        return;
      }
      _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, key, strlen(key)));

      if (_json.get() == nullptr) {
        THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
      }

      _current = _json.get();
      return;
    }

    if (name[1] == 'i' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_ID, nameLength) == 0) {
      // _id
      char buffer[512]; // big enough for max key length + max collection name length
      size_t pos = _resolver->getCollectionName(&buffer[0], _document->_info._cid);
      buffer[pos++] = '/';
      char const* key = TRI_EXTRACT_MARKER_KEY(_mptr);
      if (key == nullptr) {
        setToNull();
        return;
      }
      size_t len = strlen(key);
      memcpy(&buffer[pos], key, len);
      buffer[pos + len] = '\0';
      _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
      if (_json.get() == nullptr) {
        THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
      }
      _current = _json.get();
      return;
    }

    if (name[1] == 'r' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_REV, nameLength) == 0) {
      // _rev
      char buffer[21];
      TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_mptr);
      size_t len = TRI_StringUInt64InPlace(rid, &buffer[0]);
      _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], len));
      if (_json.get() == nullptr) {
        THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
      }
      _current = _json.get();
      return;
    }

    if (TRI_IS_EDGE_MARKER(_mptr)) {
      if (name[1] == 'f' && nameLength == 5 && memcmp(name, TRI_VOC_ATTRIBUTE_FROM, nameLength) == 0) {
        // _from
        char buffer[512]; // big enough for max key length + max collection name length
        size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_FROM_CID(_mptr));
        buffer[pos++] = '/';
        char const* key = TRI_EXTRACT_MARKER_FROM_KEY(_mptr);
        if (key == nullptr) {
          setToNull();
          return;
        }
        size_t len = strlen(key);
        memcpy(&buffer[pos], key, len);
        buffer[pos + len] = '\0';
        _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
        if (_json.get() == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
        }
        _current = _json.get();
        return;
      }

      if (name[1] == 't' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_TO, nameLength) == 0) {
        // to
        char buffer[512]; // big enough for max key length + max collection name length
        size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_TO_CID(_mptr));
        buffer[pos++] = '/';
        char const* key = TRI_EXTRACT_MARKER_TO_KEY(_mptr);
        if (key == nullptr) {
          setToNull();
          return;
        }
        size_t len = strlen(key);
        memcpy(&buffer[pos], key, len);
        buffer[pos + len] = '\0';
        _json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
        if (_json.get() == nullptr) {
          THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
        }
        _current = _json.get();
        return;
      }
    }

    // fall-through intentional
  }

  auto shaper = _document->getShaper();

  TRI_shape_pid_t pid = shaper->lookupAttributePathByName(name);

  if (pid == 0) {
    // attribute does not exist
    setToNull();
    return;
  }

  // attribute exists
  TRI_shaped_json_t document;
  TRI_EXTRACT_SHAPED_JSON_MARKER(document, _mptr->getDataPtr());

  TRI_shaped_json_t json;
  TRI_shape_t const* shape;

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

  if (ok && shape != nullptr) {
    _json.reset(TRI_JsonShapedJson(shaper, &json));
    if (_json.get() == nullptr) {
      THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
    }
    _current = _json.get();
    return;
  }

  // not found
  setToNull();
}