95 Materialised Accessors
Once a frame has been materialised as an s-relation, it is sometimes useful to extract an ordinary set, tuple, or value from that relation-shaped result. The accessors in this chapter are conveniences for that situation.
This chapter writes the accessors as $set, $tup, and $val. Those spellings are accessor
conventions in the relation view; if they are exposed as Predica surface syntax or library operations,
the shape requirements below are the behaviour they must preserve.
Each accessor deliberately forgets part of the relation structure. Therefore each accessor is defined only when the materialised relation has the required shape.
Accessor Summary
| Accessor | Required shape | Result | Structure forgotten |
|---|---|---|---|
R.$set |
R is under a unary heading. |
The set of values in the single attribute. | The attribute label and tuple wrappers. |
R.$tup |
R has exactly one tuple. |
That s-tuple. | The outer relation wrapper. |
R.$val |
R is under a unary heading and has exactly one tuple. |
The single value in that tuple. | The relation, tuple, and attribute wrappers. |
If the required shape does not hold, the accessor is undefined for that materialised result. An implementation may report this as a static error when the shape is known statically, or as a runtime error when the shape depends on the data.
Unary Set Extraction
Let R be a materialised s-relation under a unary heading:
H = { city: String }
R =
{
{ city: "London" },
{ city: "Paris" },
{ city: "Athens" }
}
Then:
R.$set = { "London", "Paris", "Athens" }
In general, for H = { a: T }:
R.$set = { s.a | s ∈ R }
The result is a set of values of type T. The attribute name a is discarded. This is why $set
is defined only for unary headings. For a non-unary heading there is no
single attribute whose values should be extracted.
Singleton Tuple Extraction
Let R be a materialised s-relation with exactly one tuple:
H = { id: Integer, city: String }
R =
{
{ id: 17, city: "London" }
}
Then:
R.$tup = { id: 17, city: "London" }
The heading need not be unary. The only requirement is that the relation body contains exactly one
s-tuple. If R is empty or contains more than one tuple, $tup is undefined.
Singleton Value Extraction
The $val accessor combines the requirements of $set and $tup. The materialised relation must
be under a unary heading and contain exactly one tuple:
H = { status: Integer }
R =
{
{ status: 20 }
}
Then:
R.$val = 20
Equivalently, if H = { a: T } and R = { { a: v } }, then:
R.$val = v
If R is empty, has more than one tuple, or is not under a unary heading, $val is
undefined.
Set-Valued Values Are Still Values
The word "value" in $val refers to the single value stored in the single result attribute. That
value may itself be a set-valued value.
For example:
H = { statuses: Set<Integer> }
R =
{
{ statuses: {} }
}
Then:
R.$val = {}
This is not the same situation as the empty relation under the unary heading
status: Integer:
H = { status: Integer }
R = {}
In that case R.$set is {}, but R.$val is undefined because there is no singleton tuple. The
difference is exactly the difference between returning a set-valued result term and returning a
single-valued relation attribute whose predicate has no witness.
Use With M-Relations
These accessors are defined on the s-relation view. If an implementation stores a result as an m-relation, it may implement the accessor without fully multiplying out the result, but the answer must be the same as applying the accessor after heading-relative expansion.
accessor(M under H) is defined iff accessor(M!_H) is defined
and then accessor(M under H) = accessor(M!_H)
This is the same trust boundary used for the rest of the m-relation operations. The implementation may keep the compact representation only when the materialised result agrees with the s-relation semantics.
Why These Are Accessors
The accessors are useful precisely because relation-shaped results are often more structure than the caller wants. A query may naturally produce a unary relation when the caller wants a set, a singleton relation when the caller wants a tuple, or a singleton unary relation when the caller wants a value.
The conversion should be explicit because it is lossy. $set drops attribute labels, $tup drops
relation cardinality, and $val drops both. Keeping these operations explicit protects the
logic-frame denotation while still giving implementors and users a compact way to consume
materialised results.