release notes

model release notes version partitions-108.5

Model 109 (after 108)

Changes

application language

// new ‘Parts Cost’: number ‘euro’ = sum ( .’Parts’* .’Part Price’ ) ‘# Products’: number ‘items’ = count ( .’Products’* )


- Sibling access is a navigation step `siblings`, so it can be taken within a path. An entry reference to a sibling ends in `[]`:
```js
// old
'Previous Year': text -> ^ sibling in ( 'Ordered Years' )
'Self or Sibling': text -> ^ sibling || self

// new
'Previous Year': text -> ^ siblings in 'Ordered Years' []
'Self or Sibling': text -> ^ siblings || self []
'Weeks': reference-set -> ^ siblings * .'Weeks'*

// ERROR: a filter that the signature of ‘Customers’ does not declare ‘# Active’: number ‘items’ = count ( >’Region’ <’Customers’[ >’Country’ .’Cities’* .’Customers’* .’Status’?’Active’ ] )

A level of a subset path may not be a reference set or a matched set, and a sibling or graph step is allowed
only where the signature has the same location. Below a level that the path pins, the filters of the signature
may be left out. A subset step produces every node once, also when several members of the set lead to it.

- The cardinality of a reference set subset is computed per level: pinning the parent level of a set that inverts a key reference yields at most one node, so a `switch` without `| nodes` is accepted:
```js
'Line found': stategroup = switch <'Lines'[ ^ >'Order'.'Lines'* ] ( // 'Line' is the key of 'Lines'
	| node => 'Yes' ( )
	| none => 'No' ( )
) ( ... )

‘Slots’: collection [‘Slot’] = union ( ‘this’ = <’Shifts’[ ^ .’Time Slots’* ] // merge: one entry per node the path produces ) { … }


- A containment `where` rule whose lookup value is unique per entry re-roots the scope of the steps after it, like a key reference step does, so a branch path may continue over it:
```js
'Orders': collection ['Order'] {
	'Order': text -> ^ .'Order Numbers'[] as $
		where 'Invoice' -> ^ .'Invoices'>[ $ ] // unique lookup value: distinct orders reach distinct invoices
}
'Debtors': collection ['Debtor'] = union (
	'this' = .'Orders'* as $ on $ .'Order'&'Invoice'>'Debtor' // accepted
) { ... }

The lookup value decides, not whether the property holding the rule is the key of its collection. A lookup on a value that repeats, or into a collection that lives inside the entry itself, does not re-root the scope.

‘ok’ = .’Items’* as $ on $ >’Ref B’ // >’Ref B’ takes the same filter ‘bad’ = .’Items’* as $ on $ >’Ref B2’ // ERROR: the filter ?’Open’ is missing

The reverse is allowed: a value path may filter where the reference does not.

- A `where` rule may supply the state filter that a reference target or a union key demands, and a `flatten` branch pops the filter together with the collection step it leaves:
```js
'Ref': text -> siblings [] as $
	where 'in S' -> $ .'Status'?'Open'
'Ref in S': text -> siblings [] .'Status'?'Open' = .'Ref'&'in S' // accepted

'Lines': collection ['Line'] = flatten (
	'open' = .'Orders'* .'Status'?'Open' as $ ( 'Debtor' = $ ^ ^ >'Debtor' )
) join - { ... }

‘Periods’: collection [‘Period’] = partition … { ‘First’: stategroup = parameter ( ‘No’ { ‘Predecessor’: text -> ^ siblings in ‘Period Order’ [] = parameter // ERROR: the partition initializes the entry } ‘Yes’ { } ) }


- `source-of` and `sink-of` take the first or last entry of one whole collection, so the path handed to them may not filter or iterate:
```js
'First Activity': text -> downstream ^ .'Activities'[] = sink-of ^ .'Activities'* in 'Order' // accepted

// ERROR: a state filter in the collection path
'First Open': text -> downstream ^ .'Activities'[] = sink-of ^ .'Activities'* .'Status'?'Open' in 'Order'

// ERROR: a reference set holds some entries, not a whole collection
'First Member': text -> downstream ^ .'Activities'[] = sink-of <'Members'* in 'Order'