From 3289b29e7d893e05a198ce9eac705623a68dab51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Wed, 28 Aug 2024 17:18:07 +0200 Subject: [PATCH] Style improvements (#1979) --- docs/odata-csdl-json/odata-csdl-json.html | 4 +- docs/odata-csdl-json/odata-csdl-json.md | 2 +- docs/odata-csdl-json/styles/odata.css | 9 +- docs/odata-csdl-xml/odata-csdl-xml.html | 4 +- docs/odata-csdl-xml/odata-csdl-xml.md | 2 +- docs/odata-csdl-xml/styles/odata.css | 9 +- .../odata-data-aggregation-ext.html | 110 +- .../odata-data-aggregation-ext.md | 112 +- .../styles/odata.css | 9 +- docs/odata-json-format/odata-json-format.html | 1988 +++++++++-------- docs/odata-json-format/odata-json-format.md | 10 +- docs/odata-json-format/styles/odata.css | 9 +- docs/odata-protocol/odata-protocol.html | 4 +- docs/odata-protocol/odata-protocol.md | 2 +- docs/odata-protocol/styles/odata.css | 9 +- .../odata-temporal-ext.html | 4 +- docs/odata-temporal-ext/odata-temporal-ext.md | 2 +- docs/odata-temporal-ext/styles/odata.css | 9 +- .../odata-url-conventions.html | 7 +- .../odata-url-conventions.md | 11 +- docs/odata-url-conventions/styles/odata.css | 9 +- lib/README.md | 22 +- lib/pandoc.js | 2 +- odata-csdl/1 Introduction.md | 2 +- odata-data-aggregation-ext/1 Introduction.md | 2 +- .../3.2 Basic Aggregation.md | 34 +- ...ations Changing the Input Set Structure.md | 2 +- .../6 Hierarchical Transformations.md | 140 +- odata-json-format/1 Introduction.md | 2 +- odata-json-format/4 Common Characteristics.md | 8 +- odata-protocol/1 Introduction.md | 2 +- odata-temporal-ext/1 Introduction.md | 2 +- odata-url-conventions/1 Introduction.md | 2 +- odata-url-conventions/4 Resource Path.md | 2 +- odata-url-conventions/5 Query Options.md | 4 +- styles/odata.css | 9 +- 36 files changed, 1337 insertions(+), 1223 deletions(-) diff --git a/docs/odata-csdl-json/odata-csdl-json.html b/docs/odata-csdl-json/odata-csdl-json.html index d5d6cf040..82ef3b238 100644 --- a/docs/odata-csdl-json/odata-csdl-json.html +++ b/docs/odata-csdl-json/odata-csdl-json.html @@ -93,7 +93,7 @@ ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; @@ -462,7 +462,7 @@

1.2.3 Document Conventions

-

Keywords defined by this specification use this monospaced font.

+

Keywords defined by this specification use this monospaced font.

Some sections of this specification are illustrated with non-normative examples.

Example 1: text describing an example uses this paragraph style

diff --git a/docs/odata-csdl-json/odata-csdl-json.md b/docs/odata-csdl-json/odata-csdl-json.md index 2f5195465..6a782123f 100644 --- a/docs/odata-csdl-json/odata-csdl-json.md +++ b/docs/odata-csdl-json/odata-csdl-json.md @@ -283,7 +283,7 @@ Section | Feature / Change | Issue ### 1.2.3 Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/docs/odata-csdl-json/styles/odata.css b/docs/odata-csdl-json/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/docs/odata-csdl-json/styles/odata.css +++ b/docs/odata-csdl-json/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code, diff --git a/docs/odata-csdl-xml/odata-csdl-xml.html b/docs/odata-csdl-xml/odata-csdl-xml.html index 22b959f2c..58749e62b 100644 --- a/docs/odata-csdl-xml/odata-csdl-xml.html +++ b/docs/odata-csdl-xml/odata-csdl-xml.html @@ -93,7 +93,7 @@ ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; @@ -466,7 +466,7 @@

1.2.3 Document Conventions

-

Keywords defined by this specification use this monospaced font.

+

Keywords defined by this specification use this monospaced font.

Some sections of this specification are illustrated with non-normative examples.

Example 1: text describing an example uses this paragraph style

diff --git a/docs/odata-csdl-xml/odata-csdl-xml.md b/docs/odata-csdl-xml/odata-csdl-xml.md index ffc9f3439..71713f017 100644 --- a/docs/odata-csdl-xml/odata-csdl-xml.md +++ b/docs/odata-csdl-xml/odata-csdl-xml.md @@ -284,7 +284,7 @@ Section | Feature / Change | Issue ### 1.2.3 Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/docs/odata-csdl-xml/styles/odata.css b/docs/odata-csdl-xml/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/docs/odata-csdl-xml/styles/odata.css +++ b/docs/odata-csdl-xml/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code, diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html index 5569267bf..0685508b9 100644 --- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html +++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.html @@ -93,7 +93,7 @@ ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; @@ -375,7 +375,7 @@

1.1.3 Document Conventions

-

Keywords defined by this specification use this monospaced font.

+

Keywords defined by this specification use this monospaced font.

Some sections of this specification are illustrated with non-normative examples.

Example 1: text describing an example uses this paragraph style

@@ -2019,11 +2019,28 @@

\(p_1,…,p_k\) are groupable property paths representing a level, \(T\) is a transformation sequence, the ellipsis (\(…\)) stands in for zero or more property paths, \(P_1\) stands in for zero or more property paths and \(P_2\) for zero or more rollup or rolluprecursive operators or property paths:

    -
  • \({\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1},p_k),P_2),T)\) is equivalent to \[\matrix{ {\tt concat}(\hfill\\ \quad {\tt groupby}((P_1,p_1,…,p_{k-1},p_k,P_2),T),\hfill&\tt (1)\\ \quad {\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1}),P_2),T)\hfill&\tt(2)\\ ).\hskip25pc\\ }\]
  • -
  • \({\tt groupby}((P_1,{\tt rollup}(p_1,p_2),P_2),T)\) is equivalent to \[\matrix{ {\tt concat}(\hfill&\tt (3)\\ \quad {\tt groupby}((P_1,p_1,p_2,P_2),T),\hfill\\ \quad {\tt groupby}((P_1,p_1,P_2),T)\hfill\\ ).\hskip25pc\\ }\]
  • +
  • \({\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1},p_k),P_2),T)\) is equivalent to \[\matrix{ +{\tt concat}(\hfill\\ +\quad {\tt groupby}((P_1,p_1,…,p_{k-1},p_k,P_2),T),\hfill&\tt (1)\\ +\quad {\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1}),P_2),T)\hfill&\tt(2)\\ +).\hskip25pc +}\]
  • +
  • \({\tt groupby}((P_1,{\tt rollup}(p_1,p_2),P_2),T)\) is equivalent to \[\matrix{ +{\tt concat}(\hfill&\tt (3)\\ +\quad {\tt groupby}((P_1,p_1,p_2,P_2),T),\hfill\\ +\quad {\tt groupby}((P_1,p_1,P_2),T)\hfill\\ +).\hskip25pc +}\]
-

Example 22: rolling up two hierarchies, the first with two levels, the second with three levels: \[({\tt rollup}(p_{1,1},p_{1,2}),{\tt rollup}(p_{2,1},p_{2,2},p_{2,3}))\] will result in the six groupings \[\matrix{ (p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ (p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2})\hfill\\ (p_{1,1},p_{1,2},\hfill&p_{2,1})\hfill\\ (p_{1,1},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ (p_{1,1},\hfill&p_{2,1},p_{2,2})\hfill\\ (p_{1,1},\hfill&p_{2,1})\hfill }\] The leveled hierarchy of the first rollup has 2 levels, the one of the second has 3 levels, and the groupings represent all possible \(6=2⋅3\) combinations of levels from both hierarchies.

+

Example 22: rolling up two hierarchies, the first with two levels, the second with three levels: \[({\tt rollup}(p_{1,1},p_{1,2}),{\tt rollup}(p_{2,1},p_{2,2},p_{2,3}))\] will result in the six groupings \[\matrix{ +(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ +(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2})\hfill\\ +(p_{1,1},p_{1,2},\hfill&p_{2,1})\hfill\\ +(p_{1,1},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ +(p_{1,1},\hfill&p_{2,1},p_{2,2})\hfill\\ +(p_{1,1},\hfill&p_{2,1})\hfill +}\] The leveled hierarchy of the first rollup has 2 levels, the one of the second has 3 levels, and the groupings represent all possible \(6=2⋅3\) combinations of levels from both hierarchies.

Example 23: answering the second question in section 2.3

@@ -2306,7 +2323,7 @@

alias.

-

The output set is constructed by copying the instances of the input set and adding one dynamic property per compute expression to each occurrence in the output set. The name of each added dynamic property is the alias of the corresponding compute expression. The value of each added dynamic property is computed relative to the corresponding instance. Services MAY support expressions that address dynamic properties added by other expressions within the same compute transformation, provided that the service can determine an evaluation sequence. The type of the property is determined by the rules for evaluating common expressions and numeric promotion defined in OData-URL, section 5.1.1.

+

The output set is constructed by copying the instances of the input set and adding one dynamic property per compute expression to each occurrence in the output set. The name of each added dynamic property is the alias of the corresponding compute expression. The value of each added dynamic property is computed relative to the corresponding instance. Services MAY support expressions that address dynamic properties added by other expressions within the same compute transformation, provided that the service can determine an evaluation sequence. The type of the property is determined by the rules for evaluating common expressions and numeric promotion defined in OData-URL, section 5.1.1.

Example 37:

GET /service/Sales?$apply=compute(Amount mul Product/TaxRate as Tax)
@@ -2998,9 +3015,47 @@

\(T\) composed of transformations listed section 3.3 or section 6.2.1 and of service-defined bound functions whose output set is a subset of their input set. \(A\) is the output set of this sequence applied to the input set.

The fifth parameter \(d\) is optional and takes an integer greater than or equal to 1 that specifies the maximum distance between start nodes and ancestors or descendants to be considered. An optional final keep start parameter drives the optional inclusion of the subset or start nodes.

The output set of the transformation \({\tt ancestors}(H,Q,p,T,d,{\tt keep\ start})\) or \({\tt descendants}(H,Q,p,T,d,{\tt keep\ start})\) is defined as the union of the output sets of transformations \(F(u)\) applied to the input set for all \(u\) in \(A\). For a given instance \(u\), the transformation \(F(u)\) determines all instances of the input set whose node identifier is an ancestor or descendant of the node identifier of \(u\):

-

If \(p\) contains only single-valued segments, then, for ancestors, \[\matrix{ F(u)={\tt filter}(\hbox{\tt Aggregation.isancestor}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Descendant}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}))\hfill }\] or, for descendants, \[\matrix{ F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill }\]

+

If \(p\) contains only single-valued segments, then, for ancestors, \[\matrix{ +F(u)={\tt filter}(\hbox{\tt Aggregation.isancestor}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Descendant}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}))\hfill +}\] or, for descendants, \[\matrix{ +F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill +}\]

Otherwise \(p=p_1/…/p_k/r\) with \(k≥1\), in this case the output set of the transformation \(F(u)\) is defined as the union of the output sets of transformations \(G(n)\) applied to the input set for all \(n\) in \(γ(u,p)\). The output set of \(G(n)\) consists of the instances of the input set whose node identifier is an ancestor or descendant of the node identifier \(n\):

-

For ancestors, \[\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }\] or, for descendants, \[\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }\] where \(y_1,…,y_k\) denote lambdaVariableExprs as defined in OData-ABNF and \({}/r\) may be absent.

+

For ancestors, \[\matrix{ +G(n)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}\] or, for descendants, \[\matrix{ +G(n)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}\] where \(y_1,…,y_k\) denote lambdaVariableExprs as defined in OData-ABNF and \({}/r\) may be absent.

If parameter \(d\) is absent, the parameter \({\tt MaxDistance}=d\) is omitted. If keep start is absent, the parameter \({\tt IncludeSelf}={\tt true}\) is omitted.

Since the output set of ancestors is constructed as a union, no instance from the input set will occur more than once in it, even if, for example, a sale is related to both a sales organization and one of its ancestor organizations. For descendants, analogously.

@@ -3071,7 +3126,7 @@

6.2.2 Transformation traverse

-

The traverse transformation returns instances of the input set that are or are related to nodes of a given recursive hierarchy in a specified tree order.

+

The traverse transformation returns instances of the input set that are or are related to nodes of a given recursive hierarchy in a specified tree order.

\(H\), \(Q\) and \(p\) are the first three parameters defined above.

The fourth parameter \(h\) of the traverse transformation is either preorder or postorder. \(S\) is an optional fifth parameter as defined above. Let \(H'\) be the output set of the transformation sequence \(S\) applied to \(H\), or let \(H'\) be the collection of root nodes in the recursive hierarchy \((H,Q)\) if \(S\) is not specified. Nodes in \(H'\) are called start nodes in this subsection (see example 117).

All following parameters are optional and form a list \(o\) of expressions that could also be passed as a $orderby system query option. If \(o\) is present, the transformation stable-sorts \(H'\) by \(o\).

@@ -3115,7 +3170,19 @@

\(F(x)\) is a transformation that determines for the specified node \(x\) the instances of the input set having the same node identifier as \(x\).

If \(p\) contains only single-valued segments, then \[F(x)={\tt filter}(p{\tt\ eq\ }x[q]).\]

-

Otherwise \(p=p_1/…/p_k/r\) with \(k≥1\) and \[\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }\] where \(y_1,…,y_k\) denote lambdaVariableExprs and \({}/r\) may be absent.

+

Otherwise \(p=p_1/…/p_k/r\) with \(k≥1\) and \[\matrix{ +F(x)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}\] where \(y_1,…,y_k\) denote lambdaVariableExprs and \({}/r\) may be absent.

Example 63: Based on the SalesOrgHierarchy defined in Hierarchy Examples

GET /service/SalesOrganizations?$apply=
@@ -3197,8 +3264,27 @@ 

If at least one of \(P_1\) or \(P_2\) is non-empty, then \[R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/{\tt groupby}((P_1,P_2),T/Z_N/\Pi_G(σ(x))).\]

The property \(χ_N=x\) is present during the evaluation of \(T\), but not afterwards. If \(P_2\) contains a rolluprecursive operator, the evaluation of the formula involves a recursive invocation (with \(N\) increased by 1) of the rolluprecursive algorithm.

Otherwise if \(P_1\) and \(P_2\) are empty, then \[R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x)).\]

