-- File: QueryProcs.mesa -- Contents: Querying procs for messages and any kind of entity -- Last edited by: -- Cattell on January 17, 1983 8:43 am DIRECTORY DB, System, WalnutDB; QueryProcs: PROGRAM IMPORTS DB, WalnutDB = BEGIN OPEN DB, WalnutDB; MsgQuery: PROC[sender, to: RName, lowDate, highDate: System.GreenwichMeanTime] RETURNS[LIST OF Msg] = BEGIN pl: LIST OF PropertyValue← NIL; dateLast: BOOL← highDate-lowDate>LONG[60]*60*24 -- one day --; IF dateLast AND highDate#lowDate THEN pl← CONS[[mDateCodeOf, LIST[[mDateCodeIs, T2V[lowDate], T2V[highDate]]]], pl]; IF to#NIL THEN pl← CONS[[mToOf, LIST[[mToIs, to]]], pl]; IF sender#NIL THEN pl← CONS[[mSenderOf, LIST[[mSenderIs, sender]]], pl]; IF NOT dateLast AND highDate#lowDate THEN pl← CONS[[mDateCodeOf, LIST[[mDateCodeIs, T2V[lowDate], T2V[highDate]]]], pl]; IF pl=NIL THEN -- Enumerate all messages!! BEGIN ml: LIST OF Msg; msgs: EntitySet← DomainSubset[MsgDomain]; FOR m: Msg← NextEntity[msgs], NextEntity[msgs] UNTIL m=NIL DO ml← CONS[m, ml] ENDLOOP; RETURN[ml] END; RETURN[EntityQuery[pl]] END; PropertyValueList: TYPE = LIST OF PropertyValue; PropertyValue: TYPE = RECORD[ from: Attribute, -- entity-valued attribute of a relation avl: AttributeValueList -- value contraints on other attributes of same relation ]; EntityQuery: PROC[pvl: PropertyValueList] RETURNS[LIST OF Entity] = -- A handy procedure for finding all the entities of a domain that have the given -- property values. Finds all the entities which, for each PropertyValue in the -- PropertyValueList list, there exists at least one relationship whose -- "from" attribute equals the entity and whose other attributes satisfy the -- attribute value list. BEGIN f: Attribute← pvl.first.from; r: Relation← V2E[GetP[f, aRelationIs]]; elNew: LIST OF Entity← NIL; nestedRS: RelshipSet← RelationSubset[r, pvl.first.avl]; FOR t: Relship← NextRelship[nestedRS], NextRelship[nestedRS] UNTIL t=NIL DO elNew← CONS[V2E[GetF[t, f]], elNew] ENDLOOP; ReleaseRelshipSet[nestedRS]; RETURN[NestedEntityQuery[elNew, pvl.rest]] END; NestedEntityQuery: PROC[elOld: LIST OF Entity, pvl: PropertyValueList] RETURNS[LIST OF Entity] = { -- Finds the entities in elOld that satisfy pvl. We do this recursively as follows. -- For each entity in elOld, we do a RelationSubset to find the tuples that satisfy pvl.first -- and also reference the entity. If this list is not empty, we can keep that entity in a -- new list elNew; otherwise we toss it. When all the entities in elOld that also -- satisfy pvl.first have been added to elNew in this way, we recursively call -- NestedEntityQuery, returning the entities in elNew which also satisfy pvl.rest. IF pvl=NIL THEN RETURN[elOld] ELSE { f: Attribute← pvl.first.from; r: Relation← V2E[GetP[f, aRelationIs]]; elNew: LIST OF Entity← NIL; -- will equal those in elOld that satisfy pvl.first FOR elOldT: LIST OF Entity← elOld, elOldT.rest UNTIL elOldT=NIL DO nestedRS: RelshipSet← RelationSubset[r, CONS[ [f, elOldT.first], pvl.first.avl]]; -- The nestedRS contains tuples that reference e and also satisfy first element of pvl. -- We can keep elOldT.first in the elNew list iff this list is non-empty. IF NextRelship[nestedRS] #NIL THEN elNew← CONS[elOldT.first, elNew]; ReleaseRelshipSet[nestedRS]; ENDLOOP; RETURN[NestedEntityQuery[elNew, pvl.rest]]; }}; END.