Skip to content

Commit

Permalink
Merge pull request #30 from aceforeverd/feat/ilike
Browse files Browse the repository at this point in the history
feature: support ilike
  • Loading branch information
jingchen2222 authored Dec 7, 2021
2 parents acec9de + 22e863d commit b28a6ef
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 6 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ jobs:
build_argv: '--features=-supports_dynamic_linker '
steps:
- uses: actions/checkout@v2

- name: Setup Bazel
run: |
curl --create-dirs -SLo /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/download/v1.8.0/bazelisk-linux-amd64
curl --create-dirs -SLo /usr/local/bin/bazel https://github.com/bazelbuild/bazelisk/releases/download/v1.10.1/bazelisk-linux-amd64
chmod +x /usr/local/bin/bazel
- name: Install Java
run: |
yum install -y java-1.8.0-openjdk-devel
Expand Down
35 changes: 34 additions & 1 deletion zetasql/parser/bison_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ class DashedIdentifierTmpNode final : public zetasql::ASTNode {
%left "AND"
%left "XOR"
%left UNARY_NOT_PRECEDENCE
%nonassoc "=" "==" "<>" ">" "<" ">=" "<=" "!=" "LIKE" "IN" "DISTINCT" "BETWEEN" "IS" "NOT_SPECIAL"
%nonassoc "=" "==" "<>" ">" "<" ">=" "<=" "!=" "LIKE" "ILIKE" "IN" "DISTINCT" "BETWEEN" "IS" "NOT_SPECIAL"
%nonassoc "ESCAPE"
%left "|"
%left "^"
Expand Down Expand Up @@ -712,6 +712,7 @@ using zetasql::ASTDropStatement;
%token KW_LAST "LAST"
%token KW_LEFT "LEFT"
%token KW_LIKE "LIKE"
%token KW_ILIKE "ILIKE"
%token KW_LIMIT "LIMIT"
%token KW_LOOKUP "LOOKUP"
%token KW_MERGE "MERGE"
Expand Down Expand Up @@ -1377,6 +1378,7 @@ using zetasql::ASTDropStatement;
%type <not_keyword_presence> in_operator
%type <not_keyword_presence> is_operator
%type <not_keyword_presence> like_operator
%type <not_keyword_presence> ilike_operator
%type <not_keyword_presence> distinct_operator

%type <preceding_or_following_keyword> preceding_or_following
Expand Down Expand Up @@ -5353,6 +5355,15 @@ like_operator:
} %prec "LIKE"
;

ilike_operator:
"ILIKE" { $$ = NotKeywordPresence::kAbsent; } %prec "ILIKE"
| "NOT_SPECIAL" "ILIKE"
{
@$ = @2; // Error messages should point at the "ILIKE".
$$ = NotKeywordPresence::kPresent;
} %prec "ILIKE"
;

