forked from jaystack/odata-v4-parser
-
Notifications
You must be signed in to change notification settings - Fork 4
/
odata-v4.abnf
1177 lines (992 loc) · 48.9 KB
/
odata-v4.abnf
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
;------------------------------------------------------------------------------
;
; OData Version 4.0 Plus Errata 02
; OASIS Standard incorporating Approved Errata 02
; 30 October 2014
; Copyright (c) OASIS Open 2014. All Rights Reserved.
; Source: http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/abnf/
;
;
; Technical Committee:
; OASIS Open Data Protocol (OData) TC
; https://www.oasis-open.org/committees/odata
;
; Chairs:
; - Barbara Hartel (barbara.hartel@sap.com), SAP AG
; - Ram Jeyaraman (Ram.Jeyaraman@microsoft.com), Microsoft
;
; Editors:
; - Ralf Handl (ralf.handl@sap.com), SAP AG
; - Michael Pizzo (mikep@microsoft.com), Microsoft
; - Martin Zurmuehl (martin.zurmuehl@sap.com), SAP AG
;
; Additional artifacts:
; This grammar is one component of a Work Product which consists of:
; - OData Version 4.0 Part 1: Protocol
; - OData Version 4.0 Part 2: URL Conventions
; - OData Version 4.0 Part 3: Common Schema Definition Language (CSDL)
; - OData ABNF Construction Rules Version 4.0 (this document)
; - OData ABNF Test Cases
; - OData Core Vocabulary
; - OData Capabilities Vocabulary
; - OData Measures Vocabulary
; - OData Metadata Service Entity Model
; - OData EDMX XML Schema
; - OData EDM XML Schema
;
; Related work:
; This work product is related to the following two Work Products, each of
; which define alternate formats for OData payloads
; - OData Atom Format Version 4.0
; - OData JSON Format Version 4.0
; This specification replaces or supersedes:
; - None
;
; Declared XML namespaces:
; - http://docs.oasis-open.org/odata/ns/edmx
; - http://docs.oasis-open.org/odata/ns/edm
;
; 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 with one extension: literals
; enclosed in single quotes (e.g. '$metadata') are treated case-sensitive.
;
; 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]
;
;------------------------------------------------------------------------------
dummyStartRule = odataUri / header / primitiveValue ; just to please the test parser
;------------------------------------------------------------------------------
odataUri = serviceRoot [ odataRelativeUri ]
serviceRoot = ( "https" / "http" ) ; Note: case-insensitive
"://" host [ ":" port ]
"/" *( segment-nz "/" )
odataRelativeUri = '$batch' ; Note: case-sensitive!
/ '$entity' "?" entityOptions
/ '$entity' "/" qualifiedEntityTypeName "?" entityCastOptions
/ '$metadata' [ "?" format ] [ context ]
/ resourcePath [ "?" queryOptions ]
;------------------------------------------------------------------------------
; 1. Resource Path
;------------------------------------------------------------------------------
resourcePath = entitySetName [ collectionNavigation ]
/ singletonEntity [ singleNavigation ]
/ actionImportCall
/ entityColFunctionImportCall [ collectionNavigation ]
/ entityFunctionImportCall [ singleNavigation ]
/ complexColFunctionImportCall [ collectionPath ]
/ complexFunctionImportCall [ complexPath ]
/ primitiveColFunctionImportCall [ collectionPath ]
/ primitiveFunctionImportCall [ singlePath ]
/ crossjoin
/ '$all'
collectionNavigation = [ "/" qualifiedEntityTypeName ] [ collectionNavPath ]
collectionNavPath = keyPredicate [ singleNavigation ]
/ collectionPath
/ ref
keyPredicate = simpleKey / compoundKey
simpleKey = OPEN keyPropertyValue CLOSE
compoundKey = OPEN keyValuePair *( COMMA keyValuePair ) CLOSE
keyValuePair = ( primitiveKeyProperty / keyPropertyAlias ) EQ keyPropertyValue
keyPropertyValue = primitiveLiteral
keyPropertyAlias = odataIdentifier
singleNavigation = [ "/" qualifiedEntityTypeName ]
[ "/" propertyPath
/ boundOperation
/ ref
/ value ; request the media resource of a media entity
]
propertyPath = entityColNavigationProperty [ collectionNavigation ]
/ entityNavigationProperty [ singleNavigation ]
/ complexColProperty [ collectionPath ]
/ complexProperty [ complexPath ]
/ primitiveColProperty [ collectionPath ]
/ primitiveProperty [ singlePath ]
/ streamProperty [ boundOperation ]
collectionPath = count / boundOperation
singlePath = value / boundOperation
complexPath = [ "/" qualifiedComplexTypeName ]
( "/" propertyPath
/ boundOperation
)
count = '/$count'
ref = '/$ref'
value = '/$value'
; 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
/ boundEntityColFuncCall [ collectionNavigation ]
/ boundEntityFuncCall [ singleNavigation ]
/ boundComplexColFuncCall [ "/" qualifiedComplexTypeName ] [ collectionPath ]
/ boundComplexFuncCall [ complexPath ]
/ boundPrimitiveColFuncCall [ collectionPath ]
/ boundPrimitiveFuncCall [ singlePath ]
)
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 boundXxxFuncCall 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 boundXxxFuncCall, and
; - the functionParameters MUST NOT include the bindingParameter.
boundEntityFuncCall = namespace "." entityFunction functionParameters
boundEntityColFuncCall = namespace "." entityColFunction functionParameters
boundComplexFuncCall = namespace "." complexFunction functionParameters
boundComplexColFuncCall = namespace "." complexColFunction functionParameters
boundPrimitiveFuncCall = namespace "." primitiveFunction functionParameters
boundPrimitiveColFuncCall = namespace "." primitiveColFunction functionParameters
entityFunctionImportCall = entityFunctionImport functionParameters
entityColFunctionImportCall = entityColFunctionImport functionParameters
complexFunctionImportCall = complexFunctionImport functionParameters
complexColFunctionImportCall = complexColFunctionImport functionParameters
primitiveFunctionImportCall = primitiveFunctionImport functionParameters
primitiveColFunctionImportCall = primitiveColFunctionImport functionParameters
functionParameters = OPEN [ functionParameter *( COMMA functionParameter ) ] CLOSE
functionParameter = parameterName EQ ( parameterAlias / primitiveLiteral )
parameterName = odataIdentifier
parameterAlias = AT odataIdentifier
crossjoin = '$crossjoin' OPEN
entitySetName *( COMMA entitySetName )
CLOSE
;------------------------------------------------------------------------------
; 2. Query Options
;------------------------------------------------------------------------------
queryOptions = queryOption *( "&" queryOption )
queryOption = systemQueryOption
/ aliasAndValue
/ customQueryOption
entityOptions = *( entityIdOption "&" ) id *( "&" entityIdOption )
entityIdOption = format
/ customQueryOption
entityCastOptions = *( entityCastOption "&" ) id *( "&" entityCastOption )
entityCastOption = entityIdOption
/ expand
/ select
id = '$id' EQ IRI-in-query
systemQueryOption = expand
/ filter
/ format
/ id
/ inlinecount
/ orderby
/ search
/ select
/ skip
/ skiptoken
/ top
expand = '$expand' EQ expandItem *( COMMA expandItem )
expandItem = STAR [ ref / OPEN levels CLOSE ]
/ expandPath
[ ref [ OPEN expandRefOption *( SEMI expandRefOption ) CLOSE ]
/ count [ OPEN expandCountOption *( SEMI expandCountOption ) CLOSE ]
/ OPEN expandOption *( SEMI expandOption ) CLOSE
]
expandPath = [ ( qualifiedEntityTypeName / qualifiedComplexTypeName ) "/" ]
*( ( complexProperty / complexColProperty ) "/" [ qualifiedComplexTypeName "/" ] )
navigationProperty
[ "/" qualifiedEntityTypeName ]
expandCountOption = filter
/ search
expandRefOption = expandCountOption
/ orderby
/ skip
/ top
/ inlinecount
expandOption = expandRefOption
/ select
/ expand
/ levels
levels = '$levels' EQ ( oneToNine *DIGIT / 'max' )
filter = '$filter' EQ boolCommonExpr
orderby = '$orderby' EQ orderbyItem *( COMMA orderbyItem )
orderbyItem = commonExpr [ RWS ( 'asc' / 'desc' ) ]
skip = '$skip' EQ 1*DIGIT
top = '$top' EQ 1*DIGIT
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' EQ booleanValue
search = '$search' EQ BWS searchExpr
searchExpr = ( OPEN BWS searchExpr BWS CLOSE
/ searchTerm
) [ searchOrExpr
/ searchAndExpr
]
searchOrExpr = RWS 'OR' RWS searchExpr
searchAndExpr = RWS [ 'AND' RWS ] searchExpr
searchTerm = [ 'NOT' RWS ] ( searchPhrase / searchWord )
searchPhrase = quotation-mark 1*qchar-no-AMP-DQUOTE quotation-mark
searchWord = 1*ALPHA ; Actually: any character from the Unicode categories L or Nl,
; but not the words AND, OR, and NOT
select = '$select' EQ selectItem *( COMMA selectItem )
selectItem = STAR
/ allOperationsInSchema
/ [ ( qualifiedEntityTypeName / qualifiedComplexTypeName ) "/" ]
( selectProperty
/ qualifiedActionName
/ qualifiedFunctionName
)
selectProperty = primitiveProperty
/ primitiveColProperty
/ navigationProperty
/ selectPath [ "/" selectProperty ]
selectPath = ( complexProperty / complexColProperty ) [ "/" qualifiedComplexTypeName ]
allOperationsInSchema = namespace "." STAR
; The parameterNames uniquely identify the bound function overload
; only if it has overloads.
qualifiedActionName = namespace "." action
qualifiedFunctionName = namespace "." function [ OPEN parameterNames CLOSE ]
; The names of all non-binding parameters, separated by commas
parameterNames = parameterName *( COMMA parameterName )
skiptoken = '$skiptoken' EQ 1*( qchar-no-AMP )
aliasAndValue = parameterAlias EQ parameterValue
parameterValue = arrayOrObject
/ commonExpr
customQueryOption = customName [ EQ customValue ]
customName = qchar-no-AMP-EQ-AT-DOLLAR *( qchar-no-AMP-EQ )
customValue = *( qchar-no-AMP )
;------------------------------------------------------------------------------
; 3. Context URL Fragments
;------------------------------------------------------------------------------
context = "#" contextFragment
contextFragment = 'Collection($ref)'
/ '$ref'
/ 'Collection(Edm.EntityType)'
/ 'Collection(Edm.ComplexType)'
/ singletonEntity [ navigation *( containmentNavigation ) [ "/" qualifiedEntityTypeName ] ] [ selectList ]
/ qualifiedTypeName [ selectList ]
/ entitySet ( '/$deletedEntity' / '/$link' / '/$deletedLink' )
/ entitySet keyPredicate "/" contextPropertyPath [ selectList ]
/ entitySet [ selectList ] [ '/$entity' / '/$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 "/" ]
( qualifiedActionName
/ qualifiedFunctionName
/ selectListProperty
)
selectListProperty = primitiveProperty
/ primitiveColProperty
/ navigationProperty [ '+' ] [ selectList ]
/ selectPath [ "/" selectListProperty ]
contextPropertyPath = primitiveProperty
/ primitiveColProperty
/ complexColProperty
/ complexProperty [ [ "/" qualifiedComplexTypeName ] "/" contextPropertyPath ]
;------------------------------------------------------------------------------
; 4. Expressions
;------------------------------------------------------------------------------
; Note: a boolCommonExpr is also a commonExpr, e.g. sort by Boolean
commonExpr = ( primitiveLiteral
/ parameterAlias
/ arrayOrObject
/ rootExpr
/ firstMemberExpr
/ functionExpr
/ negateExpr
/ methodCallExpr
/ parenExpr
/ castExpr
)
[ addExpr
/ subExpr
/ mulExpr
/ divExpr
/ modExpr
]
boolCommonExpr = ( isofExpr
/ boolMethodCallExpr
/ notExpr
/ commonExpr
[ eqExpr
/ neExpr
/ ltExpr
/ leExpr
/ gtExpr
/ geExpr
/ hasExpr
]
/ boolParenExpr
) [ andExpr / orExpr ]
rootExpr = '$root/' ( entitySetName keyPredicate / singletonEntity ) [ singleNavigationExpr ]
firstMemberExpr = memberExpr
/ inscopeVariableExpr [ "/" memberExpr ]
memberExpr = [ qualifiedEntityTypeName "/" ]
( propertyPathExpr
/ boundFunctionExpr
)
propertyPathExpr = ( entityColNavigationProperty [ collectionNavigationExpr ]
/ entityNavigationProperty [ singleNavigationExpr ]
/ complexColProperty [ collectionPathExpr ]
/ complexProperty [ complexPathExpr ]
/ primitiveColProperty [ collectionPathExpr ]
/ primitiveProperty [ singlePathExpr ]
/ streamProperty [ singlePathExpr ]
)
inscopeVariableExpr = implicitVariableExpr
/ lambdaVariableExpr ; only allowed inside a lambdaPredicateExpr
implicitVariableExpr = '$it' ; references the unnamed outer variable of the query
lambdaVariableExpr = odataIdentifier
collectionNavigationExpr = [ "/" qualifiedEntityTypeName ]
( keyPredicate [ singleNavigationExpr ]
/ collectionPathExpr
)
singleNavigationExpr = "/" memberExpr
collectionPathExpr = count
/ "/" boundFunctionExpr
/ "/" anyExpr
/ "/" allExpr
complexPathExpr = "/" [ qualifiedComplexTypeName "/" ]
( propertyPathExpr
/ boundFunctionExpr
)
singlePathExpr = "/" 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 [ collectionPathExpr ]
/ complexFunction functionExprParameters [ complexPathExpr ]
/ primitiveColFunction functionExprParameters [ collectionPathExpr ]
/ primitiveFunction functionExprParameters [ singlePathExpr ]
)
functionExprParameters = OPEN [ functionExprParameter *( COMMA functionExprParameter ) ] 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
/ yearMethodCallExpr
/ monthMethodCallExpr
/ dayMethodCallExpr
/ hourMethodCallExpr
/ minuteMethodCallExpr
/ secondMethodCallExpr
/ fractionalsecondsMethodCallExpr
/ totalsecondsMethodCallExpr
/ dateMethodCallExpr
/ timeMethodCallExpr
/ roundMethodCallExpr
/ floorMethodCallExpr
/ ceilingMethodCallExpr
/ distanceMethodCallExpr
/ geoLengthMethodCallExpr
/ totalOffsetMinutesMethodCallExpr
/ minDateTimeMethodCallExpr
/ maxDateTimeMethodCallExpr
/ nowMethodCallExpr
boolMethodCallExpr = endsWithMethodCallExpr
/ startsWithMethodCallExpr
/ containsMethodCallExpr
/ intersectsMethodCallExpr
containsMethodCallExpr = 'contains' OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
startsWithMethodCallExpr = 'startswith' OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
endsWithMethodCallExpr = 'endswith' OPEN BWS commonExpr BWS COMMA BWS commonExpr BWS CLOSE
lengthMethodCallExpr = 'length' OPEN BWS commonExpr BWS CLOSE
indexOfMethodCallExpr = 'indexof' 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
concatMethodCallExpr = 'concat' OPEN BWS commonExpr BWS COMMA 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(' BWS ')'
maxDateTimeMethodCallExpr = 'maxdatetime(' BWS ')'
nowMethodCallExpr = 'now(' BWS ')'
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
boolParenExpr = OPEN BWS boolCommonExpr BWS CLOSE
parenExpr = OPEN BWS commonExpr 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
hasExpr = RWS 'has' RWS enum
addExpr = RWS 'add' RWS commonExpr
subExpr = RWS 'sub' RWS commonExpr
mulExpr = RWS 'mul' RWS commonExpr
divExpr = RWS 'div' RWS commonExpr
modExpr = RWS 'mod' RWS commonExpr
negateExpr = "-" BWS commonExpr
notExpr = 'not' RWS boolCommonExpr
isofExpr = 'isof' OPEN BWS [ commonExpr BWS COMMA BWS ] qualifiedTypeName BWS CLOSE
castExpr = 'cast' OPEN BWS [ commonExpr BWS COMMA BWS ] qualifiedTypeName BWS CLOSE
;------------------------------------------------------------------------------
; 5. JSON format for function parameters
;------------------------------------------------------------------------------
; Note: the query part of a URI needs to be partially percent-decoded before
; applying these rules, see comment at the top of this file
;------------------------------------------------------------------------------
arrayOrObject = complexColInUri
/ complexInUri
/ rootExprCol
/ primitiveColInUri
complexColInUri = begin-array
[ complexInUri *( value-separator complexInUri ) ]
end-array
complexInUri = begin-object
[ ( annotationInUri
/ primitivePropertyInUri
/ complexPropertyInUri
/ collectionPropertyInUri
/ navigationPropertyInUri
)
*( value-separator
( annotationInUri
/ primitivePropertyInUri
/ complexPropertyInUri
/ collectionPropertyInUri
/ navigationPropertyInUri
)
)
]
end-object
collectionPropertyInUri = ( quotation-mark primitiveColProperty quotation-mark
name-separator
primitiveColInUri
)
/ ( quotation-mark complexColProperty quotation-mark
name-separator
complexColInUri
)
primitiveColInUri = begin-array
[ primitiveLiteralInJSON *( value-separator primitiveLiteralInJSON ) ]
end-array
complexPropertyInUri = quotation-mark complexProperty quotation-mark
name-separator
complexInUri
annotationInUri = quotation-mark AT namespace "." termName quotation-mark
name-separator
( complexInUri / complexColInUri / primitiveLiteralInJSON / primitiveColInUri )
primitivePropertyInUri = quotation-mark primitiveProperty quotation-mark
name-separator
primitiveLiteralInJSON
navigationPropertyInUri = singleNavPropInJSON
/ collectionNavPropInJSON
singleNavPropInJSON = quotation-mark entityNavigationProperty quotation-mark
name-separator
rootExpr
collectionNavPropInJSON = quotation-mark entityColNavigationProperty quotation-mark
name-separator
rootExprCol
rootExprCol = begin-array
[ rootExpr *( value-separator rootExpr ) ]
end-array
; JSON syntax: adapted to URI restrictions from [RFC4627]
begin-object = BWS ( "{" / "%7B" ) BWS
end-object = BWS ( "}" / "%7D" ) BWS
begin-array = BWS ( "[" / "%5B" ) BWS
end-array = BWS ( "]" / "%5D" ) BWS
quotation-mark = DQUOTE / "%22"
name-separator = BWS COLON BWS
value-separator = BWS COMMA BWS
primitiveLiteralInJSON = stringInJSON
/ numberInJSON
/ 'true'
/ 'false'
/ 'null'
stringInJSON = 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
/ 'b' ; backspace U+0008
/ 'f' ; form feed U+000C
/ 'n' ; line feed U+000A
/ 'r' ; carriage return U+000D
/ 't' ; tab U+0009
/ '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
numberInJSON = [ "-" ] int [ frac ] [ exp ]
int = "0" / ( oneToNine *DIGIT )
frac = "." 1*DIGIT
exp = "e" [ "-" / "+" ] 1*DIGIT
;------------------------------------------------------------------------------
; 6. Names and identifiers
;------------------------------------------------------------------------------
singleQualifiedTypeName = qualifiedEntityTypeName
/ qualifiedComplexTypeName
/ qualifiedTypeDefinitionName
/ qualifiedEnumTypeName
/ primitiveTypeName
qualifiedTypeName = singleQualifiedTypeName
/ 'Collection' OPEN singleQualifiedTypeName CLOSE
qualifiedEntityTypeName = namespace "." entityTypeName
qualifiedComplexTypeName = namespace "." complexTypeName
qualifiedTypeDefinitionName = namespace "." typeDefinitionName
qualifiedEnumTypeName = namespace "." enumerationTypeName
; 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
; Note: this pattern is overly restrictive, the normative definition is type TSimpleIdentifier in OData EDM XML Schema
odataIdentifier = identifierLeadingCharacter *127identifierCharacter
identifierLeadingCharacter = ALPHA / "_" ; plus Unicode characters from the categories L or Nl
identifierCharacter = ALPHA / "_" / DIGIT ; plus Unicode characters from the categories L, Nl, Nd, Mn, Mc, Pc, or Cf
primitiveTypeName = 'Edm.' ( 'Binary'
/ 'Boolean'
/ 'Byte'
/ 'Date'
/ 'DateTimeOffset'
/ 'Decimal'
/ 'Double'
/ 'Duration'
/ 'Guid'
/ 'Int16'
/ 'Int32'
/ 'Int64'
/ 'SByte'
/ 'Single'
/ 'Stream'
/ 'String'
/ 'TimeOfDay'
/ abstractSpatialTypeName [ concreteSpatialTypeName ]
)
abstractSpatialTypeName = 'Geography'
/ 'Geometry'
concreteSpatialTypeName = 'Collection'
/ 'LineString'
/ 'MultiLineString'
/ 'MultiPoint'
/ 'MultiPolygon'
/ 'Point'
/ '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 = nullValue ; plain values up to int64Value
/ booleanValue
/ guidValue
/ dateValue
/ dateTimeOffsetValue
/ timeOfDayValue
/ decimalValue
/ doubleValue
/ singleValue
/ sbyteValue
/ byteValue
/ int16Value
/ int32Value
/ int64Value
/ string ; single-quoted
/ duration ; all others are quoted and prefixed
/ binary
/ enum
/ geographyCollection
/ geographyLineString
/ geographyMultiLineString
/ geographyMultiPoint
/ geographyMultiPolygon
/ geographyPoint
/ geographyPolygon
/ geometryCollection
/ geometryLineString
/ geometryMultiLineString
/ geometryMultiPoint
/ geometryMultiPolygon
/ geometryPoint
/ geometryPolygon
; in Atom and JSON message bodies and CSDL DefaultValue attributes
primitiveValue = booleanValue
/ guidValue
/ durationValue
/ dateValue
/ dateTimeOffsetValue
/ timeOfDayValue
/ enumValue
/ fullCollectionLiteral
/ fullLineStringLiteral
/ fullMultiPointLiteral
/ fullMultiLineStringLiteral
/ fullMultiPolygonLiteral
/ fullPointLiteral
/ fullPolygonLiteral
/ decimalValue
/ doubleValue
/ singleValue
/ sbyteValue
/ byteValue
/ int16Value
/ int32Value
/ int64Value
/ binaryValue
; also valid are:
; - any XML string for strings in Atom and CSDL documents
; - any JSON string for JSON documents
nullValue = 'null'
; base64url encoding according to http://tools.ietf.org/html/rfc4648#section-5
binary = "binary" SQUOTE binaryValue SQUOTE
binaryValue = *(4base64char) [ base64b16 / base64b8 ]
base64b16 = 2base64char ( 'A' / 'E' / 'I' / 'M' / 'Q' / 'U' / 'Y' / 'c' / 'g' / 'k' / 'o' / 's' / 'w' / '0' / '4' / '8' ) [ "=" ]
base64b8 = base64char ( 'A' / 'Q' / 'g' / 'w' ) [ "==" ]
base64char = ALPHA / DIGIT / "-" / "_"
booleanValue = "true" / "false"
decimalValue = [SIGN] 1*DIGIT ["." 1*DIGIT]
doubleValue = decimalValue [ "e" [SIGN] 1*DIGIT ] / nanInfinity ; IEEE 754 binary64 floating-point number (15-17 decimal digits)
singleValue = doubleValue ; IEEE 754 binary32 floating-point number (6-9 decimal digits)
nanInfinity = 'NaN' / '-INF' / 'INF'
guidValue = 8HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 4HEXDIG "-" 12HEXDIG
byteValue = 1*3DIGIT ; numbers in the range from 0 to 255
sbyteValue = [ sign ] 1*3DIGIT ; numbers in the range from -128 to 127
int16Value = [ sign ] 1*5DIGIT ; numbers in the range from -32768 to 32767
int32Value = [ sign ] 1*10DIGIT ; numbers in the range from -2147483648 to 2147483647
int64Value = [ sign ] 1*19DIGIT ; numbers in the range from -9223372036854775808 to 9223372036854775807
string = SQUOTE *( SQUOTE-in-string / pchar-no-SQUOTE ) SQUOTE
SQUOTE-in-string = SQUOTE SQUOTE ; two consecutive single quotes represent one within a string literal
dateValue = year "-" month "-" day
dateTimeOffsetValue = year "-" month "-" day "T" hour ":" minute [ ":" second [ "." fractionalSeconds ] ] ( "Z" / sign hour ":" minute )
duration = "duration" SQUOTE durationValue SQUOTE
durationValue = [ sign ] "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
timeOfDayValue = hour ":" minute [ ":" second [ "." fractionalSeconds ] ]
oneToNine = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
zeroToFiftyNine = ( "0" / "1" / "2" / "3" / "4" / "5" ) DIGIT
year = [ "-" ] ( "0" 3DIGIT / oneToNine 3*DIGIT )
month = "0" oneToNine
/ "1" ( "0" / "1" / "2" )
day = "0" oneToNine
/ ( "1" / "2" ) DIGIT
/ "3" ( "0" / "1" )
hour = ( "0" / "1" ) DIGIT
/ "2" ( "0" / "1" / "2" / "3" )
minute = zeroToFiftyNine
second = zeroToFiftyNine
fractionalSeconds = 1*12DIGIT
enum = qualifiedEnumTypeName SQUOTE enumValue SQUOTE
enumValue = singleEnumValue *( COMMA singleEnumValue )
singleEnumValue = enumerationMember / enumMemberValue
enumMemberValue = int64Value
geographyCollection = geographyPrefix SQUOTE fullCollectionLiteral SQUOTE
fullCollectionLiteral = sridLiteral collectionLiteral
collectionLiteral = "Collection(" geoLiteral *( COMMA geoLiteral ) CLOSE
geoLiteral = collectionLiteral
/ lineStringLiteral
/ multiPointLiteral
/ multiLineStringLiteral
/ multiPolygonLiteral
/ pointLiteral
/ polygonLiteral
geographyLineString = geographyPrefix SQUOTE fullLineStringLiteral SQUOTE
fullLineStringLiteral = sridLiteral lineStringLiteral
lineStringLiteral = "LineString" lineStringData
lineStringData = OPEN positionLiteral 1*( COMMA positionLiteral ) CLOSE
geographyMultiLineString = geographyPrefix SQUOTE fullMultiLineStringLiteral SQUOTE
fullMultiLineStringLiteral = sridLiteral multiLineStringLiteral
multiLineStringLiteral = "MultiLineString(" [ lineStringData *( COMMA lineStringData ) ] CLOSE
geographyMultiPoint = geographyPrefix SQUOTE fullMultiPointLiteral SQUOTE
fullMultiPointLiteral = sridLiteral multiPointLiteral
multiPointLiteral = "MultiPoint(" [ pointData *( COMMA pointData ) ] CLOSE
geographyMultiPolygon = geographyPrefix SQUOTE fullMultiPolygonLiteral SQUOTE
fullMultiPolygonLiteral = sridLiteral multiPolygonLiteral
multiPolygonLiteral = "MultiPolygon(" [ polygonData *( COMMA polygonData ) ] CLOSE
geographyPoint = geographyPrefix SQUOTE fullPointLiteral SQUOTE
fullPointLiteral = sridLiteral pointLiteral
sridLiteral = "SRID" EQ 1*5DIGIT SEMI
pointLiteral ="Point" pointData
pointData = OPEN positionLiteral CLOSE
positionLiteral = doubleValue SP doubleValue ; longitude, then latitude
geographyPolygon = geographyPrefix SQUOTE fullPolygonLiteral SQUOTE
fullPolygonLiteral = sridLiteral polygonLiteral
polygonLiteral = "Polygon" polygonData
polygonData = OPEN ringLiteral *( COMMA ringLiteral ) CLOSE
ringLiteral = OPEN positionLiteral *( COMMA positionLiteral ) CLOSE
; Within each ringLiteral, the first and last positionLiteral elements MUST be an exact syntactic match to each other.
; Within the polygonData, the ringLiterals MUST specify their points in appropriate winding order.
; In order of traversal, points to the left side of the ring are interpreted as being in the polygon.
geometryCollection = geometryPrefix SQUOTE fullCollectionLiteral SQUOTE
geometryLineString = geometryPrefix SQUOTE fullLineStringLiteral SQUOTE
geometryMultiLineString = geometryPrefix SQUOTE fullMultiLineStringLiteral SQUOTE
geometryMultiPoint = geometryPrefix SQUOTE fullMultiPointLiteral SQUOTE
geometryMultiPolygon = geometryPrefix SQUOTE fullMultiPolygonLiteral SQUOTE
geometryPoint = geometryPrefix SQUOTE fullPointLiteral SQUOTE
geometryPolygon = geometryPrefix SQUOTE fullPolygonLiteral SQUOTE
geographyPrefix = "geography"
geometryPrefix = "geometry"
;------------------------------------------------------------------------------
; 8. Header values
;------------------------------------------------------------------------------
header = content-id
/ odata-entityid
/ odata-isolation
/ odata-maxversion
/ odata-version
/ prefer
content-id = "Content-ID" ":" OWS 1*unreserved
odata-entityid = "OData-EntityID" ":" OWS IRI-in-header
odata-isolation = "OData-Isolation" ":" OWS "snapshot"
odata-maxversion = "OData-MaxVersion" ":" OWS 1*DIGIT "." 1*DIGIT
odata-version = "OData-Version" ":" OWS "4.0"
prefer = "Prefer" ":" OWS preference *( COMMA preference )
preference = allowEntityReferencesPreference
/ callbackPreference
/ continueOnErrorPreference
/ includeAnnotationsPreference
/ maxpagesizePreference
/ respondAsyncPreference
/ returnPreference
/ trackChangesPreference
/ waitPreference
; and everything allowed by http://tools.ietf.org/html/draft-snell-http-prefer-18
; / token [ EQ-h word ] *( OWS ";" [ OWS parameter ] )