mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into devel
This commit is contained in:
commit
237ef1112e
|
@ -160,8 +160,8 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
|
||||||
{ "MIN", Function("MIN", "AQL_MIN", "l", true, true, false, true, true, &Functions::Min) },
|
{ "MIN", Function("MIN", "AQL_MIN", "l", true, true, false, true, true, &Functions::Min) },
|
||||||
{ "MAX", Function("MAX", "AQL_MAX", "l", true, true, false, true, true, &Functions::Max) },
|
{ "MAX", Function("MAX", "AQL_MAX", "l", true, true, false, true, true, &Functions::Max) },
|
||||||
{ "SUM", Function("SUM", "AQL_SUM", "l", true, true, false, true, true, &Functions::Sum) },
|
{ "SUM", Function("SUM", "AQL_SUM", "l", true, true, false, true, true, &Functions::Sum) },
|
||||||
{ "MEDIAN", Function("MEDIAN", "AQL_MEDIAN", "l", true, true, false, true, true) },
|
{ "MEDIAN", Function("MEDIAN", "AQL_MEDIAN", "l", true, true, false, true, true, &Functions::Median) },
|
||||||
{ "PERCENTILE", Function("PERCENTILE", "AQL_PERCENTILE", "l,n|s", true, true, false, true, true) },
|
{ "PERCENTILE", Function("PERCENTILE", "AQL_PERCENTILE", "l,n|s", true, true, false, true, true, &Functions::Percentile) },
|
||||||
{ "AVERAGE", Function("AVERAGE", "AQL_AVERAGE", "l", true, true, false, true, true, &Functions::Average) },
|
{ "AVERAGE", Function("AVERAGE", "AQL_AVERAGE", "l", true, true, false, true, true, &Functions::Average) },
|
||||||
{ "VARIANCE_SAMPLE", Function("VARIANCE_SAMPLE", "AQL_VARIANCE_SAMPLE", "l", true, true, false, true, true, &Functions::VarianceSample) },
|
{ "VARIANCE_SAMPLE", Function("VARIANCE_SAMPLE", "AQL_VARIANCE_SAMPLE", "l", true, true, false, true, true, &Functions::VarianceSample) },
|
||||||
{ "VARIANCE_POPULATION", Function("VARIANCE_POPULATION", "AQL_VARIANCE_POPULATION", "l", true, true, false, true, true, &Functions::VariancePopulation) },
|
{ "VARIANCE_POPULATION", Function("VARIANCE_POPULATION", "AQL_VARIANCE_POPULATION", "l", true, true, false, true, true, &Functions::VariancePopulation) },
|
||||||
|
|
|
@ -448,6 +448,29 @@ static bool Variance (Json const& values, double& value, size_t& count) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Sorts the given list of Numbers in ASC order.
|
||||||
|
/// Removes all null entries.
|
||||||
|
/// Returns false if the list contains non-number values.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static bool SortNumberList (Json const& values, std::vector<double>& result) {
|
||||||
|
TRI_ASSERT(values.isArray());
|
||||||
|
TRI_ASSERT(result.empty());
|
||||||
|
bool unused;
|
||||||
|
for (size_t i = 0; i < values.size(); ++i) {
|
||||||
|
Json element = values.at(i);
|
||||||
|
if (! element.isNull()) {
|
||||||
|
if (! element.isNumber()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
result.emplace_back(ValueToNumber(element.json(), unused));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::sort(result.begin(), result.end());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- AQL functions public helpers
|
// --SECTION-- AQL functions public helpers
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -3895,6 +3918,129 @@ AqlValue Functions::StdDevPopulation (triagens::aql::Query* query,
|
||||||
return AqlValue(new Json(sqrt(value / count)));
|
return AqlValue(new Json(sqrt(value / count)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief function MEDIAN
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
AqlValue Functions::Median (triagens::aql::Query* query,
|
||||||
|
triagens::arango::AqlTransaction* trx,
|
||||||
|
FunctionParameters const& parameters) {
|
||||||
|
size_t const n = parameters.size();
|
||||||
|
if (n != 1) {
|
||||||
|
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "MEDIAN", (int) 1, (int) 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Json list = ExtractFunctionParameter(trx, parameters, 0, false);
|
||||||
|
|
||||||
|
if (! list.isArray()) {
|
||||||
|
RegisterWarning(query, "MEDIAN", TRI_ERROR_QUERY_ARRAY_EXPECTED);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> values;
|
||||||
|
if (! SortNumberList(list, values)) {
|
||||||
|
RegisterWarning(query, "MEDIAN", TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.empty()) {
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
size_t const l = values.size();
|
||||||
|
size_t midpoint = l / 2;
|
||||||
|
|
||||||
|
if (l % 2 == 0) {
|
||||||
|
return AqlValue(new Json((values[midpoint - 1] + values[midpoint]) / 2));
|
||||||
|
}
|
||||||
|
return AqlValue(new Json(values[midpoint]));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief function PERCENTILE
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
AqlValue Functions::Percentile (triagens::aql::Query* query,
|
||||||
|
triagens::arango::AqlTransaction* trx,
|
||||||
|
FunctionParameters const& parameters) {
|
||||||
|
size_t const n = parameters.size();
|
||||||
|
if (n != 2 && n != 3) {
|
||||||
|
THROW_ARANGO_EXCEPTION_PARAMS(TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "PERCENTILE", (int) 2, (int) 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
Json list = ExtractFunctionParameter(trx, parameters, 0, false);
|
||||||
|
|
||||||
|
if (! list.isArray()) {
|
||||||
|
RegisterWarning(query, "PERCENTILE", TRI_ERROR_QUERY_ARRAY_EXPECTED);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
|
||||||
|
Json border = ExtractFunctionParameter(trx, parameters, 1, false);
|
||||||
|
|
||||||
|
if (! border.isNumber()) {
|
||||||
|
RegisterWarning(query, "PERCENTILE", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unused = false;
|
||||||
|
double p = ValueToNumber(border.json(), unused);
|
||||||
|
if (p <= 0 || p > 100) {
|
||||||
|
RegisterWarning(query, "PERCENTILE", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useInterpolation = false;
|
||||||
|
|
||||||
|
if (n == 3) {
|
||||||
|
Json methodJson = ExtractFunctionParameter(trx, parameters, 2, false);
|
||||||
|
if (! methodJson.isString()) {
|
||||||
|
RegisterWarning(query, "PERCENTILE", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
std::string method = triagens::basics::JsonHelper::getStringValue(methodJson.json(), "");
|
||||||
|
if (method == "interpolation") {
|
||||||
|
useInterpolation = true;
|
||||||
|
}
|
||||||
|
else if (method == "rank") {
|
||||||
|
useInterpolation = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RegisterWarning(query, "PERCENTILE", TRI_ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> values;
|
||||||
|
if (! SortNumberList(list, values)) {
|
||||||
|
RegisterWarning(query, "PERCENTILE", TRI_ERROR_QUERY_INVALID_ARITHMETIC_VALUE);
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.empty()) {
|
||||||
|
return AqlValue(new Json(Json::Null));
|
||||||
|
}
|
||||||
|
size_t l = values.size();
|
||||||
|
if (l == 1) {
|
||||||
|
return AqlValue(new Json(values[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useInterpolation) {
|
||||||
|
double idx = p * (l + 1) / 100;
|
||||||
|
double pos = floor(idx);
|
||||||
|
|
||||||
|
if (pos >= l) {
|
||||||
|
return AqlValue(new Json(values[l - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
double delta = idx - pos;
|
||||||
|
return AqlValue(new Json(delta * (values[pos] - values[pos - 1]) + values[pos - 1]));
|
||||||
|
}
|
||||||
|
double idx = p * l / 100;
|
||||||
|
double pos = ceil(idx);
|
||||||
|
if (pos >= l) {
|
||||||
|
return AqlValue(new Json(values[l - 1]));
|
||||||
|
}
|
||||||
|
return AqlValue(new Json(values[pos - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -145,6 +145,8 @@ namespace triagens {
|
||||||
static AqlValue VariancePopulation (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
static AqlValue VariancePopulation (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
||||||
static AqlValue StdDevSample (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
static AqlValue StdDevSample (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
||||||
static AqlValue StdDevPopulation (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
static AqlValue StdDevPopulation (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
||||||
|
static AqlValue Median (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
||||||
|
static AqlValue Percentile (triagens::aql::Query*, triagens::arango::AqlTransaction*, FunctionParameters const&);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2742,6 +2742,22 @@ function ahuacatlFunctionsTestSuite () {
|
||||||
else {
|
else {
|
||||||
assertEqual(value[0].toFixed(4), actual[0].toFixed(4));
|
assertEqual(value[0].toFixed(4), actual[0].toFixed(4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual = getQueryResults("RETURN NOOPT(MEDIAN(" + JSON.stringify(value[1]) + "))");
|
||||||
|
if (actual[0] === null) {
|
||||||
|
assertNull(value[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertEqual(value[0].toFixed(4), actual[0].toFixed(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
actual = getQueryResults("RETURN NOOPT(V8(MEDIAN(" + JSON.stringify(value[1]) + ")))");
|
||||||
|
if (actual[0] === null) {
|
||||||
|
assertNull(value[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertEqual(value[0].toFixed(4), actual[0].toFixed(4));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2757,6 +2773,22 @@ function ahuacatlFunctionsTestSuite () {
|
||||||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN MEDIAN(3)");
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN MEDIAN(3)");
|
||||||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN MEDIAN(\"yes\")");
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN MEDIAN(\"yes\")");
|
||||||
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN MEDIAN({ })");
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN MEDIAN({ })");
|
||||||
|
|
||||||
|
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(MEDIAN())");
|
||||||
|
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(MEDIAN([ ], 2))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(MEDIAN(null))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(MEDIAN(false))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(MEDIAN(3))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(MEDIAN(\"yes\"))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(MEDIAN({ }))");
|
||||||
|
|
||||||
|
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(V8(MEDIAN()))");
|
||||||
|
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(V8(MEDIAN([ ], 2)))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(MEDIAN(null)))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(MEDIAN(false)))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(MEDIAN(3)))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(MEDIAN(\"yes\")))");
|
||||||
|
assertQueryWarningAndNull(errors.ERROR_QUERY_ARRAY_EXPECTED.code, "RETURN NOOPT(V8(MEDIAN({ })))");
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2798,6 +2830,22 @@ function ahuacatlFunctionsTestSuite () {
|
||||||
else {
|
else {
|
||||||
assertEqual(value[0].toFixed(4), actual[0].toFixed(4), value);
|
assertEqual(value[0].toFixed(4), actual[0].toFixed(4), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual = getQueryResults("RETURN NOOPT(PERCENTILE(" + JSON.stringify(value[1]) + ", " + JSON.stringify(value[2]) + ", " + JSON.stringify(value[3]) + "))");
|
||||||
|
if (actual[0] === null) {
|
||||||
|
assertNull(value[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertEqual(value[0].toFixed(4), actual[0].toFixed(4), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
actual = getQueryResults("RETURN NOOPT(V8(PERCENTILE(" + JSON.stringify(value[1]) + ", " + JSON.stringify(value[2]) + ", " + JSON.stringify(value[3]) + ")))");
|
||||||
|
if (actual[0] === null) {
|
||||||
|
assertNull(value[0]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertEqual(value[0].toFixed(4), actual[0].toFixed(4), value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue