Parts Example in Galileo
This is a toy application used in "M. P. Atkinson and O. P. Buneman,
Types and Persistence in Database Programming Languages, ACM Computing
Surveys, 19(2):105-190, 1987" to compare different database programming
languages. It represents a fragment of a manufacturing company's parts and
suppliers database; in particular, the way certain parts are made of other
parts, either composite or base bought outside.
The database schema is shown in the following figure:
let NewCode:=
use Code := var 0
in fun() :int is
(Code <- at Code + 1;
at Code);
let rec Parts class
Part <->
[ Name: string;
Code:= NewCode();
Cost:= meth() :int is virtual;
Mass:= meth() :int is virtual;
UsedIn:= meth() :seq CompositePart is
CompositeParts where
(some x In Components with x.Part = self);
BasePartComponents := meth() :seq BasePart is
if self isalso BasePart
then {self As BasePart}
else use pc:= self As CompositePart
in setof(flatten(
select x.Part.BasePartComponents
from x In pc.Components
)
)
]
and BaseParts subset of Parts class
BasePart <-> is Part and
[PartCost: int;
PartMass: int;
Cost:= meth() :int is self.PartCost;
Mass:= meth() :int is self.PartMass;
SuppliedBy:= meth() :seq Supplier is
Suppliers
where self isin (at PartsSold) ]
before mk(this)
if Not (this.PartCost > 0) And (this.PartMass > 0)
do failwith "Cost and Mass must be > 0"
and CompositeParts subset of Parts class
CompositePart <-> is Part and
[AssemblyCost :int;
Cost :=
meth() :int is
self.AssemblyCost +
sum(select (Part.Cost) * Quantity
from self.Components );
Mass :=
meth() :int is
sum(select (Part.Mass) * Quantity
from self.Components );
Components: seq [ Part: Part; Quantity: int ] ]
before mk(this)
if Not this.AssemblyCost > 0
do failwith "Assembly cost must be > 0"
and Suppliers class
Supplier <->
[ Name: string;
Address: string;
PartsSold: var seq BasePart
]
before mk(this)
if use isSet := fun(x:seq BasePart):bool is setof(x) = x
in Not(count(at (this.PartsSold)) > 0
And isSet(at (this.PartsSold)) )
do failwith "Parts sold must be at least one and all different"
key(Name) ;
% ********* Data ********* %
let p1:=mkBasePart([ Name := "Piston";
PartCost := 10000;
PartMass := 1000 ]);
let p2:=mkBasePart([ Name := "Cylinder";
PartCost := 10000;
PartMass := 500 ]);
let p6:=mkBasePart([ Name := "Wheel" ;
PartCost := 2222;
PartMass := 222 ]);
let pc2:=mkCompositePart([ Name := "Piston-Cylinder" ;
AssemblyCost := 1000;
Components:=
{[ Part := p2; Quantity := 1 ];
[ Part := p1; Quantity := 1 ]}]);
let pcc1:=mkCompositePart(
[ Name := "Car" ;
AssemblyCost := 13000 ;
Components:=
{[ Part := pc2; Quantity := 6 ];
[ Part := (p6 As Part); Quantity := 4 ]} ]);
mkSupplier([ Name :="Bendini";
Address := "Via P.Tarditi 154, 11332, Biella";
PartsSold := var {p1; p2} ]);
mkSupplier([ Name :="Landini";
Address := "Via A. Lancia 1, 10121, Torino";
PartsSold := var {p6} ]);
mkSupplier([ Name := "Landocci";
Address := "Via A. Lancia 3, 10121, Torino";
PartsSold := var ({ }:seq BasePart) ]);
% ******* Queries ******* %
% Q1: Find Name, Cost and Mass of the base parts which cost more than 100 %
select [Name := p.Name;
Cost := p.PartCost;
Mass := p.PartMass ]
from (p In BaseParts)
where p.PartCost > 100 ;
% Q2: Find the name of base parts of a composite part with
a given name. %
select Name
from (get CompositeParts where Name = "Car").BasePartComponents;
select Name
from (get Parts where Name = "Car").BasePartComponents;
% Q3: Find Mass and Cost of a part with a given name.%
use p := get Parts where Name = "Car"
in [ Cost := p.Cost;
Mass := p.Mass];