-- 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.