Skip to content

Instantly share code, notes, and snippets.

@jamiecook
Created December 21, 2016 09:51
Show Gist options
  • Save jamiecook/023a17b1b7d82e59c931711a86d1016d to your computer and use it in GitHub Desktop.
Save jamiecook/023a17b1b7d82e59c931711a86d1016d to your computer and use it in GitHub Desktop.
module Selekt
grammar SQL
rule sql_query
space? select_statement (space order_by_clause)? (space limit_clause)? space?
end
rule select_statement
select_clause
(space from_clause)?
(space where_clause)?
(space group_by_clause)?
(space having_clause)?
(space named_window_clause)?
(space set_operator space select_statement)*
end
rule select_clause
SELECT space (DISTINCT space)? projection (comma projection)*
end
rule from_clause
FROM space source_with_joins (comma source_with_joins)*
/
FROM space source_with_joins (comma source_with_joins)*
end
rule source_with_joins
source (space source_join)*
/
'(' source (space source_join)* ')'
end
rule source
((table <TableReference>) (alias <Alias>)? / subquery (alias <Alias>)) <Source>
end
rule source_join
regular_join_type space source space join_clause
end
rule regular_join_type
((INNER / LEFT / RIGHT / FULL space OUTER) space)? JOIN
end
rule join_clause
ON space boolean_expression
/
USING space? '(' space? identifier (comma identifier)* ')'
end
rule comma
space? ',' space?
end
rule subquery
'(' space? select_statement space? ')'
end
rule table
schema_table / schemaless_table
end
rule schemaless_table
identifier {
def schema_name
nil
end
def table_name
elements[0].value
end
}
end
rule schema_table
schema '.' identifier {
def schema_name
schema.value
end
def table_name
elements.last.value
end
}
end
rule schema
identifier
end
rule column
table_column / identifier
end
rule table_column
identifier '.' identifier
end
rule projection
'*' / table '.' '*' / expression alias?
end
rule alias
space (AS space)? identifier
end
rule where_clause
WHERE space expression
end
rule group_by_clause
GROUP space BY space expression (comma expression)*
end
rule having_clause
HAVING space expression
end
rule order_by_clause
ORDER space BY space order_expression (comma order_expression)*
end
rule limit_clause
LIMIT space integer (space OFFSET space integer)?
end
rule order_expression
expression (space (ASC / DESC) (space NULLS space (FIRST / LAST))?)?
end
rule expression
boolean_expression
end
rule single_expression
(interval_expression / case_expression / function_call / column / literal / subquery / '(' space? expression space? ')')
(space? '::' space? type)?
end
rule case_expression
CASE space
(expression space)?
(WHEN space expression space THEN space expression space)+
(ELSE space expression space)?
END
end
rule interval_expression
INTERVAL space expression
end
rule type
unquoted_identifier
end
rule function_call
(
COUNT '(' space? (DISTINCT space)? ('*' / expression) space? ')'
/
unquoted_identifier '(' (space? expression (comma expression)*)? space? ')'
)
(space OVER (space? window_clause / space identifier))?
end
rule window_clause
'(' space?
(partition_by_clause space)?
order_by_clause
space? ')'
end
rule named_window_clause
WINDOW space identifier space AS space? window_clause
end
rule partition_by_clause
PARTITION space BY space expression (comma expression)*
end
rule arithmetic_expression
single_expression (space? arithmetic_operator space? single_expression)*
end
rule arithmetic_operator
'+' / '-' / '*' / '/' / '%' / '||'
end
rule comparison_expression
EXISTS space? subquery
/
arithmetic_expression space IS (space NOT)? space boolean
/
arithmetic_expression space (NOT space)? IN space list_of_values
/
arithmetic_expression (space? comparison_operator space? arithmetic_expression)?
end
rule list_of_values
subquery
/
'(' space? expression (comma expression)* space? ')'
end
rule comparison_operator
'<=' / '>=' / '<>' / '>' / '<' / '!=' / '=' / LIKE / ILIKE
end
rule negatable_expression
(NOT space)? comparison_expression
end
rule boolean_expression
negatable_expression (space boolean_operator space negatable_expression)*
end
rule boolean_operator
AND / OR
end
rule set_operator
UNION (space ALL)?
end
rule space
[ \t\r\n]+ (comment space?)?
end
rule comment
'--' [^\r\n]*
end
rule identifier
quoted_identifier / single_quoted_identifier / unquoted_identifier !{|seq| seq[0].reserved? } {
def value
elements.first.value
end
}
end
rule unquoted_identifier
[A-Za-z] [_A-Za-z0-9]*
{
def value
text_value
end
def reserved?
Selekt::RESERVED_SQL_KEYWORDS.include?(text_value.downcase)
end
}
end
rule quoted_identifier
'"' body:('""' / [^"])* '"' {
def value
body.text_value.gsub('""', '"')
end
}
end
rule single_quoted_identifier
"'" body:("''" / [^'])* "'" {
def value
body.text_value.gsub("''", "'")
end
}
end
rule literal
string / float / integer / boolean
end
rule string
"'" ("''" / [^'])* "'"
end
rule boolean
TRUE / FALSE / NULL
end
rule integer
"-"? [0-9]+
end
rule float
"-"? [0-9]* '.' [0-9]+
end
rule SELECT
[Ss] [Ee] [Ll] [Ee] [Cc] [Tt]
end
rule DISTINCT
[Dd] [Ii] [Ss] [Tt] [Ii] [Nn] [Cc] [Tt]
end
rule FROM
[Ff] [Rr] [Oo] [Mm]
end
rule HAVING
[Hh] [Aa] [Vv] [Ii] [Nn] [Gg]
end
rule ORDER
[Oo] [Rr] [Dd] [Ee] [Rr]
end
rule ASC
[Aa] [Ss] [Cc]
end
rule DESC
[Dd] [Ee] [Ss] [Cc]
end
rule NULLS
[Nn] [Uu] [Ll] [Ll] [Ss]
end
rule FIRST
[Ff] [Ii] [Rr] [Ss] [Tt]
end
rule LAST
[Ll] [Aa] [Ss] [Tt]
end
rule AS
[Aa] [Ss]
end
rule JOIN
[Jj] [Oo] [Ii] [Nn]
end
rule FULL
[Ff] [Uu] [Ll] [Ll]
end
rule OUTER
[Oo] [Uu] [Tt] [Ee] [Rr]
end
rule INNER
[Ii] [Nn] [Nn] [Ee] [Rr]
end
rule LEFT
[Ll] [Ee] [Ff] [Tt]
end
rule RIGHT
[Rr] [Ii] [Gg] [Hh] [Tt]
end
rule ON
[Oo] [Nn]
end
rule USING
[Uu] [Ss] [Ii] [Nn] [Gg]
end
rule WHERE
[Ww] [Hh] [Ee] [Rr] [Ee]
end
rule GROUP
[Gg] [Rr] [Oo] [Uu] [Pp]
end
rule BY
[Bb] [Yy]
end
rule LIMIT
[Ll] [Ii] [Mm] [Ii] [Tt]
end
rule OFFSET
[Oo] [Ff] [Ff] [Ss] [Ee] [Tt]
end
rule UNION
[Uu] [Nn] [Ii] [Oo] [Nn]
end
rule ALL
[Aa] [Ll] [Ll]
end
rule COUNT
[Cc] [Oo] [Uu] [Nn] [Tt]
end
rule OVER
[Oo] [Vv] [Ee] [Rr]
end
rule PARTITION
[Pp] [Aa] [Rr] [Tt] [Ii] [Tt] [Ii] [Oo] [Nn]
end
rule WINDOW
[Ww] [Ii] [Nn] [Dd] [Oo] [Ww]
end
rule CASE
[Cc] [Aa] [Ss] [Ee]
end
rule WHEN
[Ww] [Hh] [Ee] [Nn]
end
rule THEN
[Tt] [Hh] [Ee] [Nn]
end
rule ELSE
[Ee] [Ll] [Ss] [Ee]
end
rule END
[Ee] [Nn] [Dd]
end
rule INTERVAL
[Ii] [Nn] [Tt] [Ee] [Rr] [Vv] [Aa] [Ll]
end
rule IS
[Ii] [Ss]
end
rule IN
[Ii] [Nn]
end
rule EXISTS
[Ee] [Xx] [Ii] [Ss] [Tt] [Ss]
end
rule NOT
[Nn] [Oo] [Tt]
end
rule AND
[Aa] [Nn] [Dd]
end
rule OR
[Oo] [Rr]
end
rule TRUE
[Tt] [Rr] [Uu] [Ee]
end
rule FALSE
[Ff] [Aa] [Ll] [Ss] [Ee]
end
rule NULL
[Nn] [Uu] [Ll] [Ll]
end
rule LIKE
[Ll] [Ii] [Kk] [Ee]
end
rule ILIKE
[Ii] [Ll] [Ii] [Kk] [Ee]
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment