Skip to main content

SQL Grammar

The SQL parser in Wvlet is based on Apache Calcite's SQL Language definition.

statement:
setStatement
| resetStatement
| explain
| describe
| insert
| update
| merge
| delete
| query

statementList:
statement [ ';' statement ]* [ ';' ]

setStatement:
[ ALTER { SYSTEM | SESSION } ] SET identifier '=' expression

resetStatement:
[ ALTER { SYSTEM | SESSION } ] RESET identifier
| [ ALTER { SYSTEM | SESSION } ] RESET ALL

explain:
EXPLAIN PLAN
[ WITH TYPE | WITH IMPLEMENTATION | WITHOUT IMPLEMENTATION ]
[ EXCLUDING ATTRIBUTES | INCLUDING [ ALL ] ATTRIBUTES ]
[ AS JSON | AS XML | AS DOT ]
FOR { query | insert | update | merge | delete }

describe:
DESCRIBE DATABASE databaseName
| DESCRIBE CATALOG [ databaseName . ] catalogName
| DESCRIBE SCHEMA [ [ databaseName . ] catalogName ] . schemaName
| DESCRIBE [ TABLE ] [ [ [ databaseName . ] catalogName . ] schemaName . ] tableName [ columnName ]
| DESCRIBE [ STATEMENT ] { query | insert | update | merge | delete }

insert:
{ INSERT | UPSERT } INTO tablePrimary
[ '(' column [, column ]* ')' ]
query

update:
UPDATE tablePrimary
SET assign [, assign ]*
[ WHERE booleanExpression ]

assign:
identifier '=' expression

merge:
MERGE INTO tablePrimary [ [ AS ] alias ]
USING tablePrimary
ON booleanExpression
[ WHEN MATCHED THEN UPDATE SET assign [, assign ]* ]
[ WHEN NOT MATCHED THEN INSERT VALUES '(' value [ , value ]* ')' ]

delete:
DELETE FROM tablePrimary [ [ AS ] alias ]
[ WHERE booleanExpression ]

query:
values
| WITH [ RECURSIVE ] withItem [ , withItem ]* query
| {
select
| selectWithoutFrom
| query UNION [ ALL | DISTINCT ] query
| query EXCEPT [ ALL | DISTINCT ] query
| query MINUS [ ALL | DISTINCT ] query
| query INTERSECT [ ALL | DISTINCT ] query
}
[ ORDER BY orderItem [, orderItem ]* ]
[ LIMIT [ start, ] { count | ALL } ]
[ OFFSET start { ROW | ROWS } ]
[ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]

withItem:
name
[ '(' column [, column ]* ')' ]
AS '(' query ')'

orderItem:
expression [ ASC | DESC ] [ NULLS FIRST | NULLS LAST ]

select:
SELECT [ hintComment ] [ STREAM ] [ ALL | DISTINCT ]
{ * | projectItem [, projectItem ]* }
FROM tableExpression
[ WHERE booleanExpression ]
[ GROUP BY [ ALL | DISTINCT ] { groupItem [, groupItem ]* } ]
[ HAVING booleanExpression ]
[ WINDOW windowName AS windowSpec [, windowName AS windowSpec ]* ]
[ QUALIFY booleanExpression ]

selectWithoutFrom:
SELECT [ ALL | DISTINCT ]
{ * | projectItem [, projectItem ]* }

projectItem:
expression [ [ AS ] columnAlias ]
| tableAlias . *

tableExpression:
tableReference [, tableReference ]*
| tableExpression [ NATURAL ] [ { LEFT | RIGHT | FULL } [ OUTER ] ] [ ASOF ] JOIN tableExpression [ joinCondition ]
| tableExpression CROSS JOIN tableExpression
| tableExpression [ CROSS | OUTER ] APPLY tableExpression

joinCondition:
ON booleanExpression
| MATCH_CONDITION booleanExpression ON booleanExpression
| USING '(' column [, column ]* ')'

tableReference:
tablePrimary
[ FOR SYSTEM_TIME AS OF expression ]
[ pivot ]
[ unpivot ]
[ matchRecognize ]
[ [ AS ] alias [ '(' columnAlias [, columnAlias ]* ')' ] ]

tablePrimary:
[ [ catalogName . ] schemaName . ] tableName
'(' TABLE [ [ catalogName . ] schemaName . ] tableName ')'
| tablePrimary [ hintComment ] [ EXTEND ] '(' columnDecl [, columnDecl ]* ')'
| [ LATERAL ] '(' query ')'
| UNNEST '(' expression ')' [ WITH ORDINALITY ]
| [ LATERAL ] TABLE '(' [ SPECIFIC ] functionName '(' expression [, expression ]* ')' ')'

columnDecl:
column type [ NOT NULL ]

hint:
hintName
| hintName '(' hintOptions ')'

hintOptions:
hintKVOption [, hintKVOption ]*
| optionName [, optionName ]*
| optionValue [, optionValue ]*

hintKVOption:
optionName '=' stringLiteral
| stringLiteral '=' stringLiteral

optionValue:
stringLiteral
| numericLiteral

columnOrList:
column
| '(' column [, column ]* ')'

exprOrList:
expr
| '(' expr [, expr ]* ')'

pivot:
PIVOT '('
pivotAgg [, pivotAgg ]*
FOR pivotList
IN '(' pivotExpr [, pivotExpr ]* ')'
')'

pivotAgg:
agg '(' [ ALL | DISTINCT ] value [, value ]* ')'
[ [ AS ] alias ]

pivotList:
columnOrList

pivotExpr:
exprOrList [ [ AS ] alias ]

unpivot:
UNPIVOT [ INCLUDING NULLS | EXCLUDING NULLS ] '('
unpivotMeasureList
FOR unpivotAxisList
IN '(' unpivotValue [, unpivotValue ]* ')'
')'

unpivotMeasureList:
columnOrList

unpivotAxisList:
columnOrList

unpivotValue:
column [ AS literal ]
| '(' column [, column ]* ')' [ AS '(' literal [, literal ]* ')' ]

values:
{ VALUES | VALUE } expression [, expression ]*

groupItem:
expression
| '(' ')'
| '(' expression [, expression ]* ')'
| CUBE '(' expression [, expression ]* ')'
| ROLLUP '(' expression [, expression ]* ')'
| GROUPING SETS '(' groupItem [, groupItem ]* ')'

window:
windowName
| windowSpec

windowSpec:
'('
[ windowName ]
[ ORDER BY orderItem [, orderItem ]* ]
[ PARTITION BY expression [, expression ]* ]
[
RANGE numericOrIntervalExpression { PRECEDING | FOLLOWING [exclude]}
| ROWS numericExpression { PRECEDING | FOLLOWING [exclude] }
]
')'

exclude:
EXCLUDE NO OTHERS
| EXCLUDE CURRENT ROW
| EXCLUDE GROUP
| EXCLUDE TIES