-- File: NutDumpImpl.mesa -- Contents: Program to do ascii database output. -- Status: Runs in Cedar as subordinate of Squirrel. -- Created by: Rick Cattell, March 1980; stolen from DBDump created September 1980 -- Last Edited by: -- Cattell on: June 3, 1983 2:26 pm -- Maxwell on: June 4, 1982 12:10 pm -- Willie-Sue on: February 22, 1983 3:47 pm -- Donahue on: April 5, 1983 10:13 am -- Output formats: -- SegmentName [other info] on the first line -- /Domain\name\nametype\ ...for each domain -- /Relation\name\ ...for each relation -- /Attribute\name\relation\type\cardinality\length\link\ ...for each attribute -- /Index\relation\attribute\...\\ .. for each index -- /domain\name-elt1\name-elt2\...\ ...for each entity -- /relation\attr1:val1\attr2:val2\...\ ...for each relship -- In entity-centric mode, prints entities and relships that ref them in first attribute together. DIRECTORY Atom USING [MakeAtom], DBEnvironment USING [InternalError], DB, FileIO USING[Open], IO, NutDump, NutOps, NutViewer, Rope, SquirrelTool, System, ViewerClasses; NutDumpImpl: CEDAR PROGRAM IMPORTS Atom, DBEnvironment, DB, FileIO, IO, NutOps, NutViewer, Rope, SquirrelTool, System EXPORTS NutDump -- DumpToFile -- = BEGIN OPEN DB, IO, NutViewer; inf: CARDINAL = 177777B; IllegalEntity: SIGNAL = CODE; IllegalFormat: SIGNAL = CODE; squirrel: ViewerClasses.Viewer = SquirrelTool.squirrel; elapsedTime: System.GreenwichMeanTime; entityCentricFlag: BOOL; word: PROC [u: UNSPECIFIED] RETURNS [IO.Value] = -- temporary kluge for output of UNSPECIFIED to IO INLINE {RETURN[[integer[LOOPHOLE[u, INTEGER]]]]}; -- Main procedure, exported to NutDump DumpToFile: PUBLIC PROC[segment: ROPE, fileName: ROPE, dl: LIST OF DB.Domain _ NIL, rl: LIST OF DB.Relation _ NIL, complement: BOOL _ FALSE, entityCentric: BOOL _ FALSE] = TRUSTED BEGIN {ENABLE ABORTED => GO TO SqueakyClean; file: IO.Handle; seg: Segment; found: BOOLEAN _ FALSE; elapsedTime_ System.GetGreenwichMeanTime[]; entityCentricFlag_ entityCentric; IF segment=NIL OR segment.Length[] = 0 THEN { Message[squirrel, "Must specify a segment to dump"]; RETURN}; IF fileName = NIL THEN fileName _ segment.Concat[".dump"]; file _ OpenFile[fileName]; seg_ Atom.MakeAtom[segment]; FOR sl: LIST OF Segment _ DB.GetSegments[], sl.rest UNTIL sl = NIL DO IF sl.first = seg THEN { found _ TRUE; EXIT } ENDLOOP; IF NOT found THEN { Message[squirrel, segment, " not open; aborting dump"]; RETURN }; Message[squirrel, "Dumping to ", fileName, ": "]; MessageRope[squirrel, "Data schema ..."]; IF complement THEN { dl _ Complement[dl, EntitySetToList[DomainSubset[d: DomainDomain, searchSegment: seg]]]; rl _ Complement[rl, EntitySetToList[DomainSubset[d: RelationDomain, searchSegment: seg]]]}; file.Put[rope[segment], rope[" ["], time[]]; file.Put[rope["]\n"]]; WriteSchema[file, dl, rl]; MessageRope[squirrel, "Domains: "]; -- Output Domain contents FOR list: LIST OF Domain _ dl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO MessageRope[squirrel, GetName[list.first]]; MessageRope[squirrel, "... "]; WriteDomain[file, list.first]; ENDLOOP; IF entityCentric THEN { MessageRope[squirrel, "Domain references: "]; FOR list: LIST OF Domain _ dl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO MessageRope[squirrel, GetName[list.first]]; MessageRope[squirrel, "... "]; WriteDomain[file, list.first, TRUE]; ENDLOOP; MessageRope[squirrel, "Other "]; -- Output Relation contents }; MessageRope[squirrel, "Relations: "]; -- Output Relation contents FOR list: LIST OF Relation _ rl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO IF entityCentric AND FirstAttributeIsDomain[list.first] THEN LOOP; MessageRope[squirrel, GetName[list.first]]; MessageRope[squirrel, "... "]; WriteRelation[file, list.first]; ENDLOOP; CloseFile[file]; elapsedTime_ LOOPHOLE[System.GetGreenwichMeanTime[] - elapsedTime]; Message[squirrel, PutFR["Dump completed: %g elapsed seconds.\n", int[elapsedTime]] ]; EXITS SqueakyClean => {}}; END; FirstAttributeIsDomain: PROCEDURE[r: Relation] RETURNS[BOOL] = {RETURN[NutOps.EntityValued[NutOps.FirstAttributeOf[r]]]}; Complement: PROCEDURE[ignore: LIST OF Entity, all: LIST OF Entity] RETURNS[complement: LIST OF Entity] = BEGIN found: BOOLEAN; complementEnd: LIST OF Entity_ NIL; IF ignore = NIL THEN RETURN[all]; FOR listA: LIST OF Entity _ all, listA.rest WHILE listA # NIL DO found _ FALSE; FOR listI: LIST OF Entity _ ignore, listI.rest WHILE listI # NIL DO IF Eq[listI.first, listA.first] THEN {found _ TRUE; EXIT}; ENDLOOP; IF ~found THEN -- Add to end of complement list (if NIL, create first element) IF complement=NIL THEN complement_ complementEnd_ LIST[listA.first] ELSE complementEnd_ complementEnd.rest _ LIST[listA.first]; ENDLOOP; END; OpenFile: PUBLIC PROC[fileName: ROPE] RETURNS[file: IO.Handle] = TRUSTED BEGIN IF fileName=NIL THEN {Message[squirrel, "Illegal file name for dump"]; RETURN}; file _ FileIO.Open[fileName: fileName, accessOptions: write, raw: TRUE]; file.SetLength[0]; END; CloseFile: PUBLIC PROC[fileStream: Handle] = {fileStream.Close[]}; -- The output routines. WriteSchema: PUBLIC PROC[s: IO.Handle, dl: LIST OF DB.Domain, rl: LIST OF DB.Relation] = BEGIN subtype: Relship; subtypeList: RelshipSet; -- Output Domains FOR list: LIST OF Domain _ dl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO WriteSystemEntity[s, list.first]; ENDLOOP; -- Output SubTypes FOR list: LIST OF Domain _ dl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO subtypeList _ RelationSubset[dSubType, LIST[[dSubTypeOf, list.first]]]; UNTIL Null[subtype_ NextRelship[subtypeList]] AND NOT SquirrelTool.stopped DO WriteSystemRelship[s, subtype] ENDLOOP; ReleaseRelshipSet[subtypeList]; ENDLOOP; -- Output Relations FOR list: LIST OF Relation _ rl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO WriteSystemEntity[s, list.first]; ENDLOOP; -- Output Attributes FOR list: LIST OF Relation _ rl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO FOR aL: LIST OF Attribute_ VL2EL[GetPList[list.first, aRelationOf]], aL.rest UNTIL aL=NIL DO WriteSystemEntity[s, aL.first] ENDLOOP; ENDLOOP; -- Output Indexes FOR list: LIST OF Relation _ rl, list.rest WHILE list # NIL AND NOT SquirrelTool.stopped DO r: Relation_ list.first; FOR iL: LIST OF Index _ GetIndicesFor[r], iL.rest UNTIL iL = NIL OR SquirrelTool.stopped DO WriteSystemEntity[s, iL.first, NameOf[r]] ENDLOOP ENDLOOP; END; WriteSystemEntity: PUBLIC PROC [s: IO.Handle, e: Entity, also: ROPE_ NIL] = -- Will print a domain, relation, attribute, or index and any -- associated properties that are needed to recreate it. BEGIN type: Domain_ DomainOf[e]; IF SquirrelTool.stopped THEN RETURN; SELECT type FROM DomainDomain => s.Put[rope["/Domain\\"], rope[GetName[e]], char['\\]]; RelationDomain => s.Put[ rope["/Relation\\"], rope[GetName[e]], char['\\] ]; AttributeDomain => { s.Put[rope["/Attribute\\"], rope[GetName[V2E[GetP[e, aRelationIs]]]], char['\\]]; s.Put[rope[GetName[e]], char['\\]]; s.Put[rope[GetName[V2E[GetP[e, aTypeIs]]]], char['\\]]; s.Put[word[V2U[GetP[e, DB.aUniquenessIs]]], char['\\]]; s.Put[int[V2I[GetP[e, DB.aLengthIs]]], char['\\]]; s.Put[word[V2U[GetP[e, DB.aLinkIs]]], char['\\]] }; IndexDomain => { -- First get all of the index factors for this index, -- then the attribute associated with each index factor and print it s.Put[rope["/Index\\"], rope[also], rope["\\"]]; FOR ifList: LIST OF DB.Value _ GetPList[e, ifIndexOf, ifIndexIs], ifList.rest UNTIL ifList = NIL OR SquirrelTool.stopped DO s.Put[ rope[NameOf[V2E[GetP[V2E[ifList.first], ifAttributeIs]]]], rope["\\"] ] ENDLOOP; s.Put[ rope["\\"] ] }; ENDCASE; s.Put[char[CR]]; END; WriteSystemRelship: PUBLIC PROC [s: IO.Handle, r: Relship] = -- Prints a subtype relship. BEGIN IF SquirrelTool.stopped THEN RETURN; s.Put[rope["\\SubType\\"]]; s.Put[rope["of:"], rope[GetFS[r, dSubTypeOf]], char['\\]]; s.Put[rope["is:"], rope[GetFS[r, dSubTypeIs]], char['\\]]; s.Put[char[CR]]; END; WriteDomain: PUBLIC PROC[s: IO.Handle, d: Domain, refs: BOOL_ FALSE] = -- Prints entities unless refs=TRUE, in which case prints relships reffing. BEGIN entity: Entity; entityList: EntitySet_ DomainSubset[d: d, searchSubDomains: FALSE]; UNTIL Null[entity_ NextEntity[entityList]] OR SquirrelTool.stopped DO IF refs THEN WriteRelatedRelships[s, entity] ELSE WriteEntity[s, entity] ENDLOOP; ReleaseEntitySet[entityList]; END; WriteEntity: PUBLIC PROC[s: IO.Handle, e: Entity] = -- Prints an entity in ascii dump form: /domain\name\ TRUSTED BEGIN ENABLE DBEnvironment.InternalError => GOTO Error; d: Domain_ DomainOf[e]; IF SquirrelTool.stopped THEN RETURN; s.Put[char['/], rope[GetName[d]], char['\\]]; s.Put[rope[GetName[e]], char['\\], char[CR]]; EXITS Error => {Message[squirrel, "Ouch! Internal error on entity ", GetName[e]]}; END; WriteRelatedRelships: PUBLIC PROC[fh: IO.Handle, e: Entity] = -- Prints relships that reference e in their first attribute. BEGIN t: Relship; r: Relation; rs: RelshipSet; al: AttributeList; al_ GetAllRefAttributes[e]; FOR alT: AttributeList_ al, alT.rest UNTIL alT=NIL DO r_ V2E[GetP[alT.first, aRelationIs]]; IF Eq[alT.first, NutOps.FirstAttributeOf[r]] THEN BEGIN rs_ RelationSubset[r, LIST[[alT.first, e]]]; UNTIL Null[t_ NextRelship[rs]] DO WriteRelship[fh, t] ENDLOOP; ReleaseRelshipSet[rs]; END; ENDLOOP; END; WriteRelation: PUBLIC PROC[s: IO.Handle, r: Relation] = BEGIN relship: Relship; relshipList: RelshipSet_ RelationSubset[r]; UNTIL Null[relship_ NextRelship[relshipList]] OR SquirrelTool.stopped DO WriteRelship[s, relship] ENDLOOP; ReleaseRelshipSet[relshipList]; END; WriteRelship: PUBLIC PROC[s: IO.Handle, r: Relship] = -- Prints a relship in ascii dump form: \relation\a1:v1\...\aN:vN\ TRUSTED BEGIN ENABLE DBEnvironment.InternalError => GOTO Error; ts: Relation_ RelationOf[r]; IF SquirrelTool.stopped THEN RETURN; s.Put[char['\\], rope[GetName[ts]], char['\\]]; FOR aL: LIST OF Attribute_ VL2EL[GetPList[ts, aRelationOf]], aL.rest UNTIL aL=NIL DO s.Put[rope[GetName[aL.first]], char[':]]; s.Put[rope[GetFS[r, aL.first]], char['\\]]; ENDLOOP; s.Put[char[CR]]; EXITS Error => {Message[squirrel, "Ouch! Internal error on relship"]}; END; GetIndicesFor: PROC [r: Relation] RETURNS [LIST OF Index] = -- Returns the list of indices on r. Must first find attributes of r, then find any index -- factors involving those attributes, then find the indices to which the index factors belong, -- removing duplicates (indices with more than one index factor will appear more than once). BEGIN il: LIST OF Index _ NIL; FOR al: LIST OF Attribute _ VL2EL[GetPList[r, aRelationOf]], al.rest UNTIL al=NIL DO if: IndexFactor _ V2E[GetP[al.first, ifAttributeOf]]; IF if#NIL THEN il _ AppendIfNew[V2E[GetP[if, ifIndexIs]], il]; ENDLOOP; RETURN[il] END; AppendIfNew: PROC[e: Entity, el: LIST OF Entity] RETURNS [LIST OF Entity] = -- Add entity e to list el if it is not already in the list. BEGIN elT: LIST OF Entity; FOR elT_ el, elT.rest UNTIL elT=NIL DO IF Eq[elT.first, e] THEN RETURN[el] ENDLOOP; RETURN[CONS[e, el]]; END; END. Change log since October 1982: By Cattell October 11, 1982 10:54 pm: Changed Complement procedure so that it keeps the list in the same order as the input, but using a complementEnd variable. Added timing of dump. Willie-Sue December 13, 1982: aFooProp => aFooIs, for new system properties. Willie-Sue January 11, 1983 3:32 pm: new output format for segments Cattell April 6, 1983 10:35 am: fix comments at top. ŹZ˜Jš”Ļcēœ$œ%œTœCœ¶œĻk œžœžœ!žœqž œžœZžœ œžœžœžœžœžœžœžœužœ žœž œžœžœ 3œžœžœ žœžœ 'œĻn œžœžœ žœ žœžœžœžœ žœ žœžœžœ žœžœžœžœžœž œžœžœžœžœžœ"žœžœUžœ žœžœžœ;žœžœ žœžœcžœžœžœ žœžœžœžœžœžœ žœžœžœžœžœžœ;žœfžœ žœņœ^œžœžœžœžœžœžœžœwžœžœ žœ6žœžœžœžœžœžœžœƒž œ'žœ-œžœžœžœžœžœžœžœĄžœ$žœ‰žœžœŸž œžœDžœŸ œž œ žœžœžœžœžœ žœžœžœ žœžœžœ žœžœ žœžœžœ žœžœžœžœ žœžœžœžœžœžœžœ žœžœ žœžœ žœžœ žœžœžœ@œžœ žœžœ%žœžœ.žœžœžœŸœžœžœ žœžœžœ ž œžœ žœžœ3žœGžœžœŸ œžœžœ.œŸ œžœžœžœ žœžœžœ žœžœžœžœ3œžœžœžœžœžœžœžœ.žœœžœžœžœžœžœžœžœ-žœ"žœ)žœžœ1žœ,žœœžœžœžœžœžœžœžœ.žœœžœžœžœžœžœžœžœžœžœžœHžœžœžœ1žœžœœžœžœžœžœžœžœžœ#žœžœžœ#žœžœžœ8žœž œžœŸœžœžœžœ)>œ9œžœEžœžœŽžœ9žœ6žœ36œEœ;žœ žœžœžœ?žœ žœžœ]žœžœžœžœŸœžœžœžœœžœŹžœžœŸ œžœžœžœyžœQžœžœ>žœOžœ$žœŸ œžœžœžœ6œž œžœ žœ£žœžœUžœŸœžœžœžœXžœ¾žœŸ œžœžœžœžœEžœAžœžœ&žœŸ œžœžœžœCœž œžœ žœ‚žœžœžœ6žœžœžœcžœžœžœIžœŸ œžœžœžœžœ [œ`œ]œžœžœžœ žœžœžœžœ6žœžœžœAžœžœžœ6žœžœžœŸ œžœžœžœ žœžœžœ=œžœžœžœ žœžœžœžœžœžœžœžœžœžœ žœžœ£˜ö_J˜—…—/ś6Z