-

\(F(x)\) is defined as follows: If \(p\) contains only single-valued segments, then \[\matrix{ F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill }\]

-

Otherwise \(p=p_1/…/p_k/r\) with \(k≥1\) and \[\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }\] where \(y_1,…,y_k\) denote lambdaVariableExprs and \({}/r\) may be absent. (See example 113 for a case with \(k=1\).)

+

\(F(x)\) is defined as follows: If \(p\) contains only single-valued segments, then \[\matrix{ +F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill +}\]

+

Otherwise \(p=p_1/…/p_k/r\) with \(k≥1\) and \[\matrix{ +F(x)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}\] where \(y_1,…,y_k\) denote lambdaVariableExprs and \({}/r\) may be absent. (See example 113 for a case with \(k=1\).)

Informatively speaking, the effect of the algorithm can be summarized as follows: If \(M≥1\) and \(\hat F_N(x)\) denotes the collection of all instances that are related to a node \(x\) as determined by \(F(x)\) in the recursive hierarchy of the \(N\)-th rolluprecursive operator, then \(T\) is applied to each of the intersections of \(\hat F_1(χ_1),…,\hat F_M(χ_M)\), as \(χ_N\) runs over all nodes of the \(N\)-th recursive hierarchy for \(1≤N≤M\). Into the instances of the resulting output sets the \(\Pi_G\) transformations inject information about the nodes \(χ_1,…,χ_M\).

Example 65: Total number of sub-organizations for all organizations in the hierarchy defined in Hierarchy Examples with \(p=q={\tt ID}\) (case 1 of the definition of \(σ(x)\)). In this case \(\Pi_G(σ(x))\) writes back the entire node into the output set of \(T\), aggregates must have an alias to avoid overwriting by a property of the node with the same name.

diff --git a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md index 5749ad417..bdadb56b2 100644 --- a/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md +++ b/docs/odata-data-aggregation-ext/odata-data-aggregation-ext.md @@ -237,7 +237,7 @@ The following non-exhaustive list contains variable names that are used througho ### 1.1.3 Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. @@ -1552,15 +1552,32 @@ A groupby with `rollup` applied to a leveled hierarchy allows requesting aggrega Such a grouping with `rollup` for a leveled hierarchy is processed using the following equivalence relationships, in which $p_1,…,p_k$ are groupable property paths representing a level, $T$ is a transformation sequence, the ellipsis ($…$) stands in for zero or more property paths, $P_1$ stands in for zero or more property paths and $P_2$ for zero or more `rollup` or [`rolluprecursive`](#Groupingwithrolluprecursive) operators or property paths: - ${\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1},p_k),P_2),T)$ is equivalent to - $$\matrix{ {\tt concat}(\hfill\\ \quad {\tt groupby}((P_1,p_1,…,p_{k-1},p_k,P_2),T),\hfill&\tt (1)\\ \quad {\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1}),P_2),T)\hfill&\tt(2)\\ ).\hskip25pc\\ }$$ + $$\matrix{ + {\tt concat}(\hfill\\ + \quad {\tt groupby}((P_1,p_1,…,p_{k-1},p_k,P_2),T),\hfill&\tt (1)\\ + \quad {\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1}),P_2),T)\hfill&\tt(2)\\ + ).\hskip25pc + }$$ - ${\tt groupby}((P_1,{\tt rollup}(p_1,p_2),P_2),T)$ is equivalent to - $$\matrix{ {\tt concat}(\hfill&\tt (3)\\ \quad {\tt groupby}((P_1,p_1,p_2,P_2),T),\hfill\\ \quad {\tt groupby}((P_1,p_1,P_2),T)\hfill\\ ).\hskip25pc\\ }$$ + $$\matrix{ + {\tt concat}(\hfill&\tt (3)\\ + \quad {\tt groupby}((P_1,p_1,p_2,P_2),T),\hfill\\ + \quad {\tt groupby}((P_1,p_1,P_2),T)\hfill\\ + ).\hskip25pc + }$$ ::: example Example 22: rolling up two hierarchies, the first with two levels, the second with three levels: $$({\tt rollup}(p_{1,1},p_{1,2}),{\tt rollup}(p_{2,1},p_{2,2},p_{2,3}))$$ will result in the six groupings -$$\matrix{ (p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ (p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2})\hfill\\ (p_{1,1},p_{1,2},\hfill&p_{2,1})\hfill\\ (p_{1,1},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ (p_{1,1},\hfill&p_{2,1},p_{2,2})\hfill\\ (p_{1,1},\hfill&p_{2,1})\hfill }$$ +$$\matrix{ +(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ +(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2})\hfill\\ +(p_{1,1},p_{1,2},\hfill&p_{2,1})\hfill\\ +(p_{1,1},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ +(p_{1,1},\hfill&p_{2,1},p_{2,2})\hfill\\ +(p_{1,1},\hfill&p_{2,1})\hfill +}$$ The leveled hierarchy of the first rollup has 2 levels, the one of the second has 3 levels, and the groupings represent all possible $6=2⋅3$ combinations of levels from both hierarchies. ::: @@ -1910,7 +1927,7 @@ The `compute` transformation takes a comma-separated list of one or more _comput A compute expression is a common expression followed by the `as` keyword, followed by an [alias](#TypeStructureandContextURL). -The output set is constructed by copying the instances of the input set and adding one dynamic property per compute expression to [each occurrence](#SamenessandOrder) in the output set. The name of each added dynamic property is the alias of the corresponding compute expression. The value of each added dynamic property is computed relative to the corresponding instance. Services MAY support expressions that address dynamic properties added by other expressions within the same compute transformation, provided that the service can determine an evaluation sequence. The type of the property is determined by the rules for evaluating common expressions and numeric promotion defined in [OData-URL, section 5.1.1](#ODataURL). +The output set is constructed by copying the instances of the input set and adding one dynamic property per compute expression to [each occurrence](#SamenessandOrder) in the output set. The name of each added dynamic property is the alias of the corresponding compute expression. The value of each added dynamic property is computed relative to the corresponding instance. Services MAY support expressions that address dynamic properties added by other expressions within the same `compute` transformation, provided that the service can determine an evaluation sequence. The type of the property is determined by the rules for evaluating common expressions and numeric promotion defined in [OData-URL, section 5.1.1](#ODataURL). ::: example Example 37: @@ -2713,16 +2730,54 @@ The fifth parameter $d$ is optional and takes an integer greater than or equal t The output set of the transformation ${\tt ancestors}(H,Q,p,T,d,{\tt keep\ start})$ or ${\tt descendants}(H,Q,p,T,d,{\tt keep\ start})$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $F(u)$ applied to the input set for all $u$ in $A$. For a given instance $u$, the transformation $F(u)$ determines all instances of the input set whose node identifier is an ancestor or descendant of the node identifier of $u$: If $p$ contains only single-valued segments, then, for `ancestors`, -$$\matrix{ F(u)={\tt filter}(\hbox{\tt Aggregation.isancestor}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Descendant}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}))\hfill }$$ +$$\matrix{ +F(u)={\tt filter}(\hbox{\tt Aggregation.isancestor}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Descendant}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}))\hfill +}$$ or, for `descendants`, -$$\matrix{ F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill }$$ +$$\matrix{ +F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill +}$$ Otherwise $p=p_1/…/p_k/r$ with $k≥1$, in this case the output set of the transformation $F(u)$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $G(n)$ applied to the input set for all $n$ in $γ(u,p)$. The output set of $G(n)$ consists of the instances of the input set whose node identifier is an ancestor or descendant of the node identifier $n$: For `ancestors`, -$$\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$ +$$\matrix{ +G(n)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}$$ or, for `descendants`, -$$\matrix{ G(n)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$ +$$\matrix{ +G(n)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}$$ where $y_1,…,y_k$ denote `lambdaVariableExpr`s as defined in [OData-ABNF](#ODataABNF) and ${}/r$ may be absent. If parameter $d$ is absent, the parameter ${\tt MaxDistance}=d$ is omitted. If `keep start` is absent, the parameter ${\tt IncludeSelf}={\tt true}$ is omitted. @@ -2810,7 +2865,7 @@ results in ### 6.2.2 Transformation `traverse` -The traverse transformation returns instances of the input set that are or are related to nodes of a given recursive hierarchy in a specified tree order. +The `traverse` transformation returns instances of the input set that are or are related to nodes of a given recursive hierarchy in a specified tree order. $H$, $Q$ and $p$ are the first three parameters defined [above](#CommonParametersforHierarchicalTransformations). @@ -2874,7 +2929,19 @@ If $p$ contains only single-valued segments, then $$F(x)={\tt filter}(p{\tt\ eq\ }x[q]).$$ Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and -$$\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$ +$$\matrix{ +F(x)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}$$ where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent. ::: example @@ -2992,10 +3059,29 @@ Otherwise if $P_1$ and $P_2$ are empty, then $$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x)).$$ $F(x)$ is defined as follows: If $p$ contains only single-valued segments, then -$$\matrix{ F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ \quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill }$$ +$$\matrix{ +F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill +}$$ Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and -$$\matrix{ F(x)={\tt filter}(\hfill\\ \hskip1pc p_1/{\tt any}(y_1:\hfill\\ \hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ \hskip3pc ⋱\hfill\\ \hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ \hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ \hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ \hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ \hskip5pc )\hfill\\ \hskip4pc )\hfill\\ \hskip3pc ⋰\hfill\\ \hskip2pc )\hfill\\ \hskip1pc )\hfill\\ )\hfill }$$ +$$\matrix{ +F(x)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill +}$$ where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent. (See [example 113](#rollupcoll) for a case with $k=1$.) Informatively speaking, the effect of the algorithm can be summarized as follows: If $M≥1$ and $\hat F_N(x)$ denotes the collection of all instances that are related to a node $x$ as determined by $F(x)$ in the recursive hierarchy of the $N$-th `rolluprecursive` operator, then $T$ is applied to each of the intersections of $\hat F_1(χ_1),…,\hat F_M(χ_M)$, as $χ_N$ runs over all nodes of the $N$-th recursive hierarchy for $1≤N≤M$. Into the instances of the resulting output sets the $\Pi_G$ transformations inject information about the nodes $χ_1,…,χ_M$. diff --git a/docs/odata-data-aggregation-ext/styles/odata.css b/docs/odata-data-aggregation-ext/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/docs/odata-data-aggregation-ext/styles/odata.css +++ b/docs/odata-data-aggregation-ext/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code, diff --git a/docs/odata-json-format/odata-json-format.html b/docs/odata-json-format/odata-json-format.html index 0226461aa..60fca4ea6 100644 --- a/docs/odata-json-format/odata-json-format.html +++ b/docs/odata-json-format/odata-json-format.html @@ -93,7 +93,7 @@ ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; @@ -381,7 +381,7 @@

1.2.3 Document Conventions

-

Keywords defined by this specification use this monospaced font.

+

Keywords defined by this specification use this monospaced font.

Some sections of this specification are illustrated with non-normative examples.

Example 1: text describing an example uses this paragraph style

@@ -565,8 +565,10 @@

4.3 Relati "Orders@navigationLink": "Customers('ALFKI')/Orders", }

+

The resulting absolute URLs are

+
http://host/service/Customers('ALFKI')
+http://host/service/Customers('ALFKI')/Orders

-

The resulting absolute URLs are http://host/service/Customers('ALFKI') and http://host/service/Customers('ALFKI')/Orders.

4.4 Payload Ordering Constraints

@@ -611,11 +613,11 @@

relative URLs in the request payload.

Example 4:

-
{
-  "@context": "http://host/service/$metadata#Customers/$entity",
-  "@metadataEtag": "W/\"A1FF3E230954908F\"",
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Customers/$entity",
+  "@metadataEtag": "W/\"A1FF3E230954908F\"",
+  
+}

@@ -647,23 +649,23 @@

OData-CSDLJSON or OData-CSDLXML.

Example 5: entity of type Model.VipCustomer defined in the metadata document of the same service with a dynamic property of type Edm.Date

-
{
-  "@context": "http://host/service/$metadata#Customers/$entity",
-  "@type": "#Model.VipCustomer",
-  "ID": 2,
-  "DynamicValue@type": "Date",
-  "DynamicValue": "2016-09-22",
-  
-}
-
-
-

Example 6: entity of type Model.VipCustomer defined in the metadata document of a different service

{
   "@context": "http://host/service/$metadata#Customers/$entity",
-  "@type": "http://host/alternate/$metadata#Model.VipCustomer",
+  "@type": "#Model.VipCustomer",
   "ID": 2,
-  
-}
+ "DynamicValue@type": "Date", + "DynamicValue": "2016-09-22", + +}
+

+
+

Example 6: entity of type Model.VipCustomer defined in the metadata document of a different service

+
{
+  "@context": "http://host/service/$metadata#Customers/$entity",
+  "@type": "http://host/alternate/$metadata#Model.VipCustomer",
+  "ID": 2,
+  
+}
@@ -754,13 +756,13 @@

Example 7:

-
{
-  "@context": "http://host/service/$metadata#Employees/$entity",
-  "@mediaReadLink": "Employees(1)/$value",
-  "@mediaContentType": "image/jpeg",
-  "ID": 1,
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Employees/$entity",
+  "@mediaReadLink": "Employees(1)/$value",
+  "@mediaContentType": "image/jpeg",
+  "ID": 1,
+  
+}

@@ -774,26 +776,26 @@

Example 8: Annotating primitive values within a collection

