Skip to content

Commit 1ab2639

Browse files
committed
Added support for IS [NOT] NULL
1 parent 387ace2 commit 1ab2639

3 files changed

Lines changed: 28 additions & 10 deletions

File tree

include/mysql_parser/mysql_ast.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,11 @@ enum class NodeType {
9393
NODE_SHOW_OPTION_FULL, // For SHOW FULL ...
9494
NODE_SHOW_OPTION_FIELDS, // For SHOW ... FIELDS
9595
NODE_SHOW_TARGET_DATABASES, // For SHOW DATABASES
96-
NODE_TABLE_SPECIFICATION // For FROM table_name in SHOW FIELDS
96+
NODE_TABLE_SPECIFICATION, // For FROM table_name in SHOW FIELDS
9797

98+
// Added for IS NULL / IS NOT NULL
99+
NODE_IS_NULL_EXPRESSION,
100+
NODE_IS_NOT_NULL_EXPRESSION
98101
};
99102

100103
// Structure for an AST Node
@@ -211,6 +214,8 @@ inline void print_ast(const AstNode* node, int indent = 0) {
211214
case NodeType::NODE_SHOW_OPTION_FIELDS: type_str = "SHOW_OPT_FIELDS"; break;
212215
case NodeType::NODE_SHOW_TARGET_DATABASES: type_str = "SHOW_TARGET_DB"; break;
213216
case NodeType::NODE_TABLE_SPECIFICATION: type_str = "TABLE_SPEC"; break;
217+
case NodeType::NODE_IS_NULL_EXPRESSION: type_str = "IS_NULL_EXPR"; break;
218+
case NodeType::NODE_IS_NOT_NULL_EXPRESSION: type_str = "IS_NOT_NULL_EXPR"; break;
214219
default: type_str = "UNHANDLED_TYPE(" + std::to_string(static_cast<int>(node->type)) + ")"; break;
215220
}
216221
std::cout << "Type: " << type_str;

src/mysql_parser/mysql_lexer.l

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,17 @@ union MYSQL_YYSTYPE;
5151
"PERSIST_ONLY" { return TOKEN_PERSIST_ONLY;}
5252
"DEFAULT" { return TOKEN_DEFAULT; }
5353
"COLLATE" { return TOKEN_COLLATE; }
54-
54+
5555
"SHOW" { return TOKEN_SHOW; }
56-
"FULL" { return TOKEN_FULL; } /* Already present for JOIN, ensure it's usable here */
57-
"FIELDS" { return TOKEN_FIELDS; } /* Already present for INTO OUTFILE, ensure it's usable here */
56+
/* FULL is already defined for JOINs, will be reused */
57+
/* FIELDS is already defined for INTO OUTFILE, will be reused */
5858
"DATABASES" { return TOKEN_DATABASES; }
5959
"BEGIN" { return TOKEN_BEGIN; }
6060
"COMMIT" { return TOKEN_COMMIT; }
61+
"IS" { return TOKEN_IS; }
62+
"NULL" { return TOKEN_NULL_KEYWORD; }
63+
"NOT" { return TOKEN_NOT; }
64+
6165

6266
"DELETE" { return TOKEN_DELETE; }
6367
"LOW_PRIORITY" { return TOKEN_LOW_PRIORITY; }
@@ -240,4 +244,3 @@ union MYSQL_YYSTYPE;
240244
%%
241245
/* C code to be included at the end of the lexer */
242246

243-

src/mysql_parser/mysql_parser.y

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ int mysql_yylex(union MYSQL_YYSTYPE* yylval_param, yyscan_t yyscanner, MysqlPars
6363
/* TOKEN_FIELDS is already declared */
6464
/* TOKEN_FULL is already declared */
6565
%token TOKEN_BEGIN TOKEN_COMMIT /* Added for BEGIN/COMMIT */
66+
%token TOKEN_IS TOKEN_NULL_KEYWORD TOKEN_NOT /* Added for IS NULL / IS NOT NULL */
6667

6768

6869
%token <str_val> TOKEN_QUIT
@@ -113,11 +114,11 @@ int mysql_yylex(union MYSQL_YYSTYPE* yylval_param, yyscan_t yyscanner, MysqlPars
113114
%type <node_val> values_clause value_row_list value_row expression_list
114115
115116
// Precedence
116-
%left TOKEN_OR // Assuming OR might be added
117+
%left TOKEN_OR
117118
%left TOKEN_AND
118-
%right TOKEN_NOT // Assuming NOT might be added
119+
%right TOKEN_NOT // For logical NOT
119120
120-
%left TOKEN_EQUAL TOKEN_LESS TOKEN_GREATER TOKEN_LESS_EQUAL TOKEN_GREATER_EQUAL TOKEN_NOT_EQUAL
121+
%left TOKEN_EQUAL TOKEN_LESS TOKEN_GREATER TOKEN_LESS_EQUAL TOKEN_GREATER_EQUAL TOKEN_NOT_EQUAL TOKEN_IS // Added TOKEN_IS
121122
122123
%left TOKEN_PLUS TOKEN_MINUS
123124
%left TOKEN_ASTERISK TOKEN_DIVIDE
@@ -1210,10 +1211,18 @@ expression_placeholder:
12101211
}
12111212
| expression_placeholder comparison_operator expression_placeholder {
12121213
$$ = new MysqlParser::AstNode(MysqlParser::NodeType::NODE_COMPARISON_EXPRESSION, $2->value);
1213-
delete $2; // $2 is operator node, its value copied
1214+
delete $2;
12141215
$$->addChild($1);
12151216
$$->addChild($3);
12161217
}
1218+
| expression_placeholder TOKEN_IS TOKEN_NULL_KEYWORD { // Covers `expr IS NULL`
1219+
$$ = new MysqlParser::AstNode(MysqlParser::NodeType::NODE_IS_NULL_EXPRESSION);
1220+
$$->addChild($1); // The expression part
1221+
}
1222+
| expression_placeholder TOKEN_IS TOKEN_NOT TOKEN_NULL_KEYWORD { // Covers `expr IS NOT NULL`
1223+
$$ = new MysqlParser::AstNode(MysqlParser::NodeType::NODE_IS_NOT_NULL_EXPRESSION);
1224+
$$->addChild($1); // The expression part
1225+
}
12171226
| match_against_expression { $$ = $1; }
12181227
;
12191228

@@ -1227,7 +1236,7 @@ simple_expression:
12271236
| TOKEN_DEFAULT { $$ = new MysqlParser::AstNode(MysqlParser::NodeType::NODE_KEYWORD, "DEFAULT"); }
12281237
| aggregate_function_call { $$ = $1; }
12291238
| function_call_placeholder {$$ = $1; }
1230-
| TOKEN_LPAREN expression_placeholder TOKEN_RPAREN { $$ = $2; }
1239+
| TOKEN_LPAREN expression_placeholder TOKEN_RPAREN { $$ = $2; } // Important for `(expr IS NOT NULL)`
12311240
| simple_expression TOKEN_PLUS simple_expression {
12321241
$$ = new MysqlParser::AstNode(MysqlParser::NodeType::NODE_OPERATOR, "+");
12331242
$$->addChild($1); $$->addChild($3);
@@ -1333,3 +1342,4 @@ opt_expression_placeholder_list:
13331342
// }
13341343
// The default yyerror or the one provided by %define parse.error verbose should be sufficient.
13351344
// If you need custom error formatting or location tracking, you'd define mysql_yyerror here.
1345+

0 commit comments

Comments
 (0)