// Returns NotKeywordPresence to indicate whether NOT was present.
between_operator:
"BETWEEN"
Expand Down Expand Up @@ -5553,6 +5564,27 @@ expression:
binary_expression->set_op(zetasql::ASTBinaryExpression::LIKE);
$$ = binary_expression;
}
| expression ilike_operator expression %prec "ILIKE"
{
// NOT has lower precedence but can be parsed unparenthesized in the
// rhs because it is not ambiguous. This is not allowed.
if (IsUnparenthesizedNotExpression($3)) {
YYERROR_UNEXPECTED_AND_ABORT_AT(@3);
}
// Bison allows some cases ilike IN on the left hand side because it's
// not ambiguous. The language doesn't allow this.
if (!$1->IsAllowedInComparison()) {
YYERROR_AND_ABORT_AT(
@2,
"Syntax error: "
"Expression to the left of ILIKE must be parenthesized");
}
auto* binary_expression =
MAKE_NODE(ASTBinaryExpression, @1, @3, {$1, $3});
binary_expression->set_is_not($2 == NotKeywordPresence::kPresent);
binary_expression->set_op(zetasql::ASTBinaryExpression::ILIKE);
$$ = binary_expression;
}
| expression "ESCAPE" string_literal
{
$$ = MAKE_NODE(ASTEscapedExpression, @$, {$1, $3})
Expand Down Expand Up @@ -7222,6 +7254,7 @@ reserved_keyword_rule:
| "HAVING"
| "IF"
| "IGNORE"
| "ILIKE"
| "IN"
| "INNER"
| "INSTANCE_NOT_IN_WINDOW"
Expand Down
5 changes: 3 additions & 2 deletions zetasql/parser/flex_tokenizer.l
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ leave { return BisonParserImpl::token::KW_LEAVE; }
left { return BisonParserImpl::token::KW_LEFT; }
level { return BisonParserImpl::token::KW_LEVEL; }
like { return BisonParserImpl::token::KW_LIKE; }
ilike { return BisonParserImpl::token::KW_ILIKE; }
limit { return BisonParserImpl::token::KW_LIMIT; }
load { return BisonParserImpl::token::KW_LOAD; }
lookup { return BisonParserImpl::token::KW_LOOKUP; }
Expand Down Expand Up @@ -535,14 +536,14 @@ no { return BisonParserImpl::token::KW_NO; }
file will cause bad error messages. There is no situation where that is
valid syntax, so there will never be any rejections as a result.
*/
not{whitespace}(between|in|like|distinct)[^A-Z_0-9] {
not{whitespace}(between|in|like|ilike|distinct)[^A-Z_0-9] {
SET_RETURN_PREFIX_LENGTH(3);
if (mode_ == BisonParserMode::kTokenizer) {
return BisonParserImpl::token::KW_NOT;
}
return BisonParserImpl::token::KW_NOT_SPECIAL;
}
"!"{whitespace}(between|in|like|distinct)[^A-Z_0-9] {
"!"{whitespace}(between|in|like|ilike|distinct)[^A-Z_0-9] {
SET_RETURN_PREFIX_LENGTH(1);
if (mode_ == BisonParserMode::kTokenizer) {
return BisonParserImpl::token::KW_NOT;
Expand Down
1 change: 1 addition & 0 deletions zetasql/parser/keywords.cc
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ constexpr KeywordInfoPOD kAllKeywords[] = {
{"left", KW_LEFT, KeywordInfo::kReserved},
{"level", KW_LEVEL},
{"like", KW_LIKE, KeywordInfo::kReserved},
{"ilike", KW_ILIKE, KeywordInfo::kReserved},
{"limit", KW_LIMIT, KeywordInfo::kReserved},
{"load", KW_LOAD},
{"lookup", KW_LOOKUP, KeywordInfo::kReserved},
Expand Down
2 changes: 1 addition & 1 deletion zetasql/parser/keywords_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ TEST(ParserTest, DontAddNewReservedKeywords) {
// allows new queries to work that will not work on older code.
// Before changing this, co-ordinate with all engines to make sure the change
// is done safely.
EXPECT_EQ(103 /* CAUTION */, num_reserved);
EXPECT_EQ(104 /* CAUTION */, num_reserved);
}

} // namespace
Expand Down
2 changes: 2 additions & 0 deletions zetasql/parser/parse_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,8 @@ std::string ASTBinaryExpression::GetSQLForOperator() const {
return "XOR";
case DISTINCT:
return is_not_ ? "IS NOT DISTINCT FROM" : "IS DISTINCT FROM";
case ILIKE:
return is_not_ ? "NOT ILIKE" : "ILIKE";
}
}

Expand Down
2 changes: 2 additions & 0 deletions zetasql/parser/parse_tree_manual.h
Original file line number Diff line number Diff line change
Expand Up @@ -1999,6 +1999,7 @@ class ASTBinaryExpression final : public ASTExpression {
CONCAT_OP, // "||"
XOR, // "XOR"
DISTINCT, // "IS DISTINCT FROM"
ILIKE, // "ILIKE"
};

void set_op(Op op) { op_ = op; }
Expand All @@ -2016,6 +2017,7 @@ class ASTBinaryExpression final : public ASTExpression {
if (parenthesized()) return true;
switch (op()) {
case LIKE:
case ILIKE:
case IS:
case EQ:
case NE:
Expand Down
2 changes: 1 addition & 1 deletion zetasql/parser/testdata/is_distinct.test
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ SELECT
# Syntax error
SELECT 1 NOT DISTINCT FROM 2;
--
ERROR: Syntax error: Expected keyword BETWEEN or keyword IN or keyword LIKE but got keyword DISTINCT [at 1:14]
ERROR: Syntax error: Expected keyword BETWEEN or keyword ILIKE or keyword IN or keyword LIKE but got keyword DISTINCT [at 1:14]
SELECT 1 NOT DISTINCT FROM 2;
^
==
Expand Down
13 changes: 13 additions & 0 deletions zetasql/parser/testdata/standalone_expression.test
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ col1 like 'kk' escape abc
^
==

# ilike
col1 NOT ILIKE '&_' escape '&'
--
BinaryExpression(NOT ILIKE) [0-30]
PathExpression [0-4]
Identifier(col1) [0-4]
EscapedExpression [15-30]
StringLiteral('&_') [15-19]
StringLiteral('&') [27-30]
--
col1 NOT ILIKE '&_' ESCAPE '&'
==


abc + @param + @@sysvar + count(*) + (select 1) + (select x from y)
--
Expand Down

0 comments on commit b28a6ef

Please sign in to comment.