-
{
-  "@context": "http://host/service/$metadata#Employees/$entity",
-  "ID": 1,
-  "EmailAddresses@collectionAnnotations": [
-    {
-      "index": 0,
-      "@OfficeCommunication.emailType": "Personal"
-    },
-    {
-      "index": 2,
-      "@OfficeCommunication.emailType": "Work"
-    }
-  ],
-  "EmailAddresses": [
-    "Julie@Swansworth.com",
-    "JulieSwa@live.com",
-    "Julie.Swansworth@work.com"
-  ],
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Employees/$entity",
+  "ID": 1,
+  "EmailAddresses@collectionAnnotations": [
+    {
+      "index": 0,
+      "@OfficeCommunication.emailType": "Personal"
+    },
+    {
+      "index": 2,
+      "@OfficeCommunication.emailType": "Work"
+    }
+  ],
+  "EmailAddresses": [
+    "Julie@Swansworth.com",
+    "JulieSwa@live.com",
+    "Julie.Swansworth@work.com"
+  ],
+  
+}

@@ -814,38 +816,38 @@

5

Service documents MAY contain annotations in any of its JSON objects. Services MUST NOT produce name/value pairs other than the ones explicitly defined in this section, and clients MUST ignore unknown name/value pairs.

Example 9:

-
{
-  "@context": "http://host/service/$metadata",
-  "value": [
-    {
-      "name": "Orders",
-      "kind": "EntitySet",
-      "url":  "Orders"
-    },
-    {
-      "name":  "OrderItems",
-      "title": "Order Details",
-      "url":   "OrderItems"
-    },
-    {
-      "name":  "TopProducts",
-      "title": "Best-Selling Products",
-      "kind":  "FunctionImport",
-      "url":   "TopProducts"
-    },
-    {
-      "name":  "MainSupplier",
-      "title": "Main Supplier",
-      "kind":  "Singleton",
-      "url":   "MainSupplier"
-    },
-    {
-      "name": "Human Resources",
-      "kind": "ServiceDocument",
-      "url":  "http://host/HR/"
-    }
-  ]
-}
+
{
+  "@context": "http://host/service/$metadata",
+  "value": [
+    {
+      "name": "Orders",
+      "kind": "EntitySet",
+      "url":  "Orders"
+    },
+    {
+      "name":  "OrderItems",
+      "title": "Order Details",
+      "url":   "OrderItems"
+    },
+    {
+      "name":  "TopProducts",
+      "title": "Best-Selling Products",
+      "kind":  "FunctionImport",
+      "url":   "TopProducts"
+    },
+    {
+      "name":  "MainSupplier",
+      "title": "Main Supplier",
+      "kind":  "Singleton",
+      "url":   "MainSupplier"
+    },
+    {
+      "name": "Human Resources",
+      "kind": "ServiceDocument",
+      "url":  "http://host/HR/"
+    }
+  ]
+}

@@ -858,44 +860,44 @@

6 Entity

An entity representation can be (modified and) round-tripped to the service directly. The context URL is used in requests only as a base for relative URLs.

Example 10: entity with metadata=minimal

-
{
-  "@context": "http://host/service/$metadata#Customers/$entity",
-  "ID": "ALFKI",
-  "CompanyName": "Alfreds Futterkiste",
-  "ContactName": "Maria Anders",
-  "ContactTitle": "Sales Representative",
-  "Phone": "030-0074321",
-  "Fax": "030-0076545",
-  "Address": {
-    "Street": "Obere Str. 57",
-    "City": "Berlin",
-    "Region": null,
-    "PostalCode": "D-12209"
-  }
-}
-

Example 11: entity with metadata=full

{
   "@context": "http://host/service/$metadata#Customers/$entity",
-  "@id": "Customers('ALFKI')",
-  "@etag": "W/\"MjAxMy0wNS0yN1QxMTo1OFo=\"",
-  "@editLink": "Customers('ALFKI')",
-  "ID": "ALFKI",
-  "CompanyName": "Alfreds Futterkiste",
-  "ContactName": "Maria Anders",
-  "ContactTitle": "Sales Representative",
-  "Phone": "030-0074321",
-  "Fax": "030-0076545",
-  "Address": {
-    "Street": "Obere Str. 57",
-    "City": "Berlin",
-    "Region": null,
-    "PostalCode": "D-12209",
-    "Country@associationLink": "Customers('ALFKI')/Address/Country/$ref",
-    "Country@navigationLink": "Customers('ALFKI')/Address/Country"
-  },
-  "Orders@associationLink": "Customers('ALFKI')/Orders/$ref",
-  "Orders@navigationLink": "Customers('ALFKI')/Orders"
-}
+ "ID": "ALFKI", + "CompanyName": "Alfreds Futterkiste", + "ContactName": "Maria Anders", + "ContactTitle": "Sales Representative", + "Phone": "030-0074321", + "Fax": "030-0076545", + "Address": { + "Street": "Obere Str. 57", + "City": "Berlin", + "Region": null, + "PostalCode": "D-12209" + } +}
+

Example 11: entity with metadata=full

+
{
+  "@context": "http://host/service/$metadata#Customers/$entity",
+  "@id": "Customers('ALFKI')",
+  "@etag": "W/\"MjAxMy0wNS0yN1QxMTo1OFo=\"",
+  "@editLink": "Customers('ALFKI')",
+  "ID": "ALFKI",
+  "CompanyName": "Alfreds Futterkiste",
+  "ContactName": "Maria Anders",
+  "ContactTitle": "Sales Representative",
+  "Phone": "030-0074321",
+  "Fax": "030-0076545",
+  "Address": {
+    "Street": "Obere Str. 57",
+    "City": "Berlin",
+    "Region": null,
+    "PostalCode": "D-12209",
+    "Country@associationLink": "Customers('ALFKI')/Address/Country/$ref",
+    "Country@navigationLink": "Customers('ALFKI')/Address/Country"
+  },
+  "Orders@associationLink": "Customers('ALFKI')/Orders/$ref",
+  "Orders@navigationLink": "Customers('ALFKI')/Orders"
+}

@@ -918,25 +920,25 @@

7.1

Geography and geometry types have the same representation in a JSON payload. Whether the value represents a geography type or geometry type is inferred from its usage or specified using the type control information. RFC7946 does not define means for expressing instance-specific Coordinate Reference Systems.

Example 12:

-
{
-  "NullValue": null,
-  "TrueValue": true,
-  "FalseValue": false,
-  "BinaryValue": "T0RhdGE",
-  "IntegerValue": -128,
-  "DoubleValue": 3.1415926535897931,
-  "SingleValue": "INF",
-  "DecimalValue": 34.95,
-  "StringValue": "Say \"Hello\",\nthen go",
-  "DateValue": "2012-12-03",
-  "DateTimeOffsetValue": "2012-12-03T07:16:23Z",
-  "DurationValue": "P12DT23H59M59.999999999999S",
-  "TimeOfDayValue": "07:59:59.999",
-  "GuidValue": "01234567-89ab-cdef-0123-456789abcdef",
-  "Int64Value": 0,
-  "ColorEnumValue": "Yellow",
-  "GeographyPoint": { "type": "Point", "coordinates": [142.1,64.1] }
-}
+
{
+  "NullValue": null,
+  "TrueValue": true,
+  "FalseValue": false,
+  "BinaryValue": "T0RhdGE",
+  "IntegerValue": -128,
+  "DoubleValue": 3.1415926535897931,
+  "SingleValue": "INF",
+  "DecimalValue": 34.95,
+  "StringValue": "Say \"Hello\",\nthen go",
+  "DateValue": "2012-12-03",
+  "DateTimeOffsetValue": "2012-12-03T07:16:23Z",
+  "DurationValue": "P12DT23H59M59.999999999999S",
+  "TimeOfDayValue": "07:59:59.999",
+  "GuidValue": "01234567-89ab-cdef-0123-456789abcdef",
+  "Int64Value": 0,
+  "ColorEnumValue": "Yellow",
+  "GeographyPoint": { "type": "Point", "coordinates": [142.1,64.1] }
+}
@@ -946,16 +948,16 @@

7.2 Comple

It MAY have name/value pairs for instance annotations and control information.

Example 13:

-
{
-  "@context": "http://host/service/$metadata#Customers/$entity",
-  
-  "Address": {
-    "Street": "Obere Str. 57",
-    "City": "Berlin",
-    "Region": null,
-    "PostalCode": "D-12209"
-  }
-}
+
{
+  "@context": "http://host/service/$metadata#Customers/$entity",
+  
+  "Address": {
+    "Street": "Obere Str. 57",
+    "City": "Berlin",
+    "Region": null,
+    "PostalCode": "D-12209"
+  }
+}

A complex value with no selected properties, or no defined properties (such as an empty open complex type or complex type with no structural properties) is represented as an empty JSON object.

@@ -965,15 +967,15 @@

A collection of primitive values is represented as a JSON array; each element in the array is the representation of a primitive value. A JSON literal null represents a null value within the collection. An empty collection is represented as an empty array.

Example 14: partial collection of strings with next link

-
{
-  "@context": "http://host/service/$metadata#Customers/$entity",
-  
-  "EmailAddresses": [
-    "Julie@Swansworth.com",
-    "Julie.Swansworth@work.com"
-  ],
-  "EmailAddresses@nextLink": "…"
-}
+
{
+  "@context": "http://host/service/$metadata#Customers/$entity",
+  
+  "EmailAddresses": [
+    "Julie@Swansworth.com",
+    "Julie.Swansworth@work.com"
+  ],
+  "EmailAddresses@nextLink": "…"
+}
@@ -982,21 +984,21 @@

A collection of complex values is represented as a JSON array; each element in the array is the representation of a complex value. A JSON literal null represents a null value within the collection. An empty collection is represented as an empty array.

Example 15: partial collection of complex values with next link

-
{
-  "PhoneNumbers": [
-    {
-      "Number": "425-555-1212",
-      "Type": "Home"
-    },
-    {
-      "@type": "#Model.CellPhoneNumber",
-      "Number": "425-555-0178",
-      "Type": "Cell",
-      "Carrier": "Sprint"
-    }
-  ],
-  "PhoneNumbers@nextLink": "…"
-}
+
{
+  "PhoneNumbers": [
+    {
+      "Number": "425-555-1212",
+      "Type": "Home"
+    },
+    {
+      "@type": "#Model.CellPhoneNumber",
+      "Number": "425-555-0178",
+      "Type": "Cell",
+      "Carrier": "Sprint"
+    }
+  ],
+  "PhoneNumbers@nextLink": "…"
+}

@@ -1022,12 +1024,12 @@
@@ -1037,12 +1039,12 @@
@@ -1053,13 +1055,13 @@

If a collection of entities can be related, it is represented as a JSON array. Each element is the representation of an entity or the representation of an entity reference. An empty collection of entities (one that contains no entities) is represented as an empty JSON array. The navigation property MAY include context, type, count, or nextLink control information. If a navigation property is expanded with the suffix /$count, only the count control information is represented.

Example 18:

-
{
-  "@context": "http://host/service/$metadata#Customers/$entity",
-  "Orders@count": 42,
-  "Orders": [  ],
-  "Orders@nextLink": "…",
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Customers/$entity",
+  "Orders@count": 42,
+  "Orders": [  ],
+  "Orders@nextLink": "…",
+  
+}

@@ -1069,27 +1071,27 @@

8.4 Deep Insert<

Deep inserts are not allowed in update operations using PUT or PATCH requests.

Example 19: inserting a new order for a new customer with order items related to existing products:

-
{
-  "ID": 11643,
-  "Amount": 100,
-  ,
-  "Customer": {
-    "ID": "ANEWONE",
-    
-  },
-  "Items": [
-    {
-      "Product": { "@id": "Products(28)" },
-      "Quantity": 1,
-      
-    },
-    {
-      "Product": { "@id": "Products(39)" },
-      "Quantity": 5,
-      
-    }
-  ]
-}
+
{
+  "ID": 11643,
+  "Amount": 100,
+  ,
+  "Customer": {
+    "ID": "ANEWONE",
+    
+  },
+  "Items": [
+    {
+      "Product": { "@id": "Products(28)" },
+      "Quantity": 1,
+      
+    },
+    {
+      "Product": { "@id": "Products(39)" },
+      "Quantity": 5,
+      
+    }
+  ]
+}

@@ -1099,24 +1101,24 @@

8.5 Bin

For requests containing an OData-Version header with a value of 4.0, a bind operation is encoded as a property control information odata.bind on the navigation property it belongs to and has a single value for single-valued navigation properties or an array of values for collection navigation properties. For nullable single-valued navigation properties the value null may be used to remove the relationship.

Example 20: assign an existing product to an existing category with a partial update request against the product

-
PATCH http://host/service/Products(42) HTTP/1.1
-Content-Type: application/json
-
-{
-  "Category@odata.bind": "Categories(6)"
-}
-
-

The values are the ids of the related entities. They MAY be absolute or relative URLs.

-

For requests containing an OData-Version header with a value of 4.01, a relationship is bound to an existing entity using the same representation as for an expanded entity reference.

-
-

Example 21: assign an existing product to an existing category with a partial update request against the product

PATCH http://host/service/Products(42) HTTP/1.1
 Content-Type: application/json
 
 {
-  "Category": { "@id": "Categories(6)" }
+  "Category@odata.bind": "Categories(6)"
 }
+

The values are the ids of the related entities. They MAY be absolute or relative URLs.

+

For requests containing an OData-Version header with a value of 4.01, a relationship is bound to an existing entity using the same representation as for an expanded entity reference.

+
+

Example 21: assign an existing product to an existing category with a partial update request against the product

+
PATCH http://host/service/Products(42) HTTP/1.1
+Content-Type: application/json
+
+{
+  "Category": { "@id": "Categories(6)" }
+}
+

Example 22: submit a partial update request to:

At the end of the request, the updated category contains exactly the three specified products.

-
PATCH http://host/service/Categories(6) HTTP/1.1
-Content-Type: application/json
-
-{
-  "Name": "UpdatedCategory",
-  "Products": [
-    {
-      "@id": "Products(42)"
-    },
-    {
-      "@id": "Products(57)",
-      "Name": "Widgets"
-    },
-    {
-      "Name": "Wedges"
-    }
-  ]
-}
+
PATCH http://host/service/Categories(6) HTTP/1.1
+Content-Type: application/json
+
+{
+  "Name": "UpdatedCategory",
+  "Products": [
+    {
+      "@id": "Products(42)"
+    },
+    {
+      "@id": "Products(57)",
+      "Name": "Widgets"
+    },
+    {
+      "Name": "Wedges"
+    }
+  ]
+}

OData 4.01 services MUST support both the OData 4.0 representation, for requests containing an OData-Version header with a value of 4.0, and the OData 4.01 representation, for requests containing an OData-Version header with a value of 4.01. Clients MUST NOT use @odata.bind in requests with an OData-Version header with a value of 4.01.

For insert operations collection navigation property bind operations and deep insert operations can be combined. For OData 4.0 requests, the bind operations MUST appear before the deep insert operations in the payload.

@@ -1156,14 +1158,14 @@

8.6

Services MAY include this control information as appropriate.

Example 23: ETag for a collection of related entities

-
{
-  "@context": "http://host/service/$metadata#Orders/$entity",
-  "@id": "Orders(1234)",
-  "@etag": "W/\"MjAxMy0wNS0yN1QxMTo1OFo=\"",
-  "ID": 1234,
-  "Items@etag": "W/\"MjAxOS0wMy0xMlQxMDoyMlo=\""
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Orders/$entity",
+  "@id": "Orders(1234)",
+  "@etag": "W/\"MjAxMy0wNS0yN1QxMTo1OFo=\"",
+  "ID": 1234,
+  "Items@etag": "W/\"MjAxOS0wMy0xMlQxMDoyMlo=\""
+  
+}

Note: the collection ETag for a navigation property may or may not be identical to the ETag of the containing entity, the example shows a different ETag for the Items collection.

@@ -1184,16 +1186,16 @@

9 Str

If the included stream property has no value, the non-existing stream data is represented as null and the control information mediaContentType is not necessary.

Example 24:

-
{
-  "@context": "http://host/service/$metadata#Products/$entity",
-  
-  "Thumbnail@mediaReadLink": "http://server/Thumbnail546.jpg",
-  "Thumbnail@mediaEditLink": "http://server/uploads/Thumbnail546.jpg",
-  "Thumbnail@mediaContentType": "image/jpeg",
-  "Thumbnail@mediaEtag": "W/\"####\"",
-  "Thumbnail": "…base64url encoded value…",
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Products/$entity",
+  
+  "Thumbnail@mediaReadLink": "http://server/Thumbnail546.jpg",
+  "Thumbnail@mediaEditLink": "http://server/uploads/Thumbnail546.jpg",
+  "Thumbnail@mediaContentType": "image/jpeg",
+  "Thumbnail@mediaEtag": "W/\"####\"",
+  "Thumbnail": "…base64url encoded value…",
+  
+}

@@ -1204,14 +1206,14 @@

10 Media Enti

If the actual stream data for the media entity is included, it is represented as property named $value whose string value is the base64url-encoded value of the media stream, see RFC4648.

Example 25:

-
{
-  "@context": "http://host/service/$metadata#Employees/$entity",
-  "@mediaReadLink": "Employees(1)/$value",
-  "@mediaContentType": "image/jpeg",
-  "$value": "…base64url encoded value…",
-  "ID": 1,
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Employees/$entity",
+  "@mediaReadLink": "Employees(1)/$value",
+  "@mediaContentType": "image/jpeg",
+  "$value": "…base64url encoded value…",
+  "ID": 1,
+  
+}

@@ -1225,42 +1227,42 @@

collection of complex type values or collection of primitive values.

Example 26: primitive value

-
{
-  "@context": "http://host/service/$metadata#Edm.String",
-  "value": "Pilar Ackerman"
-}
-
-
-

Example 27: collection of primitive values

{
-  "@context": "http://host/service/$metadata#Collection(Edm.String)",
-  "value": ["small", "medium", "extra large"]
+  "@context": "http://host/service/$metadata#Edm.String",
+  "value": "Pilar Ackerman"
 }
-

Example 28: empty collection of primitive values

+

Example 27: collection of primitive values

{
   "@context": "http://host/service/$metadata#Collection(Edm.String)",
-  "value": []
+  "value": ["small", "medium", "extra large"]
 }
-

Example 29: complex value

+

Example 28: empty collection of primitive values

{
-  "@context": "http://host/service/$metadata#Model.Address",
-  "Street": "12345 Grant Street",
-  "City": "Taft",
-  "Region": "Ohio",
-  "PostalCode": "OH 98052",
-  "Country@navigationLink": "Countries('US')"
-}
+ "@context": "http://host/service/$metadata#Collection(Edm.String)", + "value": [] +}

-

Example 30: empty collection of complex values

+

Example 29: complex value

{
-  "@context": "http://host/service/$metadata#Collection(Model.Address)",
-  "value": []
-}
+ "@context": "http://host/service/$metadata#Model.Address", + "Street": "12345 Grant Street", + "City": "Taft", + "Region": "Ohio", + "PostalCode": "OH 98052", + "Country@navigationLink": "Countries('US')" +}
+ +
+

Example 30: empty collection of complex values

+
{
+  "@context": "http://host/service/$metadata#Collection(Model.Address)",
+  "value": []
+}

Note: the context URL is optional in requests.

@@ -1285,16 +1287,16 @@

nextLink control information MUST be included in a response that represents a partial result.

Example 31:

-
{
-  "@context": "…",
-  "@count": 37,
-  "value": [
-    {  },
-    {  },
-    {  }
-  ],
-  "@nextLink": "…?$skiptoken=342r89"
-}
+
{
+  "@context": "…",
+  "@count": 37,
+  "value": [
+    {  },
+    {  },
+    {  }
+  ],
+  "@nextLink": "…?$skiptoken=342r89"
+}

@@ -1306,20 +1308,20 @@

1

The outermost JSON object in a response MUST contain a context control information and MAY contain count, nextLink, or deltaLink control information.

Example 32: entity reference to order 10643

-
{
-  "@context": "http://host/service/$metadata#$ref",
-  "@id": "Orders(10643)"
-}
+
{
+  "@context": "http://host/service/$metadata#$ref",
+  "@id": "Orders(10643)"
+}

Example 33: collection of entity references

-
{
-  "@context": "http://host/service/$metadata#Collection($ref)",
-  "value": [
-    { "@id": "Orders(10643)" },
-    { "@id": "Orders(10759)" }
-  ]
-}
+
{
+  "@context": "http://host/service/$metadata#Collection($ref)",
+  "value": [
+    { "@id": "Orders(10643)" },
+    { "@id": "Orders(10759)" }
+  ]
+}

@@ -1343,27 +1345,27 @@

15.
  • Customer ANTON was deleted
  • ContactName for customer ALFKI was changed to Blake Smithe
  • -
    {
    -  "@context": "http://host/service/$metadata#Customers/$delta",
    -  "@count":3,
    -  "value": [
    -    {
    -      "@id": "Customers('BOTTM')",
    -      "ContactName": "Susan Halvenstern"
    -    },
    -    {
    -      "@removed": {
    -        "reason": "deleted"
    -      },
    -      "@id": "Customers('ANTON')"
    -    },
    -    {
    -      "@id": "Customers('ALFKI')",
    -      "ContactName": "Blake Smithe"
    -    }
    -  ],
    -  "@deltaLink": "Customers?$deltatoken=8015"
    -}
    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$delta",
    +  "@count":3,
    +  "value": [
    +    {
    +      "@id": "Customers('BOTTM')",
    +      "ContactName": "Susan Halvenstern"
    +    },
    +    {
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "@id": "Customers('ANTON')"
    +    },
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@deltaLink": "Customers?$deltatoken=8015"
    +}

    Example 35: a 4.0 delta response with three changes, in order of occurrence

    @@ -1372,25 +1374,25 @@

    15.
  • Customer ANTON was deleted
  • ContactName for customer ALFKI was changed to Blake Smithe
  • -
    {
    -  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    -  "@odata.count": 3,
    -  "value": [
    -    {
    -      "@odata.id": "Customers('BOTTM')",
    -      "ContactName": "Susan Halvenstern",
    -    },
    -    {
    -      "@odata.context": "#Customers/$deletedEntity",
    -      "@odata.id": "Customers('ANTON')"
    -    },
    -    {
    -      "@odata.id": "Customers('ALFKI')",
    -      "ContactName": "Blake Smithe"
    -    }
    -  ],
    -  "@odata.deltaLink": "Customers?$deltatoken=8015"
    -}
    +
    {
    +  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    +  "@odata.count": 3,
    +  "value": [
    +    {
    +      "@odata.id": "Customers('BOTTM')",
    +      "ContactName": "Susan Halvenstern",
    +    },
    +    {
    +      "@odata.context": "#Customers/$deletedEntity",
    +      "@odata.id": "Customers('ANTON')"
    +    },
    +    {
    +      "@odata.id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@odata.deltaLink": "Customers?$deltatoken=8015"
    +}

    @@ -1420,11 +1422,11 @@

    15.3 D

    Example 36: deleted entity in OData 4.0 response — note that id is a property, not control information

    -
    {
    -  "@context": "#Customers/$deletedEntity",
    -  "reason": "deleted",
    -  "id": "Customers('ANTON')"
    -}
    +
    {
    +  "@context": "#Customers/$deletedEntity",
    +  "reason": "deleted",
    +  "id": "Customers('ANTON')"
    +}

    In OData 4.01 payloads the deleted-entity object MUST include the following properties, regardless of the specified metadata value:

      @@ -1435,21 +1437,21 @@

      15.3 D

      The deleted-entity object MAY include additional properties of the entity, as well as annotations, and MAY include related entities, related deleted entities, or a delta or full representation of a related collection of entities, to represent related entities that have been modified or deleted.

      Example 37: deleted entity in OData 4.01 response with id control information (prefixed with an @)

      -
      {
      -  "@context": "#Customers/$deletedEntity",
      -  "@removed": {
      -    "reason": "deleted",
      -    "@myannoation.deletedBy": "Mario"
      -  },
      -  "@id": "Customers('ANTON')"
      -}
      +
      {
      +  "@context": "#Customers/$deletedEntity",
      +  "@removed": {
      +    "reason": "deleted",
      +    "@myannoation.deletedBy": "Mario"
      +  },
      +  "@id": "Customers('ANTON')"
      +}

      Example 38: entity removed OData 4.01 response without id control information and instead all key fields (ID is the single key field of Customer)

      -
      {
      -  "@removed": {},
      -  "ID": "ANTON"
      -}
      +
      {
      +  "@removed": {},
      +  "ID": "ANTON"
      +}

    @@ -1475,57 +1477,57 @@

    {
    -  "@context": "http://host/service/$metadata#Customers/$delta",
    -  "@count":3,
    -  "value": [
    -    {
    -      "@id": "Customers('ALFKI')",
    -      "Orders@delta": [
    -        {
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "@id": "Orders(10643)"
    -        },
    -        {
    -          "@id": "Orders(10645)",
    -          "ShippingAddress": {
    -            "Street": "23 Tsawassen Blvd.",
    -            "City": "Tsawassen",
    -            "Region": "BC",
    -            "PostalCode": "T2F 8M4"
    -          }
    -        }
    -      ]
    -    },
    -    {
    -      "@removed": {
    -        "reason": "deleted"
    -      },
    -      "@id": "Customers('ANTON')"
    -    },
    -    {
    -      "@id": "Customers('ALFKI')",
    -      "ContactName": "Blake Smithe"
    -    }
    -  ],
    -  "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
    -}
    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$delta",
    +  "@count":3,
    +  "value": [
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "Orders@delta": [
    +        {
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "@id": "Orders(10643)"
    +        },
    +        {
    +          "@id": "Orders(10645)",
    +          "ShippingAddress": {
    +            "Street": "23 Tsawassen Blvd.",
    +            "City": "Tsawassen",
    +            "Region": "BC",
    +            "PostalCode": "T2F 8M4"
    +          }
    +        }
    +      ]
    +    },
    +    {
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "@id": "Customers('ANTON')"
    +    },
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
    +}

    If the expanded navigation property is a full representation of the collection, it MUST be represented as an expanded navigation property, and its array value MUST represent the full set of entities related according to that relationship and satisfying any specified expand options, or a partial list containing a nextLink. Following this chain of next links MUST eventually return the full set of entities related according to that relationship and satisfying any specified expand options; the final page does not include a delta link.

    Members of the expanded navigation property MUST be represented as added/changed entities or entity references and MUST NOT include added links, deleted links, or deleted entities. Any entity not represented in the collection has either been removed, deleted, or changed such that it no longer satisfies the expand options in the defining query. In any case, clients SHOULD NOT receive additional notifications for such removed entities.

    Example 40: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)

    -
    {
    -  "@context": "http://host/service/$metadata#Customers/$entity/$delta",
    -  
    -  "Orders@count": 42,
    -  "Orders": [  ],
    -  "Orders@nextLink": "…",
    -  
    -  "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
    -}
    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$entity/$delta",
    +  
    +  "Orders@count": 42,
    +  "Orders": [  ],
    +  "Orders@nextLink": "…",
    +  
    +  "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
    +}

    @@ -1541,43 +1543,43 @@

    {
    -  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    -  "@odata.count": 5,
    -  "value": [
    -    {
    -      "@odata.context": "#Customers/$deletedLink",
    -      "source": "Customers('ALFKI')",
    -      "relationship": "Orders",
    -      "target": "Orders(10643)"
    -    },
    -    {
    -      "@odata.context": "#Customers/$link",
    -      "source": "Customers('BOTTM')",
    -      "relationship": "Orders",
    -      "target": "Orders(10645)"
    -    },
    -    {
    -      "@odata.context": "#Orders/$entity",
    -      "@odata.id": "Orders(10645)",
    -      "ShippingAddress": {
    -        "Street": "23 Tsawassen Blvd.",
    -        "City": "Tsawassen",
    -        "Region": "BC",
    -        "PostalCode": "T2F 8M4"
    -      }
    -    },
    -    {
    -      "@odata.context": "#Customers/$deletedEntity",
    -      "@odata.id": "Customers('ANTON')"
    -    },
    -    {
    -      "@odata.id": "Customers('ALFKI')",
    -      "ContactName": "Blake Smithe"
    -    }
    -  ],
    -  "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
    -}
    +
    {
    +  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    +  "@odata.count": 5,
    +  "value": [
    +    {
    +      "@odata.context": "#Customers/$deletedLink",
    +      "source": "Customers('ALFKI')",
    +      "relationship": "Orders",
    +      "target": "Orders(10643)"
    +    },
    +    {
    +      "@odata.context": "#Customers/$link",
    +      "source": "Customers('BOTTM')",
    +      "relationship": "Orders",
    +      "target": "Orders(10645)"
    +    },
    +    {
    +      "@odata.context": "#Orders/$entity",
    +      "@odata.id": "Orders(10645)",
    +      "ShippingAddress": {
    +        "Street": "23 Tsawassen Blvd.",
    +        "City": "Tsawassen",
    +        "Region": "BC",
    +        "PostalCode": "T2F 8M4"
    +      }
    +    },
    +    {
    +      "@odata.context": "#Customers/$deletedEntity",
    +      "@odata.id": "Customers('ANTON')"
    +    },
    +    {
    +      "@odata.id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
    +}

    If a property of an entity is dependent upon the property of another entity within the expanded set of entities being tracked, then both the change to the dependent property as well as the change to the principal property or added/deleted link corresponding to the change to the dependent property are returned in the delta response.

    @@ -1632,90 +1634,90 @@

    PATCH /service/Customers HTTP/1.1
    -Host: host
    -Content-Type: application/json
    -Content-Length: ###
    -Prefer: return=minimal, continue-on-error
    -
    -{
    -  "@context": "#$delta",
    -  "value": [
    -    {
    -      "@Org.OData.Core.V1.ContentID": "1",
    -      "CustomerID": "EASTC",
    -      "CompanyName": "Eastern Connection",
    -      "ContactName": "Ann Devon",
    -      "ContactTitle": "Sales Agent"
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "2",
    -      "CustomerID": "AROUT",
    -      "ContactName": "Thomas Hardy",
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "3",
    -      "@removed": {
    -        "reason": "deleted"
    -      },
    -      "CustomerID": "ANTON"
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "4",
    -      "CustomerID": "ALFKI",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.1",
    -          "OrderID": 11011,
    -          "CustomerID": "ALFKI",
    -          "EmployeeID": 3,
    -          "OrderDate": "1998-04-09T00:00:00Z",
    -          "RequiredDate": "1998-05-07T00:00:00Z",
    -          "ShippedDate": "1998-04-13T00:00:00Z"
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.2",
    -          "@id": "Orders(10692)"
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.3",
    -          "@id": "Orders(10835)",
    -          "RequiredDate": "1998-01-23T00:00:00Z",
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.4",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10643
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "5",
    -      "CustomerID": "ANATR",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "5.1",
    -          "OrderID": 10643
    -        }
    -      ],
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "6",
    -      "CustomerID": "DUMON",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "6.1",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10311
    -        }
    -      ]
    -    }
    -  ]
    -}
    +
    PATCH /service/Customers HTTP/1.1
    +Host: host
    +Content-Type: application/json
    +Content-Length: ###
    +Prefer: return=minimal, continue-on-error
    +
    +{
    +  "@context": "#$delta",
    +  "value": [
    +    {
    +      "@Org.OData.Core.V1.ContentID": "1",
    +      "CustomerID": "EASTC",
    +      "CompanyName": "Eastern Connection",
    +      "ContactName": "Ann Devon",
    +      "ContactTitle": "Sales Agent"
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "2",
    +      "CustomerID": "AROUT",
    +      "ContactName": "Thomas Hardy",
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "3",
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "CustomerID": "ANTON"
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "4",
    +      "CustomerID": "ALFKI",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.1",
    +          "OrderID": 11011,
    +          "CustomerID": "ALFKI",
    +          "EmployeeID": 3,
    +          "OrderDate": "1998-04-09T00:00:00Z",
    +          "RequiredDate": "1998-05-07T00:00:00Z",
    +          "ShippedDate": "1998-04-13T00:00:00Z"
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.2",
    +          "@id": "Orders(10692)"
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.3",
    +          "@id": "Orders(10835)",
    +          "RequiredDate": "1998-01-23T00:00:00Z",
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.4",
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "OrderID": 10643
    +        }
    +      ]
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "5",
    +      "CustomerID": "ANATR",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "5.1",
    +          "OrderID": 10643
    +        }
    +      ],
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "6",
    +      "CustomerID": "DUMON",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "6.1",
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "OrderID": 10311
    +        }
    +      ]
    +    }
    +  ]
    +}

    Assuming all changes can be applied without errors, the response would be

    HTTP/1.1 204 No Content
     Preference-Applied: return=minimal, continue-on-error
    @@ -1736,124 +1738,124 @@ 

    HTTP/1.1 200 OK
    -Content-Type: application/json
    -Content-Length: ###
    -Preference-Applied: return=minimal, continue-on-error
    -
    -{
    -  "@context": "#$delta",
    -  "value": [
    -    {
    -      "@Org.OData.Core.V1.ContentID": "1",
    -      "CustomerID": "EASTC",
    -      "@removed": {
    -        "reason": "changed"
    -      },
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "insert",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "incmplt",
    -          "message": "Required field(s) not provided",
    -          "target": "Address",
    -          "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "2",
    -      "CustomerID": "AROUT",
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "update",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "r-o",
    -          "message": "Customer is archived and cannot be changed",
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "3",
    -      "CustomerID": "ANTON",
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "delete",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "ufo",
    -          "message": "Customer has unfinished orders and cannot be deleted",
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "4",
    -      "CustomerID": "ALFKI",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.3",
    -          "@id": "Orders(10835)",
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "update",
    -            "responseCode": 400,
    -            "info": {
    -              "code": "b/s",
    -              "message": "RequiredDate cannot be changed because Order is already being shipped",
    -              "severity": "error"
    -            }
    -          }
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "5",
    -      "CustomerID": "ANATR",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "5.1",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10643,
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "link",
    -            "responseCode": 404,
    -            "info": null
    -          }
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "6",
    -      "CustomerID": "DUMON",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "6.1",
    -          "OrderID": 10311,
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "unlink",
    -            "responseCode": 404
    -          }
    -        }
    -      ]
    -    }
    -  ]
    -}
    -

    Without the continue-on-error preference processing would stop on the first error, and the response would be a standard OData error response

    -
    HTTP/1.1 400 Bad Request
    +
    HTTP/1.1 200 OK
     Content-Type: application/json
     Content-Length: ###
    -
    -{
    -  "error": {
    -    "code": "incmplt",
    -    "message": "Required field(s) not provided",
    -    "target": "Customers('EASTC')/Address",
    -    "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
    -  }
    -}
    +Preference-Applied: return=minimal, continue-on-error + +{ + "@context": "#$delta", + "value": [ + { + "@Org.OData.Core.V1.ContentID": "1", + "CustomerID": "EASTC", + "@removed": { + "reason": "changed" + }, + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "insert", + "responseCode": 400, + "info": { + "code": "incmplt", + "message": "Required field(s) not provided", + "target": "Address", + "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ], + "severity": "error" + } + } + }, + { + "@Org.OData.Core.V1.ContentID": "2", + "CustomerID": "AROUT", + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "update", + "responseCode": 400, + "info": { + "code": "r-o", + "message": "Customer is archived and cannot be changed", + "severity": "error" + } + } + }, + { + "@Org.OData.Core.V1.ContentID": "3", + "CustomerID": "ANTON", + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "delete", + "responseCode": 400, + "info": { + "code": "ufo", + "message": "Customer has unfinished orders and cannot be deleted", + "severity": "error" + } + } + }, + { + "@Org.OData.Core.V1.ContentID": "4", + "CustomerID": "ALFKI", + "Orders@delta": [ + { + "@Org.OData.Core.V1.ContentID": "4.3", + "@id": "Orders(10835)", + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "update", + "responseCode": 400, + "info": { + "code": "b/s", + "message": "RequiredDate cannot be changed because Order is already being shipped", + "severity": "error" + } + } + } + ] + }, + { + "@Org.OData.Core.V1.ContentID": "5", + "CustomerID": "ANATR", + "Orders@delta": [ + { + "@Org.OData.Core.V1.ContentID": "5.1", + "@removed": { + "reason": "changed" + }, + "OrderID": 10643, + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "link", + "responseCode": 404, + "info": null + } + } + ] + }, + { + "@Org.OData.Core.V1.ContentID": "6", + "CustomerID": "DUMON", + "Orders@delta": [ + { + "@Org.OData.Core.V1.ContentID": "6.1", + "OrderID": 10311, + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "unlink", + "responseCode": 404 + } + } + ] + } + ] +}
    +

    Without the continue-on-error preference processing would stop on the first error, and the response would be a standard OData error response

    +
    HTTP/1.1 400 Bad Request
    +Content-Type: application/json
    +Content-Length: ###
    +
    +{
    +  "error": {
    +    "code": "incmplt",
    +    "message": "Required field(s) not provided",
    +    "target": "Customers('EASTC')/Address",
    +    "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
    +  }
    +}

    @@ -1871,46 +1873,46 @@

    16 Boun

    If metadata=minimal is requested, the target name/value pair MUST be included if its value differs from the canonical function or action URL.

    Example 43: minimal representation of a function where all overloads are applicable

    -
    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "#Model.RemainingVacation": {},
    -  
    -}
    -
    -
    -

    Example 44: full representation of a specific overload with parameter alias for the Year parameter

    {
       "@context": "http://host/service/$metadata#Employees/$entity",
    -  "#Model.RemainingVacation(Year)": {
    -    "title": "Remaining vacation from year.",
    -    "target": "Employees(2)/RemainingVacation(Year=@Year)"
    -  },
    -  
    -}
    + "#Model.RemainingVacation": {}, + +}
    -

    Example 45: full representation in a collection

    +

    Example 44: full representation of a specific overload with parameter alias for the Year parameter

    {
    -  "@context": "http://host/service/$metadata#Employees",
    -  "#Model.RemainingVacation": {
    -    "title": "Remaining Vacation",
    -    "target": "Managers(22)/Employees/RemainingVacation"
    +  "@context": "http://host/service/$metadata#Employees/$entity",
    +  "#Model.RemainingVacation(Year)": {
    +    "title": "Remaining vacation from year.",
    +    "target": "Employees(2)/RemainingVacation(Year=@Year)"
       },
    -  "value": [  ]
    +  
     }
    -

    Example 46: full representation in a nested collection

    +

    Example 45: full representation in a collection

    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "@type": "Model.Manager",
    -  "ID":22,
    -  
    -  "Employees#RemainingVacation": {
    -    "title": "RemainingVacation",
    -    "target": "Managers(22)/Employees/RemainingVacation"
    -  }
    -}
    + "@context": "http://host/service/$metadata#Employees", + "#Model.RemainingVacation": { + "title": "Remaining Vacation", + "target": "Managers(22)/Employees/RemainingVacation" + }, + "value": [ ] +}
    + +
    +

    Example 46: full representation in a nested collection

    +
    {
    +  "@context": "http://host/service/$metadata#Employees/$entity",
    +  "@type": "Model.Manager",
    +  "ID":22,
    +  
    +  "Employees#RemainingVacation": {
    +    "title": "RemainingVacation",
    +    "target": "Managers(22)/Employees/RemainingVacation"
    +  }
    +}

    @@ -1927,46 +1929,46 @@

    17 Bound Acti

    If metadata=minimal is requested, the target name/value pair MUST be included if its value differs from the canonical function or action URL.

    Example 47: minimal representation in an entity

    -
    {
    -  "@context": "http://host/service/$metadata#LeaveRequests/$entity",
    -  "#Model.Approve": {},
    -  
    -}
    -
    -
    -

    Example 48: full representation in an entity:

    {
       "@context": "http://host/service/$metadata#LeaveRequests/$entity",
    -  "#Model.Approve": {
    -    "title": "Approve Leave Request",
    -    "target": "LeaveRequests(2)/Approve"
    -  },
    -  
    -}
    + "#Model.Approve": {}, + +}
    -

    Example 49: full representation in a collection

    +

    Example 48: full representation in an entity:

    {
    -  "@context": "http://host/service/$metadata#LeaveRequests",
    +  "@context": "http://host/service/$metadata#LeaveRequests/$entity",
       "#Model.Approve": {
    -    "title": "Approve All Leave Requests",
    -    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    +    "title": "Approve Leave Request",
    +    "target": "LeaveRequests(2)/Approve"
       },
    -  "value": [  ]
    +  
     }
    -

    Example 50: full representation in a nested collection

    +

    Example 49: full representation in a collection

    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "@type": "Model.Manager",
    -  "ID": 22,
    -  
    -  "LeaveRequests#Model.Approve": {
    -    "title": "Approve All Leave Requests",
    -    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    -  }
    -}
    + "@context": "http://host/service/$metadata#LeaveRequests", + "#Model.Approve": { + "title": "Approve All Leave Requests", + "target": "Employees(22)/Model.Manager/LeaveRequests/Approve" + }, + "value": [ ] +}
    + +
    +

    Example 50: full representation in a nested collection

    +
    {
    +  "@context": "http://host/service/$metadata#Employees/$entity",
    +  "@type": "Model.Manager",
    +  "ID": 22,
    +  
    +  "LeaveRequests#Model.Approve": {
    +    "title": "Approve All Leave Requests",
    +    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    +  }
    +}

    @@ -1978,78 +1980,78 @@

    section 6.

    Example 51: Create a quote for a product that does not yet exist. The Product parameter takes a transient entity.

    -
    POST http://host/service/CreateQuote
    -Content-Type: application/json
    -
    -{
    -  "Product": {
    -    "Name": "Our best ever",
    -    "Price": 1
    -  },
    -  "CustomerID": "ALFKI"
    -}
    -
    -
    -

    Example 52: Create a quote for an existing product. The Product parameter takes a non-transient entity which can be identified through its entity-id:

    POST http://host/service/CreateQuote
     Content-Type: application/json
     
     {
       "Product": {
    -    "@id": "Products(14)"
    -  },
    -  "CustomerID": "ALFKI"
    -}
    -

    or, as in section 15.2, through its primary key fields plus, if necessary, its context:

    + "Name": "Our best ever", + "Price": 1 + }, + "CustomerID": "ALFKI" +}
    + +
    +

    Example 52: Create a quote for an existing product. The Product parameter takes a non-transient entity which can be identified through its entity-id:

    POST http://host/service/CreateQuote
     Content-Type: application/json
     
     {
       "Product": {
    -    "@context": "#Products",
    -    "ProductID": 14
    -  },
    -  "CustomerID": "ALFKI"
    -}
    + "@id": "Products(14)" + }, + "CustomerID": "ALFKI" +}
    +

    or, as in section 15.2, through its primary key fields plus, if necessary, its context:

    +
    POST http://host/service/CreateQuote
    +Content-Type: application/json
    +
    +{
    +  "Product": {
    +    "@context": "#Products",
    +    "ProductID": 14
    +  },
    +  "CustomerID": "ALFKI"
    +}

    Alternatively, values of non-binding parameters MAY be specified as common expressions OData-URL, section 5.1.1. In the case of a bound action these MAY contain path expressions OData-URL, section 5.1.1.15, which the service evaluates on the binding parameter value. Such parameters are encoded as name/value pairs where the name is the name of the parameter followed by @expression and the value is the common expression. As the following example demonstrates, non-transient entities can be passed as non-binding action parameters through a resource path in this way.

    Example 53: An employee requests leave from their manager for the next two weeks:

    -
    POST /service/Employees(23)/self.RequestLeave
    -Host: host
    -Content-Type: application/json
    -
    -{
    -  "StartDate@expression": "now()",
    -  "EndDate@expression": "now() add duration'P14D'",
    -  "Approver@expression": "Manager"
    -}
    -

    The expression Manager is evaluated on the binding parameter value Employees(23).

    -

    When invoking an unbound action through an action import, expressions involving paths must start with $root:

    -
    POST /service/RequestLeave
    +
    POST /service/Employees(23)/self.RequestLeave
     Host: host
     Content-Type: application/json
     
     {
    -  "Requester@expression": "$root/services/Employee(23)",
    -  "StartDate@expression": "now()",
    -  "EndDate@expression": "now() add duration'P14D'",
    -  "Approver@expression": "$root/services/Employee(23)/Manager"
    -}
    + "StartDate@expression": "now()", + "EndDate@expression": "now() add duration'P14D'", + "Approver@expression": "Manager" +}
    +

    The expression Manager is evaluated on the binding parameter value Employees(23).

    +

    When invoking an unbound action through an action import, expressions involving paths must start with $root:

    +
    POST /service/RequestLeave
    +Host: host
    +Content-Type: application/json
    +
    +{
    +  "Requester@expression": "$root/services/Employee(23)",
    +  "StartDate@expression": "now()",
    +  "EndDate@expression": "now() add duration'P14D'",
    +  "Approver@expression": "$root/services/Employee(23)/Manager"
    +}

    Inside a batch request the common expressions can also be value references starting with $, as introduced in OData-Protocol, section 11.7.6.

    Non-binding parameters that are nullable or annotated with the term Core.OptionalParameter defined in OData-VocCore MAY be omitted from the request body. If an omitted parameter is not annotated (and thus nullable), it MUST be interpreted as having the null value. If it is annotated and the annotation specifies a DefaultValue, the omitted parameter is interpreted as having that default value. If omitted and the annotation does not specify a default value, the service is free on how to interpret the omitted parameter. Note: a nullable non-binding parameter is equivalent to being annotated as optional with a default value of null.

    Example 54:

    -
    {
    -  "param1": 42,
    -  "param2": {
    -    "Street": "One Microsoft Way",
    -    "Zip": 98052
    -  },
    -  "param3": [ 1, 42, 99 ],
    -  "param4": null
    -}
    +
    {
    +  "param1": 42,
    +  "param2": {
    +    "Street": "One Microsoft Way",
    +    "Zip": 98052
    +  },
    +  "param3": [ 1, 42, 99 ],
    +  "param4": null
    +}

    In order to invoke an action with no non-binding parameters, the client passes an empty JSON object in the body of the request. 4.01 Services MUST also support clients passing an empty request body for this case.

    @@ -2098,57 +2100,6 @@

    19.1 Batc
  • A second query request
  • Note: For brevity, in the example, request bodies are excluded in favor of English descriptions inside <> brackets and OData-Version headers are omitted.

    -
    POST /service/$batch HTTP/1.1
    -Host: host
    -OData-Version: 4.01
    -Content-Type: application/json
    -Content-Length: ###
    -
    -{
    -  "requests": [
    -    {
    -      "id": "0",
    -      "method": "get",
    -      "url": "/service/Customers('ALFKI')"
    -    },
    -    {
    -      "id": "1",
    -      "atomicityGroup": "group1",
    -      "dependsOn": [ "0" ],
    -      "method": "patch",
    -      "url": "/service/Customers('ALFKI')",
    -      "headers": {
    -        "Prefer": "return=minimal"
    -      },
    -      "body": <JSON representation of changes to Customer ALFKI>
    -    },
    -    {
    -      "id": "2",
    -      "atomicityGroup": "group1",
    -      "method": "post",
    -      "url": "/service/Customers",
    -      "body": <JSON representation of a new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "dependsOn": [ "group1" ],
    -      "method": "get",
    -      "url": "/service/Products"
    -    }
    -  ]
    -}
    - - -
    -

    19.2 Referencing New Entities

    -
    -

    The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.

    -
    -

    Example 56: a batch request that contains the following operations in the order listed:

    -
      -
    • Insert a new entity (with id = 1)
    • -
    • Insert a second new entity (references request with id = 1)
    • -
    POST /service/$batch HTTP/1.1
     Host: host
     OData-Version: 4.01
    @@ -2158,30 +2109,47 @@ 

    { "requests": [ { - "id": "1", - "method": "post", - "url": "/service/Customers", - "body": <JSON representation of a new Customer entity> - }, - { - "id": "2", - "dependsOn": [ "1" ] - "method": "post", - "url": "$1/Orders", - "body": <JSON representation of a new Order> - } - ] -}

    + "id": "0", + "method": "get", + "url": "/service/Customers('ALFKI')" + }, + { + "id": "1", + "atomicityGroup": "group1", + "dependsOn": [ "0" ], + "method": "patch", + "url": "/service/Customers('ALFKI')", + "headers": { + "Prefer": "return=minimal" + }, + "body": <JSON representation of changes to Customer ALFKI> + }, + { + "id": "2", + "atomicityGroup": "group1", + "method": "post", + "url": "/service/Customers", + "body": <JSON representation of a new Customer entity> + }, + { + "id": "3", + "dependsOn": [ "group1" ], + "method": "get", + "url": "/service/Products" + } + ] +}
    -

    19.3 Referencing an ETag

    +

    19.2 Referencing New Entities

    +

    The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.

    -

    Example 57: a batch request that contains the following operations in the order listed:

    +

    Example 56: a batch request that contains the following operations in the order listed:

      -
    • Get an Employee (with id = 1)
    • -
    • Update the salary only if the employee has not changed
    • +
    • Insert a new entity (with id = 1)
    • +
    • Insert a second new entity (references request with id = 1)
    POST /service/$batch HTTP/1.1
     Host: host
    @@ -2193,36 +2161,29 @@ 

    "requests": [ { "id": "1", - "method": "get", - "url": "/service/Employees(0)", - "headers": { - "accept": "application/json" - } - }, - { - "id": "2", - "dependsOn": [ "1" ], - "method": "patch", - "url": "/service/Employees(0)", - "headers": { - "if-match": "$1" - }, - "body": { - "Salary": 75000 - } - } - ] -}

    + "method": "post", + "url": "/service/Customers", + "body": <JSON representation of a new Customer entity> + }, + { + "id": "2", + "dependsOn": [ "1" ] + "method": "post", + "url": "$1/Orders", + "body": <JSON representation of a new Order> + } + ] +}
    -

    19.4 Referencing Response Body Values

    +

    19.3 Referencing an ETag

    -

    Example 58: a batch request that contains the following operations in the order listed:

    +

    Example 57: a batch request that contains the following operations in the order listed:

      -
    • Get an employee (with Content-ID = 1)
    • -
    • Get all employees residing in the same building
    • +
    • Get an Employee (with id = 1)
    • +
    • Update the salary only if the employee has not changed
    POST /service/$batch HTTP/1.1
     Host: host
    @@ -2235,7 +2196,7 @@ 

    { "id": "1", "method": "get", - "url": "/service/Employees/0?$select=Building", + "url": "/service/Employees(0)", "headers": { "accept": "application/json" } @@ -2243,14 +2204,55 @@

    { "id": "2", "dependsOn": [ "1" ], - "method": "get", - "url": "/service/Employees?$filter=Building eq $1/Building", + "method": "patch", + "url": "/service/Employees(0)", "headers": { - "accept": "application/json" - } - } - ] -}

    + "if-match": "$1" + }, + "body": { + "Salary": 75000 + } + } + ] +}
    + +
    +
    +

    19.4 Referencing Response Body Values

    +
    +
    +

    Example 58: a batch request that contains the following operations in the order listed:

    +
      +
    • Get an employee (with Content-ID = 1)
    • +
    • Get all employees residing in the same building
    • +
    +
    POST /service/$batch HTTP/1.1
    +Host: host
    +OData-Version: 4.01
    +Content-Type: application/json
    +Content-Length: ###
    +
    +{
    +  "requests": [
    +    {
    +      "id": "1",
    +      "method": "get",
    +      "url": "/service/Employees/0?$select=Building",
    +      "headers": {
    +        "accept": "application/json"
    +      }
    +    },
    +    {
    +      "id": "2",
    +      "dependsOn": [ "1" ],
    +      "method": "get",
    +      "url": "/service/Employees?$filter=Building eq $1/Building",
    +      "headers": {
    +        "accept": "application/json"
    +      }
    +    }
    +  ]
    +}
    @@ -2276,37 +2278,37 @@

    19.6 B

    Relative URLs in a response object follow the rules for relative URLs based on the request URL of the corresponding request. Especially: URLs in responses MUST NOT contain $-prefixed request identifiers.

    Example 59: referencing the batch request example 55 above, assume all the requests except the final query request succeed. In this case the response would be

    -
    HTTP/1.1 200 OK
    -OData-Version: 4.01
    -Content-Length: ####
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 200,
    -      "body": <JSON representation of the Customer entity with key ALFKI>
    -    },
    -    {
    -      "id": "1",
    -      "status": 204
    -    },
    -    {
    -      "id": "2",
    -      "status": 201,
    -      "headers": {
    -        "location": "http://host/service.svc/Customer('POIUY')"
    -      },
    -      "body": <JSON representation of the new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "status": 404,
    -      "body": <Error message>
    -    }
    -  ]
    -}
    +
    HTTP/1.1 200 OK
    +OData-Version: 4.01
    +Content-Length: ####
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 200,
    +      "body": <JSON representation of the Customer entity with key ALFKI>
    +    },
    +    {
    +      "id": "1",
    +      "status": 204
    +    },
    +    {
    +      "id": "2",
    +      "status": 201,
    +      "headers": {
    +        "location": "http://host/service.svc/Customer('POIUY')"
    +      },
    +      "body": <JSON representation of the new Customer entity>
    +    },
    +    {
    +      "id": "3",
    +      "status": 404,
    +      "body": <Error message>
    +    }
    +  ]
    +}

    @@ -2316,82 +2318,82 @@

    A service MAY return interim results to an asynchronously executing batch. It does this by responding with 200 OK to a GET request to the monitor resource and including a nextLink control information in the JSON batch response, thus signaling that the response is only a partial result. A subsequent GET request to the next link MAY result in a 202 Accepted response with a location header pointing to a new status monitor resource.

    Example 60: referencing the example 55 above again, assume that the request is sent with the respond-async preference. This results in a 202 response pointing to a status monitor resource:

    -
    HTTP/1.1 202 Accepted
    -Location: http://service-root/async-monitor-0
    -Retry-After: ###
    +
    HTTP/1.1 202 Accepted
    +Location: http://service-root/async-monitor-0
    +Retry-After: ###

    When interrogating the monitor URL only the first request in the batch has finished processing and all the remaining requests are still being processed. The service signals that asynchronous processing is “finished” and returns a partial result with the first response and a next link. The client did not explicitly accept application/http, so the response is “unwrapped” and only indicates with the AsyncResult header that it is a response to a status monitor resource:

    -
    HTTP/1.1 200 OK
    -AsyncResult: 200
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 200,
    -      "body": <JSON representation of the Customer entity with key ALFKI>
    -    }
    -  ],
    -  "@nextLink": "…?$skiptoken=YmF0Y2gx"
    -}
    +
    HTTP/1.1 200 OK
    +AsyncResult: 200
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 200,
    +      "body": <JSON representation of the Customer entity with key ALFKI>
    +    }
    +  ],
    +  "@nextLink": "…?$skiptoken=YmF0Y2gx"
    +}

    Client makes a GET request to the next link and receives a 202 response with the location of a new monitor resource.

    -
    HTTP/1.1 202 Accepted
    -Location: http://service-root/async-monitor-1
    -Retry-After: ###
    +
    HTTP/1.1 202 Accepted
    +Location: http://service-root/async-monitor-1
    +Retry-After: ###

    After some time a GET request to the monitor resource returns the remainder of the result.

    -
    HTTP/1.1 200 OK
    -AsyncResult: 200
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "1",
    -      "status": 204
    -    },
    -    {
    -      "id": "2",
    -      "status": 201,
    -      "headers": {
    -        "location": "http://host/service.svc/Customer('POIUY')"
    -      },
    -      "body": <JSON representation of the new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "status": 404,
    -      "body": <Error message>
    -    }
    -  ]
    -}
    +
    HTTP/1.1 200 OK
    +AsyncResult: 200
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "1",
    +      "status": 204
    +    },
    +    {
    +      "id": "2",
    +      "status": 201,
    +      "headers": {
    +        "location": "http://host/service.svc/Customer('POIUY')"
    +      },
    +      "body": <JSON representation of the new Customer entity>
    +    },
    +    {
    +      "id": "3",
    +      "status": 404,
    +      "body": <Error message>
    +    }
    +  ]
    +}

    In addition to the above interaction pattern individual requests within a batch with no other requests depending on it and not part of an atomicity group MAY be executed asynchronously if they specify the respond-async preference and if the service responds with a JSON batch response. In this case the response array contains a response object for each asynchronously executed individual request with a status of 202, a location header pointing to an individual status monitor resource, and optionally a retry-after header.

    Example 61: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously

    -
    HTTP/1.1 200 OK
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 202,
    -      "headers": {
    -        "location": "http://service-root/async-monitor-0"
    -      }
    -    },
    -    {
    -      "id": "1",
    -      "status": 204
    -    }
    -  ]
    -}
    +
    HTTP/1.1 200 OK
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 202,
    +      "headers": {
    +        "location": "http://service-root/async-monitor-0"
    +      }
    +    },
    +    {
    +      "id": "1",
    +      "status": 204
    +    }
    +  ]
    +}

    @@ -2406,19 +2408,19 @@

    single primitive or collection value, the annotations for the value appear next to the value property and are not prefixed with a property name.

    Example 62:

    -
    {
    -  "@context": "http://host/service/$metadata#Customers",
    -  "@com.example.customer.setkind": "VIPs",
    -  "value": [
    -    {
    -      "@com.example.display.highlight": true,
    -      "ID": "ALFKI",
    -      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
    -      "CompanyName": "Alfreds Futterkiste",
    -      "Orders@com.example.display.style#simple": { "order": 2 }
    -    }
    -  ]
    -}
    +
    {
    +  "@context": "http://host/service/$metadata#Customers",
    +  "@com.example.customer.setkind": "VIPs",
    +  "value": [
    +    {
    +      "@com.example.display.highlight": true,
    +      "ID": "ALFKI",
    +      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
    +      "CompanyName": "Alfreds Futterkiste",
    +      "Orders@com.example.display.style#simple": { "order": 2 }
    +    }
    +  ]
    +}

    20.1 Annotate a JSON Object

    @@ -2460,24 +2462,24 @@

    21.1 E

    Error responses MAY contain annotations in any of its JSON objects.

    Example 63:

    -
    {
    -  "error": {
    -    "code": "err123",
    -    "message": "Unsupported functionality",
    -    "target": "query",
    -    "details": [
    -      {
    -      "code": "forty-two",
    -      "target": "$search",
    -      "message": "$search query option not supported"
    -      }
    -    ],
    -    "innererror": {
    -      "trace": [],
    -      "context": {}
    -    }
    -  }
    -}
    +
    {
    +  "error": {
    +    "code": "err123",
    +    "message": "Unsupported functionality",
    +    "target": "query",
    +    "details": [
    +      {
    +      "code": "forty-two",
    +      "target": "$search",
    +      "message": "$search query option not supported"
    +      }
    +    ],
    +    "innererror": {
    +      "trace": [],
    +      "context": {}
    +    }
    +  }
    +}

    @@ -2492,9 +2494,9 @@

    21.2

    Example 64: note that this is one HTTP header line without any line breaks or optional whitespace

    -
    OData-error: {"code":"err123","message":"Unsupported
    -functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    -query option not supported"}]}
    +
    OData-error: {"code":"err123","message":"Unsupported
    +functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    +query option not supported"}]}

    diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index 648d0d9eb..1e8f34626 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -231,7 +231,7 @@ Section | Feature / Change | Issue ### 1.2.3 Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. @@ -655,11 +655,13 @@ Example 2: … } ``` -::: The resulting absolute URLs are -`http://host/service/Customers('ALFKI')` and -`http://host/service/Customers('ALFKI')/Orders`. +``` +http://host/service/Customers('ALFKI') +http://host/service/Customers('ALFKI')/Orders +``` +::: ## 4.4 Payload Ordering Constraints diff --git a/docs/odata-json-format/styles/odata.css b/docs/odata-json-format/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/docs/odata-json-format/styles/odata.css +++ b/docs/odata-json-format/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code, diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index dcf989d97..bc5d945a7 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -93,7 +93,7 @@ ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; @@ -592,7 +592,7 @@

    1.2.3 Document Conventions

    -

    Keywords defined by this specification use this monospaced font.

    +

    Keywords defined by this specification use this monospaced font.

    Some sections of this specification are illustrated with non-normative examples.

    Example 1: text describing an example uses this paragraph style

    diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 8ac825c93..21fbb6ccd 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -375,7 +375,7 @@ Section | Feature / Change | Issue ### 1.2.3 Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/docs/odata-protocol/styles/odata.css b/docs/odata-protocol/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/docs/odata-protocol/styles/odata.css +++ b/docs/odata-protocol/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code, diff --git a/docs/odata-temporal-ext/odata-temporal-ext.html b/docs/odata-temporal-ext/odata-temporal-ext.html index 9f3c30ea0..387a8b4a2 100644 --- a/docs/odata-temporal-ext/odata-temporal-ext.html +++ b/docs/odata-temporal-ext/odata-temporal-ext.html @@ -93,7 +93,7 @@ ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; @@ -331,7 +331,7 @@

    1.2.2 Document Conventions

    -

    Keywords defined by this specification use this monospaced font.

    +

    Keywords defined by this specification use this monospaced font.

    Some sections of this specification are illustrated with non-normative examples.

    Example 1: text describing an example uses this paragraph style

    diff --git a/docs/odata-temporal-ext/odata-temporal-ext.md b/docs/odata-temporal-ext/odata-temporal-ext.md index 3357cf386..3cd6edd57 100644 --- a/docs/odata-temporal-ext/odata-temporal-ext.md +++ b/docs/odata-temporal-ext/odata-temporal-ext.md @@ -277,7 +277,7 @@ with a `Timeline` of type `TimelineVisible`. ### 1.2.2 Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/docs/odata-temporal-ext/styles/odata.css b/docs/odata-temporal-ext/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/docs/odata-temporal-ext/styles/odata.css +++ b/docs/odata-temporal-ext/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code, diff --git a/docs/odata-url-conventions/odata-url-conventions.html b/docs/odata-url-conventions/odata-url-conventions.html index bb2d74f9d..330b689b3 100644 --- a/docs/odata-url-conventions/odata-url-conventions.html +++ b/docs/odata-url-conventions/odata-url-conventions.html @@ -93,7 +93,7 @@ ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; @@ -424,7 +424,7 @@

    1.2.3 Document Conventions

    -

    Keywords defined by this specification use this monospaced font.

    +

    Keywords defined by this specification use this monospaced font.

    Function signatures in this specification use the following paragraph style:

    Type FunctionName(Type Param1, Type Param2)

    Some sections of this specification are illustrated with non-normative examples.

    @@ -712,7 +712,8 @@

    4.3.5 Alternate Keys

    -

    In addition to the canonical (primary) key an entity set or entity type can specify one or more alternate keys with the Core.AlternateKeys term (see OData-VocCore). Alternate keys can be used by the client to address entities anywhere the canonical key can be used; for example, within entity sets, collection-valued navigation properties, collection-valued composable functions, and within delta payloads.

    +

    In addition to the canonical (primary) key an entity set or entity type can specify one or more alternate keys with the Core.AlternateKeys term (see OData-VocCore).

    +

    Alternate keys can be used by the client to address entities anywhere the canonical key can be used; for example, within entity sets, collection-valued navigation properties, collection-valued composable functions, and within delta payloads.

    Entities are addressed via an alternate key using the same parentheses-style convention as for the canonical key, with one difference: single-part alternate keys MUST specify the key property name to unambiguously determine the alternate key.

    Example 24: the same employee identified via the alternate key SSN, the canonical (primary) key ID using the non-canonical long form with specified key property name, and the canonical short form without key property name

    diff --git a/docs/odata-url-conventions/odata-url-conventions.md b/docs/odata-url-conventions/odata-url-conventions.md index 2a1569209..1393f5916 100644 --- a/docs/odata-url-conventions/odata-url-conventions.md +++ b/docs/odata-url-conventions/odata-url-conventions.md @@ -284,7 +284,7 @@ Section | Feature / Change | Issue ### 1.2.3 Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Function signatures in this specification use the following paragraph style: ``` @@ -797,7 +797,8 @@ document. In addition to the canonical (primary) key an entity set or entity type can specify one or more alternate keys with the [`Core.AlternateKeys`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#AlternateKeys) -term (see [OData-VocCore](#ODataVocCore)). +term (see [OData-VocCore](#ODataVocCore)). + Alternate keys can be used by the client to address entities anywhere the canonical key can be used; for example, within entity sets, collection-valued navigation properties, collection-valued composable functions, and within delta payloads. @@ -2484,7 +2485,8 @@ Edm.Boolean matchespattern(Edm.String,Edm.String,Edm.String) The second parameter MUST evaluate to a string containing an [ECMAScript](#_ECMAScript) (JavaScript) regular expression, otherwise the function -returns `null`. The `matchespattern` function returns `true` if the first parameter evaluates +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`. @@ -3785,7 +3787,8 @@ functions from that schema A path consists of segments separated by a forward slash (`/`). Segments are either names of single- or collection-valued complex properties, -[instance annotations](#AnnotationValuesinExpressions), or [type-cast segments](#AddressingDerivedTypes) consisting of the qualified name of a structured type that is +[instance annotations](#AnnotationValuesinExpressions), or +[type-cast segments](#AddressingDerivedTypes) consisting of the qualified name of a structured type that is derived from the type identified by the preceding path segment to reach properties defined on the derived type. diff --git a/docs/odata-url-conventions/styles/odata.css b/docs/odata-url-conventions/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/docs/odata-url-conventions/styles/odata.css +++ b/docs/odata-url-conventions/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code, diff --git a/lib/README.md b/lib/README.md index 96ef59d26..db4e5739d 100644 --- a/lib/README.md +++ b/lib/README.md @@ -53,18 +53,13 @@ The [`pandoc.js`](pandoc.js) module converts this single Markdown document to HT and effectively executes ``` -pandoc -f gfm+tex_math_dollars+fenced_divs - -t html - -o odata-data-aggregation-ext.html - -c styles/markdown-styles-v1.7.3b.css - -c styles/odata.css - -s - --mathjax - --eol=lf - --metadata pagetitle="..." +pandoc --metadata pagetitle="..." + odata-data-aggregation-ext.md ``` +where the other options are listed in the [`pandoc.js`](pandoc.js) module. + The Markdown-to-HTML conversion happens in a child process into which the Markdown is written and from which the HTML is read: ```js @@ -75,14 +70,7 @@ proc.stdout.pipe(«HTML file»); new Number("odata-data-aggregation-ext").build(proc.stdin); ``` -The HTML file uses CSS stylesheets contained in the [`docs/*/styles`](../docs/odata-data-aggregation-ext/styles) subfolder in order to render keywords in the same font (MathJax Typewriter) whether they occur standalone or in a formula: - -| Keyword occurs | Markdown source | Rendered result | -| ------------------ | ---------------------------------- | ------------------------------------ | -| standalone | ``The `aggregate` transformation`` | The ${\tt aggregate}$ transformation | -| in MathJax formula | `${\tt aggregate}(α{\tt\ as\ }D)$` | ${\tt aggregate}(α{\tt\ as\ }D)$ | - -A monospaced font (Courier New) is used for OData requests and their JSON or XML responses. +A monospaced font (Courier New) is used for keywords, OData requests and their JSON or XML responses. [`npm start`](server.js) starts a web server that serves such HTML files and the static `.css` files without writing intermediate files. This allows authors to see the effects of every change to the source folder in the working tree after saving the source files which triggers a browser auto-refresh. diff --git a/lib/pandoc.js b/lib/pandoc.js index 0bc9e50df..568d7dd3d 100644 --- a/lib/pandoc.js +++ b/lib/pandoc.js @@ -20,7 +20,7 @@ module.exports = function (options) { ready() { MathJax.startup.defaultReady(); MathJax.startup.document.outputJax.font.variant.monospace.chars - [0x2019] = [.611, -.287, .525, {f: "T", c: "'"}]; + [0x2019] = [.611, -.287, .525, {f: "T", c: "′"}]; } }}; `, diff --git a/odata-csdl/1 Introduction.md b/odata-csdl/1 Introduction.md index 3ff3e739a..eb0148375 100644 --- a/odata-csdl/1 Introduction.md +++ b/odata-csdl/1 Introduction.md @@ -66,7 +66,7 @@ Nested `If` without else part in collections| ### ##subsubsec Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/odata-data-aggregation-ext/1 Introduction.md b/odata-data-aggregation-ext/1 Introduction.md index 677201a32..f1a6d32d5 100644 --- a/odata-data-aggregation-ext/1 Introduction.md +++ b/odata-data-aggregation-ext/1 Introduction.md @@ -38,7 +38,7 @@ The following non-exhaustive list contains variable names that are used througho ### ##subsubsec Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/odata-data-aggregation-ext/3.2 Basic Aggregation.md b/odata-data-aggregation-ext/3.2 Basic Aggregation.md index 3f5756361..7c1ad4e5f 100644 --- a/odata-data-aggregation-ext/3.2 Basic Aggregation.md +++ b/odata-data-aggregation-ext/3.2 Basic Aggregation.md @@ -441,31 +441,31 @@ A groupby with `rollup` applied to a leveled hierarchy allows requesting aggrega Such a grouping with `rollup` for a leveled hierarchy is processed using the following equivalence relationships, in which $p_1,…,p_k$ are groupable property paths representing a level, $T$ is a transformation sequence, the ellipsis ($…$) stands in for zero or more property paths, $P_1$ stands in for zero or more property paths and $P_2$ for zero or more `rollup` or [`rolluprecursive`](#Groupingwithrolluprecursive) operators or property paths: - ${\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1},p_k),P_2),T)$ is equivalent to - $$\matrix{ - {\tt concat}(\hfill\\ - \quad {\tt groupby}((P_1,p_1,…,p_{k-1},p_k,P_2),T),\hfill&\tt (1)\\ - \quad {\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1}),P_2),T)\hfill&\tt(2)\\ - ).\hskip25pc\\ + $$\matrix{ + {\tt concat}(\hfill\\ + \quad {\tt groupby}((P_1,p_1,…,p_{k-1},p_k,P_2),T),\hfill&\tt (1)\\ + \quad {\tt groupby}((P_1,{\tt rollup}(p_1,…,p_{k-1}),P_2),T)\hfill&\tt(2)\\ + ).\hskip25pc }$$ - ${\tt groupby}((P_1,{\tt rollup}(p_1,p_2),P_2),T)$ is equivalent to - $$\matrix{ - {\tt concat}(\hfill&\tt (3)\\ - \quad {\tt groupby}((P_1,p_1,p_2,P_2),T),\hfill\\ - \quad {\tt groupby}((P_1,p_1,P_2),T)\hfill\\ - ).\hskip25pc\\ + $$\matrix{ + {\tt concat}(\hfill&\tt (3)\\ + \quad {\tt groupby}((P_1,p_1,p_2,P_2),T),\hfill\\ + \quad {\tt groupby}((P_1,p_1,P_2),T)\hfill\\ + ).\hskip25pc }$$ ::: example Example ##ex: rolling up two hierarchies, the first with two levels, the second with three levels: $$({\tt rollup}(p_{1,1},p_{1,2}),{\tt rollup}(p_{2,1},p_{2,2},p_{2,3}))$$ will result in the six groupings -$$\matrix{ -(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ -(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2})\hfill\\ -(p_{1,1},p_{1,2},\hfill&p_{2,1})\hfill\\ -(p_{1,1},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ -(p_{1,1},\hfill&p_{2,1},p_{2,2})\hfill\\ -(p_{1,1},\hfill&p_{2,1})\hfill +$$\matrix{ +(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ +(p_{1,1},p_{1,2},\hfill&p_{2,1},p_{2,2})\hfill\\ +(p_{1,1},p_{1,2},\hfill&p_{2,1})\hfill\\ +(p_{1,1},\hfill&p_{2,1},p_{2,2},p_{2,3})\hfill\\ +(p_{1,1},\hfill&p_{2,1},p_{2,2})\hfill\\ +(p_{1,1},\hfill&p_{2,1})\hfill }$$ The leveled hierarchy of the first rollup has 2 levels, the one of the second has 3 levels, and the groupings represent all possible $6=2⋅3$ combinations of levels from both hierarchies. ::: diff --git a/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md b/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md index aa81173d9..7cd0c8c23 100644 --- a/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md +++ b/odata-data-aggregation-ext/3.4 Transformations Changing the Input Set Structure.md @@ -19,7 +19,7 @@ The `compute` transformation takes a comma-separated list of one or more _comput A compute expression is a common expression followed by the `as` keyword, followed by an [alias](#TypeStructureandContextURL). -The output set is constructed by copying the instances of the input set and adding one dynamic property per compute expression to [each occurrence](#SamenessandOrder) in the output set. The name of each added dynamic property is the alias of the corresponding compute expression. The value of each added dynamic property is computed relative to the corresponding instance. Services MAY support expressions that address dynamic properties added by other expressions within the same compute transformation, provided that the service can determine an evaluation sequence. The type of the property is determined by the rules for evaluating common expressions and numeric promotion defined in [OData-URL, section 5.1.1](#ODataURL). +The output set is constructed by copying the instances of the input set and adding one dynamic property per compute expression to [each occurrence](#SamenessandOrder) in the output set. The name of each added dynamic property is the alias of the corresponding compute expression. The value of each added dynamic property is computed relative to the corresponding instance. Services MAY support expressions that address dynamic properties added by other expressions within the same `compute` transformation, provided that the service can determine an evaluation sequence. The type of the property is determined by the rules for evaluating common expressions and numeric promotion defined in [OData-URL, section 5.1.1](#ODataURL). ::: example Example ##ex: diff --git a/odata-data-aggregation-ext/6 Hierarchical Transformations.md b/odata-data-aggregation-ext/6 Hierarchical Transformations.md index f41af2012..0945b8a05 100644 --- a/odata-data-aggregation-ext/6 Hierarchical Transformations.md +++ b/odata-data-aggregation-ext/6 Hierarchical Transformations.md @@ -44,53 +44,53 @@ The fifth parameter $d$ is optional and takes an integer greater than or equal t The output set of the transformation ${\tt ancestors}(H,Q,p,T,d,{\tt keep\ start})$ or ${\tt descendants}(H,Q,p,T,d,{\tt keep\ start})$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $F(u)$ applied to the input set for all $u$ in $A$. For a given instance $u$, the transformation $F(u)$ determines all instances of the input set whose node identifier is an ancestor or descendant of the node identifier of $u$: If $p$ contains only single-valued segments, then, for `ancestors`, -$$\matrix{ -F(u)={\tt filter}(\hbox{\tt Aggregation.isancestor}(\hfill\\ -\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ -\quad {\tt Node}=p,\;{\tt Descendant}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}))\hfill +$$\matrix{ +F(u)={\tt filter}(\hbox{\tt Aggregation.isancestor}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Descendant}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}))\hfill }$$ or, for `descendants`, -$$\matrix{ -F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ -\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ -\quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill +$$\matrix{ +F(u)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Ancestor}=u[p],\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true})).\hfill }$$ Otherwise $p=p_1/…/p_k/r$ with $k≥1$, in this case the output set of the transformation $F(u)$ is defined as the [union](#HierarchicalTransformations) of the output sets of transformations $G(n)$ applied to the input set for all $n$ in $γ(u,p)$. The output set of $G(n)$ consists of the instances of the input set whose node identifier is an ancestor or descendant of the node identifier $n$: For `ancestors`, -$$\matrix{ -G(n)={\tt filter}(\hfill\\ -\hskip1pc p_1/{\tt any}(y_1:\hfill\\ -\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ -\hskip3pc ⋱\hfill\\ -\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ -\hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ -\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ -\hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ -\hskip5pc )\hfill\\ -\hskip4pc )\hfill\\ -\hskip3pc ⋰\hfill\\ -\hskip2pc )\hfill\\ -\hskip1pc )\hfill\\ -)\hfill +$$\matrix{ +G(n)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isancestor}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Descendant}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill }$$ or, for `descendants`, -$$\matrix{ -G(n)={\tt filter}(\hfill\\ -\hskip1pc p_1/{\tt any}(y_1:\hfill\\ -\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ -\hskip3pc ⋱\hfill\\ -\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ -\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ -\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ -\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ -\hskip5pc )\hfill\\ -\hskip4pc )\hfill\\ -\hskip3pc ⋰\hfill\\ -\hskip2pc )\hfill\\ -\hskip1pc )\hfill\\ -)\hfill +$$\matrix{ +G(n)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=n,\;{\tt MaxDistance}=d,\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill }$$ where $y_1,…,y_k$ denote `lambdaVariableExpr`s as defined in [OData-ABNF](#ODataABNF) and ${}/r$ may be absent. @@ -179,7 +179,7 @@ results in ### ##subsubsec Transformation `traverse` -The traverse transformation returns instances of the input set that are or are related to nodes of a given recursive hierarchy in a specified tree order. +The `traverse` transformation returns instances of the input set that are or are related to nodes of a given recursive hierarchy in a specified tree order. $H$, $Q$ and $p$ are the first three parameters defined [above](#CommonParametersforHierarchicalTransformations). @@ -243,18 +243,18 @@ If $p$ contains only single-valued segments, then $$F(x)={\tt filter}(p{\tt\ eq\ }x[q]).$$ Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and -$$\matrix{ -F(x)={\tt filter}(\hfill\\ -\hskip1pc p_1/{\tt any}(y_1:\hfill\\ -\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ -\hskip3pc ⋱\hfill\\ -\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ -\hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ -\hskip4pc )\hfill\\ -\hskip3pc ⋰\hfill\\ -\hskip2pc )\hfill\\ -\hskip1pc )\hfill\\ -)\hfill +$$\matrix{ +F(x)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc y_k/r{\tt\ eq\ }x[q]\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill }$$ where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent. @@ -373,28 +373,28 @@ Otherwise if $P_1$ and $P_2$ are empty, then $$R(x)=F(x)/{\tt compute}(x{\tt\ as\ }χ_N)/T/Z_N/\Pi_G(σ(x)).$$ $F(x)$ is defined as follows: If $p$ contains only single-valued segments, then -$$\matrix{ -F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ -\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ -\quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill +$$\matrix{ +F(x)={\tt filter}(\hbox{\tt Aggregation.isdescendant}(\hfill\\ +\quad {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\quad {\tt Node}=p,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true})).\hfill }$$ Otherwise $p=p_1/…/p_k/r$ with $k≥1$ and -$$\matrix{ -F(x)={\tt filter}(\hfill\\ -\hskip1pc p_1/{\tt any}(y_1:\hfill\\ -\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ -\hskip3pc ⋱\hfill\\ -\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ -\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ -\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ -\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ -\hskip5pc )\hfill\\ -\hskip4pc )\hfill\\ -\hskip3pc ⋰\hfill\\ -\hskip2pc )\hfill\\ -\hskip1pc )\hfill\\ -)\hfill +$$\matrix{ +F(x)={\tt filter}(\hfill\\ +\hskip1pc p_1/{\tt any}(y_1:\hfill\\ +\hskip2pc y_1/p_2/{\tt any}(y_2:\hfill\\ +\hskip3pc ⋱\hfill\\ +\hskip4pc y_{k-1}/p_k/{\tt any}(y_k:\hfill\\ +\hskip5pc \hbox{\tt Aggregation.isdescendant}(\hfill\\ +\hskip6pc {\tt HierarchyNodes}=H,\;{\tt HierarchyQualifier}=\hbox{\tt{'$Q$'}},\hfill\\ +\hskip6pc {\tt Node}=y_k/r,\;{\tt Ancestor}=x[q],\;{\tt IncludeSelf}={\tt true}\hfill\\ +\hskip5pc )\hfill\\ +\hskip4pc )\hfill\\ +\hskip3pc ⋰\hfill\\ +\hskip2pc )\hfill\\ +\hskip1pc )\hfill\\ +)\hfill }$$ where $y_1,…,y_k$ denote `lambdaVariableExpr`s and ${}/r$ may be absent. (See [example ##rollupcoll] for a case with $k=1$.) diff --git a/odata-json-format/1 Introduction.md b/odata-json-format/1 Introduction.md index cc5390258..869259999 100644 --- a/odata-json-format/1 Introduction.md +++ b/odata-json-format/1 Introduction.md @@ -47,7 +47,7 @@ Allow common expressions in action payloads| ### ##subsubsec Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/odata-json-format/4 Common Characteristics.md b/odata-json-format/4 Common Characteristics.md index 3fe40dd99..32f7f92e6 100644 --- a/odata-json-format/4 Common Characteristics.md +++ b/odata-json-format/4 Common Characteristics.md @@ -108,11 +108,13 @@ Example ##ex: … } ``` -::: The resulting absolute URLs are -`http://host/service/Customers('ALFKI')` and -`http://host/service/Customers('ALFKI')/Orders`. +``` +http://host/service/Customers('ALFKI') +http://host/service/Customers('ALFKI')/Orders +``` +::: ## ##subsec Payload Ordering Constraints diff --git a/odata-protocol/1 Introduction.md b/odata-protocol/1 Introduction.md index b3f5d9323..7e463bddf 100644 --- a/odata-protocol/1 Introduction.md +++ b/odata-protocol/1 Introduction.md @@ -59,7 +59,7 @@ Setting a complex property to a different type| ### ##subsubsec Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/odata-temporal-ext/1 Introduction.md b/odata-temporal-ext/1 Introduction.md index 33507eac6..2a7044c00 100644 --- a/odata-temporal-ext/1 Introduction.md +++ b/odata-temporal-ext/1 Introduction.md @@ -128,7 +128,7 @@ with a `Timeline` of type `TimelineVisible`. ### ##subsubsec Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Some sections of this specification are illustrated with non-normative examples. diff --git a/odata-url-conventions/1 Introduction.md b/odata-url-conventions/1 Introduction.md index 308912ac4..e759d0a4f 100644 --- a/odata-url-conventions/1 Introduction.md +++ b/odata-url-conventions/1 Introduction.md @@ -46,7 +46,7 @@ Allow alternative `$search` syntax| ### ##subsubsec Document Conventions -Keywords defined by this specification use `this monospaced font`. +Keywords defined by this specification use `this monospaced font`. Function signatures in this specification use the following paragraph style: ``` diff --git a/odata-url-conventions/4 Resource Path.md b/odata-url-conventions/4 Resource Path.md index 3228299d3..167ecb9fc 100644 --- a/odata-url-conventions/4 Resource Path.md +++ b/odata-url-conventions/4 Resource Path.md @@ -341,7 +341,7 @@ document. In addition to the canonical (primary) key an entity set or entity type can specify one or more alternate keys with the [`Core.AlternateKeys`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#AlternateKeys) -term (see [OData-VocCore](#ODataVocCore)). +term (see [OData-VocCore](#ODataVocCore)). Alternate keys can be used by the client to address entities anywhere the canonical key can be used; for example, within entity sets, collection-valued navigation properties, diff --git a/odata-url-conventions/5 Query Options.md b/odata-url-conventions/5 Query Options.md index b018b9851..66e3b5e50 100644 --- a/odata-url-conventions/5 Query Options.md +++ b/odata-url-conventions/5 Query Options.md @@ -912,7 +912,7 @@ Edm.Boolean matchespattern(Edm.String,Edm.String,Edm.String) The second parameter MUST evaluate to a string containing an [ECMAScript](#_ECMAScript) (JavaScript) regular expression, otherwise the function -returns `null`. The +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 @@ -2214,7 +2214,7 @@ functions from that schema A path consists of segments separated by a forward slash (`/`). Segments are either names of single- or collection-valued complex properties, -[instance annotations](#AnnotationValuesinExpressions), or +[instance annotations](#AnnotationValuesinExpressions), or [type-cast segments](#AddressingDerivedTypes) consisting of the qualified name of a structured type that is derived from the type identified by the preceding path segment to reach properties defined on the derived type. diff --git a/styles/odata.css b/styles/odata.css index cd8e0729f..42b8eaedc 100644 --- a/styles/odata.css +++ b/styles/odata.css @@ -149,16 +149,9 @@ table { p code, li code, -h1 code, -h2 code, -h3 code, -h4 code, -h5 code, -h6 code, td > code { - font-family: MJXZERO, MJXTEX-T; font-size: 1em; - line-height: 0; + font-weight: bold; } .example p code,