mirror of https://gitee.com/bigwinds/arangodb
added TYPENAME() and HASH() functions
This commit is contained in:
parent
9b6467dc60
commit
d4cb93fb9c
|
@ -16,6 +16,19 @@ AQL offers the following functions to let the user control the flow of operation
|
|||
Finally, AQL supports the following functions that do not belong to any of the other
|
||||
function categories:
|
||||
|
||||
- *HASH(value)*: Calculates a hash value for *value*. *value* is not required to be a
|
||||
string, but can have any data type. The calculated hash value will take the data type
|
||||
of *value* into account, so for example the number *1* and the string *"1"* will have
|
||||
different hash values. For arrays the hash values will be creared if the arrays contain
|
||||
exactly the same values (including value types) in the same order. For objects the same
|
||||
hash values will be created if the objects have exactly the same attribute names and
|
||||
values (including value types). The order in which attributes appear inside objects
|
||||
is not important for hashing.
|
||||
The hash value returned by this function is a number. The hash algorithm is not guaranteed
|
||||
to remain the same in future versions of ArangoDB. The hash values should therefore be
|
||||
used only for temporary calculations, e.g. to compare if two documents are the same, or
|
||||
for grouping values in queries.
|
||||
|
||||
- *COLLECTIONS()*: Returns an array of collections. Each collection is returned as a document
|
||||
with attributes *name* and *_id*
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ not not 1 // true
|
|||
converted to the number *0*.
|
||||
- An object / document is converted to the number *0*.
|
||||
|
||||
An unary plus will also try to cast to a number, but `TO_NUMBER()` is the preferred way:
|
||||
A unary plus will also cast to a number, but `TO_NUMBER()` is the preferred way:
|
||||
```js
|
||||
+'5' // 5
|
||||
+[8] // 8
|
||||
|
@ -122,3 +122,6 @@ The following type check functions are available:
|
|||
in a date function. This includes partial dates such as *2015* or *2015-10* and
|
||||
strings containing invalid dates such as *2015-02-31*. The function will return
|
||||
false for all non-string values, even if some of them may be usable in date functions.
|
||||
|
||||
- *TYPENAME(value)*: Returns the data type name of *value*. The data type name can
|
||||
be either *null*, *bool*, *number*, *string*, *array* or *object*.
|
||||
|
|
|
@ -130,6 +130,34 @@ struct AqlValue final {
|
|||
setType(AqlValueType::VPACK_INLINE);
|
||||
}
|
||||
|
||||
// construct from char* and length
|
||||
AqlValue(char const* value, size_t length) {
|
||||
if (length == 0) {
|
||||
// empty string
|
||||
_data.internal[0] = 0x40;
|
||||
setType(AqlValueType::VPACK_INLINE);
|
||||
return;
|
||||
}
|
||||
if (length < sizeof(_data.internal) - 1) {
|
||||
// short string... can store it inline
|
||||
_data.internal[0] = 0x40 + length;
|
||||
memcpy(_data.internal + 1, value, length);
|
||||
setType(AqlValueType::VPACK_INLINE);
|
||||
} else if (length <= 126) {
|
||||
// short string... cannot store inline, but we don't need to
|
||||
// create a full-features Builder object here
|
||||
_data.buffer = new arangodb::velocypack::Buffer<uint8_t>(length + 1);
|
||||
_data.buffer->push_back(0x40 + length);
|
||||
_data.buffer->append(value, length);
|
||||
setType(AqlValueType::VPACK_MANAGED);
|
||||
} else {
|
||||
// long string
|
||||
VPackBuilder builder;
|
||||
builder.add(VPackValue(value));
|
||||
initFromSlice(builder.slice());
|
||||
}
|
||||
}
|
||||
|
||||
// construct from std::string
|
||||
explicit AqlValue(std::string const& value) {
|
||||
if (value.empty()) {
|
||||
|
|
|
@ -120,6 +120,8 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
|
|||
false, true, true, &Functions::IsObject)},
|
||||
{"IS_DATESTRING", Function("IS_DATESTRING", "AQL_IS_DATESTRING", ".", true,
|
||||
true, false, true, true)},
|
||||
{"TYPENAME", Function("TYPENAME", "AQL_TYPENAME", ".", true,
|
||||
true, false, true, true)},
|
||||
|
||||
// type cast functions
|
||||
{"TO_NUMBER", Function("TO_NUMBER", "AQL_TO_NUMBER", ".", true, true, false,
|
||||
|
@ -173,6 +175,8 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
|
|||
&Functions::Md5)},
|
||||
{"SHA1", Function("SHA1", "AQL_SHA1", "s", true, true, false, true, true,
|
||||
&Functions::Sha1)},
|
||||
{"HASH", Function("HASH", "AQL_HASH", ".", true, true, false, true, true,
|
||||
&Functions::Hash)},
|
||||
{"RANDOM_TOKEN", Function("RANDOM_TOKEN", "AQL_RANDOM_TOKEN", "n", false,
|
||||
false, true, true, true)},
|
||||
|
||||
|
@ -482,9 +486,6 @@ std::unordered_map<std::string, Function const> const Executor::FunctionNames{
|
|||
/// an array / object literal "big" and pulling it out of the expression
|
||||
size_t const Executor::DefaultLiteralSizeThreshold = 32;
|
||||
|
||||
/// @brief maxmium number of array members created from range accesses
|
||||
int64_t const Executor::MaxRangeAccessArraySize = 1024 * 1024 * 32;
|
||||
|
||||
/// @brief creates an executor
|
||||
Executor::Executor(int64_t literalSizeThreshold)
|
||||
: _buffer(nullptr),
|
||||
|
|
|
@ -175,8 +175,6 @@ class Executor {
|
|||
/// an array / object literal "big" and pulling it out of the expression
|
||||
static size_t const DefaultLiteralSizeThreshold;
|
||||
|
||||
/// @brief maxmium number of array members created from range accesses
|
||||
static int64_t const MaxRangeAccessArraySize;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -884,7 +884,7 @@ AqlValue Functions::IsNull(arangodb::aql::Query* query,
|
|||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue a = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::BooleanValue(a.isNull(true)));
|
||||
return AqlValue(a.isNull(true));
|
||||
}
|
||||
|
||||
/// @brief function IS_BOOL
|
||||
|
@ -892,7 +892,7 @@ AqlValue Functions::IsBool(arangodb::aql::Query* query,
|
|||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue a = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::BooleanValue(a.isBoolean()));
|
||||
return AqlValue(a.isBoolean());
|
||||
}
|
||||
|
||||
/// @brief function IS_NUMBER
|
||||
|
@ -900,7 +900,7 @@ AqlValue Functions::IsNumber(arangodb::aql::Query* query,
|
|||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue a = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::BooleanValue(a.isNumber()));
|
||||
return AqlValue(a.isNumber());
|
||||
}
|
||||
|
||||
/// @brief function IS_STRING
|
||||
|
@ -908,7 +908,7 @@ AqlValue Functions::IsString(arangodb::aql::Query* query,
|
|||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue a = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::BooleanValue(a.isString()));
|
||||
return AqlValue(a.isString());
|
||||
}
|
||||
|
||||
/// @brief function IS_ARRAY
|
||||
|
@ -916,7 +916,7 @@ AqlValue Functions::IsArray(arangodb::aql::Query* query,
|
|||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue a = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::BooleanValue(a.isArray()));
|
||||
return AqlValue(a.isArray());
|
||||
}
|
||||
|
||||
/// @brief function IS_OBJECT
|
||||
|
@ -924,7 +924,31 @@ AqlValue Functions::IsObject(arangodb::aql::Query* query,
|
|||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue a = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::BooleanValue(a.isObject()));
|
||||
return AqlValue(a.isObject());
|
||||
}
|
||||
|
||||
/// @brief function TYPENAME
|
||||
AqlValue Functions::Typename(arangodb::aql::Query* query,
|
||||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue value = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
|
||||
if (value.isObject()) {
|
||||
return AqlValue(TRI_CHAR_LENGTH_PAIR("object"));
|
||||
}
|
||||
if (value.isArray()) {
|
||||
return AqlValue(TRI_CHAR_LENGTH_PAIR("array"));
|
||||
}
|
||||
if (value.isString()) {
|
||||
return AqlValue(TRI_CHAR_LENGTH_PAIR("string"));
|
||||
}
|
||||
if (value.isNumber()) {
|
||||
return AqlValue(TRI_CHAR_LENGTH_PAIR("number"));
|
||||
}
|
||||
if (value.isBoolean()) {
|
||||
return AqlValue(TRI_CHAR_LENGTH_PAIR("bool"));
|
||||
}
|
||||
return AqlValue(TRI_CHAR_LENGTH_PAIR("null"));
|
||||
}
|
||||
|
||||
/// @brief function TO_NUMBER
|
||||
|
@ -968,7 +992,7 @@ AqlValue Functions::ToBool(arangodb::aql::Query* query,
|
|||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue a = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
return AqlValue(arangodb::basics::VelocyPackHelper::BooleanValue(a.toBoolean()));
|
||||
return AqlValue(a.toBoolean());
|
||||
}
|
||||
|
||||
/// @brief function TO_ARRAY
|
||||
|
@ -1639,9 +1663,7 @@ AqlValue Functions::Md5(arangodb::aql::Query* query,
|
|||
|
||||
arangodb::rest::SslInterface::sslHEX(hash, 16, p, length);
|
||||
|
||||
TransactionBuilderLeaser builder(trx);
|
||||
builder->add(VPackValue(std::string(hex, 32)));
|
||||
return AqlValue(builder.get());
|
||||
return AqlValue(std::string(hex, 32));
|
||||
}
|
||||
|
||||
/// @brief function SHA1
|
||||
|
@ -1669,8 +1691,21 @@ AqlValue Functions::Sha1(arangodb::aql::Query* query,
|
|||
|
||||
arangodb::rest::SslInterface::sslHEX(hash, 20, p, length);
|
||||
|
||||
return AqlValue(std::string(hex, 40));
|
||||
}
|
||||
|
||||
/// @brief function HASH
|
||||
AqlValue Functions::Hash(arangodb::aql::Query* query,
|
||||
arangodb::AqlTransaction* trx,
|
||||
VPackFunctionParameters const& parameters) {
|
||||
AqlValue value = ExtractFunctionParameterValue(trx, parameters, 0);
|
||||
|
||||
// throw away the top bytes so the hash value can safely be used
|
||||
// without precision loss when storing in JavaScript etc.
|
||||
uint64_t hash = value.hash(trx) & 0x0007ffffffffffffULL;
|
||||
|
||||
TransactionBuilderLeaser builder(trx);
|
||||
builder->add(VPackValue(std::string(hex, 40)));
|
||||
builder->add(VPackValue(hash));
|
||||
return AqlValue(builder.get());
|
||||
}
|
||||
|
||||
|
|
|
@ -53,168 +53,172 @@ struct Functions {
|
|||
static AqlValue IsNull(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue IsBool(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue IsNumber(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue IsString(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue IsArray(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue IsObject(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Typename(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue ToNumber(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue ToString(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue ToBool(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue ToArray(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Length(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue First(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Last(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Nth(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Concat(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Like(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Passthru(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Unset(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue UnsetRecursive(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Keep(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Merge(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue MergeRecursive(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Has(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Attributes(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Values(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Min(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Max(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Sum(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Average(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Md5(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Sha1(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Hash(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Unique(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue SortedUnique(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Union(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue UnionDistinct(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Intersection(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Neighbors(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Near(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Within(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Flatten(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Zip(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue ParseIdentifier(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Minus(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Document(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Edges(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Round(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Abs(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Ceil(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Floor(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Sqrt(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Pow(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Rand(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue FirstDocument(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue FirstList(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Push(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Pop(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Append(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Unshift(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Shift(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue RemoveValue(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue RemoveValues(arangodb::aql::Query*,
|
||||
static AqlValue Union(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue UnionDistinct(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue RemoveNth(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue NotNull(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue CurrentDatabase(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue CollectionCount(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue VarianceSample(arangodb::aql::Query*,
|
||||
static AqlValue Intersection(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Neighbors(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Near(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Within(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Flatten(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Zip(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue ParseIdentifier(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue VariancePopulation(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue StdDevSample(arangodb::aql::Query*,
|
||||
static AqlValue Minus(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Document(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Edges(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Round(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Abs(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Ceil(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Floor(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Sqrt(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Pow(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Rand(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue FirstDocument(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue StdDevPopulation(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Median(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Percentile(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Range(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
static AqlValue FirstList(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Push(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Pop(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Append(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Position(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
static AqlValue Unshift(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Shift(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue RemoveValue(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue RemoveValues(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue RemoveNth(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Fulltext(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue IsSameCollection(arangodb::aql::Query*,
|
||||
static AqlValue NotNull(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue CurrentDatabase(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue CollectionCount(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue VarianceSample(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue VariancePopulation(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue StdDevSample(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue StdDevPopulation(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Median(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Percentile(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Range(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Position(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue Fulltext(arangodb::aql::Query*, arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
static AqlValue IsSameCollection(arangodb::aql::Query*,
|
||||
arangodb::AqlTransaction*,
|
||||
VPackFunctionParameters const&);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2447,6 +2447,34 @@ static void JS_QuerySleepAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes a V8 object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void JS_ObjectHash(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
// extract arguments
|
||||
if (args.Length() != 1) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("hash(<object>)");
|
||||
}
|
||||
|
||||
VPackBuilder builder;
|
||||
int res = TRI_V8ToVPack(isolate, builder, args[0], false);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_THROW_EXCEPTION(res);
|
||||
}
|
||||
|
||||
// throw away the top bytes so the hash value can safely be used
|
||||
// without precision loss when storing in JavaScript etc.
|
||||
uint64_t hash = builder.slice().normalizedHash() & 0x0007ffffffffffffULL;
|
||||
|
||||
TRI_V8_RETURN(v8::Number::New(isolate, static_cast<double>(hash)));
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief wraps a TRI_vocbase_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3556,6 +3584,10 @@ void TRI_InitV8VocBridge(v8::Isolate* isolate, v8::Handle<v8::Context> context,
|
|||
TRI_AddGlobalFunctionVocbase(
|
||||
isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_CACHE_INVALIDATE"),
|
||||
JS_QueryCacheInvalidateAql, true);
|
||||
|
||||
TRI_AddGlobalFunctionVocbase(isolate, context,
|
||||
TRI_V8_ASCII_STRING("OBJECT_HASH"),
|
||||
JS_ObjectHash, true);
|
||||
|
||||
TRI_AddGlobalFunctionVocbase(
|
||||
isolate, context, TRI_V8_ASCII_STRING("THROW_COLLECTION_NOT_LOADED"),
|
||||
|
|
|
@ -92,7 +92,7 @@ var AqlHighlightRules = function() {
|
|||
);
|
||||
|
||||
var builtinFunctions = (
|
||||
"(to_bool|to_number|to_string|to_list|is_null|is_bool|is_number|is_string|is_list|is_document|" +
|
||||
"(to_bool|to_number|to_string|to_list|is_null|is_bool|is_number|is_string|is_list|is_document|typename|" +
|
||||
"concat|concat_separator|char_length|lower|upper|substring|left|right|trim|reverse|contains|" +
|
||||
"like|floor|ceil|round|abs|rand|sqrt|pow|length|min|max|average|sum|median|variance_population|" +
|
||||
"variance_sample|first|last|unique|matches|merge|merge_recursive|has|attributes|values|unset|unset_recursive|keep|" +
|
||||
|
@ -107,7 +107,7 @@ var AqlHighlightRules = function() {
|
|||
"date_add|date_subtract|date_diff|date_compare|date_format|fail|passthru|sleep|not_null|" +
|
||||
"first_list|first_document|parse_identifier|current_user|current_database|" +
|
||||
"collections|document|union|union_distinct|intersection|flatten|is_same_collection|" +
|
||||
"ltrim|rtrim|find_first|find_last|split|substitute|md5|sha1|random_token|AQL_LAST_ENTRY)"
|
||||
"ltrim|rtrim|find_first|find_last|split|substitute|md5|sha1|hash|random_token|AQL_LAST_ENTRY)"
|
||||
);
|
||||
|
||||
var keywordMapper = this.createKeywordMapper({
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*jshint strict: false, unused: false, bitwise: false, esnext: true */
|
||||
/*global COMPARE_STRING, AQL_TO_BOOL, AQL_TO_NUMBER, AQL_TO_STRING, AQL_WARNING, AQL_QUERY_SLEEP */
|
||||
/*global CPP_SHORTEST_PATH, CPP_NEIGHBORS, Set */
|
||||
/*global CPP_SHORTEST_PATH, CPP_NEIGHBORS, Set, OBJECT_HASH */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Aql, internal query functions
|
||||
|
@ -2519,6 +2519,39 @@ function AQL_SHA1 (value) {
|
|||
return INTERNAL.sha1(AQL_TO_STRING(value));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates a hash value for an object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function AQL_HASH (value) {
|
||||
'use strict';
|
||||
|
||||
return OBJECT_HASH(value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the typename for an object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function AQL_TYPENAME (value) {
|
||||
'use strict';
|
||||
|
||||
switch (TYPEWEIGHT(value)) {
|
||||
case TYPEWEIGHT_BOOL:
|
||||
return "bool";
|
||||
case TYPEWEIGHT_NUMBER:
|
||||
return "number";
|
||||
case TYPEWEIGHT_STRING:
|
||||
return "string";
|
||||
case TYPEWEIGHT_ARRAY:
|
||||
return "array";
|
||||
case TYPEWEIGHT_OBJECT:
|
||||
return "object";
|
||||
}
|
||||
|
||||
return "null";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates a random token of the specified length
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -8133,6 +8166,8 @@ exports.AQL_SPLIT = AQL_SPLIT;
|
|||
exports.AQL_SUBSTITUTE = AQL_SUBSTITUTE;
|
||||
exports.AQL_MD5 = AQL_MD5;
|
||||
exports.AQL_SHA1 = AQL_SHA1;
|
||||
exports.AQL_HASH = AQL_HASH;
|
||||
exports.AQL_TYPENAME = AQL_TYPENAME;
|
||||
exports.AQL_RANDOM_TOKEN = AQL_RANDOM_TOKEN;
|
||||
exports.AQL_FIND_FIRST = AQL_FIND_FIRST;
|
||||
exports.AQL_FIND_LAST = AQL_FIND_LAST;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*jshint globalstrict:false, strict:false, maxlen:5000 */
|
||||
/*global assertEqual, assertTrue */
|
||||
/*global assertEqual, assertNotEqual, assertTrue */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for query language, functions
|
||||
|
@ -1323,6 +1323,101 @@ function ahuacatlStringFunctionsTestSuite () {
|
|||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test hash function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testHash : function () {
|
||||
var buildQuery = function (nr, input) {
|
||||
switch (nr) {
|
||||
case 0:
|
||||
return `RETURN HASH(${input})`;
|
||||
case 1:
|
||||
return `RETURN NOOPT(HASH(${input}))`;
|
||||
case 2:
|
||||
return `RETURN NOOPT(V8(HASH(${input})))`;
|
||||
default:
|
||||
assertTrue(false, "Undefined state");
|
||||
}
|
||||
};
|
||||
var i;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, ""));
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, "1, 2"));
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, buildQuery(i, "1, 2, 3"));
|
||||
assertEqual([ 675717317264138 ], getQueryResults(buildQuery(i, "null")));
|
||||
assertEqual([ 1217335385489389 ], getQueryResults(buildQuery(i, "false")));
|
||||
assertEqual([ 57801618404459 ], getQueryResults(buildQuery(i, "true")));
|
||||
assertEqual([ 2964198978643 ], getQueryResults(buildQuery(i, "1 / 0")));
|
||||
assertEqual([ 2964198978643 ], getQueryResults(buildQuery(i, "0")));
|
||||
assertEqual([ 2964198978643 ], getQueryResults(buildQuery(i, "0.0")));
|
||||
assertEqual([ 464020872367562 ], getQueryResults(buildQuery(i, "0.00001")));
|
||||
assertEqual([ 652971229830707 ], getQueryResults(buildQuery(i, "1")));
|
||||
assertEqual([ 510129580600084 ], getQueryResults(buildQuery(i, "-1")));
|
||||
assertEqual([ 24372339383975 ], getQueryResults(buildQuery(i, "-10.5")));
|
||||
assertEqual([ 1041198105137773 ], getQueryResults(buildQuery(i, "123452532322453")));
|
||||
assertEqual([ 876255539722551 ], getQueryResults(buildQuery(i, "123452532322454")));
|
||||
assertEqual([ 1277486662998285 ], getQueryResults(buildQuery(i, "123452532322454.434")));
|
||||
assertEqual([ 210539478145939 ], getQueryResults(buildQuery(i, "-123452532322454")));
|
||||
assertEqual([ 261745517313272 ], getQueryResults(buildQuery(i, "-9999999999999.999")));
|
||||
assertEqual([ 441814588996558 ], getQueryResults(buildQuery(i, "''")));
|
||||
assertEqual([ 1112732548475941 ], getQueryResults(buildQuery(i, "' '")));
|
||||
assertEqual([ 246233608921999 ], getQueryResults(buildQuery(i, "' '")));
|
||||
assertEqual([ 1542381651001813 ], getQueryResults(buildQuery(i, "'a'")));
|
||||
assertEqual([ 843602980995939 ], getQueryResults(buildQuery(i, "'A'")));
|
||||
assertEqual([ 1618092585478118 ], getQueryResults(buildQuery(i, "' a'")));
|
||||
assertEqual([ 725364078947946 ], getQueryResults(buildQuery(i, "' A'")));
|
||||
assertEqual([ 736233736371291 ], getQueryResults(buildQuery(i, "' foobar'")));
|
||||
assertEqual([ 360657200843601 ], getQueryResults(buildQuery(i, "'this is a string test. please ignore.'")));
|
||||
assertEqual([ 828085160327326 ], getQueryResults(buildQuery(i, "'this is a string test. please Ignore.'")));
|
||||
assertEqual([ 2072438876063292 ], getQueryResults(buildQuery(i, "'a string is a string is a string of course. even longer strings can be hashed. isn\\'t this fantastic? let\\'s see if we can cross the short-string bounds with it...'")));
|
||||
assertEqual([ 181227890622943 ], getQueryResults(buildQuery(i, "[]")));
|
||||
assertEqual([ 346113245898278 ], getQueryResults(buildQuery(i, "[0]")));
|
||||
assertEqual([ 785599515440277 ], getQueryResults(buildQuery(i, "[1]")));
|
||||
assertEqual([ 1295855700045140 ], getQueryResults(buildQuery(i, "[1,2]")));
|
||||
assertEqual([ 1295855700045140 ], getQueryResults(buildQuery(i, "1..2")));
|
||||
assertEqual([ 1255602544875390 ], getQueryResults(buildQuery(i, "[2,1]")));
|
||||
assertEqual([ 1255602544875390 ], getQueryResults(buildQuery(i, "2..1")));
|
||||
assertEqual([ 1625466870434085 ], getQueryResults(buildQuery(i, "[1,2,3]")));
|
||||
assertEqual([ 1625466870434085 ], getQueryResults(buildQuery(i, "1..3")));
|
||||
assertEqual([ 1657598895986170 ], getQueryResults(buildQuery(i, "[1,2,3,4]")));
|
||||
assertEqual([ 1657598895986170 ], getQueryResults(buildQuery(i, "1..4")));
|
||||
assertEqual([ 1580543009747638 ], getQueryResults(buildQuery(i, "[1,2,4,3]")));
|
||||
assertEqual([ 157821093310761 ], getQueryResults(buildQuery(i, "[1,2,3,2]")));
|
||||
assertEqual([ 1032992608692014 ], getQueryResults(buildQuery(i, "[1,2,3,2,1]")));
|
||||
assertEqual([ 2051766968908771 ], getQueryResults(buildQuery(i, "1..1000")));
|
||||
assertEqual([ 1954991255293719 ], getQueryResults(buildQuery(i, "{}")));
|
||||
assertEqual([ 1270059518310386 ], getQueryResults(buildQuery(i, "{a:1}")));
|
||||
assertEqual([ 1462532781001381 ], getQueryResults(buildQuery(i, "{a:2}")));
|
||||
assertEqual([ 1872109801523384 ], getQueryResults(buildQuery(i, "{a:1,b:1}")));
|
||||
assertEqual([ 599770551193312 ], getQueryResults(buildQuery(i, "{a:1,b:2}")));
|
||||
assertEqual([ 1872109801523384 ], getQueryResults(buildQuery(i, "{b:1,a:1}")));
|
||||
assertEqual([ 599770551193312 ], getQueryResults(buildQuery(i, "{b:2,a:1}")));
|
||||
assertEqual([ 876136767628139 ], getQueryResults(buildQuery(i, "{b:1,a:2}")));
|
||||
assertEqual([ 876136767628139 ], getQueryResults(buildQuery(i, "{a:2,b:1}")));
|
||||
assertEqual([ 92631926086363 ], getQueryResults(buildQuery(i, "{a:2,b:'1'}")));
|
||||
assertEqual([ 2054068497715740 ], getQueryResults(buildQuery(i, "{a:2,b:null}")));
|
||||
assertEqual([ 550542031834779 ], getQueryResults(buildQuery(i, "{A:1,B:2}")));
|
||||
assertEqual([ 2125993103279620 ], getQueryResults(buildQuery(i, "{a:'A',b:'B'}")));
|
||||
assertEqual([ 878459260153284 ], getQueryResults(buildQuery(i, "{a:'a',b:'b'}")));
|
||||
assertEqual([ 1454594333033579 ], getQueryResults(buildQuery(i, "{a:['a'],b:['b']}")));
|
||||
assertEqual([ 296899533959594 ], getQueryResults(buildQuery(i, "{a:1,b:-1}")));
|
||||
assertEqual([ 944398530367049 ], getQueryResults(buildQuery(i, "{_id:'foo',_key:'bar',_rev:'baz'}")));
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
// order does not matter
|
||||
assertEqual(getQueryResults(buildQuery(i, "{a:1,b:2}")), getQueryResults(buildQuery(i, "{b:2,a:1}")));
|
||||
assertNotEqual(getQueryResults(buildQuery(i, "{a:1,b:2}")), getQueryResults(buildQuery(i, "{a:2,b:1}")));
|
||||
// order matters
|
||||
assertNotEqual(getQueryResults(buildQuery(i, "[1,2,3]")), getQueryResults(buildQuery(i, "[3,2,1]")));
|
||||
// arrays and ranges
|
||||
assertEqual(getQueryResults(buildQuery(i, "[1,2,3]")), getQueryResults(buildQuery(i, "1..3")));
|
||||
// arrays and subqueries
|
||||
assertEqual(getQueryResults(buildQuery(i, "[1,2,3]")), getQueryResults(buildQuery(i, "FOR i IN [1,2,3] RETURN i")));
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test md5 function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -41,6 +41,47 @@ var assertQueryError = helper.assertQueryError;
|
|||
function ahuacatlTypesFunctionsTestSuite () {
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test typename function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTypename : function () {
|
||||
assertEqual([ "null" ], getQueryResults("RETURN NOOPT(TYPENAME(null))"));
|
||||
assertEqual([ "bool" ], getQueryResults("RETURN NOOPT(TYPENAME(false))"));
|
||||
assertEqual([ "bool" ], getQueryResults("RETURN NOOPT(TYPENAME(true))"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN NOOPT(TYPENAME(0))"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN NOOPT(TYPENAME(1))"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN NOOPT(TYPENAME(-99999))"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN NOOPT(TYPENAME(0.005))"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN NOOPT(TYPENAME(1334540.005))"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN NOOPT(TYPENAME(3e32))"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN NOOPT(TYPENAME(1..2))"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN NOOPT(TYPENAME(99..0))"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN NOOPT(TYPENAME(FOR i IN 1..10 RETURN i))"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN NOOPT(TYPENAME([ ]))"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN NOOPT(TYPENAME([ 'foo ' ]))"));
|
||||
assertEqual([ "object" ], getQueryResults("RETURN NOOPT(TYPENAME({ }))"));
|
||||
assertEqual([ "object" ], getQueryResults("RETURN NOOPT(TYPENAME({ 'foo': 'bar' }))"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN NOOPT(TYPENAME('foo'))"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN NOOPT(TYPENAME(''))"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN NOOPT(TYPENAME(' '))"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN NOOPT(TYPENAME('0'))"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN NOOPT(TYPENAME('1'))"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN NOOPT(TYPENAME('true'))"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN NOOPT(TYPENAME('false'))"));
|
||||
assertEqual([ "number", "number" ], getQueryResults("FOR i IN 1..2 RETURN NOOPT(TYPENAME(i))"));
|
||||
assertEqual([ "string", "string", "string", "number" ], getQueryResults("FOR i IN [ 'foo', 'bar', 'baz', 42 ] RETURN NOOPT(TYPENAME(i))"));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test typename function, invalid arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTypenameInvalid : function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(TYPENAME())");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN NOOPT(TYPENAME('a', 'b'))");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test is_string function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -65,6 +65,47 @@ function ahuacatlTypesFunctionsTestSuite () {
|
|||
db._drop(vn);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test typename function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTypename : function () {
|
||||
assertEqual([ "null" ], getQueryResults("RETURN TYPENAME(null)"));
|
||||
assertEqual([ "bool" ], getQueryResults("RETURN TYPENAME(false)"));
|
||||
assertEqual([ "bool" ], getQueryResults("RETURN TYPENAME(true)"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN TYPENAME(0)"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN TYPENAME(1)"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN TYPENAME(-99999)"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN TYPENAME(0.005)"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN TYPENAME(1334540.005)"));
|
||||
assertEqual([ "number" ], getQueryResults("RETURN TYPENAME(3e32)"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN TYPENAME(1..2)"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN TYPENAME(99..0)"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN TYPENAME(FOR i IN 1..10 RETURN i)"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN TYPENAME([ ])"));
|
||||
assertEqual([ "array" ], getQueryResults("RETURN TYPENAME([ 'foo ' ])"));
|
||||
assertEqual([ "object" ], getQueryResults("RETURN TYPENAME({ })"));
|
||||
assertEqual([ "object" ], getQueryResults("RETURN TYPENAME({ 'foo': 'bar' })"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN TYPENAME('foo')"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN TYPENAME('')"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN TYPENAME(' ')"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN TYPENAME('0')"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN TYPENAME('1')"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN TYPENAME('true')"));
|
||||
assertEqual([ "string" ], getQueryResults("RETURN TYPENAME('false')"));
|
||||
assertEqual([ "number", "number" ], getQueryResults("FOR i IN 1..2 RETURN TYPENAME(i)"));
|
||||
assertEqual([ "string", "string", "string", "number" ], getQueryResults("FOR i IN [ 'foo', 'bar', 'baz', 42 ] RETURN TYPENAME(i)"));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test typename function, invalid arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTypenameInvalid : function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN TYPENAME()");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN TYPENAME('a', 'b')");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test is_string function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -854,6 +854,47 @@ function ahuacatlQueryCollectionTestSuite () {
|
|||
var expected = [ [ "riding", "skating", "swimming", null, "swimming" ] ];
|
||||
var actual = getQueryResults("FOR u in " + users.name() + " FILTER HAS(u, 'hobbies') RETURN [ u.hobbies[0], u.hobbies[1], u.hobbies[2], u.hobbies[3], u.hobbies[-1] ]");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test hashing the documents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testHashes : function () {
|
||||
var expected = [
|
||||
1089385960271542,
|
||||
1549718497690202,
|
||||
560358553578052,
|
||||
1642812332573238,
|
||||
435359225373270,
|
||||
408295336378511,
|
||||
1897938296916959,
|
||||
713554280722917,
|
||||
369118524423277,
|
||||
1548261017980441,
|
||||
541971611858512,
|
||||
1804578553815548,
|
||||
976161958841139,
|
||||
259242346857309,
|
||||
671328068995257,
|
||||
2154779012539123,
|
||||
1413254027041724,
|
||||
854175714643442,
|
||||
178243611496212,
|
||||
791314881371364
|
||||
];
|
||||
var actual = getQueryResults("FOR u in " + users.name() + " SORT u.id RETURN HASH(UNSET(u, ['_key', '_rev', '_id']))");
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test hashing the documents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testHashSubquery : function () {
|
||||
var expected = [ 1866655274639415 ];
|
||||
var actual = getQueryResults("RETURN HASH(FOR u in " + users.name() + " SORT u.id RETURN UNSET(u, ['_key', '_rev', '_id']))");
|
||||
assertEqual(expected, actual);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue