-
Type:
Improvement
-
Status: Closed
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: V4.0_CS02
-
Fix Version/s: V4.0_CSD04
-
Component/s: Data Aggregation
-
Labels:None
-
Environment:
Applied
-
Proposal:
-
Resolution:
Original description: The groupby specification should also allow instance annotations as grouping properties.
This idea was rejected by TC 2022-03-10. Still, changes to the specification text are necessary.
Field | Original Value | New Value |
---|---|---|
Fix Version/s | V4.0_CSD04 [ 10567 ] | |
Affects Version/s | V4.0_CS02 [ 10336 ] |
Status | New [ 10000 ] | Open [ 1 ] |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more non-empty paths that is enclosed in parentheses. _Path segments are separated by a forward slash (/). Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
|
Environment | Proposed |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more non-empty paths that is enclosed in parentheses. _Path segments are separated by a forward slash (/). Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more non-empty paths that is enclosed in parentheses. _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more non-empty paths that is enclosed in parentheses. _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- __ paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- __ paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property paths, _navigation property paths or annotation paths_ that is enclosed in parentheses. ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property paths, _navigation property paths or annotation paths_ that is enclosed in parentheses. ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property paths, _navigation property paths or annotation paths_ that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property paths, _navigation property paths or annotation paths_ that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- The same property path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property paths, _navigation property paths or annotation paths_ that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property paths, _navigation property paths or annotation paths_ that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property, _navigation property or annotation_ paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ single-valued property, _navigation property or annotation_ paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnsted}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnsted}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_ -type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63] |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63] |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Resolution | Fixed [ 1 ] | |
Status | Open [ 1 ] | Resolved [ 5 ] |
Resolution |
https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69557/odata-data-aggregation-ext-v4.0-wd05.docx
ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63] still to be merged |
Resolution |
https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69557/odata-data-aggregation-ext-v4.0-wd05.docx
ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63] still to be merged |
[https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69557/odata-data-aggregation-ext-v4.0-wd05.docx]
Resolution edited on 2022-02-18 because type casts are also allowed as final segment: https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69610/odata-data-aggregation-ext-v4.0-wd05.docx ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63] still to be merged |
Environment | Proposed | Applied |
Resolution |
[https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69557/odata-data-aggregation-ext-v4.0-wd05.docx]
Resolution edited on 2022-02-18 because type casts are also allowed as final segment: https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69610/odata-data-aggregation-ext-v4.0-wd05.docx ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63] still to be merged |
[https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69557/odata-data-aggregation-ext-v4.0-wd05.docx]
Resolution edited on 2022-02-18 because type casts are also allowed as final segment: [https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69610/odata-data-aggregation-ext-v4.0-wd05.docx] Inserted example 63 on 2022-02-25: https://www.oasis-open.org/apps/org/workgroup/odata/download.php/69650/odata-data-aggregation-ext-v4.0-wd05.docx ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63] still to be merged |
Status | Resolved [ 5 ] | Open [ 1 ] |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... Other navigation properties _and entity-valued instance annotations_ specified in grouping property paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote} {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote} {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote} If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Environment | Applied | Proposed |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented ... {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote} If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Summary | Simple grouping by instance annotations | Unified treatment of paths in aggregate, groupby and transformnested |
Proposal |
Rephrase beginning of section 3.10.1, using _wording_ from the {{transformnested}} transformation:
{quote}In its simplest form the first parameter of groupby specifies the _grouping properties_, a comma-separated list of one or more _non-empty_ -single-valued property- paths that is enclosed in parentheses. -A path may consist of a sequence of single-valued navigation and complex properties.- _Path segments are separated by a forward slash. Segments are names of single-valued structural or navigation properties, or term-cast segments consisting of an @ followed by the qualified name of a single-valued instance annotation, or type-cast segments 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._ The same -property- path SHOULD NOT ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_ -grouping property- paths are expanded by default. {quote} Rephrase step 1: {quote} * Create a projection of the instance with all related entities _and instance annotations_ included that are reached via navigation properties _or term casts_ that occur in the grouping properties. * Remove from the projection all structural and navigation properties _and instance annotations_ that are not traversed by any grouping property.{quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, _and each instance annotation_ are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Instance annotations must also be mentioned in the resolution of Merge ABNF pull request [#63|https://github.com/oasis-tcs/odata-abnf/pull/63]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * _a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a custom aggregate ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand- _select_ only related entities of that derived type or one of its sub-types. _The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]._ The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization- _an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * _a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a custom aggregate ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and entity-valued instance annotations_ specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand- _select_ only related entities of that derived type or one of its sub-types. _The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]._ The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization- _an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * _a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a custom aggregate ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. _The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]._ The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * _a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a custom aggregate ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. _The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]._ The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * _a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a custom aggregate ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * _a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a custom aggregate ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method * an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method * a path P/A consisting of an optional path P and a custom aggregate A{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method * an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method * a path P/A consisting of an optional path P and a custom aggregate A{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A consisting of an optional path P, an aggregatable property A, and a type-cast segment T if A is declared on the derived type, with a specified aggregation method * _an arithmetic expression [OData-URL, section 5.1.1.2] of such paths P/T/A where A and every segment of P must be single-valued, with a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and T a type-cast segment, but only if A is declared on the derived type; this must be followed by {{with}} and a specified aggregation method * _an arithmetic expression [OData-URL, section 5.1.1.2] or unbound primitive function call_ _[OData-URL, section 4.5.2]_ _with such paths P/T/A where A and every segment of P must be single-valued, this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash (/). Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and T a type-cast segment, but only if A is declared on the derived type; this must be followed by {{with}} and a specified aggregation method * _an arithmetic expression [OData-URL, section 5.1.1.2] or unbound primitive function call_ _[OData-URL, section 4.5.2]_ _with such paths P/T/A where A and every segment of P must be single-valued, this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and T a type-cast segment, but only if A is declared on the derived type; this must be followed by {{with}} and a specified aggregation method * _an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] or unbound primitive function call expecting one or more parameters with paths P/T/A where A and every segment of P must be single-valued, this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and T a type-cast segment, but only if A is declared on the derived type; this must be followed by {{with}} and a specified aggregation method * _an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an arithmetic expression [OData-URL, section 5.1.1.2] or unbound primitive function call expecting one or more parameters with paths P/T/A where A and every segment of P must be single-valued, this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and T a type-cast segment, but only if A is declared on the derived type; this must be followed by {{with}} and a specified aggregation method * _an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and T a type-cast segment, but only if A is declared on the derived type; this must be followed by {{with}} and a specified aggregation method * _an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and the infix T is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and the infix T is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and the infix T is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P is optional, A is an aggregatable property, and the infix T is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above ...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, numeric values and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, numeric values and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, numeric or duration values, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _an aggregatable expression consisting of an unbound primitive function call_ _[OData-URL, section 4.5.2]_ _whose single parameter is a path P/T/A; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, numeric or duration values, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P{{/$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, numeric or duration values, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P{{/$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls expecting one or more parameters, numeric or duration values, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P\{{/$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], numeric or duration values, unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P\{{/$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], numeric or duration values, unbound primitive function calls expecting one or more parameters, and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P\{{/$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P\{{/$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#FF0000}_a path P followed by a parenthesised aggregatable expression like in the previous option_{color} * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths P/T/A where A and every segment of P must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#FF0000}_a path P followed by a parenthesised aggregatable expression like in the previous option_{color} * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths S/T/A like in the first option where A and every segment of S must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option_{color} * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths S/T/A like in the first option where A and every segment of S must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option_{color} * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths S/T/A like in the first option where A and every segment of S must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option__; this must be followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths S/T/A like in the first option where A and every segment of S must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option__; this must be followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional path P and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths S/T/A like in the first option where A and every segment of S must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option__; this must be followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T; this must be followed by {{with}} and a specified aggregation method * _a path P/{{$count}}, which behaves like the previous option with an aggregatable property always having the value 1; this must be followed by {{with}} and a specified aggregation method. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and paths S/T/A like in the first option where A and every segment of S must be single-valued; this must be followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option__; this must be followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}}_ _followed by {{with}} and a specified aggregation method, this_ _behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} or P/T/A/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} or P/T/A/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1. This is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1. This is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Description | The [{{groupby}}|http://docs.oasis-open.org/odata/odata-data-aggregation-ext/v4.0/cs02/odata-data-aggregation-ext-v4.0-cs02.html#_Toc435016583] specification should also allow instance annotations as grouping properties. |
Original description: The [{{groupby}}|http://docs.oasis-open.org/odata/odata-data-aggregation-ext/v4.0/cs02/odata-data-aggregation-ext-v4.0-cs02.html#_Toc435016583] specification should also allow instance annotations as grouping properties.
This idea was rejected by TC 2022-03-10. Still, changes to the specification text are necessary. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Heading 1||{{with}} required||path prefix Q||aggregated value V|| |an aggregatable property path P/T/A|yes|P|T/A| |a path P/{{$count}}, or P/T/A/$count this behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type|yes |P|1| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued|yes|absent|W| |a path P followed by a parenthesised aggregatable expression W like in the previous option|yes|P|W| * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Heading 1||{{with}} required||path prefix Q||aggregated value V|| |an aggregatable property path P/T/A|yes|P|T/A| |a path P/{{$count}}, or P/T/A/$count this behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type|yes |P|1| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued|yes|absent|W| |a path P followed by a parenthesised aggregatable expression W like in the previous option|yes|P|W| * -an aggregatable expression ...- * an aggregatable property path P/T/A followed by {{with}} and a specified aggregation method * _a path P/{{$count}} followed by {{with}} and a specified aggregation method, this behaves like an aggregatable property always having the value 1. It is also allowed if the last segment of P has a primitive type_ * _an aggregatable expression built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls,_ _numeric or duration values,_ _and aggregatable property paths S/T/A where A and every segment of S are single-valued, followed by {{with}} and a specified aggregation method (P is not present in this option)_ * {color:#ff0000}_a path P followed by a parenthesised aggregatable expression like in the previous option and_ _followed by {{with}} and a specified aggregation method_{color} * a path P/A consisting of an optional prefix P/ and a custom aggregate A * any of the above...{quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An _aggregate expression_ may be ||Option||{{with}} required||path prefix P||aggregated value V|| |an aggregatable property path A/T/B|yes|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|yes |A or A/T/B|1| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|yes|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|yes|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|no|A|C| The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An _aggregate expression_ may be ||Option||{{with}} required||path prefix P||aggregated value V|| |an aggregatable property path A/T/B|yes|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|yes |A or A/T/B|1| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|yes|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|yes|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|no|A|C| The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||V|| |an aggregatable property path A/T/B|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|1| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value of the aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||V|| |an aggregatable property path A/T/B|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|1| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value of the aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||V|| |an aggregatable property path A/T/B|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value of the aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||V|| |an aggregatable property path A/T/B|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value of the aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||V|| |an aggregatable property path A/T/B|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value of the aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||V|| |an aggregatable property path A/T/B|A|T/B| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|W| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|W| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and an expression V that evaluates to the aggregated value of the aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... Then, if R is empty, the aggregated value is computed _by evaluating V_ for all instances in E, otherwise the aggregated value is computed _by evaluating V_ for all instances addressed via R starting from E. If no paths are present, the aggregated value is computed _by evaluating V_ for all instances in the input set. {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||aggregated value|| |an aggregatable property path A/T/B|A|aggregation method(U.map(u -> u/T/B))| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|aggregation method(U.map(u -> W evaluated relative to u))| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|aggregation method(U.map(u -> W evaluated relative to u))| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C(U)| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||aggregated value|| |an aggregatable property path A/T/B|A|aggregation method(U.map(u -> u/T/B))| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|aggregation method(U.map(u -> W evaluated relative to u))| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|aggregation method(U.map(u -> W evaluated relative to u))| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C(U)| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||aggregated value|| |an aggregatable property path A/T/B|A|aggregation method(concatenation of primitive values u/T/B for each u in U)| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|aggregation method(W evaluated relative to u for each u in U)| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|aggregation method(W evaluated relative to u for each u in U)| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C(U)| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||aggregated value|| |an aggregatable property path A/T/B|A|aggregation method(concatenation of primitive values u/T/B for each u in U)| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|aggregation method(W evaluated relative to u for each u in U)| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|aggregation method(W evaluated relative to u for each u in U)| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C(U)| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||aggregated value|| |an aggregatable property path A/T/B|A|aggregation method(concatenation of primitive values u/T/B for each u in U)| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|aggregation method(W evaluated relative to each u in U)| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|aggregation method(W evaluated relative to each u in U)| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C(U)| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. An aggregate expression may be ||Option||P||aggregated value|| |an aggregatable property path A/T/B|A|aggregation method(concatenation of primitive values u/T/B for each u in U)| |a path A/{{$count}}, or A/T/B/{{$count}}, this behaves like an aggregatable property always having the value 1|A or A/T/B|??| |an aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued|absent|aggregation method(W evaluated relative to each u in U)| |a path A followed by a parenthesised aggregatable expression W like in the previous option|A|aggregation method(W evaluated relative to each u in U)| |a path A/C consisting of an optional prefix A/ and a custom aggregate C|A|C(U)| The first four options must be followed by {{with}} and a specified aggregation method. The table defines for each option a path prefix P and a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/{{$count}}, or A/T/B/{{$count}}. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/{{$count}}, or A/T/B/{{$count}}. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/{{$count}}, or A/T/B/{{$count}}. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/{{$count}}, or A/T/B/{{$count}}. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * An aggregatable property path A/T/B/{{$count}} where B is a collection-valued complex or navigation property. This option sets P = A * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first three options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * An aggregatable property path A/T/B/{{$count}} where B is a collection-valued complex or navigation property. This option sets P = A * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first three options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * An aggregatable property path A/T/B/{{$count}} where B is a collection-valued complex or navigation property. This option sets P = A and computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * An aggregatable property path A/T/B/{{$count}} where B is a collection-valued complex or navigation property. This option sets P = A and computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/T/B/{{$count}} with A and T like in the previous option and where B is a collection-valued complex or navigation property. This option sets P = A and computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/T/B/{{$count}} with A and T like in the previous option and where B is a collection-valued complex or navigation property. This option sets P = A and computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/T/B/{{$count}} with A and T like in the previous option and where B is a collection-valued navigation property. This option sets P = A and computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, A is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. A is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path A/T/B or where the prefix A/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. A/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path A/T/B. This option sets P = A and computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path A/T/B/{{$count}} with A and T like in the previous option and where B is a collection-valued navigation property. This option sets P = A and computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths A'/T/B where B and every segment of A' are single-valued. This option does not set P and computes the aggregated value as aggregation method(W evaluated relative to each u in U). * A path A followed by a parenthesised aggregatable expression W like in the previous option. This option sets P = A and computes the aggregated value like the previous option. * A path A/C consisting of an optional prefix A/ and a custom aggregate C. This option sets P = A and computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/B or where the prefix P/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. P/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path P/T/B. This option computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path P/T/B/{{$count}} with P and T like in the previous option and where B is a collection-valued navigation property. This option computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/B where B and every segment of P' are single-valued. This option computes the aggregated value as aggregation method(W evaluated relative to each u in U), P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/B or where the prefix P/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. P/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path P/T/B. This option computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path P/T/B/{{$count}} with P and T like in the previous option and where B is a collection-valued navigation property. This option computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/B where B and every segment of P' are single-valued. This option computes the aggregated value as aggregation method(W evaluated relative to each u in U), P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/B or where the prefix P/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. P/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path P/T/B. This option computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path P/T/B/{{$count}} with P and T like in the previous option and where B is a collection-valued navigation property. This option computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/B or P'/T/B/{{$count}} like in the first two options where B and every segment of P' are single-valued. This option computes the aggregated value as aggregation method(W evaluated relative to each u in U), P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/B or where the prefix P/ is optional, B is an aggregatable property, and the infix T/ is a type-cast segment that is present only if B is declared on the derived type T. P/T/B is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path P/T/B. This option computes the aggregated value as aggregation method(concatenation of primitive values u/T/B for each u in U). * A path P/T/B/{{$count}} with P and T like in the previous option and where B is a collection-valued navigation property. This option computes the aggregated value as aggregation method(cardinalities of u/T/B for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/B or P'/T/B/{{$count}} like in the first two options where B and every segment of P' are single-valued. This option computes the aggregated value as aggregation method(W evaluated relative to each u in U), P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path P/T/A. This option computes the aggregated value as aggregation method(concatenation of primitive values u/T/A for each u in U). * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value as aggregation method(cardinalities of u/T/A for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value as aggregation method(W evaluated relative to each u in U), P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The following aggregate expressions are supported. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of the given aggregate expression. * An aggregatable property path P/T/A. This option computes the aggregated value as aggregation method(concatenation of primitive values u/T/A for each u in U). * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value as aggregation method(cardinalities of u/T/A for each u in U). * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value as aggregation method(W evaluated relative to each u in U), P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). The first four options must be followed by {{with}} and a specified aggregation method. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance _containing one dynamic property per aggregate expression_ representing the aggregated value of the input set. In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance _containing one dynamic property per aggregate expression_ representing the aggregated value of the input set. In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance _containing one dynamic property per aggregate expression_ representing the aggregated value of the input set. In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the list of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1]: {quote}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance _containing one dynamic property per aggregate expression_ representing the aggregated value of the input set. In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the list of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. If P is present, ... {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the list of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the list of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U). Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the list of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U) and names the dynamic property C. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the concatenation of primitive values u/T/A for each u in U. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the list of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the list of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U) and names the dynamic property C. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the collection of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U) and names the dynamic property C. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments whose last segment has a complex or entity type. P is an instance of rule {{aggPathPrefix}} in [OData-Aggr-ABNF]. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. P/T/A is an instance of rule {{aggPathPrimitive}} in [OData-Aggr-ABNF]. The allowed options for aggregate expressions are listed below. The first four options must be followed by the keyword {{with}}, an aggregation method, the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * A path P/T/A/{{$count}} with P and T like in the previous option and where A is a collection-valued navigation property. This option computes the aggregated value by applying the aggregation method to the collection of cardinalities of u/T/A for each u in U. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and paths P'/T/A or P'/T/A'/{{$count}} like in the first two options where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P followed by a parenthesised aggregatable expression W like in the previous option. This option computes the aggregated value like the previous option. * A path P/C consisting of an optional prefix P/ and a custom aggregate C. This option computes the aggregated value as C(U) and names the dynamic property C. Each option can be followed by a {{from}} expression. Finally, the aggregate expression {{$count}} is a shortcut for {{1 with sum}}. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. A grouping property is an instance of rule {{groupingProperty}} in [OData-Aggr-ABNF]. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The path is an instance of rule {{nestPath}} in [OData-Aggr-ABNF]. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and stream properties_ specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and stream properties_ specified in _these_-grouping property- paths are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and stream properties_ specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties _and stream properties_ specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} and rephrase {quote} * _[Aggregatable Property|#sec_AggregatableProperties]_ – a property for which the values can be aggregated using an aggregation method. _Stream properties are not aggregatable._{quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} and rephrase {quote} * _[Aggregatable Property|#sec_AggregatableProperties]_ – a property for which the values can be aggregated using an aggregation method. _Stream properties are not aggregatable._{quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. Each option can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Correct example 86: {quote} {code:java} GET ~/SalesOrganizations?$apply= transformnested(Sales,filter(Product/Name eq 'Paper')) /groupby((rollup(SalesOrgHierarchy)), aggregate(Sales/$count with sum as PaperSalesCount)) {code} {quote} Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value of this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A or where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first two options must be followed by the keyword {{with}} and an aggregation method. The first three options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second and fourth options can be followed by a {{from}} expression. * An aggregatable property path P/T/A. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U, or to the concatenation of collections of primitive values u/T/A if A is collection-valued. * An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. * A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) * A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer is treated as groupby((Customer/$ref)) {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in, for example, {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property or a collection thereof, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first three options must be followed by the keyword {{with}} and an aggregation method. The first four options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second, third and fifth options can be followed by a {{from}} expression. # An aggregatable property path P/T/A where A is single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U. # An aggregatable property path P/T/A where A is a collection-valued. This option computes the aggregated value by applying the aggregation method to collection of primitive values in each u/T/A for each u in U. # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property or a collection thereof, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first three options must be followed by the keyword {{with}} and an aggregation method. The first four options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second, third and fifth options can be followed by a {{from}} expression. # An aggregatable property path P/T/A where A is single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U. # An aggregatable property path P/T/A where A is a collection-valued. This option computes the aggregated value by applying the aggregation method to collection of primitive values in each u/T/A for each u in U. # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "@odata.id": "Customers('C1')" } }, { "Customer": { "@odata.id": "Customers('C2')" } }, { "Customer": { "@odata.id": "Customers('C3')" } } ] } {code} or in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} by default. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property or a collection thereof, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first three options must be followed by the keyword {{with}} and an aggregation method. The first four options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second, third and fifth options can be followed by a {{from}} expression. # An aggregatable property path P/T/A where A is single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U. # An aggregatable property path P/T/A where A is a collection-valued. This option computes the aggregated value by applying the aggregation method to collection of primitive values in each u/T/A for each u in U. # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. An _aggregatable property path_ is a path P/T/A where the prefix P/ is optional, A is an aggregatable property or a collection thereof, and the infix T/ is a type-cast segment that is present only if A is declared on the derived type T. The allowed options for aggregate expressions are listed below. The first three options must be followed by the keyword {{with}} and an aggregation method. The first four options must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property that the aggregate expression produces. Each option defines a rule how to compute, for a collection U of instances, the aggregated value taken by this dynamic property. U is computed from the input set of the {{aggregate}} transformation and the path P that occurs in the aggregate expression, as explained below. The first, second, third and fifth options can be followed by a {{from}} expression. # An aggregatable property path P/T/A where A is single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values u/T/A for each u in U. # An aggregatable property path P/T/A where A is a collection-valued. This option computes the aggregated value by applying the aggregation method to collection of primitive values in each u/T/A for each u in U. # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and aggregatable property paths P'/T/A where A and every segment of P' are single-valued. This option computes the aggregated value by applying the aggregation method to the collection of primitive values of W evaluated relative to each u in U. P is absent in this option. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. This option computes the aggregated value as the number of entries in U. ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/C consisting of an optional prefix P/ and a custom aggregate C defined on the input set or the collection addressed by P. This option computes the aggregated value as C(U) and names the dynamic property C. {color:#57d9a3}If P is present, it must be well-defined for all instances in the input set. Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, the aggregated value is computed{color} for _U = E_, {color:#57d9a3}otherwise the aggregated value is computed for{color} _U containing_ {color:#57d9a3}all instances addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, the aggregated value is computed for{color} _U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P must be well-defined for all instances in the input set. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, this is determined based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property. In types 1, 2 and 4, it can be followed by a {{from}} expression. _Types of aggregate expression:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to u for each u in U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ and a custom aggregate c defined on the input set or the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, {color}_let U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P must be well-defined for all instances in the input set. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, this is determined based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is the name of the dynamic property. In types 1, 2 and 4, it can be followed by a {{from}} expression. _Types of aggregate expression:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to u for each u in U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ and a custom aggregate c defined on the input set or the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} Let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} {color:#57d9a3}If no paths are present, {color}_let U = input set_. -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value.- {color:#57d9a3}The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).{color} {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include all properties that the server includes in the expansion by default of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative to the input set of the {{aggregate}} transformation, this must be well-defined. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ whose last segment has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative to the input set of the {{aggregate}} transformation, this must be well-defined. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ whose last segment has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative to the input set of the {{aggregate}} transformation, this must be well-defined. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that then yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ whose last segment has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity (see example 61)._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative to the input set of the {{aggregate}} transformation, this must be well-defined. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that then yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ whose last segment has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity (see example 61)._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative the input set of the {{aggregate}} transformation, this must be well-defined for each instance in the input set. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that then yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ whose last segment has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity (see example 61)._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative the input set of the {{aggregate}} transformation, this must be well-defined for each instance in the input set. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that then yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ whose last segment has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity (see example 61)._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative the input set of the {{aggregate}} transformation, this must be well-defined for each instance in the input set. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that then yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ where the last segment of P has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity (see example 61)._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Proposal |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative the input set of the {{aggregate}} transformation, this must be well-defined for each instance in the input set. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that then yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ where the last segment of P has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- Only the name of the last segment of an aggregate expression appears in the result (see Example 64, with Q = Sales and R = Amount). {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity (see example 61)._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Introduce the following definition in [OData-Aggr, section 2.1]:
{quote}A _data aggregation path_ consists of one or more segments separated by a forward slash. Segments are names of declared or dynamic structural or navigation properties other than stream properties, or type-cast segments consisting of the (optionally qualified) name of a structured type that is derived from the type identified by the preceding path segment to reach properties declared by the derived type. {quote} Rephrase [OData-Aggr, section 3.1] (unchanged parts in {color:#57d9a3}green{color}): {quote}{color:#57d9a3}The {{aggregate}} transformation takes a comma-separated list of one or more _aggregate expressions_ as parameters and returns an output set with a single instance{color} _containing one dynamic property per aggregate expression_ {color:#57d9a3}representing the aggregated value of the input set.{color} In the following, P is a _data aggregation path_ with single- or collection-valued segments. P is evaluated relative to the input set of the {{aggregate}} transformation, this must be well-defined for each instance in the input set. The allowed types of aggregate expressions are listed below. To compute the value of the dynamic property for a given aggregate expression, the {{aggregate}} transformation first determines a collection U of instances or primitive values, based on the input set of the {{aggregate}} transformation and a path P that occurs in the aggregate expression, as explained below. Each type of aggregate expression defines a function f(U) that then yields the dynamic property value. In types 1 and 2, the aggregate expression must be followed by the keyword {{with}} and an aggregation method g. In types 1, 2 and 3, it must be followed by the keyword {{as}} and an alias, which is then the name of the dynamic property. In types 1, 2 and 4, the aggregate expression can be followed by a {{from}} expression. _Types of aggregate expressions:_ # A path P whose last segment is an aggregatable property. f(U) = g(U). # An aggregatable expression W built from arithmetic operations [OData-URL, section 5.1.1.2], unbound primitive function calls, numeric or duration values, and data aggregation paths with single-valued segments whose last segment is primitive. f(U) = g(W evaluated relative to each member of U). In this type, P is absent. # A path P/{{$count}} with optional prefix P/ where the last segment of P is collection-valued. f(U) = cardinality(U). ({{$count}} behaves like a property having the value 1 followed by {{with sum}}.) # A path P/c consisting of an optional prefix P/ where the last segment of P has a structured type and a custom aggregate c defined on the collection addressed by P. f(U) = c(U). The name of the dynamic property is the name of the custom aggregate. _Determination of U:_ _If P is absent, let U = input set._ -If P is present, it must be well-defined for all instances in the input set.-{color:#57d9a3} {color}_Otherwise,_{color:#57d9a3} let Q be the portion of P up to and including the last navigation property, if any, and let R be the remainder, if any, of P that contains no navigation properties, such that P equals the concatenated path Q/R. The aggregate transformation considers each entity reached via the path Q exactly once. To this end{color} * {color:#57d9a3}if Q is non-empty, let E be the set of distinct entities reached via Q starting from the input set{color} * {color:#57d9a3}if Q is empty, let E be the input set (which may contain multiple instances with the same value).{color} {color:#57d9a3}Then, if R is empty, {color}_let U = E_, {color:#57d9a3}otherwise {color}_let U be the collection containing_ {color:#57d9a3}all instances {color}_or primitive values (possibly with repititions)_{color:#57d9a3} addressed via R starting from E.{color} -Any aggregate expression that specifies an aggregation method MUST define an [alias|#sec_Keywordas] for the resulting aggregated value. The resulting instance contains one dynamic property per parameter representing the aggregated value. The properties of P do not appear in the result (see Example 64, with P = Q = Sales and R = empty).- {quote} Rephrase [OData-Aggr, section 3.10.1]: {quote}In its simplest form the first parameter of {{groupby}} specifies the _grouping properties_, a comma-separated list of one or more _data aggregation paths_ with single-valued segments that is enclosed in parentheses. ... If the -property- path leads to a single-valued navigation property, this means grouping by the entity-id of the related entities. -Other- navigation properties specified in grouping properties -paths- are expanded by default. {quote} Rephrase step 4: {quote}In each set resulting from the previous step, each entity and complex _property_-type-, including nested complex and navigation properties, are augmented if necessary to include all primitive property values of the corresponding projection. _In case of grouping by entity-id of a related entity, they must include at least the key properties of the related entity (see example 61)._ {quote} Rephrase [OData-Aggr, section 3.13]: {quote}Their first parameter is a _data aggregation path_ with single- or collection-valued non-primitive segments where only the last segment may have an entity type, but it can instead have a complex type. This path is optionally followed by a type-cast segment to -expand-_select_ only related entities of that derived type or one of its sub-types. The sub-path starting with the last segment that is not a type-cast is called the final sub-path in this definition. This is -a generalization-_an extension_ of the definition in [OData-URL, section 5.1.3] in that it does not require a navigation property -or entity-valued instance annotation-. {quote} Remove mentions of "entity-valued instance annotation" from sections 3.13.1 and 3.13.2. Rephrase example 61: {quote}Example 61: Grouping by navigation property Customer -is treated as groupby((Customer/$ref))- {code:java} GET ~/Sales?$apply=groupby((Customer)) {code} may result in {code:java} { "@odata.context": "$metadata#Sales(Customer)", "value": [ { "Customer": { "ID": "C1" } }, { "Customer": { "ID": "C2" } }, { "Customer": { "ID": "C3" } } ] } {code} depending on which properties the server includes when expanding {{Customer}} without {{$select}} or {{$ref}}. {quote} Add new example 63: {quote}If both subtypes have a {{Rating}} property but their common base type does not, {code:java} GET ~/Products?$apply=groupby((SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)) {code} results in {code:java} { "@odata.context": "$metadata#Products( SalesModel.FoodProduct/Rating, SalesModel.NonFoodProduct/Rating)", "value": [ {"@odata.type": "#SalesModel.FoodProduct", "Rating": 5}, {"@odata.type": "#SalesModel.FoodProduct", "Rating": null}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": "average"}, {"@odata.type": "#SalesModel.NonFoodProduct", "Rating": null} ] } {code} Note that the {{@odata.type}} context information is needed to distinguish the two groups with {{"Rating": null}}. {quote} Remove {{with sum}} after {{$count}} in example 67. Merge ABNF pull request [#75|https://github.com/oasis-tcs/odata-abnf/pull/75] and vocabularies pull request [#186|https://github.com/oasis-tcs/odata-vocabularies/pull/186]. |
Status | Open [ 1 ] | Resolved [ 5 ] |
Status | Resolved [ 5 ] | Applied [ 10002 ] |
Status | Applied [ 10002 ] | Closed [ 6 ] |