File: NutOpsImpl.mesa
Last edited by
Maxwell on: September 7, 1982 2:52 pm
Willie-Sue on: February 22, 1983 4:24 pm
Cattell on: July 28, 1983 10:37 am
Donahue, July 16, 1984 3:46:16 pm PDT
Widom, June 17, 1984 8:20:03 pm PDT
Butler, August 13, 1984 9:34:13 pm PDT
DIRECTORY
DB,
MessageWindow,
NutOps,
Rope,
PrincOpsUtils,
ViewerClasses;
NutOpsImpl: CEDAR MONITOR
IMPORTS DB, Rope, PrincOpsUtils
EXPORTS NutOps
= BEGIN OPEN DB;
Viewer: TYPE = ViewerClasses.Viewer;
ROPE: TYPE = Rope.ROPE;
generally useful DB routines
IsSystemDomain: PUBLIC PROC[ name: Rope.ROPE ] RETURNS[ BOOLEAN ] = {
RETURN[ SELECT TRUE FROM
Rope.Equal[name, "DomainDomain"] => TRUE,
Rope.Equal[name, "RelationDomain"] => TRUE,
Rope.Equal[name, "DataTypeDomain"] => TRUE,
Rope.Equal[name, "AttributeDomain"] => TRUE,
Rope.Equal[name, "IndexDomain"] => TRUE,
Rope.Equal[name, "IndexFactorDomain"] => TRUE,
ENDCASE => FALSE ] };
IsSystemRelation: PUBLIC PROC[name: Rope.ROPE] RETURNS[BOOLEAN] = {
RETURN[ SELECT TRUE FROM
Rope.Equal[name, "dSubType"] => TRUE,
Rope.Equal[name, "aRelation"] => TRUE,
Rope.Equal[name, "aType"] => TRUE,
Rope.Equal[name, "aUniqueness"] => TRUE,
Rope.Equal[name, "aLength"] => TRUE,
Rope.Equal[name, "aLink"] => TRUE,
Rope.Equal[name, "ifIndex"] => TRUE,
Rope.Equal[name, "ifAttribute"] => TRUE,
ENDCASE => FALSE ] };
IsSystemEntity: PUBLIC PROC[name: Rope.ROPE] RETURNS[BOOLEAN] =
BEGIN
RETURN[ Rope.Equal[name, "Attribute"] OR Rope.Equal[name, "DataType"]
OR Rope.Equal[name, "Domain"] OR Rope.Equal[name, "Relation"] ];
END;
AttributesOf: PUBLIC PROC[r: Relation] RETURNS[AttributeList] =
{IF Eq[r, dSubType] THEN RETURN[LIST[dSubTypeIs, dSubTypeOf]];
IF Eq[r, aRelation] THEN RETURN[LIST[aRelationOf, aRelationIs]];
IF Eq[r, aType] THEN RETURN[LIST[aTypeOf, aTypeIs]];
IF Eq[r, aUniqueness] THEN RETURN[LIST[aUniquenessOf, aUniquenessIs]];
IF Eq[r, aLength] THEN RETURN[LIST[aLengthOf, aLengthIs]];
IF Eq[r, aLink] THEN RETURN[LIST[aLinkOf, aLinkIs]];
IF Eq[r, ifIndex] THEN RETURN[LIST[ifIndexOf, ifIndexIs]];
IF Eq[r, ifAttribute] THEN RETURN[LIST[ifAttributeOf, ifAttributeIs]];
RETURN[VL2EL[GetPList[r, aRelationOf]]]};
FirstAttributeOf: PUBLIC PROC[r: Relation] RETURNS[Attribute] =
BEGIN es: AttributeList← VL2EL[GetPList[r, aRelationOf]];
IF es=NIL THEN RETURN[NIL] ELSE RETURN[es.first]
END;
EntityValued: PUBLIC PROC [a: Attribute] RETURNS[BOOL] =
BEGIN type: Entity;
IF a=NIL OR Null[a] THEN RETURN[FALSE];
type← V2E[GetP[a, aTypeIs]];
SELECT type FROM
IntType, RopeType, BoolType, RecordType, TimeType => RETURN[FALSE];
ENDCASE => RETURN[TRUE];
END;
GetUniquenessString: PUBLIC PROC[a: Attribute] RETURNS[ROPE] =
BEGIN u: Uniqueness;
IF Eq[a, dSubTypeIs] THEN RETURN["NonKey"];
IF Eq[a, dSubTypeOf] THEN RETURN["NonKey"];
IF Eq[a, aRelationOf] THEN RETURN["Key"];
IF Eq[a, aRelationIs] THEN RETURN["NonKey"];
IF Eq[a, aTypeOf] THEN RETURN["Key"];
IF Eq[a, aTypeIs] THEN RETURN["NonKey"];
IF Eq[a, aUniquenessOf] THEN RETURN["Key"];
IF Eq[a, aUniquenessIs] THEN RETURN["NonKey"];
IF Eq[a, aLengthOf] THEN RETURN["Key"];
IF Eq[a, aLengthIs] THEN RETURN["NonKey"];
IF Eq[a, aLinkOf] THEN RETURN["Key"];
IF Eq[a, aLinkIs] THEN RETURN["NonKey"];
IF Eq[a, ifIndexOf] THEN RETURN["Key"];
IF Eq[a, ifIndexIs] THEN RETURN["NonKey"];
IF Eq[a, ifAttributeOf] THEN RETURN["Key"];
IF Eq[a, ifAttributeIs] THEN RETURN["NonKey"];
u← V2U[GetP[a, aUniquenessIs]];
SELECT u FROM
Key => RETURN["Key"];
KeyPart => RETURN["KeyPart"];
None => RETURN["NonKey"];
OptionalKey => RETURN["OptionalKey"];
ENDCASE => RETURN["???"];
END;
GetTuples: PUBLIC PROC[e: Entity, a: Attribute] RETURNS [tl: LIST OF Relship] =
returns all the tuples that reference e in attribute a
{RETURN[RelshipSetToList[RelationSubset[GetRelation[a], LIST[[a, e]] ]]]};
GetRelation: PUBLIC PROC[a: Attribute] RETURNS[r: Relation] =
finds a's relation
{RETURN[V2E[GetP[a, aRelationIs]]]};
GetRefAttributes: PUBLIC PROC[d: Domain] RETURNS[al: LIST OF Attribute] =
returns all the attributes that can reference an entity from domain d
BEGIN
starRelation: Relation← DeclareRelation["*", SafeSegmentOf[d]];
starOf: Attribute;
starIs: Attribute;
starList: LIST OF Attribute;
starOf ← DeclareAttribute[r: starRelation, name: "of", type: AnyDomainType, version: OldOnly
! DB.Error => CHECKED { starOf ← NIL; CONTINUE } ];
starIs ← DeclareAttribute[r: starRelation, name: "is", type: AnyDomainType, version: OldOnly
! DB.Error => CHECKED { starIs ← NIL; CONTINUE } ];
starList ← SELECT TRUE FROM
starOf = NIL AND starIs = NIL => NIL,
starIs = NIL => LIST[starOf],
starOf = NIL => LIST[starIs],
ENDCASE => LIST[starOf, starIs];
al← GetDomainRefAttributes[d];
al← AppendAttributes[al, starList];
END;
RemoveAttribute: PUBLIC PROC[a: Attribute, al: AttributeList] RETURNS[AttributeList] =
destructively removes a from al
BEGIN alLast: AttributeList← NIL;
FOR alT: AttributeList← al, alT.rest UNTIL alT=NIL DO
IF Eq[alT.first, a] THEN
IF alLast=NIL THEN RETURN[alT.rest] -- was first element
ELSE {alLast.rest← alT.rest; RETURN[al]}; -- was another element
alLast← alT;
ENDLOOP;
RETURN[al] -- not found
END;
AppendAttributes: PUBLIC PROC [al1, al2: AttributeList] RETURNS [al: AttributeList] =
BEGIN IF al1=NIL THEN RETURN [al2];
al← al1;
UNTIL al1.rest=NIL DO
al1← al1.rest ENDLOOP;
al1.rest← al2;
RETURN[al]
END;
RSetSize: PUBLIC PROC[rs: RelshipSet] RETURNS[INT] =
BEGIN
FOR size: INT IN [0..200) DO
IF Null[NextRelship[rs]] THEN
{ReleaseRelshipSet[rs]; RETURN[size]};
ENDLOOP;
ReleaseRelshipSet[rs];
RETURN[9999]; -- just tell 'im there are lots for now
END;
SetUpSegment: PUBLIC PROC[ segmentFile: ROPE, seg: DB.Segment, number: NAT ← 0, makeReadOnly: BOOLFALSE ] RETURNS [readOnly: BOOL] =
TRUSTED {
A "foolproof" way to open a segment & transaction, regardless of whether the segment is already declared, doesn't exist, or already has a transaction open. Whenever an abort or failure occurs, just gives up.
readOnly ← FALSE;
IF DB.TransactionOf[seg] # NIL THEN
{readOnly← DB.GetSegmentInfo[seg].readOnly; RETURN};
DB.DeclareSegment[filePath: segmentFile, segment: seg, number: number, readonly: makeReadOnly, createIfNotFound: NOT makeReadOnly ];
DB.OpenTransaction[seg ! DB.Error => TRUSTED
{ SELECT code FROM
ProtectionViolation =>
IF NOT makeReadOnly THEN {readOnly ← TRUE; CONTINUE} ELSE REJECT;
ENDCASE => REJECT } ];
IF readOnly THEN
{ -- Try opening it readonly now; give up on a failure
DB.CloseTransaction[DB.TransactionOf[seg]]; -- DB has left the transaction open
DB.DeclareSegment[segmentFile, seg, number, TRUE, FALSE];
DB.OpenTransaction[seg] }
};
TryRestart: PUBLIC PROC[trans: DB.Transaction] RETURNS[success: BOOL, failureReason: ATOM] = {
segment: DB.Segment = GetSegment[trans];
fileName: ROPE = DB.GetSegmentInfo[segment].filePath;
{ ENABLE DB.Failure => {failureReason ← what; success ← FALSE; GOTO Quit};
DB.AbortTransaction[trans];
now try to open the transaction
success ← FALSE;
FOR i: INT IN [0..5) WHILE NOT success DO
DB.OpenTransaction[segment !
DB.Aborted => LOOP;
DB.Error => IF code = TransactionAlreadyOpen THEN CONTINUE];
success ← TRUE
ENDLOOP;
EXITS Quit => NULL } };
Do: PUBLIC PROC[ proc: PROC[REF ANY], clientData: REF ANYNIL] RETURNS [outcome: NutOps.Outcome] = {
ENABLE BEGIN
DB.Error => {outcome ← error; GOTO Quit};
DB.Failure => {outcome ← failure; GOTO Quit};
DB.Aborted => {outcome ← abort; GOTO Quit};
END;
outcome ← success;
proc[clientData]
EXITS Quit => NULL };
GetSegment: PROC [t: DB.Transaction] RETURNS [seg: DB.Segment] = {
Finds the first database segment associated with segment t. Note we assume all applications have only one segment per transaction right now.
segs: LIST OF DB.Segment← DB.GetSegments[];
FOR segs← segs, segs.rest UNTIL segs=NIL DO
IF DB.TransactionOf[segs.first]=t THEN RETURN[segs.first] ENDLOOP;
RETURN[NIL]
};
SafeNameOf: PUBLIC PROC[e: Entity] RETURNS [s: ROPE] =
BEGIN
IF DB.Null[e] THEN RETURN["NEW"] ELSE RETURN [ DB.NameOf[e] ]
END;
SafeSegmentOf: PUBLIC PROC[e: EntityOrRelship] RETURNS [s: Segment] =
BEGIN
IF DB.Null[e] THEN RETURN[NIL] ELSE RETURN [ DB.SegmentOf[e] ]
END;
SafeDomainOf: PUBLIC PROC[e: Entity] RETURNS [s: Domain] =
BEGIN
IF DB.Null[e] THEN RETURN[NIL] ELSE RETURN [ DB.DomainOf[e] ]
END;
END.
Changes since October 82:
Cattell October 13, 1982 9:28 am: Save and Reset buttons should Fork.
Cattell December 1, 1982 4:29 pm: Should call GetRope instead of GetToken for 2nd DBShow argument.
Cattell June 22, 1983 5:08 pm:
Butler June 26, 1984:
Updated to comply with new organization of Nut and Squirrel