Beispiel #1
0
uint64_t VelocyPackHelper::hashByAttributes(
    VPackSlice slice, std::vector<std::string> const& attributes,
    bool docComplete, int& error, std::string const& key) {
  uint64_t hash = TRI_FnvHashBlockInitial();
  error = TRI_ERROR_NO_ERROR;
  slice = slice.resolveExternal();
  if (slice.isObject()) {
    for (auto const& attr : attributes) {
      VPackSlice sub = slice.get(attr).resolveExternal();
      if (sub.isNone()) {
        if (attr == StaticStrings::KeyString && !key.empty()) {
          VPackBuilder temporaryBuilder;
          temporaryBuilder.add(VPackValue(key));
          hash = temporaryBuilder.slice().normalizedHash(hash);
          continue;
        }
        if (!docComplete) {
          error = TRI_ERROR_CLUSTER_NOT_ALL_SHARDING_ATTRIBUTES_GIVEN;
        }
        // Null is equal to None/not present
        sub = VPackSlice::nullSlice();
      }
      hash = sub.normalizedHash(hash);
    }
  }
  return hash;
}
Beispiel #2
0
void arangodb::traverser::ShortestPath::vertexToVelocyPack(Transaction* trx, ManagedDocumentResult* mmdr, 
                                                           size_t position, VPackBuilder& builder) {
  TRI_ASSERT(position < length());
  VPackSlice v = _vertices[position];
  TRI_ASSERT(v.isString());
  std::string collection =  v.copyString();
  size_t p = collection.find("/");
  TRI_ASSERT(p != std::string::npos);

  TransactionBuilderLeaser searchBuilder(trx);
  searchBuilder->add(VPackValue(collection.substr(p + 1)));
  collection = collection.substr(0, p);

  int res =
      trx->documentFastPath(collection, mmdr, searchBuilder->slice(), builder, true);
  if (res != TRI_ERROR_NO_ERROR) {
    builder.clear(); // Just in case...
    builder.add(basics::VelocyPackHelper::NullValue());
  }
}
Beispiel #3
0
void VelocyPackHelper::SanitizeExternals(VPackSlice const input, VPackBuilder& output) {
  if (input.isExternal()) {
    output.add(input.resolveExternal());
  } else if (input.isObject()) {
    output.openObject();
    for (auto const& it : VPackObjectIterator(input)) {
      output.add(VPackValue(it.key.copyString()));
      SanitizeExternals(it.value, output);
    }
    output.close();
  } else if (input.isArray()) {
    output.openArray();
    for (auto const& it : VPackArrayIterator(input)) {
      SanitizeExternals(it, output);
    }
    output.close();
  } else {
    output.add(input);
  }
}
Beispiel #4
0
void arangodb::traverser::TraverserOptions::LookupInfo::buildEngineInfo(
    VPackBuilder& result) const {
  result.openObject();
  result.add(VPackValue("handle"));
  // We only run toVelocyPack on Coordinator.
  TRI_ASSERT(idxHandles.size() == 1);
  result.openObject();
  idxHandles[0].toVelocyPack(result, false);
  result.close();
  result.add(VPackValue("expression"));
  result.openObject(); // We need to encapsulate the expression into an expression object
  result.add(VPackValue("expression"));
  expression->toVelocyPack(result, true);
  result.close();
  result.add(VPackValue("condition"));
  indexCondition->toVelocyPack(result, true);
  result.add("condNeedUpdate", VPackValue(conditionNeedUpdate));
  result.add("condMemberToUpdate", VPackValue(conditionMemberToUpdate));
  result.close();
}
Beispiel #5
0
static int V8ToVPack(BuilderContext& context,
                     v8::Handle<v8::Value> const parameter,
                     std::string const& attributeName, bool inObject) {
  
  if (parameter->IsNull() || parameter->IsUndefined()) {
    AddValue(context, attributeName, inObject,
             VPackValue(VPackValueType::Null));
    return TRI_ERROR_NO_ERROR;
  }

  if (parameter->IsBoolean()) {
    AddValue(context, attributeName, inObject,
             VPackValue(parameter->ToBoolean()->Value()));
    return TRI_ERROR_NO_ERROR;
  }
  
  if (parameter->IsNumber()) {
    if (parameter->IsInt32()) {
      AddValue(context, attributeName, inObject,
               VPackValue(parameter->ToInt32()->Value()));
      return TRI_ERROR_NO_ERROR;
    }
  
    if (parameter->IsUint32()) {
      AddValue(context, attributeName, inObject,
               VPackValue(parameter->ToUint32()->Value()));
      return TRI_ERROR_NO_ERROR;
    }

    AddValue(context, attributeName, inObject,
             VPackValue(parameter->ToNumber()->Value()));
    return TRI_ERROR_NO_ERROR;
  }

  if (parameter->IsString()) {
    v8::String::Utf8Value str(parameter->ToString());

    if (*str == nullptr) {
      return TRI_ERROR_OUT_OF_MEMORY;
    }

    AddValuePair(context, attributeName, inObject, VPackValuePair(*str, str.length(), VPackValueType::String));
    return TRI_ERROR_NO_ERROR;
  }

  if (parameter->IsArray()) {
    v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(parameter);

    AddValue(context, attributeName, inObject,
             VPackValue(VPackValueType::Array));
    uint32_t const n = array->Length();

    for (uint32_t i = 0; i < n; ++i) {
      v8::Handle<v8::Value> value = array->Get(i);
      if (value->IsUndefined()) {
        // ignore array values which are undefined
        continue;
      }

      if (++context.level > MaxLevels) {
        // too much recursion
        return TRI_ERROR_BAD_PARAMETER;
      }

      int res = V8ToVPack<performAllChecks>(context, value, NoAttribute, false);
      
      --context.level;

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

    if (!context.keepTopLevelOpen || context.level > 0) {
      context.builder.close();
    }
    return TRI_ERROR_NO_ERROR;
  }

  if (parameter->IsObject()) {
    if (performAllChecks) {
      if (parameter->IsBooleanObject()) {
        AddValue(context, attributeName, inObject,
                VPackValue(v8::Handle<v8::BooleanObject>::Cast(parameter)
                                ->BooleanValue()));
        return TRI_ERROR_NO_ERROR;
      }

      if (parameter->IsNumberObject()) {
        AddValue(context, attributeName, inObject,
                VPackValue(v8::Handle<v8::NumberObject>::Cast(parameter)
                                ->NumberValue()));
        return TRI_ERROR_NO_ERROR;
      }

      if (parameter->IsStringObject()) {
        v8::String::Utf8Value str(parameter->ToString());

        if (*str == nullptr) {
          return TRI_ERROR_OUT_OF_MEMORY;
        }

        AddValuePair(context, attributeName, inObject, VPackValuePair(*str, str.length(), VPackValueType::String));
        return TRI_ERROR_NO_ERROR;
      }

      if (parameter->IsRegExp() || parameter->IsFunction() ||
          parameter->IsExternal()) {
        return TRI_ERROR_BAD_PARAMETER;
      }
    }

    v8::Handle<v8::Object> o = parameter->ToObject();

    if (performAllChecks) {
      // first check if the object has a "toJSON" function
      if (o->Has(context.toJsonKey)) {
        // call it if yes
        v8::Handle<v8::Value> func = o->Get(context.toJsonKey);
        if (func->IsFunction()) {
          v8::Handle<v8::Function> toJson = v8::Handle<v8::Function>::Cast(func);

          v8::Handle<v8::Value> args;
          v8::Handle<v8::Value> converted = toJson->Call(o, 0, &args);

          if (!converted.IsEmpty()) {
            // return whatever toJSON returned
            v8::String::Utf8Value str(converted->ToString());

            if (*str == nullptr) {
              return TRI_ERROR_OUT_OF_MEMORY;
            }

            // this passes ownership for the utf8 string to the JSON object
            AddValuePair(context, attributeName, inObject, VPackValuePair(*str, str.length(), VPackValueType::String));
            return TRI_ERROR_NO_ERROR;
          }
        }

        // fall-through intentional
      }
    }

    v8::Handle<v8::Array> names = o->GetOwnPropertyNames();
    uint32_t const n = names->Length();

    AddValue(context, attributeName, inObject,
             VPackValue(VPackValueType::Object));

    for (uint32_t i = 0; i < n; ++i) {
      // process attribute name
      v8::Handle<v8::Value> key = names->Get(i);
      v8::String::Utf8Value str(key);

      if (*str == nullptr) {
        return TRI_ERROR_OUT_OF_MEMORY;
      }

      v8::Handle<v8::Value> value = o->Get(key);
      if (value->IsUndefined()) {
        // ignore object values which are undefined
        continue;
      }

      if (++context.level > MaxLevels) {
        // too much recursion
        return TRI_ERROR_BAD_PARAMETER;
      }

      int res = V8ToVPack<performAllChecks>(context, value, *str, true);
      
      --context.level;

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

    if (!context.keepTopLevelOpen || context.level > 0) {
      context.builder.close();
    }
    return TRI_ERROR_NO_ERROR;
  }

  return TRI_ERROR_BAD_PARAMETER;
}
Beispiel #6
0
bool TraverserExpression::matchesCheck(arangodb::Transaction* trx,
                                       VPackSlice const& element) const {
  TRI_ASSERT(trx != nullptr);
  VPackSlice base = arangodb::basics::VelocyPackHelper::EmptyObjectValue();

  VPackSlice value = element.resolveExternal(); 
  
  // initialize compare value to Null
  VPackSlice result = arangodb::basics::VelocyPackHelper::NullValue();
  // perform recursive check. this may modify value
  if (recursiveCheck(varAccess, value, base)) {
    result = value;
  }

  // hack for _id attribute
  TransactionBuilderLeaser builder(trx);
  if (result.isCustom() && base.isObject()) {
    builder->add(VPackValue(trx->extractIdString(base)));
    result = builder->slice();
  }

  TRI_ASSERT(compareTo != nullptr);
  VPackOptions* options = trx->transactionContext()->getVPackOptions();

  switch (comparisonType) {
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_EQ:
      return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), false, options) == 0; 
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NE:
      return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), false, options) != 0; 
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_LT:
      return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) < 0; 
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_LE:
      return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) <= 0; 
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GE:
      return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) >= 0; 
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_GT:
      return arangodb::basics::VelocyPackHelper::compare(result, compareTo->slice(), true, options) > 0;
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_IN: {
      // In means any of the elements in compareTo is identical
      VPackSlice compareArray = compareTo->slice();
      for (auto const& cmp : VPackArrayIterator(compareArray)) {
        if (arangodb::basics::VelocyPackHelper::compare(result, cmp, false, options) == 0) {
          // One is identical
          return true;
        }
      }
      // If we get here non is identical
      return false;
    }
    case arangodb::aql::NODE_TYPE_OPERATOR_BINARY_NIN: {
      // NIN means none of the elements in compareTo is identical
      VPackSlice compareArray = compareTo->slice();
      for (auto const& cmp : VPackArrayIterator(compareArray)) {
        if (arangodb::basics::VelocyPackHelper::compare(result, cmp, false, options) == 0) {
          // One is identical
          return false;
        }
      }
      // If we get here non is identical
      return true;
    }
    default:
      TRI_ASSERT(false);
  }
  return false;
}
Beispiel #7
0
void arangodb::traverser::TraverserOptions::buildEngineInfo(VPackBuilder& result) const {
  result.openObject();
  result.add("minDepth", VPackValue(minDepth));
  result.add("maxDepth", VPackValue(maxDepth));
  result.add("bfs", VPackValue(useBreadthFirst));

  result.add(VPackValue("uniqueVertices"));
  switch (uniqueVertices) {
    case UniquenessLevel::NONE:
      result.add(VPackValue(0));
      break;
    case UniquenessLevel::PATH:
      result.add(VPackValue(1));
      break;
    case UniquenessLevel::GLOBAL:
      result.add(VPackValue(2));
      break;
  }

  result.add(VPackValue("uniqueEdges"));
  switch (uniqueEdges) {
    case UniquenessLevel::NONE:
      result.add(VPackValue(0));
      break;
    case UniquenessLevel::PATH:
      result.add(VPackValue(1));
      break;
    case UniquenessLevel::GLOBAL:
      result.add(VPackValue(2));
      break;
  }

  result.add(VPackValue("baseLookupInfos"));
  result.openArray();
  for (auto const& it: _baseLookupInfos) {
    it.buildEngineInfo(result);
  }
  result.close();

  if (!_depthLookupInfo.empty()) {
    result.add(VPackValue("depthLookupInfo"));
    result.openObject();
    for (auto const& pair : _depthLookupInfo) {
      result.add(VPackValue(basics::StringUtils::itoa(pair.first)));
      result.openArray();
      for (auto const& it : pair.second) {
        it.buildEngineInfo(result);
      }
      result.close();
    }
    result.close();
  }

  if (!_vertexExpressions.empty()) {
    result.add(VPackValue("vertexExpressions"));
    result.openObject();
    for (auto const& pair : _vertexExpressions) {
      result.add(VPackValue(basics::StringUtils::itoa(pair.first)));
      result.openObject();
      result.add(VPackValue("expression"));
      pair.second->toVelocyPack(result, true);
      result.close();
    }
    result.close();
  }

  if (_baseVertexExpression != nullptr) {
    result.add(VPackValue("baseVertexExpression"));
    result.openObject();
    result.add(VPackValue("expression"));
    _baseVertexExpression->toVelocyPack(result, true);
    result.close();
  }

  result.add(VPackValue("tmpVar"));
  _tmpVar->toVelocyPack(result);

  result.close();
}