parser: Add support for IS (NOT) DISTINCT FROM expressions

SQLite 3.39.0 introduced expressions of these forms:
expr IS DISTINCT FROM expr
expr IS NOT DISTINCT FROM expr

Since these can be used in indexes and check expression, we need need to
add support for these expressions to the SQL parser.
This commit is contained in:
Martin Kleusberg
2022-07-23 18:01:27 +02:00
parent b01a201569
commit 5c57622f58
6 changed files with 2767 additions and 2649 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -602,7 +602,7 @@ extern int yylex (yyscan_t yyscanner);
#undef yyTABLES_NAME
#endif
#line 240 "sqlite3_lexer.ll"
#line 241 "sqlite3_lexer.ll"
#line 609 "sqlite3_lexer.h"

View File

@@ -145,6 +145,7 @@ WS [ \t\f]
"FILTER" return TOKEN(FILTER);
"FOLLOWING" return TOKEN(FOLLOWING);
"FOREIGN" return TOKEN(FOREIGN);
"FROM" return TOKEN(FROM);
"GENERATED" return TOKEN(GENERATED);
"GLOB" return TOKEN(GLOB);
"IF" return TOKEN(IF);

File diff suppressed because it is too large Load Diff

View File

@@ -498,6 +498,7 @@ namespace sqlb { namespace parser {
// "FILTER"
// "FOLLOWING"
// "FOREIGN"
// "FROM"
// "GENERATED"
// "GLOB"
// "IF"
@@ -706,63 +707,64 @@ namespace sqlb { namespace parser {
TOK_FILTER = 314, // "FILTER"
TOK_FOLLOWING = 315, // "FOLLOWING"
TOK_FOREIGN = 316, // "FOREIGN"
TOK_GENERATED = 317, // "GENERATED"
TOK_GLOB = 318, // "GLOB"
TOK_IF = 319, // "IF"
TOK_IGNORE = 320, // "IGNORE"
TOK_IMMEDIATE = 321, // "IMMEDIATE"
TOK_IN = 322, // "IN"
TOK_INDEX = 323, // "INDEX"
TOK_INITIALLY = 324, // "INITIALLY"
TOK_INSERT = 325, // "INSERT"
TOK_IS = 326, // "IS"
TOK_ISNULL = 327, // "ISNULL"
TOK_KEY = 328, // "KEY"
TOK_LIKE = 329, // "LIKE"
TOK_MATCH = 330, // "MATCH"
TOK_NO = 331, // "NO"
TOK_NOT = 332, // "NOT"
TOK_NOTNULL = 333, // "NOTNULL"
TOK_NULL = 334, // "NULL"
TOK_ON = 335, // "ON"
TOK_OR = 336, // "OR"
TOK_OVER = 337, // "OVER"
TOK_PARTITION = 338, // "PARTITION"
TOK_PRECEDING = 339, // "PRECEDING"
TOK_PRIMARY = 340, // "PRIMARY"
TOK_RAISE = 341, // "RAISE"
TOK_RANGE = 342, // "RANGE"
TOK_REFERENCES = 343, // "REFERENCES"
TOK_REGEXP = 344, // "REGEXP"
TOK_REPLACE = 345, // "REPLACE"
TOK_RESTRICT = 346, // "RESTRICT"
TOK_RETURNING = 347, // "RETURNING"
TOK_ROLLBACK = 348, // "ROLLBACK"
TOK_ROWID = 349, // "ROWID"
TOK_ROWS = 350, // "ROWS"
TOK_SELECT = 351, // "SELECT"
TOK_SET = 352, // "SET"
TOK_STORED = 353, // "STORED"
TOK_STRICT = 354, // "STRICT"
TOK_TABLE = 355, // "TABLE"
TOK_TEMP = 356, // "TEMP"
TOK_TEMPORARY = 357, // "TEMPORARY"
TOK_THEN = 358, // "THEN"
TOK_TRUE = 359, // "TRUE"
TOK_UNBOUNDED = 360, // "UNBOUNDED"
TOK_UNIQUE = 361, // "UNIQUE"
TOK_UPDATE = 362, // "UPDATE"
TOK_USING = 363, // "USING"
TOK_VIRTUAL = 364, // "VIRTUAL"
TOK_WHEN = 365, // "WHEN"
TOK_WHERE = 366, // "WHERE"
TOK_WITHOUT = 367, // "WITHOUT"
TOK_IDENTIFIER = 368, // "identifier"
TOK_NUMERIC = 369, // "numeric"
TOK_STRINGLITERAL = 370, // "string literal"
TOK_QUOTEDLITERAL = 371, // "quoted literal"
TOK_BLOBLITERAL = 372, // "blob literal"
TOK_BINDPARAMETER = 373 // "bind parameter"
TOK_FROM = 317, // "FROM"
TOK_GENERATED = 318, // "GENERATED"
TOK_GLOB = 319, // "GLOB"
TOK_IF = 320, // "IF"
TOK_IGNORE = 321, // "IGNORE"
TOK_IMMEDIATE = 322, // "IMMEDIATE"
TOK_IN = 323, // "IN"
TOK_INDEX = 324, // "INDEX"
TOK_INITIALLY = 325, // "INITIALLY"
TOK_INSERT = 326, // "INSERT"
TOK_IS = 327, // "IS"
TOK_ISNULL = 328, // "ISNULL"
TOK_KEY = 329, // "KEY"
TOK_LIKE = 330, // "LIKE"
TOK_MATCH = 331, // "MATCH"
TOK_NO = 332, // "NO"
TOK_NOT = 333, // "NOT"
TOK_NOTNULL = 334, // "NOTNULL"
TOK_NULL = 335, // "NULL"
TOK_ON = 336, // "ON"
TOK_OR = 337, // "OR"
TOK_OVER = 338, // "OVER"
TOK_PARTITION = 339, // "PARTITION"
TOK_PRECEDING = 340, // "PRECEDING"
TOK_PRIMARY = 341, // "PRIMARY"
TOK_RAISE = 342, // "RAISE"
TOK_RANGE = 343, // "RANGE"
TOK_REFERENCES = 344, // "REFERENCES"
TOK_REGEXP = 345, // "REGEXP"
TOK_REPLACE = 346, // "REPLACE"
TOK_RESTRICT = 347, // "RESTRICT"
TOK_RETURNING = 348, // "RETURNING"
TOK_ROLLBACK = 349, // "ROLLBACK"
TOK_ROWID = 350, // "ROWID"
TOK_ROWS = 351, // "ROWS"
TOK_SELECT = 352, // "SELECT"
TOK_SET = 353, // "SET"
TOK_STORED = 354, // "STORED"
TOK_STRICT = 355, // "STRICT"
TOK_TABLE = 356, // "TABLE"
TOK_TEMP = 357, // "TEMP"
TOK_TEMPORARY = 358, // "TEMPORARY"
TOK_THEN = 359, // "THEN"
TOK_TRUE = 360, // "TRUE"
TOK_UNBOUNDED = 361, // "UNBOUNDED"
TOK_UNIQUE = 362, // "UNIQUE"
TOK_UPDATE = 363, // "UPDATE"
TOK_USING = 364, // "USING"
TOK_VIRTUAL = 365, // "VIRTUAL"
TOK_WHEN = 366, // "WHEN"
TOK_WHERE = 367, // "WHERE"
TOK_WITHOUT = 368, // "WITHOUT"
TOK_IDENTIFIER = 369, // "identifier"
TOK_NUMERIC = 370, // "numeric"
TOK_STRINGLITERAL = 371, // "string literal"
TOK_QUOTEDLITERAL = 372, // "quoted literal"
TOK_BLOBLITERAL = 373, // "blob literal"
TOK_BINDPARAMETER = 374 // "bind parameter"
};
/// Backward compatibility alias (Bison 3.6).
typedef token_kind_type yytokentype;
@@ -779,7 +781,7 @@ namespace sqlb { namespace parser {
{
enum symbol_kind_type
{
YYNTOKENS = 119, ///< Number of tokens.
YYNTOKENS = 120, ///< Number of tokens.
S_YYEMPTY = -2,
S_YYEOF = 0, // "end of file"
S_YYerror = 1, // error
@@ -843,120 +845,121 @@ namespace sqlb { namespace parser {
S_FILTER = 59, // "FILTER"
S_FOLLOWING = 60, // "FOLLOWING"
S_FOREIGN = 61, // "FOREIGN"
S_GENERATED = 62, // "GENERATED"
S_GLOB = 63, // "GLOB"
S_IF = 64, // "IF"
S_IGNORE = 65, // "IGNORE"
S_IMMEDIATE = 66, // "IMMEDIATE"
S_IN = 67, // "IN"
S_INDEX = 68, // "INDEX"
S_INITIALLY = 69, // "INITIALLY"
S_INSERT = 70, // "INSERT"
S_IS = 71, // "IS"
S_ISNULL = 72, // "ISNULL"
S_KEY = 73, // "KEY"
S_LIKE = 74, // "LIKE"
S_MATCH = 75, // "MATCH"
S_NO = 76, // "NO"
S_NOT = 77, // "NOT"
S_NOTNULL = 78, // "NOTNULL"
S_NULL = 79, // "NULL"
S_ON = 80, // "ON"
S_OR = 81, // "OR"
S_OVER = 82, // "OVER"
S_PARTITION = 83, // "PARTITION"
S_PRECEDING = 84, // "PRECEDING"
S_PRIMARY = 85, // "PRIMARY"
S_RAISE = 86, // "RAISE"
S_RANGE = 87, // "RANGE"
S_REFERENCES = 88, // "REFERENCES"
S_REGEXP = 89, // "REGEXP"
S_REPLACE = 90, // "REPLACE"
S_RESTRICT = 91, // "RESTRICT"
S_RETURNING = 92, // "RETURNING"
S_ROLLBACK = 93, // "ROLLBACK"
S_ROWID = 94, // "ROWID"
S_ROWS = 95, // "ROWS"
S_SELECT = 96, // "SELECT"
S_SET = 97, // "SET"
S_STORED = 98, // "STORED"
S_STRICT = 99, // "STRICT"
S_TABLE = 100, // "TABLE"
S_TEMP = 101, // "TEMP"
S_TEMPORARY = 102, // "TEMPORARY"
S_THEN = 103, // "THEN"
S_TRUE = 104, // "TRUE"
S_UNBOUNDED = 105, // "UNBOUNDED"
S_UNIQUE = 106, // "UNIQUE"
S_UPDATE = 107, // "UPDATE"
S_USING = 108, // "USING"
S_VIRTUAL = 109, // "VIRTUAL"
S_WHEN = 110, // "WHEN"
S_WHERE = 111, // "WHERE"
S_WITHOUT = 112, // "WITHOUT"
S_IDENTIFIER = 113, // "identifier"
S_NUMERIC = 114, // "numeric"
S_STRINGLITERAL = 115, // "string literal"
S_QUOTEDLITERAL = 116, // "quoted literal"
S_BLOBLITERAL = 117, // "blob literal"
S_BINDPARAMETER = 118, // "bind parameter"
S_YYACCEPT = 119, // $accept
S_sql = 120, // sql
S_statement = 121, // statement
S_literalvalue = 122, // literalvalue
S_id = 123, // id
S_allowed_keywords_as_identifier = 124, // allowed_keywords_as_identifier
S_tableid = 125, // tableid
S_columnid = 126, // columnid
S_signednumber = 127, // signednumber
S_signednumber_or_numeric = 128, // signednumber_or_numeric
S_typename_namelist = 129, // typename_namelist
S_type_name = 130, // type_name
S_unary_expr = 131, // unary_expr
S_binary_expr = 132, // binary_expr
S_like_expr = 133, // like_expr
S_exprlist_expr = 134, // exprlist_expr
S_function_expr = 135, // function_expr
S_isnull_expr = 136, // isnull_expr
S_between_expr = 137, // between_expr
S_in_expr = 138, // in_expr
S_whenthenlist_expr = 139, // whenthenlist_expr
S_case_expr = 140, // case_expr
S_raise_expr = 141, // raise_expr
S_expr = 142, // expr
S_select_stmt = 143, // select_stmt
S_optional_if_not_exists = 144, // optional_if_not_exists
S_optional_sort_order = 145, // optional_sort_order
S_optional_unique = 146, // optional_unique
S_optional_where = 147, // optional_where
S_tableid_with_uninteresting_schema = 148, // tableid_with_uninteresting_schema
S_indexed_column = 149, // indexed_column
S_indexed_column_list = 150, // indexed_column_list
S_createindex_stmt = 151, // createindex_stmt
S_optional_exprlist_with_paren = 152, // optional_exprlist_with_paren
S_createvirtualtable_stmt = 153, // createvirtualtable_stmt
S_optional_temporary = 154, // optional_temporary
S_tableoption = 155, // tableoption
S_tableoptions_list = 156, // tableoptions_list
S_optional_tableoptions_list = 157, // optional_tableoptions_list
S_optional_conflictclause = 158, // optional_conflictclause
S_optional_typename = 159, // optional_typename
S_optional_storage_identifier = 160, // optional_storage_identifier
S_optional_always_generated = 161, // optional_always_generated
S_columnconstraint = 162, // columnconstraint
S_columnconstraint_list = 163, // columnconstraint_list
S_columndef = 164, // columndef
S_columndef_list = 165, // columndef_list
S_optional_constraintname = 166, // optional_constraintname
S_columnid_list = 167, // columnid_list
S_optional_columnid_with_paren_list = 168, // optional_columnid_with_paren_list
S_fk_clause_part = 169, // fk_clause_part
S_fk_clause_part_list = 170, // fk_clause_part_list
S_optional_fk_clause = 171, // optional_fk_clause
S_tableconstraint = 172, // tableconstraint
S_tableconstraint_list = 173, // tableconstraint_list
S_optional_tableconstraint_list = 174, // optional_tableconstraint_list
S_createtable_stmt = 175 // createtable_stmt
S_FROM = 62, // "FROM"
S_GENERATED = 63, // "GENERATED"
S_GLOB = 64, // "GLOB"
S_IF = 65, // "IF"
S_IGNORE = 66, // "IGNORE"
S_IMMEDIATE = 67, // "IMMEDIATE"
S_IN = 68, // "IN"
S_INDEX = 69, // "INDEX"
S_INITIALLY = 70, // "INITIALLY"
S_INSERT = 71, // "INSERT"
S_IS = 72, // "IS"
S_ISNULL = 73, // "ISNULL"
S_KEY = 74, // "KEY"
S_LIKE = 75, // "LIKE"
S_MATCH = 76, // "MATCH"
S_NO = 77, // "NO"
S_NOT = 78, // "NOT"
S_NOTNULL = 79, // "NOTNULL"
S_NULL = 80, // "NULL"
S_ON = 81, // "ON"
S_OR = 82, // "OR"
S_OVER = 83, // "OVER"
S_PARTITION = 84, // "PARTITION"
S_PRECEDING = 85, // "PRECEDING"
S_PRIMARY = 86, // "PRIMARY"
S_RAISE = 87, // "RAISE"
S_RANGE = 88, // "RANGE"
S_REFERENCES = 89, // "REFERENCES"
S_REGEXP = 90, // "REGEXP"
S_REPLACE = 91, // "REPLACE"
S_RESTRICT = 92, // "RESTRICT"
S_RETURNING = 93, // "RETURNING"
S_ROLLBACK = 94, // "ROLLBACK"
S_ROWID = 95, // "ROWID"
S_ROWS = 96, // "ROWS"
S_SELECT = 97, // "SELECT"
S_SET = 98, // "SET"
S_STORED = 99, // "STORED"
S_STRICT = 100, // "STRICT"
S_TABLE = 101, // "TABLE"
S_TEMP = 102, // "TEMP"
S_TEMPORARY = 103, // "TEMPORARY"
S_THEN = 104, // "THEN"
S_TRUE = 105, // "TRUE"
S_UNBOUNDED = 106, // "UNBOUNDED"
S_UNIQUE = 107, // "UNIQUE"
S_UPDATE = 108, // "UPDATE"
S_USING = 109, // "USING"
S_VIRTUAL = 110, // "VIRTUAL"
S_WHEN = 111, // "WHEN"
S_WHERE = 112, // "WHERE"
S_WITHOUT = 113, // "WITHOUT"
S_IDENTIFIER = 114, // "identifier"
S_NUMERIC = 115, // "numeric"
S_STRINGLITERAL = 116, // "string literal"
S_QUOTEDLITERAL = 117, // "quoted literal"
S_BLOBLITERAL = 118, // "blob literal"
S_BINDPARAMETER = 119, // "bind parameter"
S_YYACCEPT = 120, // $accept
S_sql = 121, // sql
S_statement = 122, // statement
S_literalvalue = 123, // literalvalue
S_id = 124, // id
S_allowed_keywords_as_identifier = 125, // allowed_keywords_as_identifier
S_tableid = 126, // tableid
S_columnid = 127, // columnid
S_signednumber = 128, // signednumber
S_signednumber_or_numeric = 129, // signednumber_or_numeric
S_typename_namelist = 130, // typename_namelist
S_type_name = 131, // type_name
S_unary_expr = 132, // unary_expr
S_binary_expr = 133, // binary_expr
S_like_expr = 134, // like_expr
S_exprlist_expr = 135, // exprlist_expr
S_function_expr = 136, // function_expr
S_isnull_expr = 137, // isnull_expr
S_between_expr = 138, // between_expr
S_in_expr = 139, // in_expr
S_whenthenlist_expr = 140, // whenthenlist_expr
S_case_expr = 141, // case_expr
S_raise_expr = 142, // raise_expr
S_expr = 143, // expr
S_select_stmt = 144, // select_stmt
S_optional_if_not_exists = 145, // optional_if_not_exists
S_optional_sort_order = 146, // optional_sort_order
S_optional_unique = 147, // optional_unique
S_optional_where = 148, // optional_where
S_tableid_with_uninteresting_schema = 149, // tableid_with_uninteresting_schema
S_indexed_column = 150, // indexed_column
S_indexed_column_list = 151, // indexed_column_list
S_createindex_stmt = 152, // createindex_stmt
S_optional_exprlist_with_paren = 153, // optional_exprlist_with_paren
S_createvirtualtable_stmt = 154, // createvirtualtable_stmt
S_optional_temporary = 155, // optional_temporary
S_tableoption = 156, // tableoption
S_tableoptions_list = 157, // tableoptions_list
S_optional_tableoptions_list = 158, // optional_tableoptions_list
S_optional_conflictclause = 159, // optional_conflictclause
S_optional_typename = 160, // optional_typename
S_optional_storage_identifier = 161, // optional_storage_identifier
S_optional_always_generated = 162, // optional_always_generated
S_columnconstraint = 163, // columnconstraint
S_columnconstraint_list = 164, // columnconstraint_list
S_columndef = 165, // columndef
S_columndef_list = 166, // columndef_list
S_optional_constraintname = 167, // optional_constraintname
S_columnid_list = 168, // columnid_list
S_optional_columnid_with_paren_list = 169, // optional_columnid_with_paren_list
S_fk_clause_part = 170, // fk_clause_part
S_fk_clause_part_list = 171, // fk_clause_part_list
S_optional_fk_clause = 172, // optional_fk_clause
S_tableconstraint = 173, // tableconstraint
S_tableconstraint_list = 174, // tableconstraint_list
S_optional_tableconstraint_list = 175, // optional_tableconstraint_list
S_createtable_stmt = 176 // createtable_stmt
};
};
@@ -1077,6 +1080,7 @@ namespace sqlb { namespace parser {
case symbol_kind::S_FILTER: // "FILTER"
case symbol_kind::S_FOLLOWING: // "FOLLOWING"
case symbol_kind::S_FOREIGN: // "FOREIGN"
case symbol_kind::S_FROM: // "FROM"
case symbol_kind::S_GENERATED: // "GENERATED"
case symbol_kind::S_GLOB: // "GLOB"
case symbol_kind::S_IF: // "IF"
@@ -1491,6 +1495,7 @@ switch (yykind)
case symbol_kind::S_FILTER: // "FILTER"
case symbol_kind::S_FOLLOWING: // "FOLLOWING"
case symbol_kind::S_FOREIGN: // "FOREIGN"
case symbol_kind::S_FROM: // "FROM"
case symbol_kind::S_GENERATED: // "GENERATED"
case symbol_kind::S_GLOB: // "GLOB"
case symbol_kind::S_IF: // "IF"
@@ -2683,6 +2688,21 @@ switch (yykind)
return symbol_type (token::TOK_FOREIGN, v, l);
}
#endif
#if 201103L <= YY_CPLUSPLUS
static
symbol_type
make_FROM (std::string v, location_type l)
{
return symbol_type (token::TOK_FROM, std::move (v), std::move (l));
}
#else
static
symbol_type
make_FROM (const std::string& v, const location_type& l)
{
return symbol_type (token::TOK_FROM, v, l);
}
#endif
#if 201103L <= YY_CPLUSPLUS
static
symbol_type
@@ -3868,7 +3888,7 @@ switch (yykind)
/// Constants.
enum
{
yylast_ = 3375, ///< Last index in yytable_.
yylast_ = 3702, ///< Last index in yytable_.
yynnts_ = 57, ///< Number of nonterminal symbols.
yyfinal_ = 13 ///< Termination state number.
};
@@ -3927,10 +3947,10 @@ switch (yykind)
85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
115, 116, 117, 118
115, 116, 117, 118, 119
};
// Last valid token kind.
const int code_max = 373;
const int code_max = 374;
if (t <= 0)
return symbol_kind::S_YYEOF;
@@ -4033,6 +4053,7 @@ switch (yykind)
case symbol_kind::S_FILTER: // "FILTER"
case symbol_kind::S_FOLLOWING: // "FOLLOWING"
case symbol_kind::S_FOREIGN: // "FOREIGN"
case symbol_kind::S_FROM: // "FROM"
case symbol_kind::S_GENERATED: // "GENERATED"
case symbol_kind::S_GLOB: // "GLOB"
case symbol_kind::S_IF: // "IF"
@@ -4249,6 +4270,7 @@ switch (yykind)
case symbol_kind::S_FILTER: // "FILTER"
case symbol_kind::S_FOLLOWING: // "FOLLOWING"
case symbol_kind::S_FOREIGN: // "FOREIGN"
case symbol_kind::S_FROM: // "FROM"
case symbol_kind::S_GENERATED: // "GENERATED"
case symbol_kind::S_GLOB: // "GLOB"
case symbol_kind::S_IF: // "IF"
@@ -4417,7 +4439,7 @@ switch (yykind)
#line 10 "sqlite3_parser.yy"
} } // sqlb::parser
#line 4421 "sqlite3_parser.hpp"
#line 4443 "sqlite3_parser.hpp"

View File

@@ -131,6 +131,7 @@
%token <std::string> FILTER "FILTER"
%token <std::string> FOLLOWING "FOLLOWING"
%token <std::string> FOREIGN "FOREIGN"
%token <std::string> FROM "FROM"
%token <std::string> GENERATED "GENERATED"
%token <std::string> GLOB "GLOB"
%token <std::string> IF "IF"
@@ -387,34 +388,36 @@ type_name:
;
unary_expr:
"-" expr %prec TILDE { $$ = "-" + $2; }
| "+" expr %prec TILDE { $$ = "+" + $2; }
| "~" expr { $$ = "~" + $2; }
| NOT expr { $$ = "NOT " + $2; }
"-" expr %prec TILDE { $$ = "-" + $2; }
| "+" expr %prec TILDE { $$ = "+" + $2; }
| "~" expr { $$ = "~" + $2; }
| NOT expr { $$ = "NOT " + $2; }
;
binary_expr:
expr "||" expr { $$ = $1 + " || " + $3; }
| expr "*" expr { $$ = $1 + " * " + $3; }
| expr "/" expr { $$ = $1 + " / " + $3; }
| expr "%" expr { $$ = $1 + " % " + $3; }
| expr "+" expr { $$ = $1 + " + " + $3; }
| expr "-" expr { $$ = $1 + " - " + $3; }
| expr "<<" expr { $$ = $1 + " << " + $3; }
| expr ">>" expr { $$ = $1 + " >> " + $3; }
| expr "&" expr { $$ = $1 + " & " + $3; }
| expr "|" expr { $$ = $1 + " | " + $3; }
| expr "<" expr { $$ = $1 + " < " + $3; }
| expr "<=" expr { $$ = $1 + " <= " + $3; }
| expr ">" expr { $$ = $1 + " > " + $3; }
| expr ">=" expr { $$ = $1 + " >= " + $3; }
| expr "=" expr { $$ = $1 + " = " + $3; }
| expr "==" expr { $$ = $1 + " == " + $3; }
| expr "!=" expr { $$ = $1 + " != " + $3; }
| expr "<>" expr { $$ = $1 + " <> " + $3; }
| expr IS expr { $$ = $1 + " IS " + $3; }
| expr AND expr { $$ = $1 + " AND " + $3; }
| expr OR expr { $$ = $1 + " OR " + $3; }
expr "||" expr { $$ = $1 + " || " + $3; }
| expr "*" expr { $$ = $1 + " * " + $3; }
| expr "/" expr { $$ = $1 + " / " + $3; }
| expr "%" expr { $$ = $1 + " % " + $3; }
| expr "+" expr { $$ = $1 + " + " + $3; }
| expr "-" expr { $$ = $1 + " - " + $3; }
| expr "<<" expr { $$ = $1 + " << " + $3; }
| expr ">>" expr { $$ = $1 + " >> " + $3; }
| expr "&" expr { $$ = $1 + " & " + $3; }
| expr "|" expr { $$ = $1 + " | " + $3; }
| expr "<" expr { $$ = $1 + " < " + $3; }
| expr "<=" expr { $$ = $1 + " <= " + $3; }
| expr ">" expr { $$ = $1 + " > " + $3; }
| expr ">=" expr { $$ = $1 + " >= " + $3; }
| expr "=" expr { $$ = $1 + " = " + $3; }
| expr "==" expr { $$ = $1 + " == " + $3; }
| expr "!=" expr { $$ = $1 + " != " + $3; }
| expr "<>" expr { $$ = $1 + " <> " + $3; }
| expr IS expr { $$ = $1 + " IS " + $3; }
| expr IS DISTINCT FROM expr %prec TILDE { $$ = $1 + " IS DISTINCT FROM " + $5; }
| expr IS NOT DISTINCT FROM expr %prec TILDE { $$ = $1 + " IS NOT DISTINCT FROM " + $6; }
| expr AND expr { $$ = $1 + " AND " + $3; }
| expr OR expr { $$ = $1 + " OR " + $3; }
;
like_expr: