1
0
Fork 0

add AQL functions CRC32 and FNV64 (#8600)

This commit is contained in:
Jan 2019-03-28 03:06:33 +01:00 committed by GitHub
parent e0ebfefddd
commit 14720b85be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 105 additions and 6 deletions

View File

@ -1,6 +1,8 @@
devel
-----
* added AQL functions CRC32 and FNV64 for hashing data
* renamed attribute key `openssl-version` in server/client tool version
details output to `openssl-version-compile-time`.

View File

@ -211,9 +211,11 @@ documents are the same, or for grouping values in queries.
See the following string functions:
- [CRC32()](String.md#crc32)
- [FNV64()](String.md#fnv64)
- [MD5()](String.md#md5)
- [SHA1()](String.md#sha1)
- [SHA512()](String.md#sha512)
- [MD5()](String.md#md5)
Function calling
----------------

View File

@ -113,6 +113,22 @@ COUNT()
This is an alias for [LENGTH()](#length).
CRC32()
-----
`CRC32(text) → hash`
Calculate the CRC32 checksum for *text* and return it in a hexadecimal
string representation. The polynomial used is 0x1EDC6F41. The initial
value used is 0xFFFFFFFF, and the final xor value is also 0xFFFFFFFF.
- **text** (string): a string
- returns **hash** (string): CRC32 checksum as hex string
```js
CRC32("foobar") // "D5F5C7F"
```
ENCODE_URI_COMPONENT()
-----------
@ -170,6 +186,21 @@ FIND_LAST("foobarbaz", "ba", 7) // -1
FIND_LAST("foobarbaz", "ba", 0, 4) // 3
```
FNV64()
-----
`FNV64(text) → hash`
Calculate the FNV-1A 64 bit hash for *text* and return it in a hexadecimal
string representation.
- **text** (string): a string
- returns **hash** (string): FNV-1A hash as hex string
```js
FNV64("foobar") // "85944171F73967E8"
```
JSON_PARSE()
------------

View File

@ -204,6 +204,8 @@ void AqlFunctionFeature::addStringFunctions() {
add({"MD5", ".", flags, &Functions::Md5});
add({"SHA1", ".", flags, &Functions::Sha1});
add({"SHA512", ".", flags, &Functions::Sha512});
add({"CRC32", ".", flags, &Functions::Crc32});
add({"FNV64", ".", flags, &Functions::Fnv64});
add({"HASH", ".", flags, &Functions::Hash});
add({"TO_BASE64", ".", flags, &Functions::ToBase64});
add({"TO_HEX", ".", flags, &Functions::ToHex});

View File

@ -39,7 +39,9 @@
#include "Basics/Utf8Helper.h"
#include "Basics/VPackStringBufferAdapter.h"
#include "Basics/VelocyPackHelper.h"
#include "Basics/conversions.h"
#include "Basics/fpconv.h"
#include "Basics/hashes.h"
#include "Basics/tri-strings.h"
#include "Geo/GeoJson.h"
#include "Geo/GeoParams.h"
@ -4191,6 +4193,36 @@ AqlValue Functions::Sha512(ExpressionContext*, transaction::Methods* trx,
return AqlValue(&hex[0], 128);
}
/// @brief function Crc32
AqlValue Functions::Crc32(ExpressionContext*, transaction::Methods* trx,
VPackFunctionParameters const& parameters) {
AqlValue const& value = extractFunctionParameterValue(parameters, 0);
transaction::StringBufferLeaser buffer(trx);
arangodb::basics::VPackStringBufferAdapter adapter(buffer->stringBuffer());
::appendAsString(trx, adapter, value);
uint32_t crc = TRI_Crc32HashPointer(buffer->c_str(), buffer->length());
char out[9];
size_t length = TRI_StringUInt32HexInPlace(crc, &out[0]);
return AqlValue(&out[0], length);
}
/// @brief function Fnv64
AqlValue Functions::Fnv64(ExpressionContext*, transaction::Methods* trx,
VPackFunctionParameters const& parameters) {
AqlValue const& value = extractFunctionParameterValue(parameters, 0);
transaction::StringBufferLeaser buffer(trx);
arangodb::basics::VPackStringBufferAdapter adapter(buffer->stringBuffer());
::appendAsString(trx, adapter, value);
uint64_t hash = TRI_FnvHashPointer(buffer->c_str(), buffer->length());
char out[17];
size_t length = TRI_StringUInt64HexInPlace(hash, &out[0]);
return AqlValue(&out[0], length);
}
/// @brief function HASH
AqlValue Functions::Hash(ExpressionContext*, transaction::Methods* trx,
VPackFunctionParameters const& parameters) {

View File

@ -270,6 +270,10 @@ struct Functions {
VPackFunctionParameters const&);
static AqlValue Sha512(arangodb::aql::ExpressionContext*,
transaction::Methods*, VPackFunctionParameters const&);
static AqlValue Crc32(arangodb::aql::ExpressionContext*, transaction::Methods*,
VPackFunctionParameters const&);
static AqlValue Fnv64(arangodb::aql::ExpressionContext*, transaction::Methods*,
VPackFunctionParameters const&);
static AqlValue Hash(arangodb::aql::ExpressionContext*, transaction::Methods*,
VPackFunctionParameters const&);
static AqlValue IsKey(arangodb::aql::ExpressionContext*,

View File

@ -523,9 +523,5 @@ uint32_t TRI_Crc32HashPointer(void const* data, size_t length) {
/// @brief computes a CRC32 for strings
uint32_t TRI_Crc32HashString(char const* data) {
size_t len = strlen(data);
uint32_t crc = TRI_InitialCrc32();
crc = (*TRI_BlockCrc32)(crc, data, len);
return TRI_FinalCrc32(crc);
return TRI_Crc32HashPointer(data, strlen(data));
}

View File

@ -60,9 +60,11 @@ extern uint32_t (*TRI_BlockCrc32)(uint32_t hash, char const* data, size_t length
}
/// @brief computes a CRC32 for memory blobs
/// the polynomial used is 0x1EDC6F41.
uint32_t TRI_Crc32HashPointer(void const*, size_t);
/// @brief computes a CRC32 for strings
/// the polynomial used is 0x1EDC6F41.
uint32_t TRI_Crc32HashString(char const*);
#endif

View File

@ -2513,6 +2513,34 @@ function ahuacatlStringFunctionsTestSuite () {
assertEqual([ '888227c44807b86059eb36f9fe0fc602a9b16fab' ], getQueryResults(`RETURN NOOPT(SHA1('[1,2,4,7,11,16,22,29,37,46,56,67,79,92,106,121,137,154,172,191,211,232,254,277,301,326,352,379,407,436,466,497,529,562,596,631,667,704,742,781,821,862,904,947,991,1036,1082,1129,1177,1226,1276,1327,1379,1432,1486,1541,1597,1654,1712,1771,1831,1892,1954,2017,2081,2146,2212,2279,2347,2416,2486,2557,2629,2702,2776,2851,2927,3004,3082,3161,3241,3322,3404,3487,3571,3656,3742,3829,3917,4006,4096,4187,4279,4372,4466,4561,4657,4754,4852,4951]'))`));
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief test crc32 function
// //////////////////////////////////////////////////////////////////////////////
testCrc32: function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, 'RETURN NOOPT(CRC32())');
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, 'RETURN NOOPT(CRC32("foo", 2))');
assertEqual([ '0' ], getQueryResults(`RETURN NOOPT(CRC32(''))`));
assertEqual([ '72C0DD8F' ], getQueryResults(`RETURN NOOPT(CRC32(' '))`));
assertEqual([ '629E1AE0' ], getQueryResults(`RETURN NOOPT(CRC32('0'))`));
assertEqual([ '90F599E3' ], getQueryResults(`RETURN NOOPT(CRC32('1'))`));
assertEqual([ '89614B3B' ], getQueryResults(`RETURN NOOPT(CRC32('This is a test string'))`));
assertEqual([ 'CC778246' ], getQueryResults(`RETURN NOOPT(CRC32('With\r\nLinebreaks\n'))`));
assertEqual([ '0' ], getQueryResults(`RETURN NOOPT(CRC32(null))`));
},
testFnv64: function () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, 'RETURN NOOPT(FNV64())');
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, 'RETURN NOOPT(FNV64("foo", 2))');
assertEqual([ 'CBF29CE484222325' ], getQueryResults(`RETURN NOOPT(FNV64(''))`));
assertEqual([ 'AF639D4C8601817F' ], getQueryResults(`RETURN NOOPT(FNV64(' '))`));
assertEqual([ 'AF63AD4C86019CAF' ], getQueryResults(`RETURN NOOPT(FNV64('0'))`));
assertEqual([ 'AF63AC4C86019AFC' ], getQueryResults(`RETURN NOOPT(FNV64('1'))`));
assertEqual([ 'D94D32CC2E5C3409' ], getQueryResults(`RETURN NOOPT(FNV64('This is a test string'))`));
assertEqual([ 'AF870D34E69ABE0A' ], getQueryResults(`RETURN NOOPT(FNV64('With\r\nLinebreaks\n'))`));
assertEqual([ 'CBF29CE484222325' ], getQueryResults(`RETURN NOOPT(FNV64(null))`));
},
// //////////////////////////////////////////////////////////////////////////////
// / @brief test random_token function
// //////////////////////////////////////////////////////////////////////////////