80 Query Examples
This chapter gives a small tour of Predica query notation using the familiar Supplier/Parts model. The examples focus on how the notation reads. The Relations part gives the fuller correspondence with relational-model operators, and the Semantics part gives the logic-frame denotation.
Example Model
entity Supplier
{
Integer id;
String name;
Integer status;
String city;
Shipment shipment* where shipment.supplier = this;
key {id};
}
entity Part
{
Integer id;
String name;
Color color;
Real weight;
String city;
Shipment shipment* where shipment.part = this;
key {id};
//constraints { shipment.part ⊆ { this }; }
}
entity Shipment
{
Supplier supplier;
Part part;
Integer qty;
key {supplier,part};
}
entity ShipmentsSystem
{
Supplier supplier*;
Part part*;
→ Shipment shipment* = either supplier.shipment, part.shipment;
}
Assume a variable s whose type is ShipmentsSystem. Paths starting at s
navigate through suppliers, parts, and shipments.
Navigation and Projection
| Question | Predica | Reading |
|---|---|---|
| All suppliers | |
Navigate from the system to its supplier values. |
| Supplier names | |
For each supplier reached, observe its name. |
| Supplier names and cities | |
Reshape each supplier into a result with two exposed labels. |
| Shipment rows with names | |
Use the shipment as the witness and expose values reached through it. |
Filtering
| Question | Predica | Reading |
|---|---|---|
| Suppliers in London | |
Keep the current suppliers whose city satisfies the filter. |
| Names of suppliers in London | |
Filter suppliers first, then observe their names. |
| Parts heavier than 15 | |
Use a numeric condition in the context of each part. |
| Shipments of red parts | |
The filter may navigate from the current shipment to related values. |
Inverse Navigation
If Supplier defines → shipment* = inverse shipment.supplier, then a supplier
can be queried directly for the shipments that refer to it.
| Question | Predica | Reading |
|---|---|---|
| Shipments for each supplier | |
Navigate backwards from supplier to referring shipments. |
| Part names shipped by each supplier | |
Combine forward and inverse navigation in one result shape. |
Folds and Set Observations
| Question | Predica | Reading |
|---|---|---|
| Suppliers with shipments | |
Fold the supplier's shipment path to a Boolean condition. |
| Suppliers with no shipments | |
Keep suppliers whose inverse shipment path is empty. |
| Number of shipments per supplier | |
Fold the reached shipments while preserving the supplier context. |
| Total quantity shipped by supplier | |
Navigate to quantities and aggregate them for each supplier. |
| Parts shipped by exactly one supplier | |
Use a folded path inside a filter condition. |
Cardinality-Aware Assignment
Queries often reach more than one value. Assigning such a result to a single-valued variable is invalid; the target must permit the cardinality of the query result.
var id1 = 0;
id1 := s.supplier.id; // static cardinality constraint check failure
var Integer id2* = {};
id2 := s.supplier.id; // ok
Value Sharing in Literals
The .. notation resolves an existing value through a query while constructing
a literal. This lets a literal share values already present in the surrounding
object graph.
Shipment {
supplier = ..supplier[id = 1],
part = ..part[id = 2],
qty = 200
}
The resolved values are still ordinary Predica values. Any internal handles or indexes used to implement this lookup are not part of the user-visible semantics.