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];