mirror of https://gitee.com/bigwinds/arangodb
Bug fix/fix in not in workaround (#9813)
This commit is contained in:
parent
8c13019900
commit
86a496b8a3
File diff suppressed because it is too large
Load Diff
|
@ -85,39 +85,39 @@ extern int Aqldebug;
|
|||
T_NOT = 290,
|
||||
T_AND = 291,
|
||||
T_OR = 292,
|
||||
T_NIN = 293,
|
||||
T_REGEX_MATCH = 294,
|
||||
T_REGEX_NON_MATCH = 295,
|
||||
T_EQ = 296,
|
||||
T_NE = 297,
|
||||
T_LT = 298,
|
||||
T_GT = 299,
|
||||
T_LE = 300,
|
||||
T_GE = 301,
|
||||
T_LIKE = 302,
|
||||
T_PLUS = 303,
|
||||
T_MINUS = 304,
|
||||
T_TIMES = 305,
|
||||
T_DIV = 306,
|
||||
T_MOD = 307,
|
||||
T_QUESTION = 308,
|
||||
T_COLON = 309,
|
||||
T_SCOPE = 310,
|
||||
T_RANGE = 311,
|
||||
T_COMMA = 312,
|
||||
T_OPEN = 313,
|
||||
T_CLOSE = 314,
|
||||
T_OBJECT_OPEN = 315,
|
||||
T_OBJECT_CLOSE = 316,
|
||||
T_ARRAY_OPEN = 317,
|
||||
T_ARRAY_CLOSE = 318,
|
||||
T_OUTBOUND = 319,
|
||||
T_INBOUND = 320,
|
||||
T_ANY = 321,
|
||||
T_ALL = 322,
|
||||
T_NONE = 323,
|
||||
UMINUS = 324,
|
||||
UPLUS = 325,
|
||||
T_REGEX_MATCH = 293,
|
||||
T_REGEX_NON_MATCH = 294,
|
||||
T_EQ = 295,
|
||||
T_NE = 296,
|
||||
T_LT = 297,
|
||||
T_GT = 298,
|
||||
T_LE = 299,
|
||||
T_GE = 300,
|
||||
T_LIKE = 301,
|
||||
T_PLUS = 302,
|
||||
T_MINUS = 303,
|
||||
T_TIMES = 304,
|
||||
T_DIV = 305,
|
||||
T_MOD = 306,
|
||||
T_QUESTION = 307,
|
||||
T_COLON = 308,
|
||||
T_SCOPE = 309,
|
||||
T_RANGE = 310,
|
||||
T_COMMA = 311,
|
||||
T_OPEN = 312,
|
||||
T_CLOSE = 313,
|
||||
T_OBJECT_OPEN = 314,
|
||||
T_OBJECT_CLOSE = 315,
|
||||
T_ARRAY_OPEN = 316,
|
||||
T_ARRAY_CLOSE = 317,
|
||||
T_OUTBOUND = 318,
|
||||
T_INBOUND = 319,
|
||||
T_ANY = 320,
|
||||
T_ALL = 321,
|
||||
T_NONE = 322,
|
||||
UMINUS = 323,
|
||||
UPLUS = 324,
|
||||
UNEGATION = 325,
|
||||
FUNCCALL = 326,
|
||||
REFERENCE = 327,
|
||||
INDEXED = 328,
|
||||
|
|
|
@ -85,39 +85,39 @@ extern int Aqldebug;
|
|||
T_NOT = 290,
|
||||
T_AND = 291,
|
||||
T_OR = 292,
|
||||
T_NIN = 293,
|
||||
T_REGEX_MATCH = 294,
|
||||
T_REGEX_NON_MATCH = 295,
|
||||
T_EQ = 296,
|
||||
T_NE = 297,
|
||||
T_LT = 298,
|
||||
T_GT = 299,
|
||||
T_LE = 300,
|
||||
T_GE = 301,
|
||||
T_LIKE = 302,
|
||||
T_PLUS = 303,
|
||||
T_MINUS = 304,
|
||||
T_TIMES = 305,
|
||||
T_DIV = 306,
|
||||
T_MOD = 307,
|
||||
T_QUESTION = 308,
|
||||
T_COLON = 309,
|
||||
T_SCOPE = 310,
|
||||
T_RANGE = 311,
|
||||
T_COMMA = 312,
|
||||
T_OPEN = 313,
|
||||
T_CLOSE = 314,
|
||||
T_OBJECT_OPEN = 315,
|
||||
T_OBJECT_CLOSE = 316,
|
||||
T_ARRAY_OPEN = 317,
|
||||
T_ARRAY_CLOSE = 318,
|
||||
T_OUTBOUND = 319,
|
||||
T_INBOUND = 320,
|
||||
T_ANY = 321,
|
||||
T_ALL = 322,
|
||||
T_NONE = 323,
|
||||
UMINUS = 324,
|
||||
UPLUS = 325,
|
||||
T_REGEX_MATCH = 293,
|
||||
T_REGEX_NON_MATCH = 294,
|
||||
T_EQ = 295,
|
||||
T_NE = 296,
|
||||
T_LT = 297,
|
||||
T_GT = 298,
|
||||
T_LE = 299,
|
||||
T_GE = 300,
|
||||
T_LIKE = 301,
|
||||
T_PLUS = 302,
|
||||
T_MINUS = 303,
|
||||
T_TIMES = 304,
|
||||
T_DIV = 305,
|
||||
T_MOD = 306,
|
||||
T_QUESTION = 307,
|
||||
T_COLON = 308,
|
||||
T_SCOPE = 309,
|
||||
T_RANGE = 310,
|
||||
T_COMMA = 311,
|
||||
T_OPEN = 312,
|
||||
T_CLOSE = 313,
|
||||
T_OBJECT_OPEN = 314,
|
||||
T_OBJECT_CLOSE = 315,
|
||||
T_ARRAY_OPEN = 316,
|
||||
T_ARRAY_CLOSE = 317,
|
||||
T_OUTBOUND = 318,
|
||||
T_INBOUND = 319,
|
||||
T_ANY = 320,
|
||||
T_ALL = 321,
|
||||
T_NONE = 322,
|
||||
UMINUS = 323,
|
||||
UPLUS = 324,
|
||||
UNEGATION = 325,
|
||||
FUNCCALL = 326,
|
||||
REFERENCE = 327,
|
||||
INDEXED = 328,
|
||||
|
|
|
@ -256,7 +256,6 @@ static AstNode* TransformOutputVariables(Parser* parser, AstNode const* names) {
|
|||
%token T_NOT "not operator"
|
||||
%token T_AND "and operator"
|
||||
%token T_OR "or operator"
|
||||
%token T_NIN "not in operator"
|
||||
|
||||
%token T_REGEX_MATCH "~= operator"
|
||||
%token T_REGEX_NON_MATCH "~! operator"
|
||||
|
@ -309,12 +308,12 @@ static AstNode* TransformOutputVariables(Parser* parser, AstNode const* names) {
|
|||
%left T_AND
|
||||
%nonassoc T_OUTBOUND T_INBOUND T_ANY T_ALL T_NONE
|
||||
%left T_EQ T_NE T_LIKE T_REGEX_MATCH T_REGEX_NON_MATCH
|
||||
%left T_IN T_NIN
|
||||
%left T_IN T_NOT
|
||||
%left T_LT T_GT T_LE T_GE
|
||||
%left T_RANGE
|
||||
%left T_PLUS T_MINUS
|
||||
%left T_TIMES T_DIV T_MOD
|
||||
%right UMINUS UPLUS T_NOT
|
||||
%right UMINUS UPLUS UNEGATION
|
||||
%left FUNCCALL
|
||||
%left REFERENCE
|
||||
%left INDEXED
|
||||
|
@ -1333,7 +1332,7 @@ operator_unary:
|
|||
| T_MINUS expression %prec UMINUS {
|
||||
$$ = parser->ast()->createNodeUnaryOperator(NODE_TYPE_OPERATOR_UNARY_MINUS, $2);
|
||||
}
|
||||
| T_NOT expression %prec T_NOT {
|
||||
| T_NOT expression %prec UNEGATION {
|
||||
$$ = parser->ast()->createNodeUnaryOperator(NODE_TYPE_OPERATOR_UNARY_NOT, $2);
|
||||
}
|
||||
;
|
||||
|
@ -1381,8 +1380,8 @@ operator_binary:
|
|||
| expression T_IN expression {
|
||||
$$ = parser->ast()->createNodeBinaryOperator(NODE_TYPE_OPERATOR_BINARY_IN, $1, $3);
|
||||
}
|
||||
| expression T_NIN expression {
|
||||
$$ = parser->ast()->createNodeBinaryOperator(NODE_TYPE_OPERATOR_BINARY_NIN, $1, $3);
|
||||
| expression T_NOT T_IN expression {
|
||||
$$ = parser->ast()->createNodeBinaryOperator(NODE_TYPE_OPERATOR_BINARY_NIN, $1, $4);
|
||||
}
|
||||
| expression T_LIKE expression {
|
||||
AstNode* arguments = parser->ast()->createNodeArray(2);
|
||||
|
@ -1424,8 +1423,17 @@ operator_binary:
|
|||
| expression quantifier T_IN expression {
|
||||
$$ = parser->ast()->createNodeBinaryArrayOperator(NODE_TYPE_OPERATOR_BINARY_ARRAY_IN, $1, $4, $2);
|
||||
}
|
||||
| expression quantifier T_NIN expression {
|
||||
$$ = parser->ast()->createNodeBinaryArrayOperator(NODE_TYPE_OPERATOR_BINARY_ARRAY_NIN, $1, $4, $2);
|
||||
| expression T_ALL T_NOT T_IN expression {
|
||||
auto quantifier = parser->ast()->createNodeQuantifier(Quantifier::ALL);
|
||||
$$ = parser->ast()->createNodeBinaryArrayOperator(NODE_TYPE_OPERATOR_BINARY_ARRAY_NIN, $1, $5, quantifier);
|
||||
}
|
||||
| expression T_ANY T_NOT T_IN expression {
|
||||
auto quantifier = parser->ast()->createNodeQuantifier(Quantifier::ANY);
|
||||
$$ = parser->ast()->createNodeBinaryArrayOperator(NODE_TYPE_OPERATOR_BINARY_ARRAY_NIN, $1, $5, quantifier);
|
||||
}
|
||||
| expression T_NONE T_NOT T_IN expression {
|
||||
auto quantifier = parser->ast()->createNodeQuantifier(Quantifier::NONE);
|
||||
$$ = parser->ast()->createNodeBinaryArrayOperator(NODE_TYPE_OPERATOR_BINARY_ARRAY_NIN, $1, $5, quantifier);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1758,8 +1766,7 @@ reference:
|
|||
// now try special variables
|
||||
if (ast->scopes()->canUseCurrentVariable() && strcmp($1.value, "CURRENT") == 0) {
|
||||
variable = ast->scopes()->getCurrentVariable();
|
||||
}
|
||||
else if (strcmp($1.value, Variable::NAME_CURRENT) == 0) {
|
||||
} else if (strcmp($1.value, Variable::NAME_CURRENT) == 0) {
|
||||
variable = ast->scopes()->getCurrentVariable();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,6 @@
|
|||
%x DOUBLE_QUOTE
|
||||
%x COMMENT_SINGLE
|
||||
%x COMMENT_MULTI
|
||||
%x NOT
|
||||
|
||||
%top{
|
||||
#include <stdint.h>
|
||||
|
@ -120,7 +119,7 @@ class Parser;
|
|||
}
|
||||
|
||||
(?i:NOT) {
|
||||
BEGIN(NOT);
|
||||
return T_NOT;
|
||||
}
|
||||
|
||||
(?i:AND) {
|
||||
|
@ -583,37 +582,6 @@ class Parser;
|
|||
yycolumn = 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* special transformation for NOT IN to T_NIN
|
||||
* --------------------------------------------------------------------------- */
|
||||
|
||||
<NOT>(?i:IN) {
|
||||
/* T_NOT + T_IN => T_NIN */
|
||||
BEGIN(INITIAL);
|
||||
return T_NIN;
|
||||
}
|
||||
|
||||
<NOT>[\r\t\n ] {
|
||||
/* ignore whitespace */
|
||||
}
|
||||
|
||||
<NOT>. {
|
||||
/* found something different to T_IN */
|
||||
/* now push the character back into the input stream and return a T_NOT token */
|
||||
BEGIN(INITIAL);
|
||||
yyless(0);
|
||||
/* must decrement offset by one character as we're pushing the char back onto the stack */
|
||||
yyextra->decreaseOffset(1);
|
||||
return T_NOT;
|
||||
}
|
||||
|
||||
<NOT><<EOF>> {
|
||||
/* make sure that we still return a T_NOT when we reach the end of the input */
|
||||
BEGIN(INITIAL);
|
||||
return T_NOT;
|
||||
}
|
||||
|
||||
|
||||
. {
|
||||
/* anything else is returned as it is */
|
||||
return (int) yytext[0];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*jshint globalstrict:false, strict:false, maxlen: 7000 */
|
||||
/*global assertEqual, assertTrue, assertMatch, fail, AQL_EXECUTE */
|
||||
/*global assertEqual, assertTrue, assertMatch, fail, AQL_EXECUTE, AQL_PARSE */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for query language, PARSE function
|
||||
|
@ -351,6 +351,83 @@ function ahuacatlParseTestSuite () {
|
|||
assertEqual(query[1][1], column);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
testPrecedenceOfNotIn : function() {
|
||||
let result = AQL_PARSE("RETURN 3..4 NOT IN 1..2").ast;
|
||||
|
||||
assertEqual("root", result[0].type);
|
||||
result = result[0].subNodes;
|
||||
|
||||
assertEqual("return", result[0].type);
|
||||
result = result[0].subNodes;
|
||||
|
||||
assertEqual("compare not in", result[0].type);
|
||||
let sub = result[0].subNodes;
|
||||
assertEqual("range", sub[0].type);
|
||||
assertEqual("value", sub[0].subNodes[0].type);
|
||||
assertEqual(3, sub[0].subNodes[0].value);
|
||||
assertEqual("value", sub[0].subNodes[1].type);
|
||||
assertEqual(4, sub[0].subNodes[1].value);
|
||||
|
||||
assertEqual("range", sub[1].type);
|
||||
assertEqual("value", sub[1].subNodes[0].type);
|
||||
assertEqual(1, sub[1].subNodes[0].value);
|
||||
assertEqual("value", sub[1].subNodes[1].type);
|
||||
assertEqual(2, sub[1].subNodes[1].value);
|
||||
|
||||
|
||||
result = AQL_PARSE("RETURN 3..(4 NOT IN 1)..2").ast;
|
||||
|
||||
assertEqual("root", result[0].type);
|
||||
result = result[0].subNodes;
|
||||
|
||||
assertEqual("return", result[0].type);
|
||||
result = result[0].subNodes;
|
||||
|
||||
assertEqual("range", result[0].type);
|
||||
sub = result[0].subNodes;
|
||||
|
||||
assertEqual("range", sub[0].type);
|
||||
assertEqual("value", sub[0].subNodes[0].type);
|
||||
assertEqual(3, sub[0].subNodes[0].value);
|
||||
assertEqual("compare not in", sub[0].subNodes[1].type);
|
||||
assertEqual("value", sub[0].subNodes[1].subNodes[0].type);
|
||||
assertEqual(4, sub[0].subNodes[1].subNodes[0].value);
|
||||
assertEqual("value", sub[0].subNodes[1].subNodes[1].type);
|
||||
assertEqual(1, sub[0].subNodes[1].subNodes[1].value);
|
||||
assertEqual("value", sub[1].type);
|
||||
assertEqual(2, sub[1].value);
|
||||
},
|
||||
|
||||
testPrecedenceOfNestedNotIn : function() {
|
||||
let result = AQL_PARSE("RETURN 3..4 NOT IN 1..2 NOT IN 7..8").ast;
|
||||
|
||||
assertEqual("root", result[0].type);
|
||||
result = result[0].subNodes;
|
||||
|
||||
assertEqual("return", result[0].type);
|
||||
result = result[0].subNodes;
|
||||
|
||||
assertEqual("compare not in", result[0].type);
|
||||
let sub = result[0].subNodes;
|
||||
assertEqual("compare not in", sub[0].type);
|
||||
assertEqual("range", sub[0].subNodes[0].type);
|
||||
assertEqual("value", sub[0].subNodes[0].subNodes[0].type);
|
||||
assertEqual(3, sub[0].subNodes[0].subNodes[0].value);
|
||||
assertEqual("value", sub[0].subNodes[0].subNodes[1].type);
|
||||
assertEqual(4, sub[0].subNodes[0].subNodes[1].value);
|
||||
assertEqual("range", sub[0].subNodes[1].type);
|
||||
assertEqual("value", sub[0].subNodes[1].subNodes[0].type);
|
||||
assertEqual(1, sub[0].subNodes[1].subNodes[0].value);
|
||||
assertEqual("value", sub[0].subNodes[1].subNodes[1].type);
|
||||
assertEqual(2, sub[0].subNodes[1].subNodes[1].value);
|
||||
|
||||
assertEqual("range", sub[1].type);
|
||||
assertEqual("value", sub[1].subNodes[0].type);
|
||||
assertEqual(7, sub[1].subNodes[0].value);
|
||||
assertEqual("value", sub[1].subNodes[1].type);
|
||||
assertEqual(8, sub[1].subNodes[1].value);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue