-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathodata-abnf-construction-rules.txt
1298 lines (1085 loc) · 57 KB
/
odata-abnf-construction-rules.txt
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;------------------------------------------------------------------------------
; OData ABNF Construction Rules Version 4.01 and 4.0
;------------------------------------------------------------------------------
; 17 September 2020
;
; Latest version: https://github.com/oasis-tcs/odata-abnf/blob/main/abnf/odata-abnf-construction-rules.txt
;------------------------------------------------------------------------------
;
; Technical Committee:
; OASIS Open Data Protocol (OData) TC
; https://www.oasis-open.org/committees/odata
;
; Chairs:
; - Ralf Handl ([email protected]), SAP SE
; - Michael Pizzo ([email protected]), Microsoft
;
; Editors:
; - Ralf Handl ([email protected]), SAP SE
; - Michael Pizzo ([email protected]), Microsoft
; - Martin Zurmuehl ([email protected]), SAP SE
;
; Additional artifacts:
; This grammar is one component of a Work Product which consists of:
; - OData Version 4.01 Part 1: Protocol
; - OData Version 4.01 Part 2: URL Conventions
; - OData ABNF Construction Rules Version 4.01 (this document)
; - OData ABNF Test Cases Version 4.01
;
; Related work:
; This specification replaces or supersedes:
; - OData ABNF Construction Rules Version 4.0
; This work product is related to
; - OData Common Schema Definition Language (CSDL) JSON Representation Version 4.01
; - OData Common Schema Definition Language (CSDL) XML Representation Version 4.01
; - OData JSON Format Version 4.01
;
; Abstract:
; The Open Data Protocol (OData) enables the creation of REST-based data
; services, which allow resources, identified using Uniform Resource
; Identifiers (URLs) and defined in a data model, to be published and
; edited by Web clients using simple HTTP messages. This document defines
; the URL syntax for requests and the serialization format for primitive
; literals in request and response payloads.
;
; Overview:
; This grammar uses the ABNF defined in RFC5234 and RFC7405.
;
; The following rules assume that URIs have been percent-encoding normalized
; as described in section 6.2.2.2 of RFC3986
; (http://tools.ietf.org/html/rfc3986#section-6.2.2.2)
; before applying the grammar to them, i.e. all characters in the unreserved
; set (see rule "unreserved" below) are plain literals and NOT
; percent-encoded.
;
; For characters outside the unreserved set the rules explicitly state
; whether the percent-encoded representation is treated identical to the
; plain literal representation.
;
; One prominent example is the single quote that delimits OData primitive
; type literals: %27 and ' are treated identically, so a single quote within
; a string literal is "encoded" as two consecutive single quotes in either
; literal or percent-encoded representation.
;
; Contents:
; 1. Resource Path
; 2. Query Options
; 3. Context URL Fragments
; 4. Expressions
; 5. JSON format for function parameters
; 6. Names and identifiers
; 7. Literal Data Values
; 8. Header values
; 9. Punctuation
;
; A. URI syntax [RFC3986]
; B. IRI syntax [RFC3986]
; C. ABNF core definitions [RFC5234]
;
;------------------------------------------------------------------------------
odataUri = serviceRoot [ odataRelativeUri ]
serviceRoot = ( "https" / "http" ) ; Note: case-insensitive
"://" host [ ":" port ]
"/" *( segment-nz "/" )
; Note: dollar-prefixed path segments are case-sensitive!
odataRelativeUri = %s"$batch" [ "?" batchOptions ]
/ %s"$entity" "?" entityOptions
/ %s"$entity" "/" optionallyQualifiedEntityTypeName "?" entityCastOptions
/ %s"$metadata" [ "?" metadataOptions ] [ context ]
/ resourcePath [ "?" [ queryOptions ] ]
;------------------------------------------------------------------------------
; 1. Resource Path
;------------------------------------------------------------------------------
resourcePath = entitySetName [ collectionNavigation ]
/ singletonEntity [ singleNavigation ]
/ actionImportCall
/ entityColFunctionImportCall [ collectionNavigation ]
/ entityFunctionImportCall [ singleNavigation ]
/ complexColFunctionImportCall [ complexColPath ]
/ complexFunctionImportCall [ complexPath ]
/ primitiveColFunctionImportCall [ collectionPath ]
/ primitiveFunctionImportCall [ primitivePath ]
/ functionImportCallNoParens [ querySegment ]
/ crossjoin [ querySegment ]
/ %s"$all" [ "/" optionallyQualifiedEntityTypeName ]
collectionNavigation = collectionNavPath
/ "/" optionallyQualifiedEntityTypeName [ collectionNavPath ]
collectionNavPath = keyPredicate [ singleNavigation ]
/ filterInPath [ collectionNavigation ]
/ each [ boundOperation ]
/ boundOperation
/ count
/ ref
/ querySegment
keyPredicate = simpleKey / compoundKey / keyPathSegments
simpleKey = OPEN ( parameterAlias / keyPropertyValue ) CLOSE
compoundKey = OPEN keyValuePair *( COMMA keyValuePair ) CLOSE
keyValuePair = ( primitiveKeyProperty / keyPropertyAlias ) EQ ( parameterAlias / keyPropertyValue )
keyPropertyAlias = odataIdentifier
keyPathSegments = 1*( "/" keyPathLiteral )
keyPathLiteral = *pchar
keyPropertyValue = boolean
/ guid
/ dateTimeOffsetLiteral
/ date
/ timeOfDayLiteral
/ decimalLiteral
/ sbyteLiteral
/ byte
/ int16Literal
/ int32Literal
/ int64Literal
/ stringLiteral
/ durationLiteral
/ enumLiteral
singleNavigation = singleNavPath
/ "/" optionallyQualifiedEntityTypeName [ singleNavPath ]
singleNavPath = "/" propertyPath
/ boundOperation
/ ref
/ value ; request the media resource of a media entity
/ querySegment
propertyPath = entityColNavigationProperty [ collectionNavigation ]
/ entityNavigationProperty [ singleNavigation ]
/ complexColProperty [ complexColPath ]
/ complexProperty [ complexPath ]
/ primitiveColProperty [ collectionPath ]
/ primitiveProperty [ primitivePath ]
/ streamProperty [ boundOperation ]
collectionPath = count / boundOperation / ordinalIndex / querySegment
primitivePath = value / boundOperation / querySegment
complexColPath = collectionPath
/ "/" optionallyQualifiedComplexTypeName [ collectionPath ]
complexPath = complexNavPath
/ "/" optionallyQualifiedComplexTypeName [ complexNavPath ]
complexNavPath = "/" propertyPath
/ boundOperation
/ querySegment
filterInPath = %s"/$filter" OPEN boolCommonExpr CLOSE
each = %s"/$each"
count = %s"/$count"
ref = %s"/$ref"
value = %s"/$value"
querySegment = %s"/$query"
ordinalIndex = "/" [ "-" ] 1*DIGIT
; boundOperation segments can only be composed if the type of the previous segment
; matches the type of the first parameter of the action or function being called.
; Note that the rule name reflects the return type of the function.
boundOperation = "/" ( boundActionCall
/ boundEntityColFunctionCall [ collectionNavigation ]
/ boundEntityFunctionCall [ singleNavigation ]
/ boundComplexColFunctionCall [ complexColPath ]
/ boundComplexFunctionCall [ complexPath ]
/ boundPrimitiveColFunctionCall [ collectionPath ]
/ boundPrimitiveFunctionCall [ primitivePath ]
/ boundFunctionCallNoParens [ querySegment ]
)
actionImportCall = actionImport
boundActionCall = [ namespace "." ] action
; with the added restriction that the binding parameter MUST be either an entity or collection of entities
; and is specified by reference using the URI immediately preceding (to the left) of the boundActionCall
; The following boundXxxFunctionCall rules have the added restrictions that
; - the function MUST support binding, and
; - the binding parameter type MUST match the type of resource identified by the
; URI immediately preceding (to the left) of the boundXxxFunctionCall, and
; - the functionParameters MUST NOT include the bindingParameter.
boundEntityFunctionCall = [ namespace "." ] entityFunction functionParameters
boundEntityColFunctionCall = [ namespace "." ] entityColFunction functionParameters
boundComplexFunctionCall = [ namespace "." ] complexFunction functionParameters
boundComplexColFunctionCall = [ namespace "." ] complexColFunction functionParameters
boundPrimitiveFunctionCall = [ namespace "." ] primitiveFunction functionParameters
boundPrimitiveColFunctionCall = [ namespace "." ] primitiveColFunction functionParameters
boundFunctionCallNoParens = [ namespace "." ] entityFunction
/ [ namespace "." ] entityColFunction
/ [ namespace "." ] complexFunction
/ [ namespace "." ] complexColFunction
/ [ namespace "." ] primitiveFunction
/ [ namespace "." ] primitiveColFunction
entityFunctionImportCall = entityFunctionImport functionParameters
entityColFunctionImportCall = entityColFunctionImport functionParameters
complexFunctionImportCall = complexFunctionImport functionParameters
complexColFunctionImportCall = complexColFunctionImport functionParameters
primitiveFunctionImportCall = primitiveFunctionImport functionParameters
primitiveColFunctionImportCall = primitiveColFunctionImport functionParameters
functionImportCallNoParens = entityFunctionImport
/ entityColFunctionImport
/ complexFunctionImport
/ complexColFunctionImport
/ primitiveFunctionImport
/ primitiveColFunctionImport
functionParameters = OPEN [ BWS functionParameter *( BWS COMMA BWS functionParameter ) ] BWS CLOSE
functionParameter = parameterName EQ ( parameterAlias / primitiveLiteral )
parameterName = odataIdentifier
parameterAlias = AT odataIdentifier
crossjoin = %s"$crossjoin" OPEN
entitySetName *( COMMA entitySetName )
CLOSE
;------------------------------------------------------------------------------
; 2. Query Options
;------------------------------------------------------------------------------
queryOptions = queryOption *( "&" queryOption )
queryOption = systemQueryOption
/ aliasAndValue
/ nameAndValue
/ customQueryOption
batchOptions = batchOption *( "&" batchOption )
batchOption = format
/ customQueryOption
metadataOptions = metadataOption *( "&" metadataOption )
metadataOption = format
/ customQueryOption
entityOptions = *( entityIdOption "&" ) id *( "&" entityIdOption )
entityIdOption = format
/ customQueryOption
entityCastOptions = *( entityCastOption "&" ) id *( "&" entityCastOption )
entityCastOption = entityIdOption
/ expand
/ select
id = ( "$id" / "id" ) EQ IRI-in-query
systemQueryOption = compute
/ deltatoken
/ expand
/ filter
/ format
/ id
/ inlinecount
/ orderby
/ schemaversion
/ search
/ select
/ skip
/ skiptoken
/ top
/ index
compute = ( "$compute" / "compute" ) EQ computeItem *( COMMA computeItem )
computeItem = commonExpr RWS "as" RWS computedProperty
computedProperty = odataIdentifier
expand = ( "$expand" / "expand" ) EQ expandItem *( COMMA expandItem )
expandItem = "$value"
/ expandPath
/ optionallyQualifiedEntityTypeName "/" expandPath
expandPath = ( STAR [ ref / OPEN levels CLOSE ]
/ ( navigationProperty / entityAnnotationInQuery ) [ "/" optionallyQualifiedEntityTypeName ]
[ ref [ OPEN expandRefOption *( SEMI expandRefOption ) CLOSE ]
/ count [ OPEN expandCountOption *( SEMI expandCountOption ) CLOSE ]
/ OPEN expandOption *( SEMI expandOption ) CLOSE
]
/ ( complexProperty / complexColProperty / optionallyQualifiedComplexTypeName / complexAnnotationInQuery ) "/" expandPath
/ streamProperty
)
expandCountOption = filter
/ search
expandRefOption = expandCountOption
/ orderby
/ skip
/ top
/ inlinecount
expandOption = expandRefOption
/ select
/ expand
/ compute
/ levels
/ aliasAndValue
levels = ( "$levels" / "levels" ) EQ ( oneToNine *DIGIT / "max" )
filter = ( "$filter" / "filter" ) EQ boolCommonExpr
orderby = ( "$orderby" / "orderby" ) EQ orderbyItem *( COMMA orderbyItem )
orderbyItem = commonExpr [ RWS ( "asc" / "desc" ) ]
skip = ( "$skip" / "skip" ) EQ 1*DIGIT
top = ( "$top" / "top" ) EQ 1*DIGIT
index = ( "$index" / "index" ) EQ [ "-" ] 1*DIGIT
format = ( "$format" / "format" ) EQ
( "atom"
/ "json"
/ "xml"
/ 1*pchar "/" 1*pchar ; <a data service specific value indicating a
) ; format specific to the specific data service> or
; <An IANA-defined [IANA-MMT] content type>
inlinecount = ( "$count" / "count" ) EQ boolean
schemaversion = ( "$schemaversion" / "schemaversion" ) EQ ( STAR / 1*unreserved )
search = ( "$search" / "search" ) EQ BWS ( searchExpr / searchExpr-incomplete )
searchExpr = ( searchParenExpr
/ searchNegateExpr
/ searchPhrase
/ searchWord
) [ searchOrExpr
/ searchAndExpr
]
searchParenExpr = OPEN BWS searchExpr BWS CLOSE
; NOT is a unary operator if followed by a search expression
searchNegateExpr = %s"NOT" RWS searchExpr
; AND and OR are binary operators if they appear between search expressions
searchOrExpr = RWS %s"OR" RWS searchExpr
searchAndExpr = RWS [ %s"AND" RWS ] searchExpr
searchPhrase = quotation-mark 1*( qchar-no-AMP-DQUOTE / SP ) quotation-mark
; A searchWord is a sequence of one or more non-whitespace characters, excluding
; - literal or percent-encoded parentheses "(", "%28", "%29", ")"
; - literal or percent-encoded double-quotes '"' and "%22"
; - the semicolon ";"
; Percent-encoding is allowed, and required for characters with special meaning in the query part of a URL, especially "&" and "#".
; Expressing this in ABNF is somewhat clumsy, so the following rule is overly generous.
; Note: the words AND, OR, and NOT are sometimes operators, depending on their position within a search expression.
searchWord = searchChar *( searchChar / SQUOTE )
searchChar = unreserved / pct-encoded-no-DQUOTE / "!" / "*" / "+" / "," / ":" / "@" / "/" / "?" / "$" / "="
searchExpr-incomplete = SQUOTE *( SQUOTE-in-string / qchar-no-AMP-SQUOTE / quotation-mark / SP ) SQUOTE
select = ( "$select" / "select" ) EQ selectItem *( COMMA selectItem )
selectItem = STAR
/ allOperationsInSchema
/ selectProperty
/ optionallyQualifiedActionName
/ optionallyQualifiedFunctionName
/ ( optionallyQualifiedEntityTypeName / optionallyQualifiedComplexTypeName )
"/" ( selectProperty
/ optionallyQualifiedActionName
/ optionallyQualifiedFunctionName
)
selectProperty = primitiveProperty / primitiveAnnotationInQuery
/ ( primitiveColProperty / primitiveColAnnotationInQuery ) [ OPEN selectOptionPC *( SEMI selectOptionPC ) CLOSE ]
/ navigationProperty
/ selectPath [ OPEN selectOption *( SEMI selectOption ) CLOSE
/ "/" selectProperty
]
selectPath = ( complexProperty / complexColProperty / complexAnnotationInQuery ) [ "/" optionallyQualifiedComplexTypeName ]
selectOptionPC = filter / search / inlinecount / orderby / skip / top
selectOption = selectOptionPC
/ compute / select / aliasAndValue
allOperationsInSchema = namespace "." STAR
; The parameterNames uniquely identify the bound function overload
; Necessary only if it has overloads
optionallyQualifiedActionName = [ namespace "." ] action
optionallyQualifiedFunctionName = [ namespace "." ] function [ OPEN parameterNames CLOSE ]
; The names of all non-binding parameters, separated by commas
parameterNames = parameterName *( COMMA parameterName )
deltatoken = "$deltatoken" EQ 1*( qchar-no-AMP )
skiptoken = "$skiptoken" EQ 1*( qchar-no-AMP )
aliasAndValue = parameterAlias EQ parameterValue
nameAndValue = parameterName EQ parameterValue
parameterValue = arrayOrObject
/ commonExpr
customQueryOption = customName [ EQ customValue ]
customName = qchar-no-AMP-EQ-AT-DOLLAR *( qchar-no-AMP-EQ )
customValue = *( qchar-no-AMP )
complexAnnotationInQuery = annotationInQuery ; complex-valued annotation
entityAnnotationInQuery = annotationInQuery ; entity-valued annotation
primitiveAnnotationInQuery = annotationInQuery ; primitive-valued annotation
primitiveColAnnotationInQuery = annotationInQuery ; primitive collection-valued annotation
;------------------------------------------------------------------------------
; 3. Context URL Fragments
;------------------------------------------------------------------------------
context = "#" contextFragment
contextFragment = %s"Collection($ref)"
/ %s"$ref"
/ %s"Collection(Edm.EntityType)"
/ %s"Collection(Edm.ComplexType)"
/ singletonEntity [ navigation *( containmentNavigation ) [ "/" qualifiedEntityTypeName ] ] [ selectList ]
/ qualifiedTypeName [ selectList ]
/ entitySet ( %s"/$deletedEntity" / %s"/$link" / %s"/$deletedLink" )
/ entitySet keyPredicate "/" contextPropertyPath [ selectList ]
/ entitySet [ selectList ] [ %s"/$entity" / %s"/$delta" ]
entitySet = entitySetName *( containmentNavigation ) [ "/" qualifiedEntityTypeName ]
containmentNavigation = keyPredicate [ "/" qualifiedEntityTypeName ] navigation
navigation = *( "/" complexProperty [ "/" qualifiedComplexTypeName ] ) "/" navigationProperty
selectList = OPEN [ selectListItem *( COMMA selectListItem ) ] CLOSE
selectListItem = STAR ; all structural properties
/ allOperationsInSchema
/ [ ( qualifiedEntityTypeName / qualifiedComplexTypeName ) "/" ]
( qualifiedActionName
/ qualifiedFunctionName
/ selectListProperty
)
selectListProperty = primitiveProperty
/ primitiveColProperty
/ ( navigationProperty / entityAnnotationInFragment ) [ "+" ] [ selectList ]
/ ( complexProperty / complexColProperty / complexAnnotationInFragment ) [ "/" qualifiedComplexTypeName ] [ "/" selectListProperty ]
contextPropertyPath = primitiveProperty
/ primitiveColProperty
/ complexColProperty
/ complexProperty [ [ "/" qualifiedComplexTypeName ] "/" contextPropertyPath ]
qualifiedActionName = namespace "." action
qualifiedFunctionName = namespace "." function [ OPEN parameterNames CLOSE ]
complexAnnotationInFragment = annotationInFragment ; complex-valued annotation
entityAnnotationInFragment = annotationInFragment ; entity-valued annotation
;------------------------------------------------------------------------------
; 4. Expressions
;------------------------------------------------------------------------------
; Note: a boolCommonExpr is also a commonExpr, e.g. sort by Boolean
commonExpr = ( primitiveLiteral
/ arrayOrObject
/ rootExpr
/ functionExpr
/ negateExpr
/ methodCallExpr
/ parenExpr
/ castExpr
/ isofExpr
/ notExpr
/ firstMemberExpr
)
[ addExpr
/ subExpr
/ mulExpr
/ divExpr
/ divbyExpr
/ modExpr
]
[ eqExpr
/ neExpr
/ ltExpr
/ leExpr
/ gtExpr
/ geExpr
/ hasExpr
/ inExpr
]
[ andExpr
/ orExpr
]
boolCommonExpr = commonExpr ; resulting in a Boolean
rootExpr = %s"$root/" ( entitySetName [ collectionNavigationExpr ]
/ singletonEntity [ singleNavigationExpr ]
/ entityColFunctionImport functionExprParameters [ collectionNavigationExpr ]
/ entityFunctionImport functionExprParameters [ singleNavigationExpr ]
/ complexColFunctionImport functionExprParameters [ complexColPathExpr ]
/ complexFunctionImport functionExprParameters [ complexPathExpr ]
/ primitiveColFunctionImport functionExprParameters [ collectionPathExpr ]
/ primitiveFunctionImport functionExprParameters [ primitivePathExpr ]
)
firstMemberExpr = memberExpr
/ inscopeVariableExpr [ "/" memberExpr ]
memberExpr = directMemberExpr
/ ( optionallyQualifiedEntityTypeName / optionallyQualifiedComplexTypeName ) "/" directMemberExpr
directMemberExpr = propertyPathExpr
/ boundFunctionExpr
/ annotationExpr
propertyPathExpr = ( entityColNavigationProperty [ collectionNavigationExpr ]
/ entityNavigationProperty [ singleNavigationExpr ]
/ complexColProperty [ complexColPathExpr ]
/ complexProperty [ complexPathExpr ]
/ primitiveColProperty [ collectionPathExpr ]
/ primitiveProperty [ primitivePathExpr ]
/ streamProperty [ primitivePathExpr ]
)
annotationExpr = annotationInQuery
[ collectionPathExpr
/ singleNavigationExpr
/ complexPathExpr
/ primitivePathExpr
]
annotationInQuery = AT [ namespace "." ] termName [ HASH annotationQualifier ]
annotationInFragment = AT [ namespace "." ] termName [ "#" annotationQualifier ]
annotationQualifier = odataIdentifier
inscopeVariableExpr = implicitVariableExpr
/ parameterAlias
/ lambdaVariableExpr ; only allowed inside a lambdaPredicateExpr
implicitVariableExpr = %s"$it" ; the current instance of the resource identified by the resource path
/ %s"$this" ; the instance on which the query option is evaluated
lambdaVariableExpr = odataIdentifier
collectionNavigationExpr = collectionNavNoCastExpr
/ "/" optionallyQualifiedEntityTypeName collectionNavNoCastExpr
collectionNavNoCastExpr = keyPredicate [ singleNavigationExpr ]
/ filterExpr [ collectionNavigationExpr ]
/ collectionPathExpr
singleNavigationExpr = "/" memberExpr
filterExpr = %s"/$filter" OPEN boolCommonExpr CLOSE
complexColPathExpr = collectionPathExpr
/ "/" optionallyQualifiedComplexTypeName [ collectionPathExpr ]
collectionPathExpr = count [ OPEN expandCountOption *( SEMI expandCountOption ) CLOSE ]
/ filterExpr [ collectionPathExpr ]
/ "/" anyExpr
/ "/" allExpr
/ "/" boundFunctionExpr
/ "/" annotationExpr
complexPathExpr = "/" directMemberExpr
/ "/" optionallyQualifiedComplexTypeName [ "/" directMemberExpr ]
primitivePathExpr = "/" [ annotationExpr / boundFunctionExpr ]
boundFunctionExpr = functionExpr ; boundFunction segments can only be composed if the type of the
; previous segment matches the type of the first function parameter
functionExpr = [ namespace "." ]
( entityColFunction functionExprParameters [ collectionNavigationExpr ]
/ entityFunction functionExprParameters [ singleNavigationExpr ]
/ complexColFunction functionExprParameters [ complexColPathExpr ]
/ complexFunction functionExprParameters [ complexPathExpr ]
/ primitiveColFunction functionExprParameters [ collectionPathExpr ]
/ primitiveFunction functionExprParameters [ primitivePathExpr ]
)
functionExprParameters = OPEN [ BWS functionExprParameter *( BWS COMMA BWS functionExprParameter ) ] BWS CLOSE
functionExprParameter = parameterName EQ ( parameterAlias / parameterValue )
anyExpr = "any" OPEN BWS [ lambdaVariableExpr BWS COLON BWS lambdaPredicateExpr ] BWS CLOSE
allExpr = "all" OPEN BWS lambdaVariableExpr BWS COLON BWS lambdaPredicateExpr BWS CLOSE
lambdaPredicateExpr = boolCommonExpr ; containing at least one lambdaVariableExpr
methodCallExpr = indexOfMethodCallExpr
/ toLowerMethodCallExpr
/ toUpperMethodCallExpr
/ trimMethodCallExpr
/ substringMethodCallExpr
/ concatMethodCallExpr
/ lengthMethodCallExpr
/ matchesPatternMethodCallExpr
/ yearMethodCallExpr
/ monthMethodCallExpr
/ dayMethodCallExpr
/ hourMethodCallExpr
/ minuteMethodCallExpr
/ secondMethodCallExpr
/ fractionalsecondsMethodCallExpr
/ totalsecondsMethodCallExpr
/ dateMethodCallExpr
/ timeMethodCallExpr
/ roundMethodCallExpr
/ floorMethodCallExpr
/ ceilingMethodCallExpr
/ distanceMethodCallExpr
/ geoLengthMethodCallExpr
/ totalOffsetMinutesMethodCallExpr
/ minDateTimeMethodCallExpr
/ maxDateTimeMethodCallExpr
/ nowMethodCallExpr
/ caseMethodCallExpr
/ boolMethodCallExpr
boolMethodCallExpr = endsWithMethodCallExpr
/ startsWithMethodCallExpr
/ containsMethodCallExpr
/ intersectsMethodCallExpr
/ hasSubsetMethodCallExpr
/ hasSubsequenceMethodCallExpr
concatMethodCallExpr = "concat" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
containsMethodCallExpr = "contains" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
endsWithMethodCallExpr = "endswith" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
indexOfMethodCallExpr = "indexof" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
lengthMethodCallExpr = "length" OPEN BWS commonExpr BWS CLOSE
matchesPatternMethodCallExpr = "matchesPattern" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
startsWithMethodCallExpr = "startswith" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
substringMethodCallExpr = "substring" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS [ COMMA BWS commonExpr BWS ] CLOSE
toLowerMethodCallExpr = "tolower" OPEN BWS commonExpr BWS CLOSE
toUpperMethodCallExpr = "toupper" OPEN BWS commonExpr BWS CLOSE
trimMethodCallExpr = "trim" OPEN BWS commonExpr BWS CLOSE
yearMethodCallExpr = "year" OPEN BWS commonExpr BWS CLOSE
monthMethodCallExpr = "month" OPEN BWS commonExpr BWS CLOSE
dayMethodCallExpr = "day" OPEN BWS commonExpr BWS CLOSE
hourMethodCallExpr = "hour" OPEN BWS commonExpr BWS CLOSE
minuteMethodCallExpr = "minute" OPEN BWS commonExpr BWS CLOSE
secondMethodCallExpr = "second" OPEN BWS commonExpr BWS CLOSE
fractionalsecondsMethodCallExpr = "fractionalseconds" OPEN BWS commonExpr BWS CLOSE
totalsecondsMethodCallExpr = "totalseconds" OPEN BWS commonExpr BWS CLOSE
dateMethodCallExpr = "date" OPEN BWS commonExpr BWS CLOSE
timeMethodCallExpr = "time" OPEN BWS commonExpr BWS CLOSE
totalOffsetMinutesMethodCallExpr = "totaloffsetminutes" OPEN BWS commonExpr BWS CLOSE
minDateTimeMethodCallExpr = "mindatetime" OPEN BWS CLOSE
maxDateTimeMethodCallExpr = "maxdatetime" OPEN BWS CLOSE
nowMethodCallExpr = "now" OPEN BWS CLOSE
roundMethodCallExpr = "round" OPEN BWS commonExpr BWS CLOSE
floorMethodCallExpr = "floor" OPEN BWS commonExpr BWS CLOSE
ceilingMethodCallExpr = "ceiling" OPEN BWS commonExpr BWS CLOSE
distanceMethodCallExpr = "geo.distance" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
geoLengthMethodCallExpr = "geo.length" OPEN BWS commonExpr BWS CLOSE
intersectsMethodCallExpr = "geo.intersects" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
hasSubsetMethodCallExpr = "hassubset" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
hasSubsequenceMethodCallExpr = "hassubsequence" OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
caseMethodCallExpr = "case" OPEN BWS boolCommonExpr BWS COLON BWS commonExpr BWS
*( COMMA BWS boolCommonExpr BWS COLON BWS commonExpr BWS ) CLOSE
parenExpr = OPEN BWS commonExpr BWS CLOSE
listExpr = OPEN BWS [ primitiveLiteral BWS *( COMMA BWS primitiveLiteral BWS ) ] CLOSE
andExpr = RWS "and" RWS boolCommonExpr
orExpr = RWS "or" RWS boolCommonExpr
eqExpr = RWS "eq" RWS commonExpr
neExpr = RWS "ne" RWS commonExpr
ltExpr = RWS "lt" RWS commonExpr
leExpr = RWS "le" RWS commonExpr
gtExpr = RWS "gt" RWS commonExpr
geExpr = RWS "ge" RWS commonExpr
inExpr = RWS "in" RWS ( listExpr / commonExpr )
hasExpr = RWS "has" RWS enumLiteral
addExpr = RWS "add" RWS commonExpr
subExpr = RWS "sub" RWS commonExpr
mulExpr = RWS "mul" RWS commonExpr
divExpr = RWS "div" RWS commonExpr
divbyExpr = RWS "divby" RWS commonExpr
modExpr = RWS "mod" RWS commonExpr
negateExpr = "-" BWS commonExpr
notExpr = "not" RWS boolCommonExpr
isofExpr = "isof" OPEN BWS [ commonExpr BWS COMMA BWS ] optionallyQualifiedTypeName BWS CLOSE
castExpr = "cast" OPEN BWS [ commonExpr BWS COMMA BWS ] optionallyQualifiedTypeName BWS CLOSE
;------------------------------------------------------------------------------
; 5. JSON format for queries
;------------------------------------------------------------------------------
; Note: the query part of a URI needs to be percent-encoding normalized before
; applying these rules, see comment at the top of this file
;------------------------------------------------------------------------------
arrayOrObject = array
/ object
array = begin-array
[ valueInUrl *( value-separator valueInUrl ) ]
end-array
object = begin-object
[ member *( value-separator member ) ]
end-object
member = stringInUrl name-separator valueInUrl
valueInUrl = stringInUrl
/ commonExpr
; JSON syntax: adapted to URI restrictions from [RFC8259]
begin-object = BWS ( "{" / "%7B" ) BWS
end-object = BWS ( "}" / "%7D" )
begin-array = BWS ( "[" / "%5B" ) BWS
end-array = BWS ( "]" / "%5D" )
quotation-mark = DQUOTE / "%22"
name-separator = BWS COLON BWS
value-separator = BWS COMMA BWS
stringInUrl = quotation-mark *charInJSON quotation-mark
charInJSON = qchar-unescaped
/ qchar-JSON-special
/ escape ( quotation-mark
/ escape
/ ( "/" / "%2F" ) ; solidus U+002F - literal form is allowed in the query part of a URL
/ %s"b" ; backspace U+0008
/ %s"f" ; form feed U+000C
/ %s"n" ; line feed U+000A
/ %s"r" ; carriage return U+000D
/ %s"t" ; tab U+0009
/ %s"u" 4HEXDIG ; U+XXXX
)
qchar-JSON-special = SP / ":" / "{" / "}" / "[" / "]" ; some agents put these unencoded into the query part of a URL
escape = "\" / "%5C" ; reverse solidus U+005C
;------------------------------------------------------------------------------
; 6. Names and identifiers
;------------------------------------------------------------------------------
qualifiedTypeName = singleQualifiedTypeName
/ %s"Collection" OPEN singleQualifiedTypeName CLOSE
optionallyQualifiedTypeName = singleQualifiedTypeName
/ %s"Collection" OPEN singleQualifiedTypeName CLOSE
/ singleTypeName
/ %s"Collection" OPEN singleTypeName CLOSE
singleQualifiedTypeName = qualifiedEntityTypeName
/ qualifiedComplexTypeName
/ qualifiedTypeDefinitionName
/ qualifiedEnumTypeName
/ primitiveTypeName
singleTypeName = entityTypeName
/ complexTypeName
/ typeDefinitionName
/ enumerationTypeName
qualifiedEntityTypeName = namespace "." entityTypeName
qualifiedComplexTypeName = namespace "." complexTypeName
qualifiedTypeDefinitionName = namespace "." typeDefinitionName
qualifiedEnumTypeName = namespace "." enumerationTypeName
optionallyQualifiedEntityTypeName = [ namespace "." ] entityTypeName
optionallyQualifiedComplexTypeName = [ namespace "." ] complexTypeName
; an alias is just a single-part namespace
namespace = namespacePart *( "." namespacePart )
namespacePart = odataIdentifier
entitySetName = odataIdentifier
singletonEntity = odataIdentifier
entityTypeName = odataIdentifier
complexTypeName = odataIdentifier
typeDefinitionName = odataIdentifier
enumerationTypeName = odataIdentifier
enumerationMember = odataIdentifier
termName = odataIdentifier
odataIdentifier = identifierLeadingCharacter *127identifierCharacter
; Note: the two following rules are overly restrictive, see comments for the full set of allowed characters
identifierLeadingCharacter = ALPHA / "_" ; plus percent-encoded Unicode characters from the categories L or Nl
identifierCharacter = ALPHA / "_" / DIGIT ; plus percent-encoded Unicode characters from the categories L, Nl, Nd, Mn, Mc, Pc, or Cf
primitiveTypeName = %s"Edm." ( %s"Binary"
/ %s"Boolean"
/ %s"Byte"
/ %s"Date"
/ %s"DateTimeOffset"
/ %s"Decimal"
/ %s"Double"
/ %s"Duration"
/ %s"Guid"
/ %s"Int16"
/ %s"Int32"
/ %s"Int64"
/ %s"SByte"
/ %s"Single"
/ %s"Stream"
/ %s"String"
/ %s"TimeOfDay"
/ abstractSpatialTypeName [ concreteSpatialTypeName ]
)
abstractSpatialTypeName = %s"Geography"
/ %s"Geometry"
concreteSpatialTypeName = %s"Collection"
/ %s"LineString"
/ %s"MultiLineString"
/ %s"MultiPoint"
/ %s"MultiPolygon"
/ %s"Point"
/ %s"Polygon"
primitiveProperty = primitiveKeyProperty / primitiveNonKeyProperty
primitiveKeyProperty = odataIdentifier
primitiveNonKeyProperty = odataIdentifier
primitiveColProperty = odataIdentifier
complexProperty = odataIdentifier
complexColProperty = odataIdentifier
streamProperty = odataIdentifier
navigationProperty = entityNavigationProperty / entityColNavigationProperty
entityNavigationProperty = odataIdentifier
entityColNavigationProperty = odataIdentifier
action = odataIdentifier
actionImport = odataIdentifier
function = entityFunction
/ entityColFunction
/ complexFunction
/ complexColFunction
/ primitiveFunction
/ primitiveColFunction
entityFunction = odataIdentifier
entityColFunction = odataIdentifier
complexFunction = odataIdentifier
complexColFunction = odataIdentifier
primitiveFunction = odataIdentifier
primitiveColFunction = odataIdentifier
entityFunctionImport = odataIdentifier
entityColFunctionImport = odataIdentifier
complexFunctionImport = odataIdentifier
complexColFunctionImport = odataIdentifier
primitiveFunctionImport = odataIdentifier
primitiveColFunctionImport = odataIdentifier
;------------------------------------------------------------------------------
; 7. Literal Data Values
;------------------------------------------------------------------------------
; in URLs
primitiveLiteral = null
/ boolean
/ guid
/ dateTimeOffsetLiteral
/ date
/ timeOfDayLiteral
/ decimalLiteral
/ doubleLiteral
/ singleLiteral
/ sbyteLiteral
/ byte
/ int16Literal
/ int32Literal
/ int64Literal
/ stringLiteral
/ durationLiteral
/ enumLiteral
/ binaryLiteral
/ geographyCollection
/ geographyLineString
/ geographyMultiLineString
/ geographyMultiPoint
/ geographyMultiPolygon
/ geographyPoint
/ geographyPolygon
/ geometryCollection
/ geometryLineString
/ geometryMultiLineString
/ geometryMultiPoint
/ geometryMultiPolygon
/ geometryPoint
/ geometryPolygon
; in CSDL XML DefaultValue attributes
primitiveValue = booleanValue
/ guidValue
/ durationValue
/ dateTimeOffsetValue
/ dateValue
/ timeOfDayValue
/ enumValue
/ fullCollectionLiteral
/ fullLineStringLiteral
/ fullMultiPointLiteral
/ fullMultiLineStringLiteral
/ fullMultiPolygonLiteral
/ fullPointLiteral
/ fullPolygonLiteral
/ decimalValue
/ doubleValue
/ singleValue
/ sbyteValue
/ byteValue
/ int16Value
/ int32Value
/ int64Value
/ binaryValue
null = %s"null"
; base64url encoding according to http://tools.ietf.org/html/rfc4648#section-5
binaryLiteral = "binary" SQUOTE binaryValue SQUOTE
binaryValue = *(4base64char) [ base64b16 / base64b8 ]
base64b16 = 2base64char ( %s"A" / %s"E" / %s"I" / %s"M" / %s"Q" / %s"U" / %s"Y" / %s"c" / %s"g" / %s"k" / %s"o" / %s"s" / %s"w" / %s"0" / %s"4" / %s"8" ) [ "=" ]
base64b8 = base64char ( %s"A" / %s"Q" / %s"g" / %s"w" ) [ "==" ]
base64char = ALPHA / DIGIT / "-" / "_"
boolean = "true" / "false"
booleanValue = %s"true" / %s"false"
decimalLiteral = [ SIGN ] 1*DIGIT [ "." 1*DIGIT ] [ "e" [ SIGN ] 1*DIGIT ] / nanInfinity
decimalValue = ["+"/"-"] 1*DIGIT [ "." 1*DIGIT ] [ "e" ["+"/"-"] 1*DIGIT ] / nanInfinity
doubleLiteral = decimalLiteral ; IEEE 754 binary64 floating-point number (15-17 decimal digits)
doubleValue = decimalValue ; IEEE 754 binary64 floating-point number (15-17 decimal digits)
singleLiteral = decimalLiteral ; IEEE 754 binary32 floating-point number (6-9 decimal digits)
singleValue = decimalValue ; IEEE 754 binary32 floating-point number (6-9 decimal digits)
nanInfinity = %s"NaN" / %s"-INF" / %s"INF"
guid = 8HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 12HEXDIG
guidValue = guid
byte = 1*3DIGIT ; numbers in the range from 0 to 255
byteValue = byte
sbyteLiteral = [ SIGN ] 1*3DIGIT ; numbers in the range from -128 to 127
sbyteValue = ["+"/"-"] 1*3DIGIT ; numbers in the range from -128 to 127
int16Literal = [ SIGN ] 1*5DIGIT ; numbers in the range from -32768 to 32767
int16Value = ["+"/"-"] 1*5DIGIT ; numbers in the range from -32768 to 32767
int32Literal = [ SIGN ] 1*10DIGIT ; numbers in the range from -2147483648 to 2147483647
int32Value = ["+"/"-"] 1*10DIGIT ; numbers in the range from -2147483648 to 2147483647
int64Literal = [ SIGN ] 1*19DIGIT ; numbers in the range from -9223372036854775808 to 9223372036854775807
int64Value = ["+"/"-"] 1*19DIGIT ; numbers in the range from -9223372036854775808 to 9223372036854775807
stringLiteral = SQUOTE *( SQUOTE-in-string / pchar-no-SQUOTE ) SQUOTE
SQUOTE-in-string = SQUOTE SQUOTE ; two consecutive single quotes represent one within a string literal
date = year "-" month "-" day
dateValue = date
dateTimeOffsetLiteral = date "T" timeOfDayLiteral ( "Z" / SIGN hour COLON minute )
dateTimeOffsetValueInUrl = dateTimeOffsetLiteral ; legacy name referenced in Temporal spec
dateTimeOffsetValue = date "T" timeOfDayValue ( "Z" / ("+"/"-") hour ":" minute )
durationLiteral = [ "duration" ] SQUOTE durationValue SQUOTE
durationValue = [ "-" ] "P" [ 1*DIGIT "D" ] [ "T" [ 1*DIGIT "H" ] [ 1*DIGIT "M" ] [ 1*DIGIT [ "." 1*DIGIT ] "S" ] ]
; the above is an approximation of the rules for an xml dayTimeDuration.
; see the lexical representation for dayTimeDuration in http://www.w3.org/TR/xmlschema11-2#dayTimeDuration for more information
timeOfDayLiteral = hour COLON minute [ COLON second [ "." fractionalSeconds ] ]
timeOfDayValue = hour ":" minute [ ":" second [ "." fractionalSeconds ] ]