1
0
Fork 0

Merge branch 'devel' of github.com:arangodb/arangodb into devel

This commit is contained in:
Michael Hackstein 2016-04-21 13:33:45 +02:00
commit 0d08febc60
11 changed files with 150 additions and 52 deletions

View File

@ -33,6 +33,7 @@
#include <memory> #include <memory>
#include "velocypack/velocypack-common.h" #include "velocypack/velocypack-common.h"
#include "velocypack/Options.h"
#include "velocypack/Slice.h" #include "velocypack/Slice.h"
namespace arangodb { namespace arangodb {
@ -79,8 +80,8 @@ class AttributeTranslatorScope {
public: public:
explicit AttributeTranslatorScope(AttributeTranslator* translator) explicit AttributeTranslatorScope(AttributeTranslator* translator)
: _old(Slice::attributeTranslator) { : _old(Options::Defaults.attributeTranslator) {
Slice::attributeTranslator = translator; Options::Defaults.attributeTranslator = translator;
} }
~AttributeTranslatorScope() { ~AttributeTranslatorScope() {
@ -89,7 +90,7 @@ class AttributeTranslatorScope {
// prematurely revert the change // prematurely revert the change
void revert() { void revert() {
Slice::attributeTranslator = _old; Options::Defaults.attributeTranslator = _old;
} }
private: private:

View File

@ -55,7 +55,7 @@ struct Exception : std::exception {
NeedCustomTypeHandler = 19, NeedCustomTypeHandler = 19,
NeedAttributeTranslator = 20, NeedAttributeTranslator = 20,
CannotTranslateKey = 21, CannotTranslateKey = 21,
KeyNotFound = 22, KeyNotFound = 22, // not used anymore
BuilderNotSealed = 30, BuilderNotSealed = 30,
BuilderNeedOpenObject = 31, BuilderNeedOpenObject = 31,

View File

@ -48,7 +48,6 @@ namespace velocypack {
// forward for fasthash64 function declared elsewhere // forward for fasthash64 function declared elsewhere
uint64_t fasthash64(void const*, size_t, uint64_t); uint64_t fasthash64(void const*, size_t, uint64_t);
class AttributeTranslator;
class SliceScope; class SliceScope;
class Slice { class Slice {
@ -62,8 +61,6 @@ class Slice {
public: public:
static AttributeTranslator* attributeTranslator;
// constructor for an empty Value of type None // constructor for an empty Value of type None
Slice() : Slice("\x00") {} Slice() : Slice("\x00") {}
@ -220,7 +217,7 @@ class Slice {
// check if slice is any Number-type object // check if slice is any Number-type object
bool isNumber() const throw() { return isInteger() || isDouble(); } bool isNumber() const throw() { return isInteger() || isDouble(); }
bool isSorted() const { bool isSorted() const throw() {
auto const h = head(); auto const h = head();
return (h >= 0x0b && h <= 0x0e); return (h >= 0x0b && h <= 0x0e);
} }
@ -750,6 +747,10 @@ class Slice {
std::string hexType() const; std::string hexType() const;
private: private:
// return the value for a UInt object, without checks
// returns 0 for invalid values/types
uint64_t getUIntUnchecked() const;
// translates an integer key into a string, without checks // translates an integer key into a string, without checks
Slice translateUnchecked() const; Slice translateUnchecked() const;
@ -783,7 +784,7 @@ class Slice {
// get the offset for the nth member from a compact Array or Object type // get the offset for the nth member from a compact Array or Object type
ValueLength getNthOffsetFromCompact(ValueLength index) const; ValueLength getNthOffsetFromCompact(ValueLength index) const;
ValueLength indexEntrySize(uint8_t head) const { inline ValueLength indexEntrySize(uint8_t head) const throw() {
VELOCYPACK_ASSERT(head <= 0x12); VELOCYPACK_ASSERT(head <= 0x12);
return static_cast<ValueLength>(WidthMap[head]); return static_cast<ValueLength>(WidthMap[head]);
} }

View File

@ -93,7 +93,7 @@ uint8_t const* AttributeTranslator::translate(uint64_t id) const {
auto it = _idToKey.find(id); auto it = _idToKey.find(id);
if (it == _idToKey.end()) { if (it == _idToKey.end()) {
throw Exception(Exception::KeyNotFound); return nullptr;
} }
return (*it).second; return (*it).second;

View File

@ -593,18 +593,17 @@ uint8_t* Builder::set(Value const& item) {
break; break;
} }
case ValueType::String: { case ValueType::String: {
if (ctype != Value::CType::String && ctype != Value::CType::CharPtr) {
throw Exception(
Exception::BuilderUnexpectedValue,
"Must give a string or char const* for ValueType::String");
}
std::string const* s; std::string const* s;
std::string value; std::string value;
if (ctype == Value::CType::String) { if (ctype == Value::CType::String) {
s = item.getString(); s = item.getString();
} else { } else if (ctype == Value::CType::CharPtr) {
value = item.getCharPtr(); value = item.getCharPtr();
s = &value; s = &value;
} else {
throw Exception(
Exception::BuilderUnexpectedValue,
"Must give a string or char const* for ValueType::String");
} }
size_t const size = s->size(); size_t const size = s->size();
if (size <= 126) { if (size <= 126) {

View File

@ -39,8 +39,6 @@
using namespace arangodb::velocypack; using namespace arangodb::velocypack;
using VT = arangodb::velocypack::ValueType; using VT = arangodb::velocypack::ValueType;
AttributeTranslator* Slice::attributeTranslator = nullptr;
VT const Slice::TypeMap[256] = { VT const Slice::TypeMap[256] = {
/* 0x00 */ VT::None, /* 0x01 */ VT::Array, /* 0x00 */ VT::None, /* 0x01 */ VT::Array,
/* 0x02 */ VT::Array, /* 0x03 */ VT::Array, /* 0x02 */ VT::Array, /* 0x03 */ VT::Array,
@ -231,19 +229,35 @@ Slice Slice::translate() const {
throw Exception(Exception::InvalidValueType, throw Exception(Exception::InvalidValueType,
"Cannot translate key of this type"); "Cannot translate key of this type");
} }
if (attributeTranslator == nullptr) { if (Options::Defaults.attributeTranslator == nullptr) {
throw Exception(Exception::NeedAttributeTranslator); throw Exception(Exception::NeedAttributeTranslator);
} }
return translateUnchecked(); return translateUnchecked();
} }
// return the value for a UInt object, without checks!
// returns 0 for invalid values/types
uint64_t Slice::getUIntUnchecked() const {
uint8_t const h = head();
if (h >= 0x28 && h <= 0x2f) {
// UInt
return readInteger<uint64_t>(_start + 1, h - 0x27);
}
if (h >= 0x30 && h <= 0x39) {
// Smallint >= 0
return static_cast<uint64_t>(h - 0x30);
}
return 0;
}
// translates an integer key into a string, without checks // translates an integer key into a string, without checks
Slice Slice::translateUnchecked() const { Slice Slice::translateUnchecked() const {
uint8_t const* result = attributeTranslator->translate(getUInt()); uint8_t const* result = Options::Defaults.attributeTranslator->translate(getUIntUnchecked());
if (result == nullptr) { if (result != nullptr) {
return Slice(); return Slice(result);
} }
return Slice(result); return Slice();
} }
// check if two Slices are equal on the binary level // check if two Slices are equal on the binary level
@ -336,7 +350,6 @@ Slice Slice::get(std::string const& attribute) const {
ValueLength const offsetSize = indexEntrySize(h); ValueLength const offsetSize = indexEntrySize(h);
ValueLength end = readInteger<ValueLength>(_start + 1, offsetSize); ValueLength end = readInteger<ValueLength>(_start + 1, offsetSize);
ValueLength dataOffset = 0;
// read number of items // read number of items
ValueLength n; ValueLength n;
@ -348,19 +361,19 @@ Slice Slice::get(std::string const& attribute) const {
if (n == 1) { if (n == 1) {
// Just one attribute, there is no index table! // Just one attribute, there is no index table!
if (dataOffset == 0) { Slice key = Slice(_start + findDataOffset(h));
dataOffset = findDataOffset(h);
}
Slice key = Slice(_start + dataOffset); if (key.isString()) {
if (key.isEqualString(attribute)) {
if (key.isString() && key.isEqualString(attribute)) { return Slice(key.start() + key.byteSize());
return Slice(key.start() + key.byteSize()); }
} // fall through to returning None Slice below
} else if (key.isSmallInt() || key.isUInt()) {
if (key.isSmallInt() || key.isUInt()) {
// translate key // translate key
if (key.translate().isEqualString(attribute)) { if (Options::Defaults.attributeTranslator == nullptr) {
throw Exception(Exception::NeedAttributeTranslator);
}
if (key.translateUnchecked().isEqualString(attribute)) {
return Slice(key.start() + key.byteSize()); return Slice(key.start() + key.byteSize());
} }
} }
@ -376,7 +389,8 @@ Slice Slice::get(std::string const& attribute) const {
// otherwise we'll always use the linear search // otherwise we'll always use the linear search
static ValueLength const SortedSearchEntriesThreshold = 4; static ValueLength const SortedSearchEntriesThreshold = 4;
if (isSorted() && n >= SortedSearchEntriesThreshold) { bool const isSorted = (h >= 0x0b && h <= 0x0e);
if (isSorted && n >= SortedSearchEntriesThreshold) {
// This means, we have to handle the special case n == 1 only // This means, we have to handle the special case n == 1 only
// in the linear search! // in the linear search!
return searchObjectKeyBinary(attribute, ieBase, offsetSize, n); return searchObjectKeyBinary(attribute, ieBase, offsetSize, n);
@ -516,24 +530,25 @@ ValueLength Slice::getNthOffset(ValueLength index) const {
auto const h = head(); auto const h = head();
if (h == 0x01 || h == 0x0a) {
// special case: empty Array or empty Object
throw Exception(Exception::IndexOutOfBounds);
}
if (h == 0x13 || h == 0x14) { if (h == 0x13 || h == 0x14) {
// compact Array or Object // compact Array or Object
return getNthOffsetFromCompact(index); return getNthOffsetFromCompact(index);
} }
if (h == 0x01 || h == 0x0a) {
// special case: empty Array or empty Object
throw Exception(Exception::IndexOutOfBounds);
}
ValueLength const offsetSize = indexEntrySize(h); ValueLength const offsetSize = indexEntrySize(h);
ValueLength end = readInteger<ValueLength>(_start + 1, offsetSize); ValueLength end = readInteger<ValueLength>(_start + 1, offsetSize);
ValueLength dataOffset = findDataOffset(h); ValueLength dataOffset = 0;
// find the number of items // find the number of items
ValueLength n; ValueLength n;
if (h <= 0x05) { // No offset table or length, need to compute: if (h <= 0x05) { // No offset table or length, need to compute:
dataOffset = findDataOffset(h);
Slice first(_start + dataOffset); Slice first(_start + dataOffset);
n = (end - dataOffset) / first.byteSize(); n = (end - dataOffset) / first.byteSize();
} else if (offsetSize < 8) { } else if (offsetSize < 8) {
@ -588,7 +603,7 @@ Slice Slice::makeKey() const {
return *this; return *this;
} }
if (isSmallInt() || isUInt()) { if (isSmallInt() || isUInt()) {
if (attributeTranslator == nullptr) { if (Options::Defaults.attributeTranslator == nullptr) {
throw Exception(Exception::NeedAttributeTranslator); throw Exception(Exception::NeedAttributeTranslator);
} }
return translateUnchecked(); return translateUnchecked();
@ -613,8 +628,7 @@ ValueLength Slice::getNthOffsetFromCompact(ValueLength index) const {
uint8_t const* s = _start + offset; uint8_t const* s = _start + offset;
offset += Slice(s).byteSize(); offset += Slice(s).byteSize();
if (h == 0x14) { if (h == 0x14) {
Slice value = Slice(_start + offset); offset += Slice(_start + offset).byteSize();
offset += value.byteSize();
} }
++current; ++current;
} }
@ -625,7 +639,7 @@ ValueLength Slice::getNthOffsetFromCompact(ValueLength index) const {
Slice Slice::searchObjectKeyLinear(std::string const& attribute, Slice Slice::searchObjectKeyLinear(std::string const& attribute,
ValueLength ieBase, ValueLength offsetSize, ValueLength ieBase, ValueLength offsetSize,
ValueLength n) const { ValueLength n) const {
bool const useTranslator = (attributeTranslator != nullptr); bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr);
for (ValueLength index = 0; index < n; ++index) { for (ValueLength index = 0; index < n; ++index) {
ValueLength offset = ieBase + index * offsetSize; ValueLength offset = ieBase + index * offsetSize;
@ -661,7 +675,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute,
Slice Slice::searchObjectKeyBinary(std::string const& attribute, Slice Slice::searchObjectKeyBinary(std::string const& attribute,
ValueLength ieBase, ValueLength offsetSize, ValueLength ieBase, ValueLength offsetSize,
ValueLength n) const { ValueLength n) const {
bool const useTranslator = (attributeTranslator != nullptr); bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr);
VELOCYPACK_ASSERT(n > 0); VELOCYPACK_ASSERT(n > 0);
ValueLength l = 0; ValueLength l = 0;

View File

@ -1,6 +1,18 @@
v3.0.0 (XXXX-XX-XX) v3.0.0 (XXXX-XX-XX)
------------------- -------------------
* added AQL string comparison operator `LIKE`
The operator can be used to compare strings like this:
value LIKE search
The operator is currently implemented by calling the already existing AQL
function `LIKE`.
This change also makes `LIKE` an AQL keyword. Using `like` in either case as
an attribute or collection name in AQL thus requires quoting.
* make AQL optimizer rule "remove-unnecessary-calculations" fire in more cases * make AQL optimizer rule "remove-unnecessary-calculations" fire in more cases
The rule will now remove calculations that are used exactly once in other The rule will now remove calculations that are used exactly once in other

View File

@ -18,13 +18,17 @@ The following comparison operators are supported:
- *>=* greater or equal - *>=* greater or equal
- *IN* test if a value is contained in an array - *IN* test if a value is contained in an array
- *NOT IN* test if a value is not contained in an array - *NOT IN* test if a value is not contained in an array
- *LIKE* tests if a string value matches a pattern
These operators accept any data types for the first and second operands.
Each of the comparison operators returns a boolean value if the comparison can Each of the comparison operators returns a boolean value if the comparison can
be evaluated and returns *true* if the comparison evaluates to true, and *false* be evaluated and returns *true* if the comparison evaluates to true, and *false*
otherwise. Please note that the comparison operators will not perform any otherwise.
implicit type casts if the compared operands have different types.
The comparison operators accept any data types for the first and second operands.
However, *IN* and *NOT IN* will only return a meaningful result if their right-hand
operand is a string, and *LIKE* will only execute if both operands are string values.
The comparison operators will not perform any implicit type casts if the compared
operands have different or non-sensible types.
Some examples for comparison operations in AQL: Some examples for comparison operations in AQL:
@ -39,8 +43,26 @@ true != null // true
1.5 IN [ 2, 3, 1.5 ] // true 1.5 IN [ 2, 3, 1.5 ] // true
"foo" IN null // false "foo" IN null // false
42 NOT IN [ 17, 40, 50 ] // true 42 NOT IN [ 17, 40, 50 ] // true
"abc" == "abc" // true
"abc" == "ABC" // false
"foo" LIKE "f%" // true
``` ```
The *LIKE* operator checks whether its left operand matches the pattern specified
in its right operand. The pattern can consist of regular characters and wildcards.
The supported wildcards are *_* to match a single arbitrary character, and *%* to
match any number of arbitrary characters. Literal *%* and *_* need to be escaped
with a backslash.
```
"abc" LIKE "a%" // true
"abc" LIKE "_bc" // true
"a_b_foo" LIKE "a\\_b\\_f%" // true
```
The pattern matching performed by the *LIKE* operator is case-sensitive.
!SUBSUBSECTION Array comparison operators !SUBSUBSECTION Array comparison operators
The comparison operators also exist as *array variant*. In the array The comparison operators also exist as *array variant*. In the array

View File

@ -109,6 +109,7 @@ The current list of keywords is:
- NOT - NOT
- AND - AND
- OR - OR
- LIKE
- NULL - NULL
- TRUE - TRUE
- FALSE - FALSE

View File

@ -60,6 +60,11 @@ function ahuacatlStringFunctionsTestSuite () {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
testLikeInvalid : function () { testLikeInvalid : function () {
assertQueryError(errors.ERROR_QUERY_PARSE.code, "RETURN LIKE");
assertQueryError(errors.ERROR_QUERY_PARSE.code, "RETURN \"test\" LIKE");
assertQueryError(errors.ERROR_QUERY_PARSE.code, "RETURN LIKE \"test\"");
assertQueryError(errors.ERROR_QUERY_PARSE.code, "RETURN \"test\" LIKE \"meow\", \"foo\", \"bar\")");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN LIKE()"); assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN LIKE()");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN LIKE(\"test\")"); assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN LIKE(\"test\")");
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN LIKE(\"test\", \"meow\", \"foo\", \"bar\")"); assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN LIKE(\"test\", \"meow\", \"foo\", \"bar\")");
@ -70,6 +75,21 @@ function ahuacatlStringFunctionsTestSuite () {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
testLike : function () { testLike : function () {
// containment
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"test\""));
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"%test\""));
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"test%\""));
assertEqual([ true ], getQueryResults("RETURN \"this is a test string\" LIKE \"%test%\""));
assertEqual([ true ], getQueryResults("RETURN \"this is a test string\" LIKE \"this%test%\""));
assertEqual([ true ], getQueryResults("RETURN \"this is a test string\" LIKE \"this%is%test%\""));
assertEqual([ true ], getQueryResults("RETURN \"this is a test string\" LIKE \"this%g\""));
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"this%n\""));
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"This%n\""));
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"his%\""));
assertEqual([ true ], getQueryResults("RETURN \"this is a test string\" LIKE \"%g\""));
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"%G\""));
assertEqual([ false ], getQueryResults("RETURN \"this is a test string\" LIKE \"this%test%is%\""));
assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"test\")")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"test\")"));
assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"%test\")")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"%test\")"));
assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"test%\")")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"test%\")"));
@ -84,6 +104,27 @@ function ahuacatlStringFunctionsTestSuite () {
assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"%G\")")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"%G\")"));
assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"this%test%is%\")")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"this is a test string\", \"this%test%is%\")"));
// special characters
assertEqual([ true ], getQueryResults("RETURN \"%\" LIKE \"\\%\""));
assertEqual([ true ], getQueryResults("RETURN \"a%c\" LIKE \"a%c\""));
assertEqual([ false ], getQueryResults("RETURN \"a%c\" LIKE \"ac\""));
assertEqual([ false ], getQueryResults("RETURN \"a%c\" LIKE \"a\\\\%\""));
assertEqual([ false ], getQueryResults("RETURN \"a%c\" LIKE \"\\\\%a%\""));
assertEqual([ false ], getQueryResults("RETURN \"a%c\" LIKE \"\\\\%\\\\%\""));
assertEqual([ true ], getQueryResults("RETURN \"%%\" LIKE \"\\\\%\\\\%\""));
assertEqual([ true ], getQueryResults("RETURN \"_\" LIKE \"\\\\_\""));
assertEqual([ true ], getQueryResults("RETURN \"_\" LIKE \"\\\\_%\""));
assertEqual([ true ], getQueryResults("RETURN \"abcd\" LIKE \"_bcd\""));
assertEqual([ true ], getQueryResults("RETURN \"abcde\" LIKE \"_bcd%\""));
assertEqual([ false ], getQueryResults("RETURN \"abcde\" LIKE \"\\\\_bcd%\""));
assertEqual([ true ], getQueryResults("RETURN \"\\\\abc\" LIKE \"\\\\\\\\%\""));
assertEqual([ true ], getQueryResults("RETURN \"\\abc\" LIKE \"\\a%\""));
assertEqual([ true ], getQueryResults("RETURN \"[ ] ( ) % * . + -\" LIKE \"[%\""));
assertEqual([ true ], getQueryResults("RETURN \"[ ] ( ) % * . + -\" LIKE \"[ ] ( ) \\% * . + -\""));
assertEqual([ true ], getQueryResults("RETURN \"[ ] ( ) % * . + -\" LIKE \"%. +%\""));
assertEqual([ true ], getQueryResults("RETURN \"abc^def$g\" LIKE \"abc^def$g\""));
assertEqual([ true ], getQueryResults("RETURN \"abc^def$g\" LIKE \"%^%$g\""));
assertEqual([ true ], getQueryResults("RETURN LIKE(\"%\", \"\\%\")")); assertEqual([ true ], getQueryResults("RETURN LIKE(\"%\", \"\\%\")"));
assertEqual([ true ], getQueryResults("RETURN LIKE(\"a%c\", \"a%c\")")); assertEqual([ true ], getQueryResults("RETURN LIKE(\"a%c\", \"a%c\")"));
assertEqual([ false ], getQueryResults("RETURN LIKE(\"a%c\", \"ac\")")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"a%c\", \"ac\")"));
@ -104,6 +145,11 @@ function ahuacatlStringFunctionsTestSuite () {
assertEqual([ true ], getQueryResults("RETURN LIKE(\"abc^def$g\", \"abc^def$g\")")); assertEqual([ true ], getQueryResults("RETURN LIKE(\"abc^def$g\", \"abc^def$g\")"));
assertEqual([ true ], getQueryResults("RETURN LIKE(\"abc^def$g\", \"%^%$g\")")); assertEqual([ true ], getQueryResults("RETURN LIKE(\"abc^def$g\", \"%^%$g\")"));
// case-sensivity
assertEqual([ false ], getQueryResults("RETURN \"ABCD\" LIKE \"abcd\""));
assertEqual([ false ], getQueryResults("RETURN \"abcd\" LIKE \"ABCD\""));
assertEqual([ false ], getQueryResults("RETURN \"MÖterTräNenMÜtterSöhne\" LIKE \"MÖTERTRÄNENMÜTTERSÖHNE\""));
assertEqual([ false ], getQueryResults("RETURN LIKE(\"ABCD\", \"abcd\", false)")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"ABCD\", \"abcd\", false)"));
assertEqual([ true ], getQueryResults("RETURN LIKE(\"ABCD\", \"abcd\", true)")); assertEqual([ true ], getQueryResults("RETURN LIKE(\"ABCD\", \"abcd\", true)"));
assertEqual([ false ], getQueryResults("RETURN LIKE(\"abcd\", \"ABCD\", false)")); assertEqual([ false ], getQueryResults("RETURN LIKE(\"abcd\", \"ABCD\", false)"));
@ -130,6 +176,9 @@ function ahuacatlStringFunctionsTestSuite () {
actual = getQueryResults("RETURN LIKE(" + JSON.stringify(value) + ", " + JSON.stringify(value) + ")"); actual = getQueryResults("RETURN LIKE(" + JSON.stringify(value) + ", " + JSON.stringify(value) + ")");
assertEqual([ true ], actual); assertEqual([ true ], actual);
actual = getQueryResults("RETURN " + JSON.stringify(value) + " LIKE " + JSON.stringify(value));
assertEqual([ true ], actual);
}); });
}, },

View File

@ -89,7 +89,6 @@ void VelocyPackHelper::initialize() {
// set the attribute translator in the global options // set the attribute translator in the global options
VPackOptions::Defaults.attributeTranslator = Translator.get(); VPackOptions::Defaults.attributeTranslator = Translator.get();
VPackSlice::attributeTranslator = Translator.get();
// VPackOptions::Defaults.unsupportedTypeBehavior = VPackOptions::ConvertUnsupportedType; // VPackOptions::Defaults.unsupportedTypeBehavior = VPackOptions::ConvertUnsupportedType;
// initialize exclude handler for system attributes // initialize exclude handler for system attributes