Created
June 9, 2019 18:57
-
-
Save hoehrmann/a68057d67e13262401fb1917036d3a02 to your computer and use it in GitHub Desktop.
ABNF for SQLite 3.28 SQL
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; FIXME: The grammar has been transformed so that `w` appears after a | |
; token, but there is no way in ABNF to define it as token-separator | |
; that can optionally contain a mix of comments and white-space. Take | |
; `;;` as an example, for that to match `sql-stmt-list` `w` would | |
; have to match the empty string. But if `w` matches the empty string | |
; then `ISNOT` is the same as `IS NOT`. | |
sql-stmt-list = [ sql-stmt ] *( ";" w [ sql-stmt ] ) | |
sql-stmt = [ "EXPLAIN" w [ "QUERY" w "PLAN" w ] ] ( alter-table-stmt / analyze-stmt / attach-stmt / begin-stmt / commit-stmt / create-index-stmt / create-table-stmt / create-trigger-stmt / create-view-stmt / create-virtual-table-stmt / delete-stmt / delete-stmt-limited / detach-stmt / drop-index-stmt / drop-table-stmt / drop-trigger-stmt / drop-view-stmt / insert-stmt / pragma-stmt / reindex-stmt / release-stmt / rollback-stmt / savepoint-stmt / select-stmt / update-stmt / update-stmt-limited / vacuum-stmt ) | |
alter-table-stmt = "ALTER" w "TABLE" w [ schema-name w "." w ] table-name w ( "RENAME" w "TO" w new-table-name w / "RENAME" w [ "COLUMN" w ] column-name w "TO" w new-column-name w / "ADD" w [ "COLUMN" w ] column-def ) | |
analyze-stmt = "ANALYZE" w [ schema-name w / table-or-index-name w / schema-name w "." w table-or-index-name w ] | |
attach-stmt = "ATTACH" w [ "DATABASE" w ] expr "AS" w schema-name w | |
begin-stmt = "BEGIN" w [ "DEFERRED" w / "IMMEDIATE" w / "EXCLUSIVE" w ] [ "TRANSACTION" w ] | |
commit-stmt = ( "COMMIT" w / "END" w ) [ "TRANSACTION" w ] | |
rollback-stmt = "ROLLBACK" w [ "TRANSACTION" w ] [ "TO" w [ "SAVEPOINT" w ] savepoint-name w ] | |
savepoint-stmt = "SAVEPOINT" w savepoint-name w | |
release-stmt = "RELEASE" w [ "SAVEPOINT" w ] savepoint-name w | |
create-index-stmt = "CREATE" w [ "UNIQUE" w ] "INDEX" w [ "IF" w "NOT" w "EXISTS" w ] [ schema-name w "." w ] index-name w "ON" w table-name w "(" w indexed-column *( "," w indexed-column ) ")" w [ "WHERE" w expr ] | |
indexed-column = ( column-name w / expr ) [ "COLLATE" w collation-name w ] [ "ASC" w / "DESC" w ] | |
create-table-stmt = "CREATE" w [ "TEMP" w / "TEMPORARY" w ] "TABLE" w [ "IF" w "NOT" w "EXISTS" w ] [ schema-name w "." w ] table-name w ( "(" w column-def *( "," w column-def ) *( "," w table-constraint ) ")" w [ "WITHOUT" w "ROWID" w ] / "AS" w select-stmt ) | |
column-def = column-name w [ type-name ] *( column-constraint ) | |
type-name = name w [ "(" w signed-number ")" w / "(" w signed-number "," w signed-number ")" w ] | |
column-constraint = [ "CONSTRAINT" w name w ] ( "PRIMARY" w "KEY" w [ "ASC" w / "DESC" w ] conflict-clause [ "AUTOINCREMENT" w ] / "NOT" w "NULL" w conflict-clause / "UNIQUE" w conflict-clause / "CHECK" w "(" w expr ")" w / "DEFAULT" w ( signed-number / literal-value / "(" w expr ")" w ) / "COLLATE" w collation-name w / foreign-key-clause ) | |
signed-number = [ "+" w / "-" w ] numeric-literal | |
table-constraint = [ "CONSTRAINT" w name w ] ( ( "PRIMARY" w "KEY" w / "UNIQUE" w ) "(" w indexed-column *( "," w indexed-column ) ")" w conflict-clause / "CHECK" w "(" w expr ")" w / "FOREIGN" w "KEY" w "(" w column-name w *( "," w column-name w ) ")" w foreign-key-clause ) | |
foreign-key-clause = "REFERENCES" w foreign-table w [ "(" w column-name w *( "," w column-name w ) ")" w ] [ ( "ON" w ( "DELETE" w / "UPDATE" w ) ( "SET" w "NULL" w / "SET" w "DEFAULT" w / "CASCADE" w / "RESTRICT" w / "NO" w "ACTION" w ) / "MATCH" w name w ) ] [ [ "NOT" w ] "DEFERRABLE" w [ "INITIALLY" w "DEFERRED" w / "INITIALLY" w "IMMEDIATE" w ] ] | |
conflict-clause = [ "ON" w "CONFLICT" w ( "ROLLBACK" w / "ABORT" w / "FAIL" w / "IGNORE" w / "REPLACE" w ) ] | |
create-trigger-stmt = "CREATE" w [ "TEMP" w / "TEMPORARY" w ] "TRIGGER" w [ "IF" w "NOT" w "EXISTS" w ] [ schema-name w "." w ] trigger-name w [ "BEFORE" w / "AFTER" w / "INSTEAD" w "OF" w ] ( "DELETE" w / "INSERT" w / "UPDATE" w [ "OF" w column-name w *( "," w column-name w ) ] ) "ON" w table-name w [ "FOR" w "EACH" w "ROW" w ] [ "WHEN" w expr ] "BEGIN" w ( update-stmt / insert-stmt / delete-stmt / select-stmt ) ";" w "END" w | |
create-view-stmt = "CREATE" w [ "TEMP" w / "TEMPORARY" w ] "VIEW" w [ "IF" w "NOT" w "EXISTS" w ] [ schema-name w "." w ] view-name w [ "(" w column-name w *( "," w column-name w ) ")" w ] "AS" w select-stmt | |
create-virtual-table-stmt = "CREATE" w "VIRTUAL" w "TABLE" w [ "IF" w "NOT" w "EXISTS" w ] [ schema-name w "." w ] table-name w "USING" w module-name w [ "(" w module-argument w *( "," w module-argument w ) ")" w ] | |
with-clause = "WITH" w [ "RECURSIVE" w ] cte-table-name "AS" w "(" w select-stmt ")" w *( "," w cte-table-name "AS" w "(" w select-stmt ")" w ) | |
cte-table-name = table-name w [ "(" w column-name w *( "," w column-name w ) ")" w ] | |
common-table-expression = table-name w [ "(" w column-name w *( "," w column-name w ) ")" w ] "AS" w "(" w select-stmt ")" w | |
delete-stmt = [ with-clause ] "DELETE" w "FROM" w qualified-table-name [ "WHERE" w expr ] | |
delete-stmt-limited = [ with-clause ] "DELETE" w "FROM" w qualified-table-name [ "WHERE" w expr ] [ [ "ORDER" w "BY" w ordering-term *( "," w ordering-term ) ] "LIMIT" w expr [ ( "OFFSET" w / "," w ) expr ] ] | |
detach-stmt = "DETACH" w [ "DATABASE" w ] schema-name w | |
drop-index-stmt = "DROP" w "INDEX" w [ "IF" w "EXISTS" w ] [ schema-name w "." w ] index-name w | |
drop-table-stmt = "DROP" w "TABLE" w [ "IF" w "EXISTS" w ] [ schema-name w "." w ] table-name w | |
drop-trigger-stmt = "DROP" w "TRIGGER" w [ "IF" w "EXISTS" w ] [ schema-name w "." w ] trigger-name w | |
drop-view-stmt = "DROP" w "VIEW" w [ "IF" w "EXISTS" w ] [ schema-name w "." w ] view-name w | |
; FIXME: bogus when binary-operator includes IS NOT and such | |
expr = ( literal-value | |
/ bind-parameter w | |
/ [ [ schema-name w "." w ] table-name w "." w ] column-name w | |
/ unary-operator w expr | |
/ expr binary-operator w expr | |
/ function-name w "(" w [ [ "DISTINCT" w ] expr *( "," w expr ) / "*" w ] ")" w | |
/ "(" w expr *( "," w expr ) ")" w | |
/ "CAST" w "(" w expr "AS" w type-name ")" w | |
/ expr "COLLATE" w collation-name w | |
/ expr [ "NOT" w ] ( "LIKE" w / "GLOB" w / "REGEXP" w / "MATCH" w ) expr [ "ESCAPE" w expr ] | |
/ expr ( "ISNULL" w / "NOTNULL" w / "NOT" w "NULL" w ) | |
/ expr "IS" w [ "NOT" w ] expr | |
/ expr [ "NOT" w ] "BETWEEN" w expr "AND" w expr | |
/ expr [ "NOT" w ] "IN" w ( "(" w [ select-stmt / expr *( "," w expr ) ] ")" w / [ schema-name w "." w ] table-name w / [ schema-name w "." w ] table-function w "(" w [ expr *( "," w expr ) ] ")" w ) | |
/ [ [ "NOT" w ] "EXISTS" w ] "(" w select-stmt ")" w | |
/ "CASE" w [ expr ] "WHEN" w expr "THEN" w expr [ "ELSE" w expr ] "END" w | |
/ raise-function | |
/ window-func w "(" w [ expr *( "," w expr ) / "*" w ] ")" w [ filter ] "OVER" w ( window-defn / window-name w ) ) | |
raise-function = "RAISE" w "(" w ( "IGNORE" w / ( "ROLLBACK" w / "ABORT" w / "FAIL" w ) "," w error-message w ) ")" w | |
literal-value = ( numeric-literal | |
/ string-literal w | |
/ blob-literal w | |
/ "NULL" w | |
/ "TRUE" w | |
/ "FALSE" w | |
/ "CURRENT-TIME" w | |
/ "CURRENT-DATE" w | |
/ "CURRENT-TIMESTAMP" w ) | |
numeric-literal = ( ( digit w [ decimal-point w *( digit w ) ] / decimal-point w digit ) [ "E" w [ "+" w / "-" w ] digit w ] | |
/ "0x" w hexdigit w ) | |
insert-stmt = [ with-clause ] ( "INSERT" w / "REPLACE" w / "INSERT" w "OR" w "REPLACE" w / "INSERT" w "OR" w "ROLLBACK" w / "INSERT" w "OR" w "ABORT" w / "INSERT" w "OR" w "FAIL" w / "INSERT" w "OR" w "IGNORE" w ) "INTO" w [ schema-name w "." w ] table-name w [ "AS" w alias w ] [ "(" w column-name w *( "," w column-name w ) ")" w ] ( "VALUES" w "(" w expr *( "," w expr ) ")" w *( "," w "(" w expr *( "," w expr ) ")" w ) / select-stmt / "DEFAULT" w "VALUES" w ) [ upsert-clause ] | |
upsert-clause = "ON" w "CONFLICT" w [ "(" w indexed-column *( "," w indexed-column ) ")" w [ "WHERE" w expr ] ] "DO" w ( "NOTHING" w / "UPDATE" w "SET" w ( column-name w / column-name-list ) "=" w expr *( "," w ( column-name w / column-name-list ) "=" w expr ) [ "WHERE" w expr ] ) | |
pragma-stmt = "PRAGMA" w [ schema-name w "." w ] pragma-name w [ "=" w pragma-value / "(" w pragma-value ")" w ] | |
pragma-value = ( signed-number | |
/ name w | |
/ string-literal w ) | |
reindex-stmt = "REINDEX" w [ collation-name w / [ schema-name w "." w ] ( table-name w / index-name w ) ] | |
select-stmt = [ "WITH" w [ "RECURSIVE" w ] common-table-expression *( "," w common-table-expression ) ] ( "SELECT" w [ "DISTINCT" w / "ALL" w ] result-column *( "," w result-column ) [ "FROM" w ( table-or-subquery *( "," w table-or-subquery ) / join-clause ) ] [ "WHERE" w expr ] [ "GROUP" w "BY" w expr *( "," w expr ) [ "HAVING" w expr ] ] [ "WINDOW" w window-name w "AS" w window-defn *( "," w window-name w "AS" w window-defn ) ] / "VALUES" w "(" w expr *( "," w expr ) ")" w *( "," w "(" w expr *( "," w expr ) ")" w ) ) *( compound-operator ( "SELECT" w [ "DISTINCT" w / "ALL" w ] result-column *( "," w result-column ) [ "FROM" w ( table-or-subquery *( "," w table-or-subquery ) / join-clause ) ] [ "WHERE" w expr ] [ "GROUP" w "BY" w expr *( "," w expr ) [ "HAVING" w expr ] ] [ "WINDOW" w window-name w "AS" w window-defn *( "," w window-name w "AS" w window-defn ) ] / "VALUES" w "(" w expr *( "," w expr ) ")" w *( "," w "(" w expr *( "," w expr ) ")" w ) ) ) [ "ORDER" w "BY" w ordering-term *( "," w ordering-term ) ] [ "LIMIT" w expr [ ( "OFFSET" w / "," w ) expr ] ] | |
join-clause = table-or-subquery [ join-operator table-or-subquery join-constraint ] | |
select-core = ( "SELECT" w [ "DISTINCT" w / "ALL" w ] result-column *( "," w result-column ) [ "FROM" w ( table-or-subquery *( "," w table-or-subquery ) / join-clause ) ] [ "WHERE" w expr ] [ "GROUP" w "BY" w expr *( "," w expr ) [ "HAVING" w expr ] ] [ "WINDOW" w window-name w "AS" w window-defn *( "," w window-name w "AS" w window-defn ) ] | |
/ "VALUES" w "(" w expr *( "," w expr ) ")" w *( "," w "(" w expr *( "," w expr ) ")" w ) ) | |
factored-select-stmt = [ "WITH" w [ "RECURSIVE" w ] common-table-expression *( "," w common-table-expression ) ] select-core *( compound-operator select-core ) [ "ORDER" w "BY" w ordering-term *( "," w ordering-term ) ] [ "LIMIT" w expr [ ( "OFFSET" w / "," w ) expr ] ] | |
simple-select-stmt = [ "WITH" w [ "RECURSIVE" w ] common-table-expression *( "," w common-table-expression ) ] select-core [ "ORDER" w "BY" w ordering-term *( "," w ordering-term ) ] [ "LIMIT" w expr [ ( "OFFSET" w / "," w ) expr ] ] | |
compound-select-stmt = [ "WITH" w [ "RECURSIVE" w ] common-table-expression *( "," w common-table-expression ) ] select-core ( "UNION" w / "UNION" w "ALL" w / "INTERSECT" w / "EXCEPT" w ) select-core [ "ORDER" w "BY" w ordering-term *( "," w ordering-term ) ] [ "LIMIT" w expr [ ( "OFFSET" w / "," w ) expr ] ] | |
table-or-subquery = ( [ schema-name w "." w ] table-name w [ [ "AS" w ] table-alias w ] [ "INDEXED" w "BY" w index-name w / "NOT" w "INDEXED" w ] | |
/ [ schema-name w "." w ] table-function-name w "(" w [ expr *( "," w expr ) ] ")" w [ [ "AS" w ] table-alias w ] | |
/ "(" w ( table-or-subquery *( "," w table-or-subquery ) / join-clause ) ")" w | |
/ "(" w select-stmt ")" w [ [ "AS" w ] table-alias w ] ) | |
result-column = ( expr [ [ "AS" w ] column-alias w ] | |
/ "*" w | |
/ table-name w "." w "*" w ) | |
join-operator = ( "," w | |
/ [ "NATURAL" w ] [ "LEFT" w [ "OUTER" w ] / "INNER" w / "CROSS" w ] "JOIN" w ) | |
join-constraint = [ "ON" w expr / "USING" w "(" w column-name w *( "," w column-name w ) ")" w ] | |
ordering-term = expr [ "COLLATE" w collation-name w ] [ "ASC" w / "DESC" w ] | |
compound-operator = ( "UNION" w | |
/ "UNION" w "ALL" w | |
/ "INTERSECT" w | |
/ "EXCEPT" w ) | |
update-stmt = [ with-clause ] "UPDATE" w [ "OR" w "ROLLBACK" w / "OR" w "ABORT" w / "OR" w "REPLACE" w / "OR" w "FAIL" w / "OR" w "IGNORE" w ] qualified-table-name "SET" w ( column-name w / column-name-list ) "=" w expr *( "," w ( column-name w / column-name-list ) "=" w expr ) [ "WHERE" w expr ] | |
column-name-list = "(" w column-name w *( "," w column-name w ) ")" w | |
update-stmt-limited = [ with-clause ] "UPDATE" w [ "OR" w "ROLLBACK" w / "OR" w "ABORT" w / "OR" w "REPLACE" w / "OR" w "FAIL" w / "OR" w "IGNORE" w ] qualified-table-name "SET" w ( column-name w / column-name-list ) "=" w expr *( "," w ( column-name w / column-name-list ) "=" w expr ) [ "WHERE" w expr ] [ [ "ORDER" w "BY" w ordering-term *( "," w ordering-term ) ] "LIMIT" w expr [ ( "OFFSET" w / "," w ) expr ] ] | |
qualified-table-name = [ schema-name w "." w ] table-name w [ "AS" w alias w ] [ "INDEXED" w "BY" w index-name w / "NOT" w "INDEXED" w ] | |
vacuum-stmt = "VACUUM" w [ schema-name w ] [ "INTO" w filename w ] | |
filter = "FILTER" w "(" w "WHERE" w expr ")" w | |
window-defn = "(" w [ base-window-name w ] [ "PARTITION" w "BY" w expr *( "," w expr ) ] [ "ORDER" w "BY" w ordering-term *( "," w ordering-term ) ] [ frame-spec ] ")" w | |
frame-spec = ( "RANGE" w / "ROWS" w / "GROUPS" w ) ( "BETWEEN" w ( "UNBOUNDED" w "PRECEDING" w / expr "PRECEDING" w / "CURRENT" w "ROW" w / expr "FOLLOWING" w ) "AND" w ( expr "PRECEDING" w / "CURRENT" w "ROW" w / expr "FOLLOWING" w / "UNBOUNDED" w "FOLLOWING" w ) / ( "UNBOUNDED" w "PRECEDING" w / expr "PRECEDING" w / "CURRENT" w "ROW" w ) ) [ "EXCLUDE" w "NO" w "OTHERS" w / "EXCLUDE" w "CURRENT" w "ROW" w / "EXCLUDE" w "GROUP" w / "EXCLUDE" w "TIES" w ] | |
function-invocation = function-name w "(" w [ [ "DISTINCT" w ] expr *( "," w expr ) / "*" w ] ")" w | |
window-function-invocation = window-func w "(" w [ expr *( "," w expr ) / "*" w ] ")" w [ filter ] "OVER" w ( window-defn / window-name w ) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; hand-written token defintions | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
alias = name | |
base-window-name = window-name | |
collation-name = name | |
column-alias = alias | |
column-name = name | |
foreign-table = table-name | |
error-message = string-literal | |
function-name = name | |
index-name = name | |
module-name = name | |
new-column-name = column-name | |
new-table-name = table-name | |
pragma-name = name | |
savepoint-name = name | |
schema-name = name | |
table-alias = alias | |
table-function = table-function-name | |
table-function-name = name | |
table-name = name | |
table-or-index-name = table-name / index-name | |
trigger-name = name | |
view-name = name | |
window-func = function-name | |
window-name = name | |
string-literal = "'" *("''" / %x00-26 / %x28-ff) "'" | |
w = 1*(%x0a / %x0d / %x20 / %x09) ; FIXME: comment or white space | |
newline = %x0d / %x0a | |
name = 1*ident ; FIXME: quoted name | |
ident = %x24 / %x30 / %x31 / %x32 / %x33 / %x34 / %x35 / %x36 / | |
%x37 / %x38 / %x39 / %x41 / %x42 / %x43 / %x44 / %x45 / | |
%x46 / %x47 / %x48 / %x49 / %x4a / %x4b / %x4c / %x4d / | |
%x4e / %x4f / %x50 / %x51 / %x52 / %x53 / %x54 / %x55 / | |
%x56 / %x57 / %x58 / %x59 / %x5a / %x5f / %x61 / %x62 / | |
%x63 / %x64 / %x65 / %x66 / %x67 / %x68 / %x69 / %x6a / | |
%x6b / %x6c / %x6d / %x6e / %x6f / %x70 / %x71 / %x72 / | |
%x73 / %x74 / %x75 / %x76 / %x77 / %x78 / %x79 / %x7a / | |
%x80 / %x81 / %x82 / %x83 / %x84 / %x85 / %x86 / %x87 / | |
%x88 / %x89 / %x8a / %x8b / %x8c / %x8d / %x8e / %x8f / | |
%x90 / %x91 / %x92 / %x93 / %x94 / %x95 / %x96 / %x97 / | |
%x98 / %x99 / %x9a / %x9b / %x9c / %x9d / %x9e / %x9f / | |
%xa0 / %xa1 / %xa2 / %xa3 / %xa4 / %xa5 / %xa6 / %xa7 / | |
%xa8 / %xa9 / %xaa / %xab / %xac / %xad / %xae / %xaf / | |
%xb0 / %xb1 / %xb2 / %xb3 / %xb4 / %xb5 / %xb6 / %xb7 / | |
%xb8 / %xb9 / %xba / %xbb / %xbc / %xbd / %xbe / %xbf / | |
%xc0 / %xc1 / %xc2 / %xc3 / %xc4 / %xc5 / %xc6 / %xc7 / | |
%xc8 / %xc9 / %xca / %xcb / %xcc / %xcd / %xce / %xcf / | |
%xd0 / %xd1 / %xd2 / %xd3 / %xd4 / %xd5 / %xd6 / %xd7 / | |
%xd8 / %xd9 / %xda / %xdb / %xdc / %xdd / %xde / %xdf / | |
%xe0 / %xe1 / %xe2 / %xe3 / %xe4 / %xe5 / %xe6 / %xe7 / | |
%xe8 / %xe9 / %xea / %xeb / %xec / %xed / %xee / %xef / | |
%xf0 / %xf1 / %xf2 / %xf3 / %xf4 / %xf5 / %xf6 / %xf7 / | |
%xf8 / %xf9 / %xfa / %xfb / %xfc / %xfd / %xfe / %xff | |
filename = string-literal | |
hexdigit = HEXDIG | |
blob-literal = "x" "'" *HEXDIG "'" | |
bind-parameter = "?" 1*DIGIT / ":" name / "@" name / bind-parameter-tcl | |
bind-parameter-tcl = "$" name ; FIXME | |
decimal-point = "." | |
digit = DIGIT | |
binary-operator = | |
"||" / | |
"*" / | |
"/" / | |
"%" / | |
"+" / | |
"-" / | |
"<<" / | |
">>" / | |
"&" / | |
"|" / | |
"<" / | |
"<=" / | |
">" / | |
">=" / | |
"=" / | |
"==" / | |
"!=" / | |
"<>" / | |
"IS" / | |
"IS" w "NOT" / | |
"IN" / | |
"LIKE" / | |
"GLOB" / | |
"MATCH" / | |
"REGEXP" / | |
"AND" / | |
"OR" | |
unary-operator = "-" / "+" / "~" / "NOT" | |
; FIXME: "The arguments can be just about any text | |
; as long as it has balanced parentheses." | |
module-argument = name |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment