diff --git a/docs/odata-url-conventions/odata-url-conventions.html b/docs/odata-url-conventions/odata-url-conventions.html index 7573b439..20c8dd81 100644 --- a/docs/odata-url-conventions/odata-url-conventions.html +++ b/docs/odata-url-conventions/odata-url-conventions.html @@ -1047,33 +1047,41 @@
commonExpr
syntax rule defines the formal grammar of common expressions.
+The following subsections specify situations in which expressions evaluate to null
if operands or parameters do not have the types expected by an operator or function. Notwithstanding these rules, if a service can infer such a type discrepancy for an expression that appears in a request independently of the underlying data, it MUST reject the request with an error message explaining the discrepancy. The inferral can be based on, for example, the declared type of a property or the type of a literal value that occurs in the expression.
Example 52: In a search for people above a certain age
+http://host/service/People?$filter=Age gt '50'
+the expression would always evaluate to null
because the age 50 is erroneously given as a string and the $filter
would return an empty result, although this is really the result of a typing error. That’s why a “type mismatch” error must instead be returned in such a case.
OData defines a set of logical operators that evaluate to true or false (i.e. a boolCommonExpr
as defined in OData-ABNF). Logical operators are typically used to filter a collection of resources.
OData defines a set of logical operators that evaluate to true
or false
(i.e. a boolCommonExpr
as defined in OData-ABNF). Logical operators are typically used to filter a collection of resources.
The syntax rules for the logical operators are defined in OData-ABNF. 4.01 Services MUST support case-insensitive operator names. Clients that want to work with 4.0 services MUST use lower case operator names.
The six comparison operators can be used with all primitive values except Edm.Binary
, Edm.Stream
, and the Edm.Geo
types. Edm.Binary
, Edm.Stream
, and the Edm.Geo
types can only be compared to the null
value using the eq
and ne
operators.
When applied to operands of numeric types, numeric promotion rules are applied.
The eq
, ne
, and in
operators can be used with collection-valued operands, and the eq
and ne
operators can be used with operands of a structured type.
If at least one operand of an eq
, ne
, lt
, le
, gt
, or ge
operator is non-numeric and the operands have different types, the operator returns null
.
The rules for the Boolean operators and
, or
, and not
assume Boolean operands. If an operand of a Boolean operator is not Boolean, the operator returns null
.
The eq
operator returns true if the left operand is equal to the right operand, otherwise it returns false.
When applied to operands of entity types, the eq
operator returns true if both operands represent the same entity, or both operands represent null.
When applied to operands of complex types, the eq
operator returns true if both operands have the same structure and same values, or both operands represent null.
When applied to ordered collections, the eq
operator returns true if both operands have the same cardinality and each member of the left operand is equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the eq
operator returns true if both operands are equal after applying the same ordering on both collections.
The eq
operator returns true
if the left operand is equal to the right operand, otherwise it returns false
.
When applied to operands of entity types, the eq
operator returns true
if both operands represent the same entity, or both operands represent null
.
When applied to operands of complex types, the eq
operator returns true
if both operands have the same structure and same values, or both operands represent null
.
When applied to ordered collections, the eq
operator returns true
if both operands have the same cardinality and each member of the left operand is equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the eq
operator returns true
if both operands are equal after applying the same ordering on both collections.
Each of the special values null
, -INF
, and INF
is equal to itself, and only to itself.
The special value NaN
is not equal to anything, even to itself.
The ne
operator returns true if the left operand is not equal to the right operand, otherwise it returns false.
When applied to operands of entity types, the ne
operator returns true if the two operands do not represent the same entity.
When applied to operands of complex types, the ne
operator returns true if the operands do not have the same structure and same values.
When applied to ordered collections, the ne
operator returns true if both operands do not have the same cardinality or any member of the left operand is not equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the ne
operator returns true if both operands do not have the same cardinality or do not contain the same members, in any order.
The ne
operator returns true
if the left operand is not equal to the right operand, otherwise it returns false
.
When applied to operands of entity types, the ne
operator returns true
if the two operands do not represent the same entity.
When applied to operands of complex types, the ne
operator returns true
if the operands do not have the same structure and same values.
When applied to ordered collections, the ne
operator returns true
if both operands do not have the same cardinality or any member of the left operand is not equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the ne
operator returns true
if both operands do not have the same cardinality or do not contain the same members, in any order.
Each of the special values null
, -INF
, and INF
is not equal to any value but itself.
The special value NaN
is not equal to anything, even to itself.
The null
value is not equal to any value but itself.
The gt
operator returns true if the left operand is greater than the right operand, otherwise it returns false.
The gt
operator returns true
if the left operand is greater than the right operand, otherwise it returns false
.
The special value INF
is greater than any number, and any number is greater than -INF
.
The Boolean value true
is greater than false
.
Services SHOULD order language-dependent strings according to the Content-Language
of the response, and SHOULD annotate string properties with language-dependent order with the term Core.IsLanguageDependent
, see OData-VocCore.
If any operand is null
, the operator returns false.
If any operand is null
, the operator returns false
.
The ge
operator returns true if the left operand is greater than or equal to the right operand, otherwise it returns false.
The ge
operator returns true
if the left operand is greater than or equal to the right operand, otherwise it returns false
.
The lt
operator returns true if the left operand is less than the right operand, otherwise it returns false.
The lt
operator returns true
if the left operand is less than the right operand, otherwise it returns false
.
The special value -INF
is less than any number, and any number is less than INF
.
The Boolean value false
is less than true
.
Services SHOULD order language-dependent strings according to the Content-Language
of the response, and SHOULD annotate string properties with language-dependent order with the term Core.IsLanguageDependent
, see OData-VocCore.
If any operand is null
, the operator returns false.
If any operand is null
, the operator returns false
.
The le
operator returns true if the left operand is less than or equal to the right operand, otherwise it returns false.
The le
operator returns true
if the left operand is less than or equal to the right operand, otherwise it returns false
.
The and
operator returns true if both the left and right operands evaluate to true, otherwise it returns false.
The null
value is treated as unknown, so if one operand evaluates to null
and the other operand to false, the and
operator returns false. All other combinations with null
return null
.
The and
operator returns true
if both the left and right operands evaluate to true
, otherwise it returns false
.
The null
value is treated as unknown, so if one operand evaluates to null
and the other operand to false
, the and
operator returns false
. All other combinations with null
return null
.
The or
operator returns false if both the left and right operands both evaluate to false, otherwise it returns true.
The null
value is treated as unknown, so if one operand evaluates to null
and the other operand to true, the or
operator returns true. All other combinations with null
return null
.
The or
operator returns false
if both the left and right operands both evaluate to false
, otherwise it returns true
.
The null
value is treated as unknown, so if one operand evaluates to null
and the other operand to true
, the or
operator returns true
. All other combinations with null
return null
.
The not
operator returns true if the operand returns false, otherwise it returns false.
The not
operator returns true
if the operand returns false
, otherwise it returns false
.
The null
value is treated as unknown, so not null
returns null
.
The has
operator returns true if the right operand is an enumeration value whose flag(s) are set on the left operand.
The has
operator returns true
if the right operand is an enumeration value whose flag(s) are set on the left operand.
The null
value is treated as unknown, so if one operand evaluates to null
, the has
operator returns null
.
The in
operator returns true if the left operand is a member of the right operand. The right operand MUST be either a comma-separated list of zero or more primitive values, enclosed in parentheses, or a single expression that resolves to a collection. If the right operand is an empty collection or list of values, the expression returns false.
The in
operator returns true
if the equality comparison of the left operand with at least one member of the right operand returns true
. The right operand MUST be either a comma-separated list of zero or more primitive values, enclosed in parentheses, or a single expression that resolves to a collection. If the right operand is an empty collection or list of values, the in
operator returns false
.
The following examples illustrate the use and semantics of each of the logical operators.
Example 52: all products with a Name
equal to Milk
Example 53: all products with a Name
equal to Milk
http://host/service/Products?$filter=Name eq 'Milk'
Example 53: all products with a Name
not equal to Milk
Example 54: all products with a Name
not equal to Milk
http://host/service/Products?$filter=Name ne 'Milk'
Example 54: all products with a Name
greater than Milk
:
Example 55: all products with a Name
greater than Milk
:
http://host/service/Products?$filter=Name gt 'Milk'
Example 55: all products with a Name
greater than or equal to Milk
:
Example 56: all products with a Name
greater than or equal to Milk
:
http://host/service/Products?$filter=Name ge 'Milk'
Example 56: all products with a Name
less than Milk
:
Example 57: all products with a Name
less than Milk
:
http://host/service/Products?$filter=Name lt 'Milk'
Example 57: all products with a Name
less than or equal to Milk
:
Example 58: all products with a Name
less than or equal to Milk
:
http://host/service/Products?$filter=Name le 'Milk'
Example 58: all products with a Name
equal to Milk
that also have a Price
less than 2.55:
Example 59: all products with a Name
equal to Milk
that also have a Price
less than 2.55:
http://host/service/Products?$filter=Name eq 'Milk' and Price lt 2.55
Example 59: all products that either have a Name
equal to Milk
or have a Price
less than 2.55:
Example 60: all products that either have a Name
equal to Milk
or have a Price
less than 2.55:
http://host/service/Products?$filter=Name eq 'Milk' or Price lt 2.55
Example 60: all products that do not have a Name
that ends with ilk
:
Example 61: all products that do not have a Name
that ends with ilk
:
http://host/service/Products?$filter=not endswith(Name,'ilk')
Example 61: all products whose style
value includes Yellow
:
Example 62: all products whose style
value includes Yellow
:
http://host/service/Products?$filter=style has Sales.Pattern'Yellow'
Example 62: all products whose Name
is Milk
or Cheese
:
Example 63: all products whose Name
is Milk
or Cheese
:
http://host/service/Products?$filter=Name in ('Milk', 'Cheese')
OData defines a set of arithmetic operators that require operands that evaluate to numeric types. Arithmetic operators are typically used to filter a collection of resources. However, services MAY allow using arithmetic operators with the $orderby
system query option.
If an operand of an arithmetic operator is null, the result is null.
+If an operand of an arithmetic operator is null
or has a non-allowed type, the result is null
.
The syntax rules for the arithmetic operators are defined in OData-ABNF. 4.01 Services MUST support case-insensitive operator names. Clients that want to work with 4.0 services MUST use lower case operator names.
The following examples illustrate the use and semantics of each of the Arithmetic operators.
Example 63: all products with a Price of 2.55:
+Example 64: all products with a Price of 2.55:
http://host/service/Products?$filter=Price add 2.45 eq 5.00
Example 64: all products with a Price of 2.55:
+Example 65: all products with a Price of 2.55:
http://host/service/Products?$filter=Price sub 0.55 eq 2.00
Example 65: all products with a Price of 2.55:
+Example 66: all products with a Price of 2.55:
http://host/service/Products?$filter=Price mul 2.0 eq 5.10
Example 66: all products with a Price of 2.55:
+Example 67: all products with a Price of 2.55:
http://host/service/Products?$filter=Price div 2.55 eq 1
Example 67: all products with an integer Rating value of 4 or 5:
+Example 68: all products with an integer Rating value of 4 or 5:
http://host/service/Products?$filter=Rating div 2 eq 2
Example 68: all products with an integer Rating value of 5:
+Example 69: all products with an integer Rating value of 5:
http://host/service/Products?$filter=Rating divby 2 eq 2.5
Example 69: all products with a Rating exactly divisible by 5:
+Example 70: all products with a Rating exactly divisible by 5:
http://host/service/Products?$filter=Rating mod 5 eq 0
The Grouping operator (open and close parenthesis “( )
”) controls the evaluation order of an expression. The Grouping operator returns the expression grouped inside the parenthesis.
Example 70: all products because 9 mod 3 is 0
+Example 71: all products because 9 mod 3 is 0
http://host/service/Products?$filter=(4 add 5) mod (4 sub 1) eq 0
$compute
, $filter
or $orderby
system query options, or in parameter alias values. The following sections describe the available functions.
Note: ISNULL or COALESCE operators are not defined. Instead, OData defines a null
literal that can be used in comparisons.
If a parameter of a canonical function is null
, the function returns null
.
If a parameter of a canonical function is null
, the function returns null
. If the types of parameters do not match the function signature, the function also returns null
.
The syntax rules for all functions are defined in OData-ABNF. 4.01 Services MUST support case-insensitive canonical function names. Clients that want to work with 4.0 services MUST use lower case canonical function names.
concatThe concat function with collection parameter values returns a collection that appends all items of the second collection to the first. If both collections are ordered, the result is also ordered.
The concatMethodCallExpr
syntax rule defines how the concat
function is invoked.
-Example 71: all customers from Berlin, Germany
+Example 72: all customers from Berlin, Germany
http://host/service/Customers?$filter=concat(concat(City,', '),Country) eq 'Berlin, Germany'
cont
The contains
function has two overloads, with the following signatures:
Edm.Boolean contains(Edm.String,Edm.String)
Edm.Boolean contains(OrderedCollection,OrderedCollection)
-The contains
function with string parameter values returns true if the second string is a substring of the first string, otherwise it returns false. String comparison is case-sensitive, case-insensitive comparison can be achieved in combination with tolower
or toupper
.
-The contains
function with ordered collection parameter values returns true if the first collection can be transformed into the second collection by removing zero or more items from the beginning or the end of the first collection.
+The contains
function with string parameter values returns true
if the second string is a substring of the first string, otherwise it returns false
. String comparison is case-sensitive, case-insensitive comparison can be achieved in combination with tolower
or toupper
.
+The contains
function with ordered collection parameter values returns true
if the first collection can be transformed into the second collection by removing zero or more items from the beginning or the end of the first collection.
The containsMethodCallExpr
syntax rule defines how the contains
function is invoked.
-Example 72: all customers with a CompanyName
that contains Alfreds
+Example 73: all customers with a CompanyName
that contains Alfreds
http://host/service/Customers?$filter=contains(CompanyName,'Alfreds')
@@ -1341,11 +1349,11 @@ 5.1.1.5.3 ends
The endswith
function has two overloads, with the following signatures:
Edm.Boolean endswith(Edm.String,Edm.String)
Edm.Boolean endswith(OrderedCollection,OrderedCollection)
-The endswith
function with string parameter values returns true if the first string ends with the second string, otherwise it returns false. String comparison is case-sensitive, case-insensitive comparison can be achieved in combination with tolower
or toupper
.
-The endswith
function with ordered collection parameter values returns true if the first collection can be transformed into the second collection by removing zero or more items from the beginning of the first collection.
+The endswith
function with string parameter values returns true
if the first string ends with the second string, otherwise it returns false
. String comparison is case-sensitive, case-insensitive comparison can be achieved in combination with tolower
or toupper
.
+The endswith
function with ordered collection parameter values returns true
if the first collection can be transformed into the second collection by removing zero or more items from the beginning of the first collection.
The endsWithMethodCallExpr
syntax rule defines how the endswith
function is invoked.
-Example 73: all customers with a CompanyName
that ends with Futterkiste
+Example 74: all customers with a CompanyName
that ends with Futterkiste
http://host/service/Customers?$filter=endswith(CompanyName,'Futterkiste')
@@ -1359,7 +1367,7 @@ 5.1.1.5.4 indexof
The indexof
function with ordered collection parameter values returns the zero-based index of the first occurrence of the second collection in the first collection, or -1 if the first collection does not contain the second collection.
The indexOfMethodCallExpr
syntax rule defines how the indexof
function is invoked.
-Example 74: all customers with a CompanyName
containing lfreds
starting at the second character
+Example 75: all customers with a CompanyName
containing lfreds
starting at the second character
http://host/service/Customers?$filter=indexof(CompanyName,'lfreds') eq 1
@@ -1373,7 +1381,7 @@ 5.1.1.5.5 lengthThe length
function with a collection parameter value returns the number of itens in the collection.
The lengthMethodCallExpr
syntax rule defines how the length
function is invoked.
-Example 75: all customers with a CompanyName
that is 19 characters long
+Example 76: all customers with a CompanyName
that is 19 characters long
http://host/service/Customers?$filter=length(CompanyName) eq 19
@@ -1383,11 +1391,11 @@ 5.1.1.5.6 The startswith
function has two overloads, with the following signatures:
Edm.Boolean startswith(Edm.String,Edm.String)
Edm.Boolean startswith(Collection,Collection)
-The startswith
function with string parameter values returns true if the first string starts with the second string, otherwise it returns false. String comparison is case-sensitive, case-insensitive comparison can be achieved in combination with tolower
or toupper
.
-The startswith
function with ordered collection parameter values returns true if the first collection can be transformed into the second collection by removing zero or more items from the end of the first collection.
+The startswith
function with string parameter values returns true
if the first string starts with the second string, otherwise it returns false
. String comparison is case-sensitive, case-insensitive comparison can be achieved in combination with tolower
or toupper
.
+The startswith
function with ordered collection parameter values returns true
if the first collection can be transformed into the second collection by removing zero or more items from the end of the first collection.
The startsWithMethodCallExpr
syntax rule defines how the startswith
function is invoked.
-Example 76: all customers with a CompanyName
that starts with Alfr
+Example 77: all customers with a CompanyName
that starts with Alfr
http://host/service/Customers?$filter=startswith(CompanyName,'Alfr')
@@ -1408,11 +1416,11 @@ 5.1.1.5.7 s
A negative start index N, if supported, returns a string/collection starting N characters/items before the end of the string/collection.
The substringMethodCallExpr
syntax rule defines how the substring
function is invoked.
-Example 77: all customers with a CompanyName
of lfreds Futterkiste
once the first character has been removed
+Example 78: all customers with a CompanyName
of lfreds Futterkiste
once the first character has been removed
http://host/service/Customers?$filter=substring(CompanyName,1) eq 'lfreds Futterkiste'
-Example 78: all customers with a CompanyName
that has lf
as the second and third characters, e.g, Alfreds Futterkiste
+Example 79: all customers with a CompanyName
that has lf
as the second and third characters, e.g, Alfreds Futterkiste
http://host/service/Customers?$filter=substring(CompanyName,1,2) eq 'lf'
@@ -1425,9 +1433,9 @@ 5.1.1.6.1 h
The hassubset
function has the following signature:
Edm.Boolean hassubset(Collection, Collection)
-The hassubset
function returns true if the first collection can be transformed into the second collection by reordering and/or removing zero or more items. The hasSubsetMethodCallExpr
syntax rule defines how the hassubset
function is invoked.
+The hassubset
function returns true
if the first collection can be transformed into the second collection by reordering and/or removing zero or more items. The hasSubsetMethodCallExpr
syntax rule defines how the hassubset
function is invoked.
-Example 79: hassubset
expressions that return true
+Example 80: hassubset
expressions that return true
hassubset([4,1,3],[4,1,3])
hassubset([4,1,3],[1,3,4])
hassubset([4,1,3],[3,1])
@@ -1435,7 +1443,7 @@ 5.1.1.6.1 h
hassubset([4,1,3,1],[1,1])
-Example 80: hassubset
expression that returns false: 1 appears only once in the left operand
+Example 81: hassubset
expression that returns false
: 1
appears only once in the left operand
hassubset([1,2],[1,1,2])
@@ -1444,16 +1452,16 @@ 5.
The hassubsequence
function has the following signature:
Edm.Boolean hassubsequence(OrderedCollection,OrderedCollection)
-The hassubsequence
function returns true if the first collection can be transformed into the second collection by removing zero or more items. The hasSubsequenceMethodCallExpr
syntax rule defines how the hassubsequence
function is invoked.
+The hassubsequence
function returns true
if the first collection can be transformed into the second collection by removing zero or more items. The hasSubsequenceMethodCallExpr
syntax rule defines how the hassubsequence
function is invoked.
-Example 81: hassubsequence
expressions that return true
+Example 82: hassubsequence
expressions that return true
hassubsequence([4,1,3],[4,1,3])
hassubsequence([4,1,3],[4,1])
hassubsequence([4,1,3],[4,3])
hassubsequence([4,1,3,1],[1,1])
-Example 82: hassubsequence
expressions that return false
+Example 83: hassubsequence
expressions that return false
hassubsequence([4,1,3],[1,3,4])
hassubsequence([4,1,3],[3,1])
hassubsequence([1,2],[1,1,2])
@@ -1469,13 +1477,13 @@ 5.
The matchespattern
function has the following signatures:
Edm.Boolean matchespattern(Edm.String,Edm.String)
Edm.Boolean matchespattern(Edm.String,Edm.String,Edm.String)
-The second parameter MUST evaluate to a string containing an ECMAScript (JavaScript) regular expression. The matchespattern
function returns true if the first parameter evaluates to a string matching that regular expression, using syntax and semantics of ECMAScript regular expressions, otherwise it returns false. If the optional third parameter is provided, it MUST evaluate to a string consisting of ECMAScript regular expression flags to modify the match.
+The second parameter MUST evaluate to a string containing an ECMAScript (JavaScript) regular expression, otherwise the function returns null
. The matchespattern
function returns true
if the first parameter evaluates to a string matching that regular expression, using syntax and semantics of ECMAScript regular expressions, otherwise it returns false
. If the optional third parameter is provided, it MUST evaluate to a string consisting of ECMAScript regular expression flags to modify the match, otherwise the function returns null
.
-Example 83: all customers with a CompanyName
that match the (percent-encoded) regular expression ^A.*e$
+Example 84: all customers with a CompanyName
that match the (percent-encoded) regular expression ^A.*e$
http://host/service/Customers?$filter=matchespattern(CompanyName,'%5EA.*e$')
-Example 84: all customers with a FormattedAddress
that contains a line ending with berg
or ends with berg
+Example 85: all customers with a FormattedAddress
that contains a line ending with berg
or ends with berg
http://host/service/Customers?$filter=matchespattern(FormattedAddress,'berg$','m')
@@ -1486,7 +1494,7 @@ 5.1.1.7.2 tolower
Edm.String tolower(Edm.String)
The tolower
function returns the input parameter string value with all uppercase characters converted to lowercase according to Unicode rules. The toLowerMethodCallExpr
syntax rule defines how the tolower
function is invoked.
-Example 85: all customers with a CompanyName
that equals alfreds futterkiste
once any uppercase characters have been converted to lowercase
+Example 86: all customers with a CompanyName
that equals alfreds futterkiste
once any uppercase characters have been converted to lowercase
http://host/service/Customers?$filter=tolower(CompanyName) eq 'alfreds futterkiste'
@@ -1497,7 +1505,7 @@ 5.1.1.7.3 toupper
Edm.String toupper(Edm.String)
The toupper
function returns the input parameter string value with all lowercase characters converted to uppercase according to Unicode rules. The toUpperMethodCallExpr
syntax rule defines how the toupper
function is invoked.
-Example 86: all customers with a CompanyName
that equals ALFREDS FUTTERKISTE
once any lowercase characters have been converted to uppercase
+Example 87: all customers with a CompanyName
that equals ALFREDS FUTTERKISTE
once any lowercase characters have been converted to uppercase
http://host/service/Customers?$filter=toupper(CompanyName) eq 'ALFREDS FUTTERKISTE'
@@ -1508,7 +1516,7 @@ 5.1.1.7.4 trim
<
Edm.String trim(Edm.String)
The trim
function returns the input parameter string value with all leading and trailing whitespace characters, according to Unicode rules, removed. The trimMethodCallExpr
syntax rule defines how the trim
function is invoked.
-Example 87: all customers with a CompanyName
without leading or trailing whitespace characters
+Example 88: all customers with a CompanyName
without leading or trailing whitespace characters
http://host/service/Customers?$filter=trim(CompanyName) eq CompanyName
@@ -1532,7 +1540,7 @@ 5.1.1.8.2 day
The day
function returns the day component Date
or DateTimeOffset
parameter value, evaluated in the time zone of the DateTimeOffset
parameter value. The dayMethodCallExpr
syntax rule defines how the day
function is invoked.
Services that are unable to preserve the offset of Edm.DateTimeOffset
values and instead normalize the values to some common time zone (for example UTC) MUST fail evaluation of the day
function for literal Edm.DateTimeOffset
values that are not stated in the time zone of the normalized values.
-Example 88: all employees born on the 8th day of a month
+Example 89: all employees born on the 8th day of a month
http://host/service/Employees?$filter=day(BirthDate) eq 8
@@ -1544,7 +1552,7 @@
-Example 89: all employees born less than 100 milliseconds after a full second of any minute of any hour on any day
+Example 90: all employees born less than 100 milliseconds after a full second of any minute of any hour on any day
http://host/service/Employees?$filter=[fractionalseconds(BirthDate) lt 0.1
@@ -1557,7 +1565,7 @@ 5.1.1.8.4 hour
<
The hour
function returns the hour component (0
to 23
) of the DateTimeOffset
or TimeOfDay
parameter value, evaluated in the time zone of the DateTimeOffset
parameter value. The hourMethodCallExpr
syntax rule defines how the hour
function is invoked.
Services that are unable to preserve the offset of Edm.DateTimeOffset
values and instead normalize the values to some common time zone (for example UTC) MUST fail evaluation of the hour
function for literal Edm.DateTimeOffset
values that are not stated in the time zone of the normalized values.
-Example 90: all employees born in hour 4, between 04:00 (inclusive) and 05:00 (exclusive)
+Example 91: all employees born in hour 4, between 04:00 (inclusive) and 05:00 (exclusive)
http://host/service/Employees?$filter=hour(BirthDate) eq 4
@@ -1583,7 +1591,7 @@ 5.1.1.8.7 minute
The minute
function returns the minute component (0
to 59
) of the DateTimeOffset
or TimeOfDay
parameter value, evaluated in the time zone of the DateTimeOffset
parameter value. The minuteMethodCallExpr
syntax rule defines how the minute
function is invoked.
-Example 91: all employees born in minute 40 of any hour on any day
+Example 92: all employees born in minute 40 of any hour on any day
http://host/service/Employees?$filter=minute(BirthDate) eq 40
@@ -1596,7 +1604,7 @@ 5.1.1.8.8 month
<
The month
function returns the month component of the Date
or DateTimeOffset
parameter value, evaluated in the time zone of the DateTimeOffset
parameter value. The monthMethodCallExpr
syntax rule defines how the month
function is invoked.
Services that are unable to preserve the offset of Edm.DateTimeOffset
values and instead normalize the values to some common time zone (for example UTC) MUST fail evaluation of the month
function for literal Edm.DateTimeOffset
values that are not stated in the time zone of the normalized values.
-Example 92: all employees born in May
+Example 93: all employees born in May
http://host/service/Employees?$filter=month(BirthDate) eq 5
@@ -1616,7 +1624,7 @@ 5.1.1.8.10 second
Edm.Int32 second(Edm.TimeOfDay)
The second
function returns the second component (0
to 59
for regular seconds, and 60
for leap seconds, without the fractional part) of the DateTimeOffset
or TimeOfDay
parameter value. The secondMethodCallExpr
syntax rule defines how the second
function is invoked.
-Example 93: all employees born in second 40 of any minute of any hour on any day
+Example 94: all employees born in second 40 of any minute of any hour on any day
http://host/service/Employees?$filter=second(BirthDate) eq 40
@@ -1651,7 +1659,7 @@ 5.1.1.8.14 year
The year
function returns the year component of the Date
or DateTimeOffset
parameter value, evaluated in the time zone of the DateTimeOffset
parameter value. The yearMethodCallExpr
syntax rule defines how the year
function is invoked.
Services that are unable to preserve the offset of Edm.DateTimeOffset
values and instead normalize the values to some common time zone (for example UTC) MUST fail evaluation of the year
function for literal Edm.DateTimeOffset
values that are not stated in the time zone of the normalized values.
-Example 94: all employees born in 1971
+Example 95: all employees born in 1971
http://host/service/Employees?$filter=year(BirthDate) eq 1971
@@ -1667,7 +1675,7 @@ 5.1.1.9.1 ceiling
Edm.Decimal ceiling(Edm.Decimal)
The ceiling
function rounds the input numeric parameter up to the nearest numeric value with no decimal component. The ceilingMethodCallExpr
syntax rule defines how the ceiling
function is invoked.
-Example 95: all orders with freight costs that round up to 32
+Example 96: all orders with freight costs that round up to 32
http://host/service/Orders?$filter=ceiling(Freight) eq 32
@@ -1679,7 +1687,7 @@ 5.1.1.9.2 floor
<
Edm.Decimal floor(Edm.Decimal)
The floor
function rounds the input numeric parameter down to the nearest numeric value with no decimal component. The floorMethodCallExpr
syntax rule defines how the floor
function is invoked.
-Example 96: all orders with freight costs that round down to 32
+Example 97: all orders with freight costs that round down to 32
http://host/service/Orders?$filter=floor(Freight) eq 32
@@ -1691,7 +1699,7 @@ 5.1.1.9.3 round
<
Edm.Decimal round(Edm.Decimal)
The round
function rounds the input numeric parameter to the nearest numeric value with no decimal component. The mid-point between two integers is rounded away from zero, i.e. 0.5 is rounded to 1 and -0.5 is rounded to -1. The roundMethodCallExpr
syntax rule defines how the round
function is invoked.
-Example 97: all orders with freight costs that round to 32
+Example 98: all orders with freight costs that round to 32
http://host/service/Orders?$filter=round(Freight) eq 32
@@ -1720,7 +1728,6 @@ 5.1.1.10.1 cast
Integer types are cast to enumeration types based on the numeric value of the enumeration members of the target type. For non-flag enumeration types the cast fails if there is no enumeration member with the same numeric value as the integer value. For flag enumeration types the cast fails if the integer value is not in the value range of the underlying integer type of the enumeration type.
String values containing a representation of a date-time value according to XML-Schema-2, section 3.3.7 dateTime, can be cast to Edm.DateTimeOffset
. If the string value does not contain a time-zone offset, it is treated as UTC.
-The cast
function is optional for primitive values (first five rules) and up-casts (seventh rule).
If the cast fails, the cast
function returns null
.
@@ -1729,16 +1736,16 @@ 5.1.1.10.2 isof
The isof
function has the following signatures
Edm.Boolean isof(type)
Edm.Boolean isof(expression,type)
-
The single parameter isof
function returns true if the current instance is assignable to the type specified, according to the assignment rules for the cast
function, otherwise it returns false
.
-The two parameter isof
function returns true if the object referred to by the expression is assignable to the type specified, according to the same rules, otherwise it returns false.
+The single parameter isof
function returns true
if the current instance is assignable to the type specified, according to the assignment rules for the cast
function, otherwise it returns false
.
+The two parameter isof
function returns true
if the object referred to by the expression is assignable to the type specified, according to the same rules, otherwise it returns false
.
The isofExpr
syntax rule defines how the isof
function is invoked.
-Example 98: orders that are also BigOrders
+Example 99: orders that are also BigOrders
http://host/service/Orders?$filter=isof(NorthwindModel.BigOrder)
http://host/service/Orders?$filter=isof($it,NorthwindModel.BigOrder)
-Example 99: orders of a customer that is a VIPCustomer
+Example 100: orders of a customer that is a VIPCustomer
http://host/service/Orders?$filter=isof(Customer,NorthwindModel.VIPCustomer)
@@ -1760,7 +1767,7 @@ 5.1.
The geo.intersects
function has the following signatures:
Edm.Boolean geo.intersects(Edm.GeographyPoint,Edm.GeographyPolygon)
Edm.Boolean geo.intersects(Edm.GeometryPoint,Edm.GeometryPolygon)
-The geo.intersects
function returns true if the specified point lies within the interior or on the boundary of the specified polygon, otherwise it returns false.
+The geo.intersects
function returns true
if the specified point lies within the interior or on the boundary of the specified polygon, otherwise it returns false
.
5.1.1.11.3 geo.length
@@ -1780,12 +1787,12 @@ 5.1.1.12.1 case
The case
function has the following signature:
expression case(Edm.Boolean:expression, …, Edm.Boolean:expression)
Each parameter is a pair of expressions separated by a colon (:
), where the first expression — the condition — MUST be a Boolean expression, and the second expression — the result — may evaluate to any type.
-The case function evaluates the condition in each pair, starting with the leftmost pair, and stops as soon as a condition evaluates to true
. It then returns the value of the result of this pair. It returns null
if none of the conditions in any pair evaluates to true
. Clients can specify a last pair whose condition is true
to get a non-null “default/else/otherwise” result.
+The case function evaluates the condition in each pair, starting with the leftmost pair, and stops as soon as a condition evaluates to true
. It then returns the value of the result of this pair. It returns null
if none of the conditions in any pair evaluates to true
. Clients can specify a last pair whose condition is true
to get a non-null
“default/else/otherwise” result.
Boolean expressions containing DateTimeOffset
or TimeOfDay
literals without the optional seconds part will introduce ambiguity for parsers. Clients SHOULD use whitespace or parentheses to avoid ambiguity.
Clients SHOULD ensure that the results in all pairs are compatible. If all results are of the same type, the type of the case
expression is of that type. If all results are of numeric type, then the type of the case
expression is a numeric type capable of representing any of these expressions according to standard type promotion rules.
Services MAY support case
expressions containing parameters of incompatible types, in which case the case expression is treated as Edm.Untyped
and its value has the type of the parameter expression selected by the case statement.
-Example 100: compute signum(X)
+Example 101: compute signum(X)
$compute=case(X gt 0:1,X lt 0:-1,true:0) as SignumX
@@ -1801,18 +1808,18 @@ 5.1.1.13.1 any
-The any
operator applies a Boolean expression to each member of a collection and returns true if and only if the expression is true for any member of the collection, otherwise it returns false. This implies that the any
operator always returns false for an empty collection.
-The any
operator can be used without an argument expression. This short form returns false if and only if the collection is empty.
+The any
operator applies a Boolean expression to each member of a collection and returns true
if and only if the expression is true
for any member of the collection, otherwise it returns false
. This implies that the any
operator always returns false
for an empty collection.
+The any
operator can be used without an argument expression. This short form returns false
if and only if the collection is empty.
-Example 101: all Orders
that have any Items
with a Quantity
greater than 100
+Example 102: all Orders
that have any Items
with a Quantity
greater than 100
http://host/service/Orders?$filter=Items/any(d:d/Quantity gt 100)
-Example 102: all customers having an order with a deviating shipping address. The Address
in the argument expression is evaluated in the scope of the Customers
collection.
+Example 103: all customers having an order with a deviating shipping address. The Address
in the argument expression is evaluated in the scope of the Customers
collection.
http://host/service/Customers?$filter=Orders/any(o:o/ShippingAddress ne Address)
-Example 103: all categories along with their products used in some order with a deviating unit price. The unprefixed UnitPrice
in the argument expression is evaluated in the scope of the expanded Products
.
+Example 104: all categories along with their products used in some order with a deviating unit price. The unprefixed UnitPrice
in the argument expression is evaluated in the scope of the expanded Products
.
http://host/service/Categories?$expand=Products(
$filter=OrderItems/any(oi:oi/UnitPrice ne UnitPrice))
@@ -1820,10 +1827,10 @@ 5.1.1.13.1 any
5.1.1.13.2 all
-
The all
operator applies a Boolean expression to each member of a collection and returns true if the expression is true for all members of the collection, otherwise it returns false. This implies that the all
operator always returns true for an empty collection.
+The all
operator applies a Boolean expression to each member of a collection and returns true
if the expression is true
for all members of the collection, otherwise it returns false
. This implies that the all
operator always returns true
for an empty collection.
The all
operator cannot be used without an argument expression.
-Example 104: all Orders
that have only Items
with a Quantity
greater than 100
+Example 105: all Orders
that have only Items
with a Quantity
greater than 100
http://host/service/Orders?$filter=Items/all(d:d/Quantity gt 100)
@@ -1836,7 +1843,7 @@ $filter
expressions. They are represented according to the primitiveLiteral
rule in OData-ABNF.
-Example 105: expressions using primitive literals
+Example 106: expressions using primitive literals
NullValue eq null
TrueValue eq true
FalseValue eq false
@@ -1867,11 +1874,11 @@ MUST be percent-encoded in URLs although some browsers will accept and pass them on unencoded.
-Example 106: collection of string literals
+Example 107: collection of string literals
http://host/service/ProductsByColors(colors=@c)?@c=["red","green"]
-Example 107: check whether a pair of properties has one of several possible pair values
+Example 108: check whether a pair of properties has one of several possible pair values
$filter=[FirstName,LastName] in [["John","Doe"],["Jane","Smith"]]
@@ -1889,15 +1896,15 @@ 5.1.1.14.4 $it
Note: property names and property paths in $filter
expressions nested within $expand
are evaluated in the context of the declared type of the expanded navigation property, so property names and property paths for the current instance of the collection identified by the resource path MUST be prefixed with $it/
.
The $it
literal can also be used as a path prefix to invoke a bound function overload on the current instance within an expression. Function names without a path prefix refer to an unbound function overload.
-Example 108: email addresses ending with .com
assuming EmailAddresses
is a collection of strings
+Example 109: email addresses ending with .com
assuming EmailAddresses
is a collection of strings
http://host/service/Customers(1)/EmailAddresses?$filter=endswith($it,'.com')
-Example 109: customers along with their orders that shipped to the same city as the customer’s address. The nested filter expression is evaluated in the context of Orders; $it
allows referring to values in the outer context of Customers. Note: the nested filter condition could equivalently be expressed as $it/Address/City eq
$this
/ShipTo/City
.
+Example 110: customers along with their orders that shipped to the same city as the customer’s address. The nested filter expression is evaluated in the context of Orders; $it
allows referring to values in the outer context of Customers. Note: the nested filter condition could equivalently be expressed as $it/Address/City eq
$this
/ShipTo/City
.
http://host/service/Customers?$expand=Orders($filter=$it/Address/City eq ShipTo/City)
-Example 110: products with at least 10 positive reviews. Model.PositiveReviews
is a function bound to Model.Product
returning a collection of reviews.
+Example 111: products with at least 10 positive reviews. Model.PositiveReviews
is a function bound to Model.Product
returning a collection of reviews.
http://host/service/Products?$filter=$it/Model.PositiveReviews()/$count ge 10
@@ -1906,16 +1913,16 @@ 5.1.1.14.5 $root
The $root
literal can be used in expressions to refer to resources of the same service.
-Example 111: all employees with the same last name as employee A1235
+Example 112: all employees with the same last name as employee A1235
http://host/service/Employees?$filter=LastName eq $root/Employees('A1245')/LastName
-Example 112: products ordered by a set of customers, where the set of customers is passed as a JSON array containing the resource paths from $root
to each customer
+Example 113: products ordered by a set of customers, where the set of customers is passed as a JSON array containing the resource paths from $root
to each customer
http://host/service/ProductsOrderedBy(Customers=@c)
?@c=[$root/Customers('ALFKI'),$root/Customers('BLAUS')]
-Example 113: function call returning the average rating of a given employee by their peers (employees in department D1)
+Example 114: function call returning the average rating of a given employee by their peers (employees in department D1)
http://host/service/Employees('A1245')/self.AvgRating(RatedBy=@peers)
?@peers=$root/Employees/$filter(Department eq 'D1')
@@ -1925,7 +1932,7 @@ 5.1.1.14.6 $this
The $this
literal can be used in $filter
and $orderby
expressions nested within $expand
and $select
for collection-valued properties and navigation properties. It refers to the current instance of the collection.
-Example 114: select only email addresses ending with .com
+Example 115: select only email addresses ending with .com
http://host/service/Customers?$select=EmailAddresses($filter=endswith($this,'.com'))
@@ -1938,11 +1945,11 @@
-Example 115: similar behavior whether HeadquarterAddress
is a nullable complex type or a nullable navigation property
+Example 116: similar behavior whether HeadquarterAddress
is a nullable complex type or a nullable navigation property
Companies(1)/HeadquarterAddress/Street
To access properties of derived types, the property name MUST be prefixed with the qualified name of the derived type on which the property is defined, followed by a forward slash (/
), see addressing derived types. If the current instance is not of the specified derived type, the path expression returns null
.
-If the property or navigation property is not defined for the type of the resource and that type supports dynamic properties or navigation properties, then the property or navigation property is treated as null for all instances on which it has no value.
+If the property or navigation property is not defined for the type of the resource and that type supports dynamic properties or navigation properties, then the property or navigation property is treated as null
for all instances on which it has no value.
If the property or navigation property is not defined for the type of the resource and that type does not support dynamic properties or navigation properties, then the request may be considered malformed.
@@ -1952,11 +1959,11 @@ path expression leading to the annotated resource or property.
If an annotation is not applied to the resource or property, then its value, and the values of its components, are treated as null
.
-Example 116: Return Products that have prices in Euro
+Example 117: Return Products that have prices in Euro
http://host/service/Products?$filter=Price/@Measures.Currency eq 'EUR'
-Example 117: Return Employees that have any error messages in the Core.Messages
annotation
+Example 118: Return Employees that have any error messages in the Core.Messages
annotation
http://host/service/Employees?$filter=@Core.Messages/any(m:m/severity eq 'error')
Services MAY additionally support the use of the unqualified term name by defining one or more default namespaces through the Core.DefaultNamespace
annotation term defined in OData-VocCore. For more information on default namespaces, see Default Namespaces in OData-Protocol. This short notation however uses the same name pattern as parameter aliases. If a query option is specified as a parameter alias, then any occurrence of the parameter alias name in an expression MUST evaluate to the parameter alias value and MUST NOT evaluate to the annotation value of an identical unqualified term name.
@@ -2136,7 +2143,7 @@ 5.1.2 System Query Option $filter
-The $filter
system query option allows clients to filter a collection of resources that are addressed by a request URL. The expression specified with $filter
is evaluated for each resource in the collection, and only items where the expression evaluates to true are included in the response. Resources for which the expression evaluates to false or to null, or which reference properties that are unavailable due to permissions, are omitted from the response.
+The $filter
system query option allows clients to filter a collection of resources that are addressed by a request URL. The expression specified with $filter
is evaluated for each resource in the collection, and only items where the expression evaluates to true
are included in the response. Resources for which the expression evaluates to false
or to null
, or which reference properties that are unavailable due to permissions, are omitted from the response.
The OData-ABNF filter
syntax rule defines the formal grammar of the $filter
query option.
@@ -2155,65 +2162,65 @@
-Example 118: expand a navigation property of an entity type
+Example 119: expand a navigation property of an entity type
http://host/service/Products?$expand=Category
-Example 119: expand a navigation property of a complex type
+Example 120: expand a navigation property of a complex type
http://host/service/Customers?$expand=Addresses/Country
A path MUST NOT appear in more than one expand item.
Query options can be applied to an expanded navigation property by appending a semicolon-separated list of query options, enclosed in parentheses, to the navigation property name. Allowed system query options are $compute
, $select
, $expand
, and $levels
for all navigation properties, plus $filter
, $orderby
, $skip
, $top
, $count
, and $search
for collection-valued navigation properties.
-Example 120: all categories and for each category all related products with a discontinued date equal to null
+Example 121: all categories and for each category all related products with a discontinued date equal to null
http://host/service/Categories?$expand=Products($filter=DiscontinuedDate eq null)
The $count
segment can be appended to a navigation property name or type-cast segment following a navigation property name to return just the count of the related entities. The $filter
and $search
system query options can be used to limit the number of related entities included in the count.
-Example 121: all categories and for each category the number of all related products
+Example 122: all categories and for each category the number of all related products
http://host/service/Categories?$expand=Products/$count
-Example 122: all categories and for each category the number of all related blue products
+Example 123: all categories and for each category the number of all related blue products
http://host/service/Categories?$expand=Products/$count($search=blue)
To retrieve entity references instead of the related entities, append /$ref
to the navigation property name or type-cast segment following a navigation property name. The system query options $filter
, $search
, $skip
, $top
, and $count
can be used to limit the number of expanded entity references.
-Example 123: all categories and for each category the references of all related products
+Example 124: all categories and for each category the references of all related products
http://host/service/Categories?$expand=Products/$ref
-Example 124: all categories and for each category the references of all related products of the derived type Sales.PremierProduct
+Example 125: all categories and for each category the references of all related products of the derived type Sales.PremierProduct
http://host/service/Categories?$expand=Products/Sales.PremierProduct/$ref
-Example 125: all categories and for each category the references of all related premier products with a current promotion equal to null
+Example 126: all categories and for each category the references of all related premier products with a current promotion equal to null
http://host/service/Categories
?$expand=Products/Sales.PremierProduct/$ref($filter=CurrentPromotion eq null)
-Example 126: all employees with their manager, manager’s manager, and manager’s manager’s manager
+Example 127: all employees with their manager, manager’s manager, and manager’s manager’s manager
http://host/service/Employees?$expand=ReportsTo($levels=3)
It is also possible to expand all declared and dynamic navigation properties using a star (*
). To retrieve references to all related entities use */$ref
, and to expand all related entities with a certain distance use the star operator with the $levels
option. The star operator can be combined with explicitly named navigation properties, which take precedence over the star operator.
The star operator does not implicitly include stream properties.
-Example 127: expand Supplier
and include references for all other related entities
+Example 128: expand Supplier
and include references for all other related entities
http://host/service/Categories?$expand=*/$ref,Supplier
-Example 128: expand all related entities and their related entities
+Example 129: expand all related entities and their related entities
http://host/service/Categories?$expand=*($levels=2)
Specifying a stream property includes the media stream inline according to the specified format.
-Example 129: include Employee’s Photo
stream property along with other properties of the customer
+Example 130: include Employee’s Photo
stream property along with other properties of the customer
http://host/service/Employees?$expand=Photo
Specifying $value
for a media entity includes the media entity’s stream value inline according to the specified format.
-Example 130: Include the Product’s media stream along with other properties of the product
+Example 131: Include the Product’s media stream along with other properties of the product
http://host/service/Products?$expand=$value
@@ -2239,34 +2246,34 @@
-Example 131: rating and release date of all products
+Example 132: rating and release date of all products
http://host/service/Products?$select=Rating,ReleaseDate
It is also possible to request all declared and dynamic structural properties using a star (*
).
-Example 132: all structural properties of all products
+Example 133: all structural properties of all products
http://host/service/Products?$select=*
-If the select item is not defined for the type of the resource, and that type supports dynamic properties or instance annotations, then the property is treated as null for all instances on which it is not defined.
+If the select item is not defined for the type of the resource, and that type supports dynamic properties or instance annotations, then the property is treated as null
for all instances on which it is not defined.
If the select item is not defined for the type of the resource, and that type does not support dynamic properties or instance annotations, then the request is considered malformed.
If the select item is an instance annotation of type entity or collection of entities, then the request is considered malformed. Entity-valued annotations can be included using $expand
.
If the select item is a navigation property, then the corresponding navigation link is represented in the response. If the navigation property also appears in an $expand
query option, then it is additionally represented as inline content. This inline content can itself be restricted with a nested $select
query option, see section 5.1.2.
-Example 133: name and description of all products, plus name of expanded category
+Example 134: name and description of all products, plus name of expanded category
http://host/service/Products?$select=Name,Description
&$expand=Category($select=Name)
The select item MUST be prefixed with a qualified structured type name in order to select a property defined on a type derived from the type of the resource segment.
A select item that is a complex type or collection of complex type can be followed by a forward slash, an optional type-cast segment, and the name of a property of the complex type (and so on for nested complex types).
-Example 134: the AccountRepresentative
property of any supplier that is of the derived type Namespace.PreferredSupplier
, together with the Street
property of the complex property Address
, and the Location property of the derived complex type Namespace.AddressWithLocation
+Example 135: the AccountRepresentative
property of any supplier that is of the derived type Namespace.PreferredSupplier
, together with the Street
property of the complex property Address
, and the Location property of the derived complex type Namespace.AddressWithLocation
http://host/service/Suppliers
?$select=Namespace.PreferredSupplier/AccountRepresentative,
Address/Street,Address/Namespace.AddressWithLocation/Location
Query options can be applied to a select item that is a path to a single complex value or a collection of primitive or complex values by appending a semicolon-separated list of query options, enclosed in parentheses, to the select item. The allowed system query options depend on the type of the resource identified by the select item, see section System Query Options, with the exception of $expand
. The same property MUST NOT have select options specified in more than one place in a request and MUST NOT be specified in more than one expand.
-Example 135: select up to five addresses whose City
starts with an H
, sorted, and with the Country
expanded
+Example 136: select up to five addresses whose City
starts with an H
, sorted, and with the Country
expanded
http://host/service/Customers
?$select=Addresses($filter=startswith(City,'H');$top=5;
$orderby=Country/Name,City,Street)
@@ -2278,7 +2285,7 @@
-Example 136: the ID
property, the ActionName
action defined in Model
and all actions and functions defined in the Model2
for each product if those actions and functions can be bound to that product
+Example 137: the ID
property, the ActionName
action defined in Model
and all actions and functions defined in the Model2
for each product if those actions and functions can be bound to that product
http://host/service/Products?$select=ID,Model.ActionName,Model2.*
When multiple select item exist in a $select
clause, then the total set of properties, open properties, navigation properties, actions and functions to be returned is equal to the union of the set of those identified by each select item.
@@ -2310,7 +2317,7 @@ $filter
are applied to the same request, the results include only those items that match both criteria.
The OData-ABNF search
syntax rule defines the formal grammar of the $search
query option.
-Example 137: all products that are blue or green. It is up to the service to decide what makes a product blue or green.
+Example 138: all products that are blue or green. It is up to the service to decide what makes a product blue or green.
http://host/service/Products?$search=blue OR green
Clients should be aware that services MAY implement search based on a different syntax provided they advertise this with the annotation SearchRestrictions/SearchSyntax
defined in OData-VocCap. Services MAY treat keywords defined in the standard OData-ABNF $search
syntax as terms to be matched if they are listed in SearchRestrictions/UnsupportedExpressions
.
@@ -2320,12 +2327,12 @@ $search
system query option to request entities matching the specified expression. Leading and trailing spaces are not considered part of the search expression.
Terms can be any single word to be matched within the expression.
Terms enclosed in double-quotes comprise a phrase.
-Each individual term or phrase comprises a Boolean expression that returns true if the term or phrase is matched, otherwise false. The semantics of what is considered a match is dependent upon the service.
+Each individual term or phrase comprises a Boolean expression that returns true
if the term or phrase is matched, otherwise false
. The semantics of what is considered a match is dependent upon the service.
Expressions enclosed in parenthesis comprise a group expression.
The search expression can contain any number of terms, phrases, or group expressions, along with the case-sensitive keywords NOT
, AND
, and OR
, evaluated in that order.
-Expressions prefaced with NOT
evaluate to true if the expression is not matched, otherwise false.
-Two expressions not enclosed in quotes and separated by a space are equivalent to the same two expressions separated by the AND
keyword. Such expressions evaluate to true
if both expressions evaluate to true, otherwise false.
-Expressions separated by an OR
evaluate to true if either of the expressions evaluate to true, otherwise false.
+Expressions prefaced with NOT
evaluate to true
if the expression is not matched, otherwise false
.
+Two expressions not enclosed in quotes and separated by a space are equivalent to the same two expressions separated by the AND
keyword. Such expressions evaluate to true
if both expressions evaluate to true
, otherwise false
.
+Expressions separated by an OR
evaluate to true
if either of the expressions evaluate to true
, otherwise false
.
To support type-ahead use cases, incomplete search expressions can be sent as OData string literals enclosed in single-quotes, and single-quotes within the search expression doubled. Such an expression can also be used to search for double quotes: ?$search='"'
.
The OData-ABNF searchExpr
syntax rule defines the formal grammar of the search expression.
@@ -2346,7 +2353,7 @@ The OData-ABNF compute
syntax rule defines the formal grammar of the $compute
query option.
Computed properties SHOULD be included as dynamic properties in the result and MUST be included if $select
is specified with the computed property name, or star (*
).
-Example 138: compute total price for order items
+Example 139: compute total price for order items
http://host/service/Orders(10)/Items
?$select=Product/Description,Total
&$filter=Total gt 100
@@ -2373,7 +2380,7 @@ OData-ABNF.
Custom query options MUST NOT begin with a $
or @
character.
-Example 139: service-specific custom query option debug-mode
+Example 140: service-specific custom query option debug-mode
http://host/service/Products?debug-mode=true
@@ -2384,15 +2391,15 @@ OData-ABNF.
The semantics of parameter aliases are covered in OData-Protocol. The OData-ABNF rule aliasAndValue
defines the formal grammar for passing parameter alias values as query options.
-Example 140:
+Example 141:
http://host/service/Movies?$filter=contains(@word,Title)&@word='Black'
-Example 141:
+Example 142:
http://host/service/Movies?$filter=Title eq @title&@title='Wizard of Oz'
-Example 142: JSON array of strings as parameter alias value — note that [
, ]
, and "
need to be percent-encoded in real URLs, the clear-text representation used here is just for readability
+Example 143: JSON array of strings as parameter alias value — note that [
, ]
, and "
need to be percent-encoded in real URLs, the clear-text representation used here is just for readability
http://host/service/Products/Model.WithIngredients(Ingredients=@i)
?@i=["Carrots","Ginger","Oranges"]
diff --git a/docs/odata-url-conventions/odata-url-conventions.md b/docs/odata-url-conventions/odata-url-conventions.md
index 3c69e4c9..9914370e 100644
--- a/docs/odata-url-conventions/odata-url-conventions.md
+++ b/docs/odata-url-conventions/odata-url-conventions.md
@@ -1593,9 +1593,29 @@ The following operators, functions, and literals can be used in
The [OData-ABNF](#ODataABNF) `commonExpr` syntax rule defines the formal
grammar of common expressions.
+The following subsections specify situations in which expressions evaluate to `null`
+if operands or parameters do not have the types expected by an operator or function.
+Notwithstanding these rules, if a service can infer such a type discrepancy for an expression
+that appears in a request independently of the underlying data,
+it MUST reject the request with an error message
+explaining the discrepancy. The inferral can be based on, for example, the
+declared type of a property or the type of a literal value that occurs in the
+expression.
+
+::: example
+Example 52: In a search for people above a certain age
+```
+http://host/service/People?$filter=Age gt '50'
+```
+the expression would always evaluate to `null` because the age 50 is erroneously
+given as a string and the [`$filter`](#SystemQueryOptionfilter) would return an empty result, although this is
+really the result of a typing error. That's why a "type mismatch" error must
+instead be returned in such a case.
+:::
+
#### 5.1.1.1 Logical Operators
-OData defines a set of logical operators that evaluate to true or false
+OData defines a set of logical operators that evaluate to `true` or `false`
(i.e. a `boolCommonExpr` as defined in [OData-ABNF](#ODataABNF)).
Logical operators are typically used to filter a collection of
resources.
@@ -1618,25 +1638,31 @@ The `eq`, `ne`, and `in` operators can be used with collection-valued
operands, and the `eq` and `ne` operators can be used with operands of a
structured type.
+If at least one operand of an `eq`, `ne`, `lt`, `le`, `gt`, or `ge` operator
+is non-numeric and the operands have different types, the operator returns `null`.
+
+The rules for the Boolean operators `and`, `or`, and `not` assume Boolean operands.
+If an operand of a Boolean operator is not Boolean, the operator returns `null`.
+
##### 5.1.1.1.1 Equals
-The `eq` operator returns true if the left operand is equal to the right
-operand, otherwise it returns false.
+The `eq` operator returns `true` if the left operand is equal to the right
+operand, otherwise it returns `false`.
-When applied to operands of entity types, the `eq` operator returns true
+When applied to operands of entity types, the `eq` operator returns `true`
if both operands represent the same entity, or both operands represent
-null.
+`null`.
When applied to operands of complex types, the `eq` operator returns
-true if both operands have the same structure and same values, or both
-operands represent null.
+`true` if both operands have the same structure and same values, or both
+operands represent `null`.
-When applied to ordered collections, the `eq` operator returns true if
+When applied to ordered collections, the `eq` operator returns `true` if
both operands have the same cardinality and each member of the left
operand is equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the `eq`
-operator returns true if both operands are equal after applying the same
+operator returns `true` if both operands are equal after applying the same
ordering on both collections.
Each of the special values `null`, `-INF`, and `INF` is equal to itself,
@@ -1646,21 +1672,21 @@ The special value `NaN` is not equal to anything, even to itself.
##### 5.1.1.1.2 Not Equals
-The `ne` operator returns true if the left operand is not equal to the
-right operand, otherwise it returns false.
+The `ne` operator returns `true` if the left operand is not equal to the
+right operand, otherwise it returns `false`.
-When applied to operands of entity types, the `ne` operator returns true
+When applied to operands of entity types, the `ne` operator returns `true`
if the two operands do not represent the same entity.
When applied to operands of complex types, the `ne` operator returns
-true if the operands do not have the same structure and same values.
+`true` if the operands do not have the same structure and same values.
-When applied to ordered collections, the `ne` operator returns true if
+When applied to ordered collections, the `ne` operator returns `true` if
both operands do not have the same cardinality or any member of the left
operand is not equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the `ne`
-operator returns true if both operands do not have the same cardinality
+operator returns `true` if both operands do not have the same cardinality
or do not contain the same members, in any order.
Each of the special values `null`, `-INF`, and `INF` is not equal to any
@@ -1672,8 +1698,8 @@ The `null` value is not equal to any value but itself.
##### 5.1.1.1.3 Greater Than
-The `gt` operator returns true if the left operand is greater than the
-right operand, otherwise it returns false.
+The `gt` operator returns `true` if the left operand is greater than the
+right operand, otherwise it returns `false`.
The special value `INF` is greater than any number, and any number is
greater than `-INF`.
@@ -1686,19 +1712,19 @@ with language-dependent order with the term
[`Core.IsLanguageDependent`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#IsLanguageDependent),
see [OData-VocCore](#ODataVocCore).
-If any operand is `null`, the operator returns false.
+If any operand is `null`, the operator returns `false`.
##### 5.1.1.1.4 Greater Than or Equal
-The `ge` operator returns true if the left operand is greater than or
-equal to the right operand, otherwise it returns false.
+The `ge` operator returns `true` if the left operand is greater than or
+equal to the right operand, otherwise it returns `false`.
See rules for [`gt`](#GreaterThan) and [`eq`](#Equals) for details.
##### 5.1.1.1.5 Less Than
-The `lt` operator returns true if the left operand is less than the
-right operand, otherwise it returns false.
+The `lt` operator returns `true` if the left operand is less than the
+right operand, otherwise it returns `false`.
The special value `-INF` is less than any number, and any number is less
than `INF`.
@@ -1711,43 +1737,43 @@ with language-dependent order with the term
[`Core.IsLanguageDependent`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#IsLanguageDependent),
see [OData-VocCore](#ODataVocCore).
-If any operand is `null`, the operator returns false.
+If any operand is `null`, the operator returns `false`.
##### 5.1.1.1.6 Less Than or Equal
-The `le` operator returns true if the left operand is less than or equal
-to the right operand, otherwise it returns false.
+The `le` operator returns `true` if the left operand is less than or equal
+to the right operand, otherwise it returns `false`.
See rules for [`lt`](#LessThan) and [`eq`](#Equals) for details.
##### 5.1.1.1.7 And
-The `and` operator returns true if both the left and right operands
-evaluate to true, otherwise it returns false.
+The `and` operator returns `true` if both the left and right operands
+evaluate to `true`, otherwise it returns `false`.
The `null` value is treated as unknown, so if one operand evaluates to
-`null` and the other operand to false, the `and` operator returns false.
+`null` and the other operand to `false`, the `and` operator returns `false`.
All other combinations with `null` return `null`.
##### 5.1.1.1.8 Or
-The `or` operator returns false if both the left and right operands both
-evaluate to false, otherwise it returns true.
+The `or` operator returns `false` if both the left and right operands both
+evaluate to `false`, otherwise it returns `true`.
The `null` value is treated as unknown, so if one operand evaluates to
-`null` and the other operand to true, the `or` operator returns true.
+`null` and the other operand to `true`, the `or` operator returns `true`.
All other combinations with `null` return `null`.
##### 5.1.1.1.9 Not
-The `not` operator returns true if the operand returns false, otherwise
-it returns false.
+The `not` operator returns `true` if the operand returns `false`, otherwise
+it returns `false`.
The `null` value is treated as unknown, so `not null` returns `null`.
##### 5.1.1.1.10 Has
-The `has` operator returns true if the right operand is an enumeration
+The `has` operator returns `true` if the right operand is an enumeration
value whose flag(s) are set on the left operand.
The `null` value is treated as unknown, so if one operand evaluates to
@@ -1755,11 +1781,12 @@ The `null` value is treated as unknown, so if one operand evaluates to
##### 5.1.1.1.11 In
-The `in` operator returns true if the left operand is a member of the
-right operand. The right operand MUST be either a comma-separated list
+The `in` operator returns `true` if the [equality](#Equals) comparison of the left
+operand with at least one member of the right operand returns `true`.
+The right operand MUST be either a comma-separated list
of zero or more primitive values, enclosed in parentheses, or a single expression
that resolves to a collection. If the right operand is an empty collection
-or list of values, the expression returns false.
+or list of values, the `in` operator returns `false`.
##### 5.1.1.1.12 Logical Operator Examples
@@ -1767,49 +1794,49 @@ The following examples illustrate the use and semantics of each of the
logical operators.
::: example
-Example 52: all products with a `Name` equal to `Milk`
+Example 53: all products with a `Name` equal to `Milk`
```
http://host/service/Products?$filter=Name eq 'Milk'
```
:::
::: example
-Example 53: all products with a `Name` not equal to `Milk`
+Example 54: all products with a `Name` not equal to `Milk`
```
http://host/service/Products?$filter=Name ne 'Milk'
```
:::
::: example
-Example 54: all products with a `Name` greater than `Milk`:
+Example 55: all products with a `Name` greater than `Milk`:
```
http://host/service/Products?$filter=Name gt 'Milk'
```
:::
::: example
-Example 55: all products with a `Name` greater than or equal to `Milk`:
+Example 56: all products with a `Name` greater than or equal to `Milk`:
```
http://host/service/Products?$filter=Name ge 'Milk'
```
:::
::: example
-Example 56: all products with a `Name` less than `Milk`:
+Example 57: all products with a `Name` less than `Milk`:
```
http://host/service/Products?$filter=Name lt 'Milk'
```
:::
::: example
-Example 57: all products with a `Name` less than or equal to `Milk`:
+Example 58: all products with a `Name` less than or equal to `Milk`:
```
http://host/service/Products?$filter=Name le 'Milk'
```
:::
::: example
-Example 58: all products with a `Name` equal to `Milk` that also have a `Price`
+Example 59: all products with a `Name` equal to `Milk` that also have a `Price`
less than 2.55:
```
http://host/service/Products?$filter=Name eq 'Milk' and Price lt 2.55
@@ -1817,7 +1844,7 @@ http://host/service/Products?$filter=Name eq 'Milk' and Price lt 2.55
:::
::: example
-Example 59: all products that either have a `Name` equal to `Milk` or have a
+Example 60: all products that either have a `Name` equal to `Milk` or have a
`Price` less than 2.55:
```
http://host/service/Products?$filter=Name eq 'Milk' or Price lt 2.55
@@ -1825,21 +1852,21 @@ http://host/service/Products?$filter=Name eq 'Milk' or Price lt 2.55
:::
::: example
-Example 60: all products that do not have a `Name` that ends with `ilk`:
+Example 61: all products that do not have a `Name` that ends with `ilk`:
```
http://host/service/Products?$filter=not endswith(Name,'ilk')
```
:::
::: example
-Example 61: all products whose `style` value includes `Yellow`:
+Example 62: all products whose `style` value includes `Yellow`:
```
http://host/service/Products?$filter=style has Sales.Pattern'Yellow'
```
:::
::: example
-Example 62: all products whose `Name` is `Milk` or `Cheese`:
+Example 63: all products whose `Name` is `Milk` or `Cheese`:
```
http://host/service/Products?$filter=Name in ('Milk', 'Cheese')
```
@@ -1853,7 +1880,8 @@ filter a collection of resources. However, services MAY allow using
arithmetic operators with the [`$orderby`](#SystemQueryOptionorderby)
system query option.
-If an operand of an arithmetic operator is null, the result is null.
+If an operand of an arithmetic operator is `null` or has a non-allowed type,
+the result is `null`.
The syntax rules for the arithmetic operators are defined in
[OData-ABNF](#ODataABNF). 4.01 Services MUST support case-insensitive
@@ -1970,49 +1998,49 @@ The following examples illustrate the use and semantics of each of the
Arithmetic operators.
::: example
-Example 63: all products with a Price of 2.55:
+Example 64: all products with a Price of 2.55:
```
http://host/service/Products?$filter=Price add 2.45 eq 5.00
```
:::
::: example
-Example 64: all products with a Price of 2.55:
+Example 65: all products with a Price of 2.55:
```
http://host/service/Products?$filter=Price sub 0.55 eq 2.00
```
:::
::: example
-Example 65: all products with a Price of 2.55:
+Example 66: all products with a Price of 2.55:
```
http://host/service/Products?$filter=Price mul 2.0 eq 5.10
```
:::
::: example
-Example 66: all products with a Price of 2.55:
+Example 67: all products with a Price of 2.55:
```
http://host/service/Products?$filter=Price div 2.55 eq 1
```
:::
::: example
-Example 67: all products with an integer Rating value of 4 or 5:
+Example 68: all products with an integer Rating value of 4 or 5:
```
http://host/service/Products?$filter=Rating div 2 eq 2
```
:::
::: example
-Example 68: all products with an integer Rating value of 5:
+Example 69: all products with an integer Rating value of 5:
```
http://host/service/Products?$filter=Rating divby 2 eq 2.5
```
:::
::: example
-Example 69: all products with a Rating exactly divisible by 5:
+Example 70: all products with a Rating exactly divisible by 5:
```
http://host/service/Products?$filter=Rating mod 5 eq 0
```
@@ -2025,7 +2053,7 @@ evaluation order of an expression. The Grouping operator returns the
expression grouped inside the parenthesis.
::: example
-Example 70: all products because 9 mod 3 is 0
+Example 71: all products because 9 mod 3 is 0
```
http://host/service/Products?$filter=(4 add 5) mod (4 sub 1) eq 0
```
@@ -2044,7 +2072,8 @@ not defined. Instead, OData defines a [`null`](#null) literal that can
be used in comparisons.
If a parameter of a canonical function is `null`, the function returns
-`null`.
+`null`. If the types of parameters do not match the function signature,
+the function also returns `null`.
The syntax rules for all functions are defined in
[OData-ABNF](#ODataABNF). 4.01 Services MUST support case-insensitive
@@ -2075,7 +2104,7 @@ The `concatMethodCallExpr` syntax rule defines how the `concat` function
is invoked.
::: example
-Example 71: all customers from Berlin, Germany
+Example 72: all customers from Berlin, Germany
```
http://host/service/Customers?$filter=concat(concat(City,', '),Country) eq 'Berlin, Germany'
```
@@ -2091,14 +2120,14 @@ Edm.Boolean contains(Edm.String,Edm.String)
Edm.Boolean contains(OrderedCollection,OrderedCollection)
```
-The `contains` function with string parameter values returns true if the
+The `contains` function with string parameter values returns `true` if the
second string is a substring of the first string, otherwise it returns
-false. String comparison is case-sensitive, case-insensitive comparison
+`false`. String comparison is case-sensitive, case-insensitive comparison
can be achieved in combination with [`tolower`](#tolower) or
[`toupper`](#toupper).
The `contains` function with ordered collection parameter values returns
-true if the first collection can be transformed into the second
+`true` if the first collection can be transformed into the second
collection by removing zero or more items from the beginning or the end
of the first collection.
@@ -2106,7 +2135,7 @@ The `containsMethodCallExpr` syntax rule defines how the `contains`
function is invoked.
::: example
-Example 72: all customers with a `CompanyName` that contains `Alfreds`
+Example 73: all customers with a `CompanyName` that contains `Alfreds`
```
http://host/service/Customers?$filter=contains(CompanyName,'Alfreds')
```
@@ -2122,14 +2151,14 @@ Edm.Boolean endswith(Edm.String,Edm.String)
Edm.Boolean endswith(OrderedCollection,OrderedCollection)
```
-The `endswith` function with string parameter values returns true if the
-first string ends with the second string, otherwise it returns false.
+The `endswith` function with string parameter values returns `true` if the
+first string ends with the second string, otherwise it returns `false`.
String comparison is case-sensitive, case-insensitive comparison can be
achieved in combination with [`tolower`](#tolower) or
[`toupper`](#toupper).
The `endswith` function with ordered collection parameter values returns
-true if the first collection can be transformed into the second
+`true` if the first collection can be transformed into the second
collection by removing zero or more items from the beginning of the
first collection.
@@ -2137,7 +2166,7 @@ The `endsWithMethodCallExpr` syntax rule defines how the `endswith`
function is invoked.
::: example
-Example 73: all customers with a `CompanyName` that ends with
+Example 74: all customers with a `CompanyName` that ends with
`Futterkiste`
```
http://host/service/Customers?$filter=endswith(CompanyName,'Futterkiste')
@@ -2169,7 +2198,7 @@ The `indexOfMethodCallExpr` syntax rule defines how the `indexof`
function is invoked.
::: example
-Example 74: all customers with a `CompanyName` containing `lfreds`
+Example 75: all customers with a `CompanyName` containing `lfreds`
starting at the second character
```
http://host/service/Customers?$filter=indexof(CompanyName,'lfreds') eq 1
@@ -2195,7 +2224,7 @@ The `lengthMethodCallExpr` syntax rule defines how the `length` function
is invoked.
::: example
-Example 75: all customers with a `CompanyName` that is 19 characters
+Example 76: all customers with a `CompanyName` that is 19 characters
long
```
http://host/service/Customers?$filter=length(CompanyName) eq 19
@@ -2212,14 +2241,14 @@ Edm.Boolean startswith(Edm.String,Edm.String)
Edm.Boolean startswith(Collection,Collection)
```
-The `startswith` function with string parameter values returns true if
+The `startswith` function with string parameter values returns `true` if
the first string starts with the second string, otherwise it returns
-false. String comparison is case-sensitive, case-insensitive comparison
+`false`. String comparison is case-sensitive, case-insensitive comparison
can be achieved in combination with [`tolower`](#tolower) or
[`toupper`](#toupper).
The `startswith` function with ordered collection parameter values
-returns true if the first collection can be transformed into the second
+returns `true` if the first collection can be transformed into the second
collection by removing zero or more items from the end of the first
collection.
@@ -2227,7 +2256,7 @@ The `startsWithMethodCallExpr` syntax rule defines how the `startswith`
function is invoked.
::: example
-Example 76: all customers with a `CompanyName` that starts with `Alfr`
+Example 77: all customers with a `CompanyName` that starts with `Alfr`
```
http://host/service/Customers?$filter=startswith(CompanyName,'Alfr')
```
@@ -2281,7 +2310,7 @@ The `substringMethodCallExpr` syntax rule defines how the `substring`
function is invoked.
::: example
-Example 77: all customers with a `CompanyName` of `lfreds Futterkiste`
+Example 78: all customers with a `CompanyName` of `lfreds Futterkiste`
once the first character has been removed
```
http://host/service/Customers?$filter=substring(CompanyName,1) eq 'lfreds Futterkiste'
@@ -2289,7 +2318,7 @@ http://host/service/Customers?$filter=substring(CompanyName,1) eq 'lfreds Futter
:::
::: example
-Example 78: all customers with a `CompanyName` that has `lf` as the
+Example 79: all customers with a `CompanyName` that has `lf` as the
second and third characters, e.g, `Alfreds Futterkiste`
```
http://host/service/Customers?$filter=substring(CompanyName,1,2) eq 'lf'
@@ -2306,13 +2335,13 @@ The `hassubset` function has the following signature:
Edm.Boolean hassubset(Collection, Collection)
```
-The `hassubset` function returns true if the first collection can be
+The `hassubset` function returns `true` if the first collection can be
transformed into the second collection by reordering and/or removing
zero or more items. The `hasSubsetMethodCallExpr` syntax rule defines
how the `hassubset` function is invoked.
::: example
-Example 79: `hassubset` expressions that return true
+Example 80: `hassubset` expressions that return `true`
```
hassubset([4,1,3],[4,1,3])
```
@@ -2335,7 +2364,7 @@ hassubset([4,1,3,1],[1,1])
:::
::: example
-Example 80: `hassubset` expression that returns false: 1 appears only
+Example 81: `hassubset` expression that returns `false`: `1` appears only
once in the left operand
```
hassubset([1,2],[1,1,2])
@@ -2350,13 +2379,13 @@ The `hassubsequence` function has the following signature:
Edm.Boolean hassubsequence(OrderedCollection,OrderedCollection)
```
-The `hassubsequence` function returns true if the first collection can
+The `hassubsequence` function returns `true` if the first collection can
be transformed into the second collection by removing zero or more
items. The `hasSubsequenceMethodCallExpr` syntax rule defines how the
`hassubsequence` function is invoked.
::: example
-Example 81: `hassubsequence` expressions that return true
+Example 82: `hassubsequence` expressions that return `true`
```
hassubsequence([4,1,3],[4,1,3])
```
@@ -2375,7 +2404,7 @@ hassubsequence([4,1,3,1],[1,1])
:::
::: example
-Example 82: `hassubsequence` expressions that return false
+Example 83: `hassubsequence` expressions that return `false`
```
hassubsequence([4,1,3],[1,3,4])
```
@@ -2401,15 +2430,17 @@ Edm.Boolean matchespattern(Edm.String,Edm.String,Edm.String)
```
The second parameter MUST evaluate to a string containing an
-[ECMAScript](#_ECMAScript) (JavaScript) regular expression. The `matchespattern` function returns true if the first parameter evaluates
+[ECMAScript](#_ECMAScript) (JavaScript) regular expression, otherwise the function
+returns `null`. The `matchespattern` function returns `true` if the first parameter evaluates
to a string matching that regular expression, using syntax and semantics
of ECMAScript regular expressions, otherwise it
-returns false.
+returns `false`.
If the optional third parameter is provided, it MUST evaluate to a string
-consisting of ECMAScript regular expression flags to modify the match.
+consisting of ECMAScript regular expression flags to modify the match, otherwise
+the function returns `null`.
::: example
-Example 83: all customers with a `CompanyName` that match the
+Example 84: all customers with a `CompanyName` that match the
(percent-encoded) regular expression `^A.*e$`
```
http://host/service/Customers?$filter=matchespattern(CompanyName,'%5EA.*e$')
@@ -2417,7 +2448,7 @@ http://host/service/Customers?$filter=matchespattern(CompanyName,'%5EA.*e$')
:::
::: example
-Example 84: all customers with a `FormattedAddress` that contains a line ending with `berg` or ends with `berg`
+Example 85: all customers with a `FormattedAddress` that contains a line ending with `berg` or ends with `berg`
```
http://host/service/Customers?$filter=matchespattern(FormattedAddress,'berg$','m')
```
@@ -2437,7 +2468,7 @@ The `toLowerMethodCallExpr` syntax rule defines how the `tolower`
function is invoked.
::: example
-Example 85: all customers with a `CompanyName` that equals
+Example 86: all customers with a `CompanyName` that equals
`alfreds futterkiste` once any uppercase characters have been
converted to lowercase
```
@@ -2459,7 +2490,7 @@ The `toUpperMethodCallExpr` syntax rule defines how the `toupper`
function is invoked.
::: example
-Example 86: all customers with a `CompanyName` that equals
+Example 87: all customers with a `CompanyName` that equals
`ALFREDS FUTTERKISTE` once any lowercase characters have been
converted to uppercase
```
@@ -2481,7 +2512,7 @@ removed. The `trimMethodCallExpr` syntax rule defines how the `trim`
function is invoked.
::: example
-Example 87: all customers with a `CompanyName` without leading or
+Example 88: all customers with a `CompanyName` without leading or
trailing whitespace characters
```
http://host/service/Customers?$filter=trim(CompanyName) eq CompanyName
@@ -2523,7 +2554,7 @@ UTC) MUST fail evaluation of the `day` function for literal
normalized values.
::: example
-Example 88: all employees born on the 8th day of a month
+Example 89: all employees born on the 8th day of a month
```
http://host/service/Employees?$filter=day(BirthDate) eq 8
```
@@ -2545,7 +2576,7 @@ non-negative decimal value less than 1. The
`fractionalseconds` function is invoked.
::: example
-Example 89: all employees born less than 100 milliseconds after a full
+Example 90: all employees born less than 100 milliseconds after a full
second of any minute of any hour on any day
```
http://host/service/Employees?$filter=[fractionalseconds(BirthDate) lt 0.1
@@ -2573,7 +2604,7 @@ UTC) MUST fail evaluation of the `hour` function for literal
normalized values.
::: example
-Example 90: all employees born in hour 4, between 04:00 (inclusive) and
+Example 91: all employees born in hour 4, between 04:00 (inclusive) and
05:00 (exclusive)
```
http://host/service/Employees?$filter=hour(BirthDate) eq 4
@@ -2617,7 +2648,7 @@ zone of the `DateTimeOffset` parameter value. The `minuteMethodCallExpr`
syntax rule defines how the `minute` function is invoked.
::: example
-Example 91: all employees born in minute 40 of any hour on any day
+Example 92: all employees born in minute 40 of any hour on any day
```
http://host/service/Employees?$filter=minute(BirthDate) eq 40
```
@@ -2644,7 +2675,7 @@ UTC) MUST fail evaluation of the `month` function for literal
normalized values.
::: example
-Example 92: all employees born in May
+Example 93: all employees born in May
```
http://host/service/Employees?$filter=month(BirthDate) eq 5
```
@@ -2683,7 +2714,7 @@ of the `DateTimeOffset` or `TimeOfDay` parameter value. The
invoked.
::: example
-Example 93: all employees born in second 40 of any minute of any hour on
+Example 94: all employees born in second 40 of any minute of any hour on
any day
```
http://host/service/Employees?$filter=second(BirthDate) eq 40
@@ -2752,7 +2783,7 @@ UTC) MUST fail evaluation of the `year` function for literal
normalized values.
::: example
-Example 94: all employees born in 1971
+Example 95: all employees born in 1971
```
http://host/service/Employees?$filter=year(BirthDate) eq 1971
```
@@ -2775,7 +2806,7 @@ nearest numeric value with no decimal component. The
is invoked.
::: example
-Example 95: all orders with freight costs that round up to 32
+Example 96: all orders with freight costs that round up to 32
```
http://host/service/Orders?$filter=ceiling(Freight) eq 32
```
@@ -2796,7 +2827,7 @@ nearest numeric value with no decimal component. The
invoked.
::: example
-Example 96: all orders with freight costs that round down to 32
+Example 97: all orders with freight costs that round down to 32
```
http://host/service/Orders?$filter=floor(Freight) eq 32
```
@@ -2818,7 +2849,7 @@ rounded to -1. The `roundMethodCallExpr` syntax rule defines how the
`round` function is invoked.
::: example
-Example 97: all orders with freight costs that round to 32
+Example 98: all orders with freight costs that round to 32
```
http://host/service/Orders?$filter=round(Freight) eq 32
```
@@ -2861,9 +2892,6 @@ The `cast` function follows these assignment rules:
[section 3.3.7 dateTime](https://www.w3.org/TR/xmlschema11-2/#dateTime), can be cast to `Edm.DateTimeOffset`.
If the string value does not contain a time-zone offset, it is treated as UTC.
-The `cast` function is optional for primitive values (first five rules)
-and up-casts (seventh rule).
-
If the cast fails, the `cast` function returns `null`.
##### 5.1.1.10.2 `isof`
@@ -2875,19 +2903,19 @@ Edm.Boolean isof(type)
Edm.Boolean isof(expression,type)
```
-The single parameter `isof` function returns true if the current
+The single parameter `isof` function returns `true` if the current
instance is assignable to the type specified, according to the
assignment rules for the [`cast`](#cast) function, otherwise it returns
`false`.
-The two parameter `isof` function returns true if the object referred to
+The two parameter `isof` function returns `true` if the object referred to
by the expression is assignable to the type specified, according to the
-same rules, otherwise it returns false.
+same rules, otherwise it returns `false`.
The `isofExpr` syntax rule defines how the `isof` function is invoked.
::: example
-Example 98: orders that are also `BigOrders`
+Example 99: orders that are also `BigOrders`
```
http://host/service/Orders?$filter=isof(NorthwindModel.BigOrder)
```
@@ -2898,7 +2926,7 @@ http://host/service/Orders?$filter=isof($it,NorthwindModel.BigOrder)
:::
::: example
-Example 99: orders of a customer that is a `VIPCustomer`
+Example 100: orders of a customer that is a `VIPCustomer`
```
http://host/service/Orders?$filter=isof(Customer,NorthwindModel.VIPCustomer)
```
@@ -2928,9 +2956,9 @@ Edm.Boolean geo.intersects(Edm.GeographyPoint,Edm.GeographyPolygon)
Edm.Boolean geo.intersects(Edm.GeometryPoint,Edm.GeometryPolygon)
```
-The `geo.intersects` function returns true if the specified point lies
+The `geo.intersects` function returns `true` if the specified point lies
within the interior or on the boundary of the specified polygon,
-otherwise it returns false.
+otherwise it returns `false`.
##### 5.1.1.11.3 `geo.length`
@@ -2963,7 +2991,7 @@ The case function evaluates the condition in each pair, starting with
the leftmost pair, and stops as soon as a condition evaluates to `true`.
It then returns the value of the result of this pair. It returns `null`
if none of the conditions in any pair evaluates to `true`. Clients can
-specify a last pair whose condition is `true` to get a non-null
+specify a last pair whose condition is `true` to get a non-`null`
"default/else/otherwise" result.
Boolean expressions containing `DateTimeOffset` or `TimeOfDay` literals without
@@ -2982,7 +3010,7 @@ incompatible types, in which case the case expression is treated as
selected by the case statement.
::: example
-Example 100: compute signum(X)
+Example 101: compute signum(X)
```
$compute=case(X gt 0:1,X lt 0:-1,true:0) as SignumX
```
@@ -3016,15 +3044,15 @@ the lambda operator.
##### 5.1.1.13.1 `any`
The `any` operator applies a Boolean expression to each member of a
-collection and returns true if and only if the expression is true for
-any member of the collection, otherwise it returns false. This implies
-that the `any` operator always returns false for an empty collection.
+collection and returns `true` if and only if the expression is `true` for
+any member of the collection, otherwise it returns `false`. This implies
+that the `any` operator always returns `false` for an empty collection.
The `any` operator can be used without an argument expression. This
-short form returns false if and only if the collection is empty.
+short form returns `false` if and only if the collection is empty.
::: example
-Example 101: all `Orders` that have any `Items` with a `Quantity` greater
+Example 102: all `Orders` that have any `Items` with a `Quantity` greater
than `100`
```
http://host/service/Orders?$filter=Items/any(d:d/Quantity gt 100)
@@ -3032,7 +3060,7 @@ http://host/service/Orders?$filter=Items/any(d:d/Quantity gt 100)
:::
::: example
-Example 102: all customers having an order with a deviating shipping
+Example 103: all customers having an order with a deviating shipping
address. The `Address` in the argument expression is evaluated in the
scope of the `Customers` collection.
```
@@ -3041,7 +3069,7 @@ http://host/service/Customers?$filter=Orders/any(o:o/ShippingAddress ne Address)
:::
::: example
-Example 103: all categories along with their products used in some order
+Example 104: all categories along with their products used in some order
with a deviating unit price. The unprefixed `UnitPrice` in the argument
expression is evaluated in the scope of the expanded `Products`.
```
@@ -3053,14 +3081,14 @@ http://host/service/Categories?$expand=Products(
##### 5.1.1.13.2 `all`
The `all` operator applies a Boolean expression to each member of a
-collection and returns true if the expression is true for all members of
-the collection, otherwise it returns false. This implies that the `all`
-operator always returns true for an empty collection.
+collection and returns `true` if the expression is `true` for all members of
+the collection, otherwise it returns `false`. This implies that the `all`
+operator always returns `true` for an empty collection.
The `all` operator cannot be used without an argument expression.
::: example
-Example 104: all `Orders` that have only `Items` with a `Quantity`
+Example 105: all `Orders` that have only `Items` with a `Quantity`
greater than `100`
```
http://host/service/Orders?$filter=Items/all(d:d/Quantity gt 100)
@@ -3077,7 +3105,7 @@ values, and in the query part, for example, as operands in
according to the `primitiveLiteral` rule in [OData-ABNF](#ODataABNF).
::: example
-Example 105: expressions using primitive literals
+Example 106: expressions using primitive literals
```
NullValue eq null
```
@@ -3182,14 +3210,14 @@ percent-encoded in URLs although some browsers will accept and pass them
on unencoded.
::: example
-Example 106: collection of string literals
+Example 107: collection of string literals
```
http://host/service/ProductsByColors(colors=@c)?@c=["red","green"]
```
:::
::: example
-Example 107: check whether a pair of properties has one of several
+Example 108: check whether a pair of properties has one of several
possible pair values
```
$filter=[FirstName,LastName] in [["John","Doe"],["Jane","Smith"]]
@@ -3235,7 +3263,7 @@ function overload on the current instance within an expression. Function
names without a path prefix refer to an unbound function overload.
::: example
-Example 108: email addresses ending with `.com` assuming
+Example 109: email addresses ending with `.com` assuming
`EmailAddresses` is a collection of strings
```
http://host/service/Customers(1)/EmailAddresses?$filter=endswith($it,'.com')
@@ -3243,7 +3271,7 @@ http://host/service/Customers(1)/EmailAddresses?$filter=endswith($it,'.com')
:::
::: example
-Example 109: customers along with their orders that shipped to the same
+Example 110: customers along with their orders that shipped to the same
city as the customer's address. The nested filter expression is
evaluated in the context of Orders; `$it` allows referring to values in
the outer context of Customers.
@@ -3254,7 +3282,7 @@ http://host/service/Customers?$expand=Orders($filter=$it/Address/City eq ShipTo/
:::
::: example
-Example 110: products with at least 10 positive reviews.
+Example 111: products with at least 10 positive reviews.
`Model.PositiveReviews` is a function bound to `Model.Product` returning
a collection of reviews.
```
@@ -3268,14 +3296,14 @@ The `$root` literal can be used in expressions to refer to resources of
the same service.
::: example
-Example 111: all employees with the same last name as employee `A1235`
+Example 112: all employees with the same last name as employee `A1235`
```
http://host/service/Employees?$filter=LastName eq $root/Employees('A1245')/LastName
```
:::
::: example
-Example 112: products ordered by a set of customers, where the set of
+Example 113: products ordered by a set of customers, where the set of
customers is passed as a JSON array containing the resource paths from
`$root` to each customer
```
@@ -3285,7 +3313,7 @@ http://host/service/ProductsOrderedBy(Customers=@c)
:::
::: example
-Example 113: function call returning the average rating of a given employee by their peers (employees in department D1)
+Example 114: function call returning the average rating of a given employee by their peers (employees in department D1)
```
http://host/service/Employees('A1245')/self.AvgRating(RatedBy=@peers)
?@peers=$root/Employees/$filter(Department eq 'D1')
@@ -3302,7 +3330,7 @@ and navigation properties. It refers to the current instance of the
collection.
::: example
-Example 114: select only email addresses ending with `.com`
+Example 115: select only email addresses ending with `.com`
```
http://host/service/Customers?$select=EmailAddresses($filter=endswith($this,'.com'))
```
@@ -3329,7 +3357,7 @@ target cardinality 0..1), its value, and the values of its components,
are treated as `null`.
::: example
-Example 115: similar behavior whether `HeadquarterAddress` is a nullable
+Example 116: similar behavior whether `HeadquarterAddress` is a nullable
complex type or a nullable navigation property
```
Companies(1)/HeadquarterAddress/Street
@@ -3344,7 +3372,7 @@ of the specified derived type, the path expression returns `null`.
If the property or navigation property is not defined for the type of
the resource and that type supports dynamic properties or navigation
-properties, then the property or navigation property is treated as null
+properties, then the property or navigation property is treated as `null`
for all instances on which it has no value.
If the property or navigation property is not defined for the type of
@@ -3370,14 +3398,14 @@ If an annotation is not applied to the resource or property, then its
value, and the values of its components, are treated as `null`.
::: example
-Example 116: Return Products that have prices in Euro
+Example 117: Return Products that have prices in Euro
```
http://host/service/Products?$filter=Price/@Measures.Currency eq 'EUR'
```
:::
::: example
-Example 117: Return Employees that have any error messages in the
+Example 118: Return Employees that have any error messages in the
[`Core.Messages`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Messages)
annotation
```
@@ -3459,9 +3487,9 @@ types.
The `$filter` system query option allows clients to filter a collection
of resources that are addressed by a request URL. The expression
specified with `$filter` is evaluated for each resource in the
-collection, and only items where the expression evaluates to true are
+collection, and only items where the expression evaluates to `true` are
included in the response. Resources for which the expression evaluates
-to false or to null, or which reference properties that are unavailable
+to `false` or to `null`, or which reference properties that are unavailable
due to permissions, are omitted from the response.
The [OData-ABNF](#ODataABNF) `filter` syntax rule defines the formal
@@ -3512,14 +3540,14 @@ segment does not specify a declared property, then the expanded property
appears only for those instances on which it has a value.
::: example
-Example 118: expand a navigation property of an entity type
+Example 119: expand a navigation property of an entity type
```
http://host/service/Products?$expand=Category
```
:::
::: example
-Example 119: expand a navigation property of a complex type
+Example 120: expand a navigation property of a complex type
```
http://host/service/Customers?$expand=Addresses/Country
```
@@ -3543,7 +3571,7 @@ Allowed system query options are
for collection-valued navigation properties.
::: example
-Example 120: all categories and for each category all related products
+Example 121: all categories and for each category all related products
with a discontinued date equal to `null`
```
http://host/service/Categories?$expand=Products($filter=DiscontinuedDate eq null)
@@ -3557,7 +3585,7 @@ property name to return just the count of the related entities. The
number of related entities included in the count.
::: example
-Example 121: all categories and for each category the number of all
+Example 122: all categories and for each category the number of all
related products
```
http://host/service/Categories?$expand=Products/$count
@@ -3565,7 +3593,7 @@ http://host/service/Categories?$expand=Products/$count
:::
::: example
-Example 122: all categories and for each category the number of all
+Example 123: all categories and for each category the number of all
related blue products
```
http://host/service/Categories?$expand=Products/$count($search=blue)
@@ -3582,7 +3610,7 @@ The system query options [`$filter`](#SystemQueryOptionfilter),
expanded entity references.
::: example
-Example 123: all categories and for each category the references of all
+Example 124: all categories and for each category the references of all
related products
```
http://host/service/Categories?$expand=Products/$ref
@@ -3590,7 +3618,7 @@ http://host/service/Categories?$expand=Products/$ref
:::
::: example
-Example 124: all categories and for each category the references of all
+Example 125: all categories and for each category the references of all
related products of the derived type `Sales.PremierProduct`
```
http://host/service/Categories?$expand=Products/Sales.PremierProduct/$ref
@@ -3598,7 +3626,7 @@ http://host/service/Categories?$expand=Products/Sales.PremierProduct/$ref
:::
::: example
-Example 125: all categories and for each category the references of all
+Example 126: all categories and for each category the references of all
related premier products with a current promotion equal to `null`
```
http://host/service/Categories
@@ -3615,7 +3643,7 @@ A `$levels` option with a value of 1 specifies a single expand with no
recursion.
::: example
-Example 126: all employees with their manager, manager's manager, and
+Example 127: all employees with their manager, manager's manager, and
manager's manager's manager
```
http://host/service/Employees?$expand=ReportsTo($levels=3)
@@ -3632,7 +3660,7 @@ which take precedence over the star operator.
The star operator does not implicitly include stream properties.
::: example
-Example 127: expand `Supplier` and include references for all other
+Example 128: expand `Supplier` and include references for all other
related entities
```
http://host/service/Categories?$expand=*/$ref,Supplier
@@ -3640,7 +3668,7 @@ http://host/service/Categories?$expand=*/$ref,Supplier
:::
::: example
-Example 128: expand all related entities and their related entities
+Example 129: expand all related entities and their related entities
```
http://host/service/Categories?$expand=*($levels=2)
```
@@ -3650,7 +3678,7 @@ Specifying a stream property includes the media stream inline according
to the specified format.
::: example
-Example 129: include Employee's `Photo` stream property along with other
+Example 130: include Employee's `Photo` stream property along with other
properties of the customer
```
http://host/service/Employees?$expand=Photo
@@ -3661,7 +3689,7 @@ Specifying `$value` for a media entity includes the media entity's
stream value inline according to the specified format.
::: example
-Example 130: Include the Product's media stream along with other
+Example 131: Include the Product's media stream along with other
properties of the product
```
http://host/service/Products?$expand=$value
@@ -3720,7 +3748,7 @@ The simplest form of a select item explicitly requests a property defined on the
type of the resources identified by the resource path section of the URL.
::: example
-Example 131: rating and release date of all products
+Example 132: rating and release date of all products
```
http://host/service/Products?$select=Rating,ReleaseDate
```
@@ -3730,7 +3758,7 @@ It is also possible to request all declared and dynamic structural
properties using a star (`*`).
::: example
-Example 132: all structural properties of all products
+Example 133: all structural properties of all products
```
http://host/service/Products?$select=*
```
@@ -3738,7 +3766,7 @@ http://host/service/Products?$select=*
If the select item is not defined for the type of the resource, and that
type supports dynamic properties or instance annotations, then the
-property is treated as null for all instances on which it is not
+property is treated as `null` for all instances on which it is not
defined.
If the select item is not defined for the type of the resource, and that
@@ -3758,7 +3786,7 @@ inline content can itself be restricted with a nested `$select` query
option, see [section 5.1.2](#SystemQueryOptionfilter).
::: example
-Example 133: name and description of all products, plus name of expanded
+Example 134: name and description of all products, plus name of expanded
category
```
http://host/service/Products?$select=Name,Description
@@ -3775,7 +3803,7 @@ be followed by a forward slash, an optional [type-cast segment](#AddressingDeriv
complex type (and so on for nested complex types).
::: example
-Example 134: the `AccountRepresentative` property of any supplier that
+Example 135: the `AccountRepresentative` property of any supplier that
is of the derived type `Namespace.PreferredSupplier`, together with the
`Street` property of the complex property
`Address`, and the Location property of the derived complex type `Namespace.AddressWithLocation`
@@ -3797,7 +3825,7 @@ select options specified in more than one place in a request and MUST
NOT be specified in more than one expand.
::: example
-Example 135: select up to five addresses whose `City` starts with an
+Example 136: select up to five addresses whose `City` starts with an
`H`, sorted, and with the `Country` expanded
```
http://host/service/Customers
@@ -3834,7 +3862,7 @@ qualified name and that operation cannot be bound to the entities
requested, the service MUST ignore the select item.
::: example
-Example 136: the `ID` property, the `ActionName` action defined in
+Example 137: the `ID` property, the `ActionName` action defined in
`Model` and all actions and functions defined in the `Model2` for each
product if those actions and functions can be bound to that product
```
@@ -3900,7 +3928,7 @@ The [OData-ABNF](#ODataABNF) `search` syntax rule defines the formal
grammar of the `$search` query option.
::: example
-Example 137: all products that are blue or green. It is up to the
+Example 138: all products that are blue or green. It is up to the
service to decide what makes a product blue or green.
```
http://host/service/Products?$search=blue OR green
@@ -3925,7 +3953,7 @@ Leading and trailing spaces are not considered part of the search expression.
Terms enclosed in double-quotes comprise a *phrase*.
Each individual term or phrase comprises a Boolean expression that
-returns true if the term or phrase is matched, otherwise false. The
+returns `true` if the term or phrase is matched, otherwise `false`. The
semantics of what is considered a match is dependent upon the service.
Expressions enclosed in parenthesis comprise a *group expression*.
@@ -3934,16 +3962,16 @@ The search expression can contain any number of terms, phrases, or group
expressions, along with the case-sensitive keywords `NOT`, `AND`, and
`OR`, evaluated in that order.
-Expressions prefaced with `NOT` evaluate to true if the expression is
-not matched, otherwise false.
+Expressions prefaced with `NOT` evaluate to `true` if the expression is
+not matched, otherwise `false`.
Two expressions not enclosed in quotes and separated by a space are
equivalent to the same two expressions separated by the `AND` keyword.
Such expressions evaluate to `true` if both expressions evaluate to
-true, otherwise false.
+`true`, otherwise `false`.
-Expressions separated by an `OR` evaluate to true if either of the
-expressions evaluate to true, otherwise false.
+Expressions separated by an `OR` evaluate to `true` if either of the
+expressions evaluate to `true`, otherwise `false`.
To support type-ahead use cases, incomplete search expressions can be
sent as OData string literals enclosed in single-quotes, and
@@ -3995,7 +4023,7 @@ result and MUST be included if `$select` is specified with the computed
property name, or star (`*`).
::: example
-Example 138: compute total price for order items
+Example 139: compute total price for order items
```
http://host/service/Orders(10)/Items
?$select=Product/Description,Total
@@ -4039,7 +4067,7 @@ custom query option is any query option of the form shown by the rule
Custom query options MUST NOT begin with a `$` or `@` character.
::: example
-Example 139: service-specific custom query option `debug-mode`
+Example 140: service-specific custom query option `debug-mode`
```
http://host/service/Products?debug-mode=true
```
@@ -4061,21 +4089,21 @@ The semantics of parameter aliases are covered in
values as query options.
::: example
-Example 140:
+Example 141:
```
http://host/service/Movies?$filter=contains(@word,Title)&@word='Black'
```
:::
::: example
-Example 141:
+Example 142:
```
http://host/service/Movies?$filter=Title eq @title&@title='Wizard of Oz'
```
:::
::: example
-Example 142: JSON array of strings as parameter alias value --- note that
+Example 143: JSON array of strings as parameter alias value --- note that
`[`, `]`, and `"` need to be percent-encoded in real URLs, the
clear-text representation used here is just for readability
```
diff --git a/odata-url-conventions/5 Query Options.md b/odata-url-conventions/5 Query Options.md
index fb2df09f..73b34c56 100644
--- a/odata-url-conventions/5 Query Options.md
+++ b/odata-url-conventions/5 Query Options.md
@@ -74,9 +74,29 @@ The following operators, functions, and literals can be used in
The [OData-ABNF](#ODataABNF) `commonExpr` syntax rule defines the formal
grammar of common expressions.
+The following subsections specify situations in which expressions evaluate to `null`
+if operands or parameters do not have the types expected by an operator or function.
+Notwithstanding these rules, if a service can infer such a type discrepancy for an expression
+that appears in a request independently of the underlying data,
+it MUST reject the request with an error message
+explaining the discrepancy. The inferral can be based on, for example, the
+declared type of a property or the type of a literal value that occurs in the
+expression.
+
+::: example
+Example ##ex: In a search for people above a certain age
+```
+http://host/service/People?$filter=Age gt '50'
+```
+the expression would always evaluate to `null` because the age 50 is erroneously
+given as a string and the [`$filter`](#SystemQueryOptionfilter) would return an empty result, although this is
+really the result of a typing error. That's why a "type mismatch" error must
+instead be returned in such a case.
+:::
+
#### ##subsubsubsec Logical Operators
-OData defines a set of logical operators that evaluate to true or false
+OData defines a set of logical operators that evaluate to `true` or `false`
(i.e. a `boolCommonExpr` as defined in [OData-ABNF](#ODataABNF)).
Logical operators are typically used to filter a collection of
resources.
@@ -99,25 +119,31 @@ The `eq`, `ne`, and `in` operators can be used with collection-valued
operands, and the `eq` and `ne` operators can be used with operands of a
structured type.
+If at least one operand of an `eq`, `ne`, `lt`, `le`, `gt`, or `ge` operator
+is non-numeric and the operands have different types, the operator returns `null`.
+
+The rules for the Boolean operators `and`, `or`, and `not` assume Boolean operands.
+If an operand of a Boolean operator is not Boolean, the operator returns `null`.
+
##### ##subsubsubsubsec Equals
-The `eq` operator returns true if the left operand is equal to the right
-operand, otherwise it returns false.
+The `eq` operator returns `true` if the left operand is equal to the right
+operand, otherwise it returns `false`.
-When applied to operands of entity types, the `eq` operator returns true
+When applied to operands of entity types, the `eq` operator returns `true`
if both operands represent the same entity, or both operands represent
-null.
+`null`.
When applied to operands of complex types, the `eq` operator returns
-true if both operands have the same structure and same values, or both
-operands represent null.
+`true` if both operands have the same structure and same values, or both
+operands represent `null`.
-When applied to ordered collections, the `eq` operator returns true if
+When applied to ordered collections, the `eq` operator returns `true` if
both operands have the same cardinality and each member of the left
operand is equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the `eq`
-operator returns true if both operands are equal after applying the same
+operator returns `true` if both operands are equal after applying the same
ordering on both collections.
Each of the special values `null`, `-INF`, and `INF` is equal to itself,
@@ -127,21 +153,21 @@ The special value `NaN` is not equal to anything, even to itself.
##### ##subsubsubsubsec Not Equals
-The `ne` operator returns true if the left operand is not equal to the
-right operand, otherwise it returns false.
+The `ne` operator returns `true` if the left operand is not equal to the
+right operand, otherwise it returns `false`.
-When applied to operands of entity types, the `ne` operator returns true
+When applied to operands of entity types, the `ne` operator returns `true`
if the two operands do not represent the same entity.
When applied to operands of complex types, the `ne` operator returns
-true if the operands do not have the same structure and same values.
+`true` if the operands do not have the same structure and same values.
-When applied to ordered collections, the `ne` operator returns true if
+When applied to ordered collections, the `ne` operator returns `true` if
both operands do not have the same cardinality or any member of the left
operand is not equal to the corresponding member of the right operand.
For services that support comparing unordered collections, the `ne`
-operator returns true if both operands do not have the same cardinality
+operator returns `true` if both operands do not have the same cardinality
or do not contain the same members, in any order.
Each of the special values `null`, `-INF`, and `INF` is not equal to any
@@ -153,8 +179,8 @@ The `null` value is not equal to any value but itself.
##### ##subsubsubsubsec Greater Than
-The `gt` operator returns true if the left operand is greater than the
-right operand, otherwise it returns false.
+The `gt` operator returns `true` if the left operand is greater than the
+right operand, otherwise it returns `false`.
The special value `INF` is greater than any number, and any number is
greater than `-INF`.
@@ -167,19 +193,19 @@ with language-dependent order with the term
[`Core.IsLanguageDependent`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#IsLanguageDependent),
see [OData-VocCore](#ODataVocCore).
-If any operand is `null`, the operator returns false.
+If any operand is `null`, the operator returns `false`.
##### ##subsubsubsubsec Greater Than or Equal
-The `ge` operator returns true if the left operand is greater than or
-equal to the right operand, otherwise it returns false.
+The `ge` operator returns `true` if the left operand is greater than or
+equal to the right operand, otherwise it returns `false`.
See rules for [`gt`](#GreaterThan) and [`eq`](#Equals) for details.
##### ##subsubsubsubsec Less Than
-The `lt` operator returns true if the left operand is less than the
-right operand, otherwise it returns false.
+The `lt` operator returns `true` if the left operand is less than the
+right operand, otherwise it returns `false`.
The special value `-INF` is less than any number, and any number is less
than `INF`.
@@ -192,43 +218,43 @@ with language-dependent order with the term
[`Core.IsLanguageDependent`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#IsLanguageDependent),
see [OData-VocCore](#ODataVocCore).
-If any operand is `null`, the operator returns false.
+If any operand is `null`, the operator returns `false`.
##### ##subsubsubsubsec Less Than or Equal
-The `le` operator returns true if the left operand is less than or equal
-to the right operand, otherwise it returns false.
+The `le` operator returns `true` if the left operand is less than or equal
+to the right operand, otherwise it returns `false`.
See rules for [`lt`](#LessThan) and [`eq`](#Equals) for details.
##### ##subsubsubsubsec And
-The `and` operator returns true if both the left and right operands
-evaluate to true, otherwise it returns false.
+The `and` operator returns `true` if both the left and right operands
+evaluate to `true`, otherwise it returns `false`.
The `null` value is treated as unknown, so if one operand evaluates to
-`null` and the other operand to false, the `and` operator returns false.
+`null` and the other operand to `false`, the `and` operator returns `false`.
All other combinations with `null` return `null`.
##### ##subsubsubsubsec Or
-The `or` operator returns false if both the left and right operands both
-evaluate to false, otherwise it returns true.
+The `or` operator returns `false` if both the left and right operands both
+evaluate to `false`, otherwise it returns `true`.
The `null` value is treated as unknown, so if one operand evaluates to
-`null` and the other operand to true, the `or` operator returns true.
+`null` and the other operand to `true`, the `or` operator returns `true`.
All other combinations with `null` return `null`.
##### ##subsubsubsubsec Not
-The `not` operator returns true if the operand returns false, otherwise
-it returns false.
+The `not` operator returns `true` if the operand returns `false`, otherwise
+it returns `false`.
The `null` value is treated as unknown, so `not null` returns `null`.
##### ##subsubsubsubsec Has
-The `has` operator returns true if the right operand is an enumeration
+The `has` operator returns `true` if the right operand is an enumeration
value whose flag(s) are set on the left operand.
The `null` value is treated as unknown, so if one operand evaluates to
@@ -236,11 +262,12 @@ The `null` value is treated as unknown, so if one operand evaluates to
##### ##subsubsubsubsec In
-The `in` operator returns true if the left operand is a member of the
-right operand. The right operand MUST be either a comma-separated list
+The `in` operator returns `true` if the [equality](#Equals) comparison of the left
+operand with at least one member of the right operand returns `true`.
+The right operand MUST be either a comma-separated list
of zero or more primitive values, enclosed in parentheses, or a single expression
that resolves to a collection. If the right operand is an empty collection
-or list of values, the expression returns false.
+or list of values, the `in` operator returns `false`.
##### ##subsubsubsubsec Logical Operator Examples
@@ -334,7 +361,8 @@ filter a collection of resources. However, services MAY allow using
arithmetic operators with the [`$orderby`](#SystemQueryOptionorderby)
system query option.
-If an operand of an arithmetic operator is null, the result is null.
+If an operand of an arithmetic operator is `null` or has a non-allowed type,
+the result is `null`.
The syntax rules for the arithmetic operators are defined in
[OData-ABNF](#ODataABNF). 4.01 Services MUST support case-insensitive
@@ -525,7 +553,8 @@ not defined. Instead, OData defines a [`null`](#null) literal that can
be used in comparisons.
If a parameter of a canonical function is `null`, the function returns
-`null`.
+`null`. If the types of parameters do not match the function signature,
+the function also returns `null`.
The syntax rules for all functions are defined in
[OData-ABNF](#ODataABNF). 4.01 Services MUST support case-insensitive
@@ -572,14 +601,14 @@ Edm.Boolean contains(Edm.String,Edm.String)
Edm.Boolean contains(OrderedCollection,OrderedCollection)
```
-The `contains` function with string parameter values returns true if the
+The `contains` function with string parameter values returns `true` if the
second string is a substring of the first string, otherwise it returns
-false. String comparison is case-sensitive, case-insensitive comparison
+`false`. String comparison is case-sensitive, case-insensitive comparison
can be achieved in combination with [`tolower`](#tolower) or
[`toupper`](#toupper).
The `contains` function with ordered collection parameter values returns
-true if the first collection can be transformed into the second
+`true` if the first collection can be transformed into the second
collection by removing zero or more items from the beginning or the end
of the first collection.
@@ -603,14 +632,14 @@ Edm.Boolean endswith(Edm.String,Edm.String)
Edm.Boolean endswith(OrderedCollection,OrderedCollection)
```
-The `endswith` function with string parameter values returns true if the
-first string ends with the second string, otherwise it returns false.
+The `endswith` function with string parameter values returns `true` if the
+first string ends with the second string, otherwise it returns `false`.
String comparison is case-sensitive, case-insensitive comparison can be
achieved in combination with [`tolower`](#tolower) or
[`toupper`](#toupper).
The `endswith` function with ordered collection parameter values returns
-true if the first collection can be transformed into the second
+`true` if the first collection can be transformed into the second
collection by removing zero or more items from the beginning of the
first collection.
@@ -693,14 +722,14 @@ Edm.Boolean startswith(Edm.String,Edm.String)
Edm.Boolean startswith(Collection,Collection)
```
-The `startswith` function with string parameter values returns true if
+The `startswith` function with string parameter values returns `true` if
the first string starts with the second string, otherwise it returns
-false. String comparison is case-sensitive, case-insensitive comparison
+`false`. String comparison is case-sensitive, case-insensitive comparison
can be achieved in combination with [`tolower`](#tolower) or
[`toupper`](#toupper).
The `startswith` function with ordered collection parameter values
-returns true if the first collection can be transformed into the second
+returns `true` if the first collection can be transformed into the second
collection by removing zero or more items from the end of the first
collection.
@@ -787,13 +816,13 @@ The `hassubset` function has the following signature:
Edm.Boolean hassubset(Collection, Collection)
```
-The `hassubset` function returns true if the first collection can be
+The `hassubset` function returns `true` if the first collection can be
transformed into the second collection by reordering and/or removing
zero or more items. The `hasSubsetMethodCallExpr` syntax rule defines
how the `hassubset` function is invoked.
::: example
-Example ##ex: `hassubset` expressions that return true
+Example ##ex: `hassubset` expressions that return `true`
```
hassubset([4,1,3],[4,1,3])
```
@@ -816,7 +845,7 @@ hassubset([4,1,3,1],[1,1])
:::
::: example
-Example ##ex: `hassubset` expression that returns false: 1 appears only
+Example ##ex: `hassubset` expression that returns `false`: `1` appears only
once in the left operand
```
hassubset([1,2],[1,1,2])
@@ -831,13 +860,13 @@ The `hassubsequence` function has the following signature:
Edm.Boolean hassubsequence(OrderedCollection,OrderedCollection)
```
-The `hassubsequence` function returns true if the first collection can
+The `hassubsequence` function returns `true` if the first collection can
be transformed into the second collection by removing zero or more
items. The `hasSubsequenceMethodCallExpr` syntax rule defines how the
`hassubsequence` function is invoked.
::: example
-Example ##ex: `hassubsequence` expressions that return true
+Example ##ex: `hassubsequence` expressions that return `true`
```
hassubsequence([4,1,3],[4,1,3])
```
@@ -856,7 +885,7 @@ hassubsequence([4,1,3,1],[1,1])
:::
::: example
-Example ##ex: `hassubsequence` expressions that return false
+Example ##ex: `hassubsequence` expressions that return `false`
```
hassubsequence([4,1,3],[1,3,4])
```
@@ -882,13 +911,15 @@ Edm.Boolean matchespattern(Edm.String,Edm.String,Edm.String)
```
The second parameter MUST evaluate to a string containing an
-[ECMAScript](#_ECMAScript) (JavaScript) regular expression. The
-`matchespattern` function returns true if the first parameter evaluates
+[ECMAScript](#_ECMAScript) (JavaScript) regular expression, otherwise the function
+returns `null`. The
+`matchespattern` function returns `true` if the first parameter evaluates
to a string matching that regular expression, using syntax and semantics
of ECMAScript regular expressions, otherwise it
-returns false.
+returns `false`.
If the optional third parameter is provided, it MUST evaluate to a string
-consisting of ECMAScript regular expression flags to modify the match.
+consisting of ECMAScript regular expression flags to modify the match, otherwise
+the function returns `null`.
::: example
Example ##ex: all customers with a `CompanyName` that match the
@@ -1343,9 +1374,6 @@ The `cast` function follows these assignment rules:
[section 3.3.7 dateTime](https://www.w3.org/TR/xmlschema11-2/#dateTime), can be cast to `Edm.DateTimeOffset`.
If the string value does not contain a time-zone offset, it is treated as UTC.
-The `cast` function is optional for primitive values (first five rules)
-and up-casts (seventh rule).
-
If the cast fails, the `cast` function returns `null`.
##### ##subsubsubsubsec `isof`
@@ -1357,14 +1385,14 @@ Edm.Boolean isof(type)
Edm.Boolean isof(expression,type)
```
-The single parameter `isof` function returns true if the current
+The single parameter `isof` function returns `true` if the current
instance is assignable to the type specified, according to the
assignment rules for the [`cast`](#cast) function, otherwise it returns
`false`.
-The two parameter `isof` function returns true if the object referred to
+The two parameter `isof` function returns `true` if the object referred to
by the expression is assignable to the type specified, according to the
-same rules, otherwise it returns false.
+same rules, otherwise it returns `false`.
The `isofExpr` syntax rule defines how the `isof` function is invoked.
@@ -1410,9 +1438,9 @@ Edm.Boolean geo.intersects(Edm.GeographyPoint,Edm.GeographyPolygon)
Edm.Boolean geo.intersects(Edm.GeometryPoint,Edm.GeometryPolygon)
```
-The `geo.intersects` function returns true if the specified point lies
+The `geo.intersects` function returns `true` if the specified point lies
within the interior or on the boundary of the specified polygon,
-otherwise it returns false.
+otherwise it returns `false`.
##### ##subsubsubsubsec `geo.length`
@@ -1445,7 +1473,7 @@ The case function evaluates the condition in each pair, starting with
the leftmost pair, and stops as soon as a condition evaluates to `true`.
It then returns the value of the result of this pair. It returns `null`
if none of the conditions in any pair evaluates to `true`. Clients can
-specify a last pair whose condition is `true` to get a non-null
+specify a last pair whose condition is `true` to get a non-`null`
"default/else/otherwise" result.
Boolean expressions containing `DateTimeOffset` or `TimeOfDay` literals without
@@ -1498,12 +1526,12 @@ the lambda operator.
##### ##subsubsubsubsec `any`
The `any` operator applies a Boolean expression to each member of a
-collection and returns true if and only if the expression is true for
-any member of the collection, otherwise it returns false. This implies
-that the `any` operator always returns false for an empty collection.
+collection and returns `true` if and only if the expression is `true` for
+any member of the collection, otherwise it returns `false`. This implies
+that the `any` operator always returns `false` for an empty collection.
The `any` operator can be used without an argument expression. This
-short form returns false if and only if the collection is empty.
+short form returns `false` if and only if the collection is empty.
::: example
Example ##ex: all `Orders` that have any `Items` with a `Quantity` greater
@@ -1535,9 +1563,9 @@ http://host/service/Categories?$expand=Products(
##### ##subsubsubsubsec `all`
The `all` operator applies a Boolean expression to each member of a
-collection and returns true if the expression is true for all members of
-the collection, otherwise it returns false. This implies that the `all`
-operator always returns true for an empty collection.
+collection and returns `true` if the expression is `true` for all members of
+the collection, otherwise it returns `false`. This implies that the `all`
+operator always returns `true` for an empty collection.
The `all` operator cannot be used without an argument expression.
@@ -1826,7 +1854,7 @@ of the specified derived type, the path expression returns `null`.
If the property or navigation property is not defined for the type of
the resource and that type supports dynamic properties or navigation
-properties, then the property or navigation property is treated as null
+properties, then the property or navigation property is treated as `null`
for all instances on which it has no value.
If the property or navigation property is not defined for the type of
@@ -1941,9 +1969,9 @@ types.
The `$filter` system query option allows clients to filter a collection
of resources that are addressed by a request URL. The expression
specified with `$filter` is evaluated for each resource in the
-collection, and only items where the expression evaluates to true are
+collection, and only items where the expression evaluates to `true` are
included in the response. Resources for which the expression evaluates
-to false or to null, or which reference properties that are unavailable
+to `false` or to `null`, or which reference properties that are unavailable
due to permissions, are omitted from the response.
The [OData-ABNF](#ODataABNF) `filter` syntax rule defines the formal
@@ -2221,7 +2249,7 @@ http://host/service/Products?$select=*
If the select item is not defined for the type of the resource, and that
type supports dynamic properties or instance annotations, then the
-property is treated as null for all instances on which it is not
+property is treated as `null` for all instances on which it is not
defined.
If the select item is not defined for the type of the resource, and that
@@ -2408,7 +2436,7 @@ Leading and trailing spaces are not considered part of the search expression.
Terms enclosed in double-quotes comprise a *phrase*.
Each individual term or phrase comprises a Boolean expression that
-returns true if the term or phrase is matched, otherwise false. The
+returns `true` if the term or phrase is matched, otherwise `false`. The
semantics of what is considered a match is dependent upon the service.
Expressions enclosed in parenthesis comprise a *group expression*.
@@ -2417,16 +2445,16 @@ The search expression can contain any number of terms, phrases, or group
expressions, along with the case-sensitive keywords `NOT`, `AND`, and
`OR`, evaluated in that order.
-Expressions prefaced with `NOT` evaluate to true if the expression is
-not matched, otherwise false.
+Expressions prefaced with `NOT` evaluate to `true` if the expression is
+not matched, otherwise `false`.
Two expressions not enclosed in quotes and separated by a space are
equivalent to the same two expressions separated by the `AND` keyword.
Such expressions evaluate to `true` if both expressions evaluate to
-true, otherwise false.
+`true`, otherwise `false`.
-Expressions separated by an `OR` evaluate to true if either of the
-expressions evaluate to true, otherwise false.
+Expressions separated by an `OR` evaluate to `true` if either of the
+expressions evaluate to `true`, otherwise `false`.
To support type-ahead use cases, incomplete search expressions can be
sent as OData string literals enclosed in single-quotes, and