Exemplo n.º 1
0
double VelocyPackHelper::toDouble(VPackSlice const& slice, bool& failed) {
  TRI_ASSERT(!slice.isNone());

  failed = false;
  switch (slice.type()) {
    case VPackValueType::None:
    case VPackValueType::Null:
      return 0.0;
    case VPackValueType::Bool:
      return (slice.getBoolean() ? 1.0 : 0.0);
    case VPackValueType::Double:
    case VPackValueType::Int:
    case VPackValueType::UInt:
    case VPackValueType::SmallInt:
      return slice.getNumericValue<double>();
    case VPackValueType::String: {
      std::string tmp(slice.copyString());
      try {
        // try converting string to number
        return std::stod(tmp);
      } catch (...) {
        if (tmp.empty()) {
          return 0.0;
        }
        // conversion failed
      }
      break;
    }
    case VPackValueType::Array: {
      VPackValueLength const n = slice.length();

      if (n == 0) {
        return 0.0;
      } else if (n == 1) {
        return VelocyPackHelper::toDouble(slice.at(0).resolveExternal(), failed);
      }
      break;
    }
    case VPackValueType::External: {
      return VelocyPackHelper::toDouble(slice.resolveExternal(), failed);
    }
    case VPackValueType::Illegal:
    case VPackValueType::Object:
    case VPackValueType::UTCDate:
    case VPackValueType::MinKey:
    case VPackValueType::MaxKey:
    case VPackValueType::Binary:
    case VPackValueType::BCD:
    case VPackValueType::Custom:
      break;
  }

  failed = true;
  return 0.0;
}
Exemplo n.º 2
0
/// @brief create the block from VelocyPack, note that this can throw
AqlItemBlock::AqlItemBlock(VPackSlice const slice) {
  bool exhausted = VelocyPackHelper::getBooleanValue(slice, "exhausted", false);

  if (exhausted) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                   "exhausted must be false");
  }

  _nrItems = VelocyPackHelper::getNumericValue<size_t>(slice, "nrItems", 0);
  if (_nrItems == 0) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "nrItems must be > 0");
  }

  _nrRegs = VelocyPackHelper::getNumericValue<RegisterId>(slice, "nrRegs", 0);

  // Initialize the data vector:
  if (_nrRegs > 0) {
    _data.resize(_nrItems * _nrRegs);
  }

  // Now put in the data:
  VPackSlice data = slice.get("data");
  VPackSlice raw = slice.get("raw");

  std::vector<AqlValue> madeHere;
  madeHere.reserve(static_cast<size_t>(raw.length()));
  madeHere.emplace_back();  // an empty AqlValue
  madeHere.emplace_back();  // another empty AqlValue, indices start w. 2

  try {
    size_t posInRaw = 2;
    size_t posInData = 0;
    int64_t emptyRun = 0;

    for (RegisterId column = 0; column < _nrRegs; column++) {
      for (size_t i = 0; i < _nrItems; i++) {
        if (emptyRun > 0) {
          emptyRun--;
        } else {
          VPackSlice dataEntry = data.at(posInData++);
          if (!dataEntry.isNumber()) {
            THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                           "data must contain only numbers");
          }
          int64_t n = dataEntry.getNumericValue<int64_t>();
          if (n == 0) {
            // empty, do nothing here
          } else if (n == -1) {
            // empty run:
            VPackSlice runLength = data.at(posInData++);
            TRI_ASSERT(runLength.isNumber());
            emptyRun = runLength.getNumericValue<int64_t>();
            emptyRun--;
          } else if (n == -2) {
            // a range
            VPackSlice lowBound = data.at(posInData++);
            VPackSlice highBound = data.at(posInData++);
            
            int64_t low =
                VelocyPackHelper::getNumericValue<int64_t>(lowBound, 0);
            int64_t high =
                VelocyPackHelper::getNumericValue<int64_t>(highBound, 0);
            AqlValue a(low, high);
            try {
              setValue(i, column, a);
            } catch (...) {
              a.destroy();
              throw;
            }
          } else if (n == 1) {
            // a VelocyPack value
            AqlValue a(raw.at(posInRaw++));
            try {
              setValue(i, column, a);  // if this throws, a is destroyed again
            } catch (...) {
              a.destroy();
              throw;
            }
            madeHere.emplace_back(a);
          } else if (n >= 2) {
            setValue(i, column, madeHere[static_cast<size_t>(n)]);
            // If this throws, all is OK, because it was already put into
            // the block elsewhere.
          } else {
            THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                           "found undefined data value");
          }
        }
      }
    }
  } catch (...) {
    destroy();
  }
}
Exemplo n.º 3
0
int VelocyPackHelper::compare(VPackSlice lhs, VPackSlice rhs,
                              bool useUTF8, VPackOptions const* options,
                              VPackSlice const* lhsBase, VPackSlice const* rhsBase) {
  {
    // will resolve externals...
    int lWeight = TypeWeight(lhs);
    int rWeight = TypeWeight(rhs);

    if (lWeight < rWeight) {
      return -1;
    }

    if (lWeight > rWeight) {
      return 1;
    }
  
    TRI_ASSERT(lWeight == rWeight);
  }
  
  lhs = lhs.resolveExternal(); // follow externals
  rhs = rhs.resolveExternal(); // follow externals

  // lhs and rhs have equal weights
  if (lhs.isNone() || rhs.isNone()) {
    // either lhs or rhs is none. we cannot be sure here that both are
    // nones.
    // there can also exist the situation that lhs is a none and rhs is a
    // null value
    // (or vice versa). Anyway, the compare value is the same for both,
    return 0;
  }

  auto lhsType = lhs.type();

  switch (lhsType) {
    case VPackValueType::Illegal:
    case VPackValueType::MinKey:
    case VPackValueType::MaxKey:
    case VPackValueType::None:
    case VPackValueType::Null:
      return 0;  
    case VPackValueType::Bool: {
      bool left = lhs.getBoolean();
      bool right = rhs.getBoolean();
      if (left == right) {
        return 0;
      }
      if (!left && right) {
        return -1;
      }
      return 1;
    }
    case VPackValueType::Double:
    case VPackValueType::Int:
    case VPackValueType::UInt:
    case VPackValueType::SmallInt: {
      return compareNumberValues(lhsType, lhs, rhs);
    }
    case VPackValueType::Custom:
    case VPackValueType::String: {
      std::string lhsString;
      VPackValueLength nl;
      char const* left;
      if (lhs.isCustom()) {
        if (lhsBase == nullptr || options == nullptr || options->customTypeHandler == nullptr) {
          THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                         "Could not extract custom attribute.");
        }
        lhsString.assign(options->customTypeHandler->toString(lhs, options, *lhsBase));
        left = lhsString.c_str();
        nl = lhsString.size();
      } else {
        left = lhs.getString(nl);
      }
      TRI_ASSERT(left != nullptr);

      std::string rhsString;
      VPackValueLength nr;
      char const* right;
      if (rhs.isCustom()) {
        if (rhsBase == nullptr || options == nullptr || options->customTypeHandler == nullptr) {
          THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
                                         "Could not extract custom attribute.");
        }
        rhsString.assign(options->customTypeHandler->toString(rhs, options, *rhsBase));
        right = rhsString.c_str();
        nr = rhsString.size();
      } else {
        right = rhs.getString(nr);
      }
      TRI_ASSERT(right != nullptr);

      int res;
      if (useUTF8) {
        res = TRI_compare_utf8(left, static_cast<size_t>(nl), right, static_cast<size_t>(nr));
      } else {
        size_t len = static_cast<size_t>(nl < nr ? nl : nr);
        res = memcmp(left, right, len);
      }
      if (res < 0) {
        return -1;
      }
      if (res > 0) {
        return 1;
      }
      // res == 0
      if (nl == nr) {
        return 0;
      }
      // res == 0, but different string lengths
      return nl < nr ? -1 : 1;
    }
    case VPackValueType::Array: {
      VPackValueLength const nl = lhs.length();
      VPackValueLength const nr = rhs.length();
      VPackValueLength const n = (std::max)(nr, nl);
      for (VPackValueLength i = 0; i < n; ++i) {
        VPackSlice lhsValue;
        if (i < nl) {
          lhsValue = lhs.at(i).resolveExternal();
        }
        VPackSlice rhsValue;
        if (i < nr) {
          rhsValue = rhs.at(i).resolveExternal();
        }

        int result = compare(lhsValue, rhsValue, useUTF8, options, &lhs, &rhs);
        if (result != 0) {
          return result;
        }
      }
      return 0;
    }
    case VPackValueType::Object: {
      std::set<std::string, AttributeSorterUTF8> keys;
      VPackCollection::keys(lhs, keys);
      VPackCollection::keys(rhs, keys);
      for (auto const& key : keys) {
        VPackSlice lhsValue = lhs.get(key).resolveExternal();
        if (lhsValue.isNone()) {
          // not present => null
          lhsValue = VPackSlice::nullSlice();
        }
        VPackSlice rhsValue = rhs.get(key).resolveExternal();
        if (rhsValue.isNone()) {
          // not present => null
          rhsValue = VPackSlice::nullSlice();
        }

        int result = compare(lhsValue, rhsValue, useUTF8, options, &lhs, &rhs);
        if (result != 0) {
          return result;
        }
      }

      return 0;
    }
    default:
      // Contains all other ValueTypes of VelocyPack.
      // They are not used in ArangoDB so this cannot occur
      TRI_ASSERT(false);
      return 0;
  }
}
Exemplo n.º 4
0
arangodb::traverser::TraverserOptions::TraverserOptions(
    arangodb::aql::Query* query, VPackSlice info, VPackSlice collections)
    : _trx(query->trx()),
      _baseVertexExpression(nullptr),
      _tmpVar(nullptr),
      _ctx(new aql::FixedVarExpressionContext()),
      _isCoordinator(arangodb::ServerState::instance()->isCoordinator()),
      minDepth(1),
      maxDepth(1),
      useBreadthFirst(false),
      uniqueVertices(UniquenessLevel::NONE),
      uniqueEdges(UniquenessLevel::PATH) {
      // NOTE collections is an array of arrays of strings
  VPackSlice read = info.get("minDepth");
  if (!read.isInteger()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                   "The options require a minDepth");
  }
  minDepth = read.getNumber<uint64_t>();

  read = info.get("maxDepth");
  if (!read.isInteger()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                   "The options require a maxDepth");
  }
  maxDepth = read.getNumber<uint64_t>();

  read = info.get("bfs");
  if (!read.isBoolean()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                   "The options require a bfs");
  }
  useBreadthFirst = read.getBool();

  read = info.get("tmpVar");
  if (!read.isObject()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                   "The options require a tmpVar");
  }
  _tmpVar = query->ast()->variables()->createVariable(read);

  read = info.get("uniqueVertices");
  if (!read.isInteger()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                   "The options require a uniqueVertices");
  }
  size_t i = read.getNumber<size_t>();
  switch (i) {
    case 0:
      uniqueVertices = UniquenessLevel::NONE;
      break;
    case 1:
      uniqueVertices = UniquenessLevel::PATH;
      break;
    case 2:
      uniqueVertices = UniquenessLevel::GLOBAL;
      break;
    default:
      THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                     "The options require a uniqueVertices");
  }

  read = info.get("uniqueEdges");
  if (!read.isInteger()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                   "The options require a uniqueEdges");
  }
  i = read.getNumber<size_t>();
  switch (i) {
    case 0:
      uniqueEdges = UniquenessLevel::NONE;
      break;
    case 1:
      uniqueEdges = UniquenessLevel::PATH;
      break;
    case 2:
      uniqueEdges = UniquenessLevel::GLOBAL;
      break;
    default:
      THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                     "The options require a uniqueEdges");
  }

  read = info.get("baseLookupInfos");
  if (!read.isArray()) {
    THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
                                   "The options require a baseLookupInfos");
  }

  size_t length = read.length();
  TRI_ASSERT(read.length() == collections.length());
  _baseLookupInfos.reserve(length);
  for (size_t j = 0; j < length; ++j) {
    _baseLookupInfos.emplace_back(query, read.at(j), collections.at(j));
  }

  read = info.get("depthLookupInfo");
  if (!read.isNone()) {
    if (!read.isObject()) {
      THROW_ARANGO_EXCEPTION_MESSAGE(
          TRI_ERROR_BAD_PARAMETER,
          "The options require depthLookupInfo to be an object");
    }
    _depthLookupInfo.reserve(read.length());
    for (auto const& depth : VPackObjectIterator(read)) {
      size_t d = basics::StringUtils::uint64(depth.key.copyString());
      auto it = _depthLookupInfo.emplace(d, std::vector<LookupInfo>());
      TRI_ASSERT(it.second);
      VPackSlice list = depth.value;
      TRI_ASSERT(length == list.length());
      it.first->second.reserve(length);
      for (size_t j = 0; j < length; ++j) {
        it.first->second.emplace_back(query, list.at(j), collections.at(j));
      }
    }
  }

  read = info.get("vertexExpressions");
  if (!read.isNone()) {
    if (!read.isObject()) {
      THROW_ARANGO_EXCEPTION_MESSAGE(
          TRI_ERROR_BAD_PARAMETER,
          "The options require vertexExpressions to be an object");
    }

    _vertexExpressions.reserve(read.length());
    for (auto const& info : VPackObjectIterator(read)) {
      size_t d = basics::StringUtils::uint64(info.key.copyString());
#ifdef ARANGODB_ENABLE_MAINAINER_MODE
      auto it = _vertexExpressions.emplace(
          d, new aql::Expression(query->ast(), info.value));
      TRI_ASSERT(it.second);
#else
      _vertexExpressions.emplace(
          d, new aql::Expression(query->ast(), info.value));
#endif
    }
  }

  read = info.get("baseVertexExpression");
  if (!read.isNone()) {
    if (!read.isObject()) {
      THROW_ARANGO_EXCEPTION_MESSAGE(
          TRI_ERROR_BAD_PARAMETER,
          "The options require vertexExpressions to be an object");
    }
    _baseVertexExpression = new aql::Expression(query->ast(), read);
  }
  // Check for illegal option combination:
  TRI_ASSERT(uniqueEdges !=
             arangodb::traverser::TraverserOptions::UniquenessLevel::GLOBAL);
  TRI_ASSERT(
      uniqueVertices !=
          arangodb::traverser::TraverserOptions::UniquenessLevel::GLOBAL ||
      useBreadthFirst);
}