sql-parser
sql-parser copied to clipboard
Grammar railroad diagram
Using this tool https://www.bottlecaps.de/convert/ and manually adding the tokens from src/parser/flex_lexer.l we can see a railroad diagram for the grammar in src/parser/bison_parser.y copy and paste the EBNF shown bellow on https://www.bottlecaps.de/rr/ui in the tab Edit Grammar then switching to the tab View Diagram.
/*
From https://raw.githubusercontent.com/hyrise/sql-parser/master/src/parser/bison_parser.y
*/
/* converted on Sun Jul 18, 2021, 10:06 (UTC+02) by bison-to-w3c v0.53 which is Copyright (c) 2011-2021 by Gunther Rademacher <[email protected]> */
input ::= statement ( ';' statement )* opt_semicolon
statement
::= ( prepare_statement | preparable_statement ) opt_hints
| show_statement
| import_statement
| export_statement
preparable_statement
::= select_statement
| create_statement
| insert_statement
| delete_statement
| truncate_statement
| update_statement
| drop_statement
| execute_statement
| transaction_statement
opt_hints
::= ( WITH HINT '(' hint ( ',' hint )* ')' )?
hint ::= IDENTIFIER ( '(' literal_list ')' )?
transaction_statement
::= ( BEGIN | ROLLBACK | COMMIT ) opt_transaction_keyword
opt_transaction_keyword
::= TRANSACTION?
prepare_statement
::= PREPARE IDENTIFIER FROM prepare_target_query
prepare_target_query
::= STRING
execute_statement
::= EXECUTE IDENTIFIER ( '(' opt_literal_list ')' )?
import_statement
::= IMPORT FROM file_type FILE file_path INTO table_name
| COPY table_name FROM file_path opt_file_type
file_type
::= IDENTIFIER
file_path
::= string_literal
opt_file_type
::= ( WITH FORMAT file_type )?
export_statement
::= COPY table_name TO file_path opt_file_type
show_statement
::= SHOW ( TABLES | COLUMNS table_name )
| DESCRIBE table_name
create_statement
::= CREATE ( TABLE opt_not_exists table_name ( FROM IDENTIFIER FILE file_path | '(' column_def ( ',' column_def )* ')' | AS select_statement ) | VIEW opt_not_exists table_name opt_column_list AS select_statement )
opt_not_exists
::= ( IF NOT EXISTS )?
column_def
::= IDENTIFIER column_type opt_column_nullable
column_type
::= INT
| INTEGER
| LONG
| FLOAT
| DOUBLE
| ( VARCHAR | CHAR ) '(' INTVAL ')'
| TEXT
| DATETIME
| DATE
opt_column_nullable
::= ( NOT? NULL )?
drop_statement
::= DROP ( TABLE | VIEW ) opt_exists table_name
| DEALLOCATE PREPARE IDENTIFIER
opt_exists
::= ( IF EXISTS )?
delete_statement
::= DELETE FROM table_name opt_where
truncate_statement
::= TRUNCATE table_name
insert_statement
::= INSERT INTO table_name opt_column_list ( VALUES '(' literal_list ')' | select_no_paren )
opt_column_list
::= ( '(' ident_commalist ')' )?
update_statement
::= UPDATE table_ref_name_no_alias SET update_clause ( ',' update_clause )* opt_where
update_clause
::= IDENTIFIER '=' expr
select_statement
::= opt_with_clause ( select_with_paren ( set_operator select_within_set_operation opt_order opt_limit )? | select_no_paren )
select_within_set_operation
::= select_with_paren
| select_within_set_operation_no_parentheses
select_within_set_operation_no_parentheses
::= select_clause ( set_operator select_within_set_operation )?
select_with_paren
::= '(' ( select_no_paren | select_with_paren ) ')'
select_no_paren
::= select_clause ( set_operator select_within_set_operation )? opt_order opt_limit
set_operator
::= set_type opt_all
set_type ::= UNION
| INTERSECT
| EXCEPT
opt_all ::= ALL?
select_clause
::= SELECT opt_top opt_distinct select_list opt_from_clause opt_where opt_group
opt_distinct
::= DISTINCT?
select_list
::= expr_list
opt_from_clause
::= from_clause?
from_clause
::= FROM table_ref
opt_where
::= ( WHERE expr )?
opt_group
::= ( GROUP BY expr_list opt_having )?
opt_having
::= ( HAVING expr )?
opt_order
::= ( ORDER BY order_desc ( ',' order_desc )* )?
order_desc
::= expr opt_order_type
opt_order_type
::= ( ASC | DESC )?
opt_top ::= ( TOP int_literal )?
opt_limit
::= ( LIMIT ( expr | ALL ) )? ( OFFSET expr )?
expr_list
::= expr_alias ( ',' expr_alias )*
opt_literal_list
::= literal_list?
literal_list
::= literal ( ',' literal )*
expr_alias
::= expr opt_alias
expr ::= operand
| between_expr
| logic_expr
| exists_expr
| in_expr
operand ::= '(' ( expr | select_no_paren ) ')'
| array_index
| scalar_expr
| unary_expr
| binary_expr
| case_expr
| function_expr
| extract_expr
| cast_expr
| array_expr
scalar_expr
::= column_name
| literal
unary_expr
::= ( '-' | NOT ) operand
| operand ( ISNULL | IS NOT? NULL )
binary_expr
::= comp_expr
| operand ( '-' | '+' | '/' | '*' | '%' | '^' | NOT? LIKE | ILIKE | CONCAT ) operand
logic_expr
::= expr ( AND | OR ) expr
in_expr ::= operand NOT? IN '(' ( expr_list | select_no_paren ) ')'
case_expr
::= CASE expr? case_list ( ELSE expr )? END
case_list
::= ( WHEN expr THEN expr )+
exists_expr
::= NOT? EXISTS '(' select_no_paren ')'
comp_expr
::= operand ( '=' | EQUALS | NOTEQUALS | '<' | '>' | LESSEQ | GREATEREQ ) operand
function_expr
::= IDENTIFIER '(' ( opt_distinct expr_list )? ')'
extract_expr
::= EXTRACT '(' datetime_field FROM expr ')'
cast_expr
::= CAST '(' expr AS column_type ')'
datetime_field
::= SECOND
| MINUTE
| HOUR
| DAY
| MONTH
| YEAR
array_expr
::= ARRAY '[' expr_list ']'
array_index
::= operand '[' int_literal ']'
between_expr
::= operand BETWEEN operand AND operand
column_name
::= IDENTIFIER ( '.' ( IDENTIFIER | '*' ) )?
| '*'
literal ::= string_literal
| bool_literal
| num_literal
| null_literal
| date_literal
| '?'
string_literal
::= STRING
bool_literal
::= TRUE
| FALSE
num_literal
::= FLOATVAL
| int_literal
int_literal
::= INTVAL
null_literal
::= NULL
date_literal
::= DATE STRING
table_ref
::= table_ref_atomic ( ',' table_ref_atomic )*
table_ref_atomic
::= nonjoin_table_ref_atomic
| join_clause
nonjoin_table_ref_atomic
::= table_ref_name
| '(' select_statement ')' opt_table_alias
table_ref_name
::= table_name opt_table_alias
table_ref_name_no_alias
::= table_name
table_name
::= IDENTIFIER ( '.' IDENTIFIER )?
table_alias
::= alias
| AS IDENTIFIER '(' ident_commalist ')'
opt_table_alias
::= table_alias?
alias ::= AS? IDENTIFIER
opt_alias
::= alias?
opt_with_clause
::= with_clause?
with_clause
::= WITH with_description ( ',' with_description )*
with_description
::= IDENTIFIER AS select_with_paren
join_clause
::= table_ref_atomic ( NATURAL JOIN nonjoin_table_ref_atomic | opt_join_type JOIN table_ref_atomic ( ON join_condition | USING '(' column_name ')' ) )
opt_join_type
::= ( LEFT | RIGHT | FULL )? OUTER?
| INNER
| CROSS
join_condition
::= expr
opt_semicolon
::= ';'?
ident_commalist
::= IDENTIFIER ( ',' IDENTIFIER )*
// Tokens from https://github.com/hyrise/sql-parser/blob/master/src/parser/flex_lexer.l
DEALLOCATE ::= "DEALLOCATE"
PARAMETERS ::= "PARAMETERS"
INTERSECT ::= "INTERSECT"
TEMPORARY ::= "TEMPORARY"
TIMESTAMP ::= "TIMESTAMP"
DESCRIBE ::= "DESCRIBE"
DISTINCT ::= "DISTINCT"
NVARCHAR ::= "NVARCHAR"
RESTRICT ::= "RESTRICT"
TRUNCATE ::= "TRUNCATE"
ANALYZE ::= "ANALYZE"
BETWEEN ::= "BETWEEN"
CASCADE ::= "CASCADE"
COLUMNS ::= "COLUMNS"
CONTROL ::= "CONTROL"
DEFAULT ::= "DEFAULT"
EXECUTE ::= "EXECUTE"
EXPLAIN ::= "EXPLAIN"
INTEGER ::= "INTEGER"
NATURAL ::= "NATURAL"
PREPARE ::= "PREPARE"
PRIMARY ::= "PRIMARY"
SCHEMAS ::= "SCHEMAS"
SPATIAL ::= "SPATIAL"
VARCHAR ::= "VARCHAR"
VIRTUAL ::= "VIRTUAL"
BEFORE ::= "BEFORE"
COLUMN ::= "COLUMN"
CREATE ::= "CREATE"
DELETE ::= "DELETE"
DIRECT ::= "DIRECT"
DOUBLE ::= "DOUBLE"
ESCAPE ::= "ESCAPE"
EXCEPT ::= "EXCEPT"
EXISTS ::= "EXISTS"
EXTRACT ::= "EXTRACT"
CAST ::= "CAST"
FORMAT ::= "FORMAT"
GLOBAL ::= "GLOBAL"
HAVING ::= "HAVING"
IMPORT ::= "IMPORT"
INSERT ::= "INSERT"
ISNULL ::= "ISNULL"
OFFSET ::= "OFFSET"
RENAME ::= "RENAME"
SCHEMA ::= "SCHEMA"
SELECT ::= "SELECT"
SORTED ::= "SORTED"
TABLES ::= "TABLES"
UNIQUE ::= "UNIQUE"
UNLOAD ::= "UNLOAD"
UPDATE ::= "UPDATE"
VALUES ::= "VALUES"
AFTER ::= "AFTER"
ALTER ::= "ALTER"
ARRAY ::= "ARRAY"
CROSS ::= "CROSS"
DELTA ::= "DELTA"
FLOAT ::= "FLOAT"
GROUP ::= "GROUP"
INDEX ::= "INDEX"
INNER ::= "INNER"
LIMIT ::= "LIMIT"
LOCAL ::= "LOCAL"
MERGE ::= "MERGE"
MINUS ::= "MINUS"
ORDER ::= "ORDER"
OUTER ::= "OUTER"
RIGHT ::= "RIGHT"
TABLE ::= "TABLE"
UNION ::= "UNION"
USING ::= "USING"
WHERE ::= "WHERE"
CALL ::= "CALL"
CASE ::= "CASE"
CHAR ::= "CHAR"
COPY ::= "COPY"
DATE ::= "DATE"
DATETIME ::= "DATETIME"
DESC ::= "DESC"
DROP ::= "DROP"
ELSE ::= "ELSE"
FILE ::= "FILE"
FROM ::= "FROM"
FULL ::= "FULL"
HASH ::= "HASH"
HINT ::= "HINT"
INTO ::= "INTO"
JOIN ::= "JOIN"
LEFT ::= "LEFT"
LIKE ::= "LIKE"
ILIKE ::= "ILIKE"
LOAD ::= "LOAD"
LONG ::= "LONG"
NULL ::= "NULL"
PLAN ::= "PLAN"
SHOW ::= "SHOW"
TEXT ::= "TEXT"
THEN ::= "THEN"
TIME ::= "TIME"
VIEW ::= "VIEW"
WHEN ::= "WHEN"
WITH ::= "WITH"
ADD ::= "ADD"
ALL ::= "ALL"
AND ::= "AND"
ASC ::= "ASC"
END ::= "END"
FOR ::= "FOR"
INT ::= "INT"
KEY ::= "KEY"
NOT ::= "NOT"
OFF ::= "OFF"
SET ::= "SET"
TOP ::= "TOP"
AS ::= "AS"
BY ::= "BY"
IF ::= "IF"
IN ::= "IN"
IS ::= "IS"
OF ::= "OF"
ON ::= "ON"
OR ::= "OR"
TO ::= "TO"
SECOND ::= "SECOND"
MINUTE ::= "MINUTE"
HOUR ::= "HOUR"
DAY ::= "DAY"
MONTH ::= "MONTH"
YEAR ::= "YEAR"
TRUE ::= "TRUE"
FALSE ::= "FALSE"
TRANSACTION ::= "TRANSACTION"
BEGIN ::= "BEGIN"
ROLLBACK ::= "ROLLBACK"
COMMIT ::= "COMMIT"
/* Allow =/== see https://sqlite.org/lang_expr.html#collateop */
EQUALS ::= "=="
NOTEQUALS ::= "!="
NOTEQUALS ::= "<>"
LESSEQ ::= "<="
GREATEREQ ::= ">="
CONCAT ::= "||"