Overture Tool

Formal Modelling in VDM

Overture Tool

Go to our GitHub Profile

Follow @overturetool

NDBSL

Author: Rich Bradford

The Non-programmer database system (NDB) is a nicely engineered binary relational database system invented by Norman Winterbottom of IBM. The formal Specification of NDB was originally undertaken by Anne Walshe, who has subsequently documented the specification and its refinement. NDB has been used as an example problem for modular specification in VDM-SL. However, the version available here is a “flat” specification. The postscript file includes a significant description of the validation of the specification using execution. Test coverage is not used though. Relevant publications are:

A. Walshe, “NDB: The Formal Specification and Rigorous Design of a Single-User Database System”, in C.B. Jones and R.C. Shaw (eds), “Case Studies in Systematic Software Development”, Prentice Hall 1990, ISBN 0-13-116088-5

J.S. Fitzgerald and C.B. Jones, “Modularizing the Formal Description of a Database System”, in D. Bjorner, C.A.R. Hoare and H. Langmaack (eds), VDM ‘90: VDM and Z - Formal Methods in Software Development, Springer-Verlag, LNCS 428, 1990

Properties Values
Language Version: classic

ndb.vdmsl

types

	Eid = token;
	Value = token; 
	Esetnm = token;
	Rnm = token;
	
	Maptp = <ONETOONE>|<ONETOMANY>|<MANYTOONE>|<MANYTOMANY>;

	Tuple :: fv : Eid
		 tv : Eid;

	Rinf :: tp : Maptp
		 r : set of Tuple;
		 
	Rkey :: nm : [Rnm]
		fs : Esetnm
		ts : Esetnm

functions

checkinv : map Esetnm to set of Eid * map Eid to [Value] * map Rkey to
Rinf -> bool
checkinv (esm,em,rm) ==
dom em = dunion rng esm and
              forall rk in set dom rm &
                 let mk_Rkey(-,fs,ts)=rk in
                 let mk_Rinf(tp,r) = rm(rk) in
                        {fs,ts} subset dom esm and
                        (tp = <ONETOMANY> => forall t1,t2 in
                        set r & t1.tv = t2.tv  => t1.fv = t2.fv) and
                        (tp = <MANYTOONE> => forall t1,t2 in
                        set r & t1.fv = t2.fv =>t1.tv = t2.tv) and
                        (tp = <ONETOONE> => forall t1,t2 in
                        set r & t1.fv = t2.fv <=> t1.tv = t2.tv) and
                        forall mk_Tuple(fv,tv) in set r & fv
                        in set esm(fs) and tv in set esm(ts)



state Ndb of

	 esm : map Esetnm to set of Eid
	 em  : map Eid to [Value]
	 rm  : map Rkey to Rinf

	 inv mk_Ndb(esm,em,rm) == checkinv (esm,em,rm)

init  ndb == ndb = mk_Ndb({|->},{|->},{|->})
end

	operations

	
	ADDES(es:Esetnm)
	ext wr esm : map Esetnm to set of Eid
	pre es not in set dom esm
	post esm = esm~ munion {es |-> {}};

	DELES(es:Esetnm)
	ext wr esm : map Esetnm to set of Eid
	    rd rm  : map Rkey to Rinf
	pre es in set dom esm and esm(es) = {} and
	    es not in set {rk.fs | rk in set dom rm } union {rk.ts |
	    rk in set dom rm}
	post esm = {es} <-: esm~;


	ADDENT(memb : set of Esetnm, val : [Value]) eid :Eid
	ext wr esm : map Esetnm to set of Eid
	    wr em  : map Eid to [Value]
	pre memb subset dom esm
	post eid not in set dom em~ and
	     em = em~ munion {eid |-> val} and
	     esm = esm~ ++ {es |-> esm~(es) union {eid} | es in set
	     memb };

	DELENT(eid:Eid)
	ext wr esm : map Esetnm to set of Eid
	    wr em  : map Eid to [Value]
	    rd rm  : map Rkey to Rinf
	pre eid in set dom em and
	    forall t in set dunion{ri.r|ri in set rng rm}& t.fv <>
	    eid and t.tv <> eid
	post esm = {es |-> esm~(es) \ {eid} | es in set dom esm~} and
	     em = {eid} <-: em~;

	ADDREL( rk:Rkey, tp:Maptp)
	ext rd esm : map Esetnm to set of Eid
	    wr rm  : map Rkey to Rinf
	pre {rk.fs,rk.ts} subset dom esm and
	    rk not in set dom rm
	post rm = rm~ munion {rk |-> mk_Rinf(tp,{})};

	DELREL (rk:Rkey)
	ext wr rm : map Rkey to Rinf
	pre rk in set dom rm and (rm(rk)).r ={}
	post rm ={rk} <-:rm~;

	ADDTUP (fval,tval : Eid, rk:Rkey)
	ext wr rm  : map Rkey to Rinf
	    rd esm : map Esetnm to set of Eid 
        rd em  : map Eid to [Value]
	pre rk in set dom rm and 
	    let ri = mu(rm(rk),r |-> (rm(rk)).r union
	    {mk_Tuple(fval,tval)}) in
		checkinv (esm,em,rm ++ {rk |->ri})
	post let ri =mu(rm~(rk),r |-> (rm~(rk)).r union
	{mk_Tuple(fval,tval)}) in rm =rm~ ++ {rk |->ri};

	DELTUP(fval,tval:Eid, rk:Rkey)
	ext wr rm : map Rkey to Rinf
	pre rk in set dom rm
	post let ri = mu(rm~(rk),r |-> (rm~(rk)).r \
	     {mk_Tuple(fval,tval)}) in
	     rm =rm~ ++ {rk |->ri}