1
0
Fork 0

Bug fix/fix in not in workaround (#9813)

This commit is contained in:
Jan 2019-08-27 12:51:10 +02:00 committed by GitHub
parent 8c13019900
commit 86a496b8a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 3836 additions and 2924 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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];

View File

@ -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);
}
};