forked from couchbaselabs/query
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathn1ql-select.ebnf
145 lines (129 loc) · 4.86 KB
/
n1ql-select.ebnf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/****************
* N1QL SELECT *
****************/
/*
* select statement
*/
select ::= subselect (set-op 'ALL'? subselect)* order-by-clause? limit-clause? offset-clause?
set-op ::= 'UNION' | 'INTERSECT' | 'EXCEPT'
subselect ::= select-from | from-select
select-from ::= select-clause from-clause? let-clause? where-clause? group-by-clause?
from-select ::= from-clause let-clause? where-clause? group-by-clause? select-clause
/*
* select clause
*/
select-clause ::= 'SELECT' ('ALL' | 'DISTINCT')? (result-expr (',' result-expr)* | ('RAW' | 'ELEMENT') expr ('AS'? alias)?)
result-expr ::= (path '.')? '*' | expr ('AS'? alias)?
path ::= identifier ('[' expr ']')? ('.' path)?
alias ::= identifier
/*
* from clause
*/
from-clause ::= 'FROM' from-term
from-term ::= from-path ('AS'? alias)? use-keys-clause? | '(' select ')' 'AS'? alias | from-term join-clause | from-term nest-clause | from-term unnest-clause
from-path ::= (namespace ':')? path
namespace ::= identifier
use-keys-clause ::= 'USE' 'PRIMARY'? 'KEYS' expr
join-clause ::= join-type? 'JOIN' from-path ('AS'? alias)? on-keys-clause
join-type ::= 'INNER' | 'LEFT' 'OUTER'?
on-keys-clause ::= 'ON' 'PRIMARY'? 'KEYS' expr
nest-clause ::= join-type? 'NEST' from-path ('AS'? alias)? on-keys-clause
unnest-clause ::= join-type? ('UNNEST' | 'FLATTEN') expr ('AS'? alias)?
/*
* let clause
*/
let-clause ::= 'LET' alias '=' expr (',' alias '=' expr)*
/*
* where clause
*/
where-clause ::= 'WHERE' cond
cond ::= expr
/*
* group-by clause
*/
group-by-clause ::= 'GROUP' 'BY' expr (',' expr)* letting-clause? having-clause? | letting-clause
letting-clause ::= 'LETTING' alias '=' expr (',' alias '=' expr)*
having-clause ::= 'HAVING' cond
/*
* order-by clause
*/
order-by-clause ::= 'ORDER' 'BY' ordering-term (',' ordering-term)*
ordering-term ::= expr ('ASC' | 'DESC')?
/*
* limit clause
*/
limit-clause ::= 'LIMIT' expr
/*
* offset clause
*/
offset-clause ::= 'OFFSET' expr
/*
* expressions
*/
expr ::= literal | identifier | nested-expr | case-expr | logical-term | comparison-term | arithmetic-term | concatenation-term | function-call | subquery-expr | collection-expr | construction-expr | '(' expr ')'
logical-term ::= cond 'AND' cond | cond 'OR' cond | 'NOT' cond
case-expr ::= simple-case-expr | searched-case-expr
simple-case-expr ::= 'CASE' expr ('WHEN' expr 'THEN' expr)+ ('ELSE' expr)? 'END'
searched-case-expr ::= 'CASE' ('WHEN' cond 'THEN' expr)+ ('ELSE' expr)? 'END'
comparison-term ::= expr '=' expr | expr '==' expr | expr '!=' expr | expr '<>' expr | expr '>' expr | expr '>=' expr | expr '<' expr | expr '<=' expr | expr 'NOT'? 'BETWEEN' expr 'AND' expr | expr 'NOT'? 'LIKE' expr | expr 'IS' 'NOT'? 'VALUED' | expr 'IS' 'NOT'? 'NULL' | expr 'IS' 'NOT'? 'MISSING'
arithmetic-term ::= expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '%' expr | '-' expr
concatenation-term ::= expr '||' expr
nested-expr ::= field-expr | element-expr | slice-expr
field-expr ::= expr '.' (identifier | (escaped-identifier 'i'?))
element-expr ::= expr '[' expr ']'
slice-expr ::= expr '[' expr ':' expr? ']'
subquery-expr ::= '(' select ')'
/*
* function calls
*/
function-call ::= function-name '(' ('*' | ('DISTINCT'? expr (',' expr)*))? ')'
function-name ::= identifier
/*
* collections
*/
collection-expr ::= exists-expr | in-expr | within-expr | range-cond | range-xform
exists-expr ::= 'EXISTS' expr
in-expr ::= expr 'NOT'? 'IN' expr
within-expr ::= (name-expr ':')? expr 'NOT'? 'WITHIN' expr
name-expr ::= expr
range-cond ::= ('ANY' | 'SOME' | 'EVERY') (var 'IN' expr (',' var 'IN' expr)* | name-var ':' var 'IN' expr | var 'WITHIN' expr | name-var ':' var 'WITHIN' expr) 'SATISFIES' cond 'END'
var ::= identifier
name-var ::= identifier
range-xform ::= (('ARRAY' | 'FIRST') expr | 'OBJECT' name-expr ':' expr) 'FOR' (var 'IN' expr (',' var 'IN' expr)* | name-var ':' var 'IN' expr | var 'WITHIN' expr | name-var ':' var 'WITHIN' expr) ('WHEN' cond)? 'END'
/*
* construction
*/
construction-expr ::= object | array
object ::= '{' members? '}'
members ::= pair (',' members)?
pair ::= name-expr ':' expr
array ::= '[' elements? ']'
elements ::= expr (',' elements)?
/*
* identifiers
*/
identifier ::= unescaped-identifier | escaped-identifier
unescaped-identifier ::= [a-zA-Z_] ( [0-9a-zA-Z_$] )*
escaped-identifier ::= '`' chars '`'
/*
* literals
*/
literal ::= string | number | 'TRUE' | 'FALSE' | 'NULL' | 'MISSING'
string ::= '"' chars? '"'
chars ::= char chars?
char ::= unicode-character | '\' ('\' | '/' | 'b' | 'f' | 'n' | 'r' | 't' | 'u' hex-digit hex-digit hex-digit hex-digit )
number ::= int frac? exp?
int ::= '-'? uint
uint ::= digit | non-zero-digit digits
frac ::= '.' digits
exp ::= e digits
digits ::= digit digits?
non-zero-digit ::= [1-9]
digit ::= [0-9]
e ::= ('e' | 'E') ('-' | '+')?
hex-digit ::= [0-9a-fA-F]
/**
* comments
**/
block-comment ::= '/*' ((text)? newline?)+ '*/'
line-comment ::= '--' (text)? newline?