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; 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] = {RETURN[RelshipSetToList[RelationSubset[GetRelation[a], LIST[[a, e]] ]]]}; GetRelation: PUBLIC PROC[a: Attribute] RETURNS[r: Relation] = {RETURN[V2E[GetP[a, aRelationIs]]]}; GetRefAttributes: PUBLIC PROC[d: Domain] RETURNS[al: LIST OF Attribute] = 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] = 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: BOOL _ FALSE ] RETURNS [readOnly: BOOL] = TRUSTED { 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]; 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 ANY _ NIL] 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] = { 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 XFile: 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 generally useful DB routines returns all the tuples that reference e in attribute a finds a's relation returns all the attributes that can reference an entity from domain d destructively removes a from al 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. now try to open the transaction Finds the first database segment associated with segment t. Note we assume all applications have only one segment per transaction right now. Ê ˜Jšœ™šœ™Jšœ%™%Jšœ(™(Jšœ"™"Jšœ%™%Jšœ#™#Jšœ&™&J˜—šÏk ˜ Jšœ˜J˜J˜J˜J˜J˜J˜—šœ œ˜Jšœœ˜Jšœ˜J˜Jšœœœœ˜J˜Jšœœ˜%Jšœœœ˜J˜—Jšœ™J˜š Ïnœœœ œœœ˜Fšœœœ˜Jšœ$œ˜)Jšœ&œ˜+Jšœ&œ˜+Jšœ'œ˜,Jšœ#œ˜(Jšœ)œ˜.Jšœœ˜J˜——š žœœœ œœœ˜Cšœœœ˜Jšœ œ˜%Jšœ!œ˜&Jšœœ˜"Jšœ#œ˜(Jšœœ˜$Jšœœ˜"Jšœœ˜$Jšœ#œ˜(Jšœœ˜J˜J˜——š žœœœ œœœ˜?š˜šœ œ˜EJšœœ ˜@—Jšœ˜J˜J˜——šž œœœœ˜?š œœœœœ˜>Jšœœœœ˜@Jšœœœœ˜4Jšœœœœ ˜FJšœœœœ˜:Jšœœœœ˜4Jšœœœœ˜:šœœœœ ˜FJšœ#˜)J˜———šžœœœœ ˜?Jšœ4˜9Jšœœœœœœœ ˜0Jšœ˜J˜—š ž œœœœœ˜8Jšœ˜Jš œœœ œœœ˜'J˜šœ˜Jšœ5œœ˜CJšœœœ˜—Jšœ˜J˜—š žœœœœœ˜>Jšœ˜Jšœœœ ˜+Jšœœœ ˜+Jšœœœ˜)Jšœœœ ˜,Jšœœœ˜%Jšœœœ ˜(Jšœœœ˜+Jšœœœ ˜.Jšœœœ˜'Jšœœœ ˜*Jšœœœ˜%Jšœœœ ˜(Jšœœœ˜'Jšœœœ ˜*Jšœœœ˜+Jšœœœ ˜.J˜šœ˜ Jšœœ˜Jšœ œ ˜Jšœœ ˜Jšœœ˜%Jšœœ˜—Jšœ˜J˜—š ž œœœœœœ ˜OJšœ6™6Jšœœ1œ˜JJ˜—šž œœœœ˜=Jšœ™Jšœœ˜$J˜—š žœœœ œœœ ˜IJšœE™EJš˜J˜?J˜J˜Jšœ œœ ˜˜\Jš œœ œ œœ˜3—˜\Jš œœ œ œœ˜3—šœ œœ˜Jš œ œœ œœ˜%Jšœ œœ ˜Jšœ œœ ˜Jšœœ˜ —J˜J˜#Jšœ˜J˜—šžœœœ"œ˜VJšœ™Jšœœ˜!šœ"œœ˜5šœ˜Jš œœœœ Ïc˜8JšœœŸ˜@—J˜ Jšœ˜—JšœŸ ˜Jšœ˜J˜—šžœœœœ˜UJš œœœœœ˜#J˜šœ œ˜Jšœœ˜—J˜Jšœ˜ Jšœ˜J˜—š žœœœœœ˜4Jš˜šœœœ ˜šœ˜Jšœœ˜&—Jšœ˜—J˜JšœŸ'˜5Jšœ˜J˜—šž œœœœœœœœœ œ˜‡šœ˜ JšœÏ™Ïšœ œ˜šœœœ˜#Jšœ œœ˜4—Jšœoœ˜„šœœ ˜,šœœ˜˜Jšœœœ œœœœ˜A—Jšœœ˜——šœ ˜JšœŸ4˜6JšœœŸ#˜OJšœ*œœ˜9Jšœ˜———J˜J˜—šž œœœœœ œœ˜^Jšœ œ˜(Jšœ œœ"˜5š œœœ-œœ˜JJšœ˜Jšœ™Jšœ œ˜š œœœœœ ˜)šœ˜Jšœ œ˜Jšœ œœœ˜<—Jšœ ˜Jšœ˜—Jšœ œ˜J˜——šžœœœœœœœœœœ˜fšœ˜ Jšœœ˜)Jšœ œ˜-Jšœœ˜+Jšœ˜—J˜J˜Jšœ œ˜J˜—š ž œœœœœ ˜BJšœŒ™ŒJš œœœœ œ˜+šœœœ˜+Jš œœœœ œ˜BJšœœ˜ J˜J˜——š ž œœœ œœ˜6š˜Jšœœ œœœœœ ˜=Jšœ˜J˜——šž œœœœ˜Eš˜Jšœœ œœœœœœ˜>Jšœ˜J˜——šž œœœ œ˜:š˜Jšœœ œœœœœœ˜=Jšœ˜J˜——Jšœ˜J˜J˜J˜J˜EJ˜J˜bJ˜J˜J˜J˜J˜;J˜J˜J˜—…—î-c