DIRECTORY CardTable, DBCommon, DBStorage, DBDefs, DB, DBModel, DBModelPrivate, Rope, SymTab; DBModelDomainImpl: CEDAR PROGRAM IMPORTS CardTable, DBStorage, DB, DBModelPrivate, Rope, SymTab EXPORTS DBModel, DBModelPrivate SHARES Rope = BEGIN OPEN DBCommon, DBDefs; STSVecType: TYPE = ARRAY[1..DBStorage.MaxSystemTupleID] OF TupleHandle; systemTupleVec: REF STSVecType _ NEW[STSVecType _ ALL[NIL]]; DomainTupleSet: PUBLIC DBStorage.SystemTuplesetHandle; DomainDomain: PUBLIC DBCommon.TupleHandle; RelationDomain: PUBLIC DBCommon.TupleHandle; RelationTupleSet: PUBLIC DBStorage.SystemTuplesetHandle; IndexTupleSet: PUBLIC DBStorage.SystemTuplesetHandle; IndexDomain: PUBLIC DBCommon.TupleHandle; SetSystemTable: PUBLIC PROC[tid: TID] RETURNS[tupleSet: DBStorage.SystemTuplesetHandle, tuple: DBCommon.TupleHandle] = TRUSTED { tupleSet _ DBStorage.CreateSystemTupleset[tid]; tuple _ DBStorage.ConsSystemTupleObject[]; tuple.tid _ tid; systemTupleVec[tid] _ tuple }; InitializeDomainSchema: PUBLIC PROC[] = TRUSTED { DBStorage.SetSystemTupleTable[systemTupleVec]; [DomainTupleSet, DomainDomain] _ SetSystemTable[DBModelPrivate.DomainTSID]; [IndexTupleSet, IndexDomain] _ SetSystemTable[DBModelPrivate.IndexTSID]; [RelationTupleSet, RelationDomain] _ SetSystemTable[DBModelPrivate.RelationTSID]; [] _ DBStorage.AddSystemField[DomainTupleSet, DBModelPrivate.TupleSetDescriptor]; nameHandle _ DBStorage.AddSystemField[DomainTupleSet, DBModelPrivate.NameDescriptor]; indexHandle _ DBStorage.AddSystemField[DomainTupleSet, DBStorage.FieldDescriptor[Group[groupID: IndexDomain]]]; superHandle _ DBStorage.AddSystemField[DomainTupleSet, DBStorage.FieldDescriptor[Group[groupID: DomainDomain]]]; nameHandleHandle _ DBStorage.AddSystemField[DomainTupleSet, DBModelPrivate.HandleDescriptor] }; nameHandle, indexHandle, superHandle, nameHandleHandle: DBStorage.FieldHandle; DeclareDomain: PUBLIC PROC [name: ROPE, segment: Segment] RETURNS [d: Domain] = { sh: SegmentHandle = DBModelPrivate.SegmentToHandle[segment]; domainIndex: DBStorage.IndexHandle = sh.indices[DBCommon.domainIndex]; AddToCache: PROC[tuple: TupleHandle] RETURNS[d: Domain] = { cachedTuple: TupleHandle = DBModelPrivate.CopyTupleHandle[tuple]; domainEntry: REF DomainObject = NEW[DomainObject _ [key: sh.key, segment: segment, name: name, tupleSet: cachedTuple]]; d _ domainEntry; [] _ SymTab.Store[x: sh.domainTable, key: name, val: domainEntry]; [] _ CardTable.Store[x: sh.domainsByTID, key: tuple.tid, val: domainEntry]; RETURN[d] }; d _ LookupDomain[name, segment]; IF d # NIL THEN RETURN[d]; BEGIN t: TupleHandle = DBStorage.CreateSystemPageTuple[x: DomainTupleSet, y: NIL, s: segment]; i: TupleHandle = DBStorage.CreateSystemPageTuple[x: IndexTupleSet, y: t, s: segment]; DBStorage.CreateTupleset[t]; DBStorage.CreateIndex[i]; DBStorage.WriteVarByte[t, nameHandle, name]; DBStorage.InsertIntoIndex[domainIndex, name, t]; SetTupleField[t, indexHandle, i]; d _ AddToCache[t]; d.entityNameHandle _ DBStorage.AddField[t, DBModelPrivate.NameDescriptor]; DBModelPrivate.SetFieldField[t, nameHandleHandle, d.entityNameHandle]; d.index _ CopyTupleHandle[i]; d.detailsKnown _ TRUE; sh.schemaUpdated _ TRUE; RETURN[d] END }; LookupDomain: PUBLIC PROC [name: ROPE, segment: Segment] RETURNS [d: Domain] = { sh: SegmentHandle = DBModelPrivate.SegmentToHandle[segment]; domainIndex: DBStorage.IndexHandle = sh.indices[DBCommon.domainIndex]; AddToCache: PROC[tuple: TupleHandle] RETURNS[d: Domain] = { cachedTuple: TupleHandle = DBModelPrivate.CopyTupleHandle[tuple]; domainEntry: REF DomainObject = NEW[DomainObject _ [key: sh.key, segment: segment, name: name, tupleSet: cachedTuple]]; d _ domainEntry; [] _ SymTab.Store[x: sh.domainTable, key: name, val: domainEntry]; [] _ CardTable.Store[x: sh.domainsByTID, key: tuple.tid, val: domainEntry]; RETURN[d] }; val: REF ANY = SymTab.Fetch[x: sh.domainTable, key: name].val; d _ NARROW[val]; IF d # NIL THEN RETURN[d]; BEGIN tuple: TupleHandle = GetNamedTuple[domainIndex, name]; IF tuple = NIL THEN RETURN[NIL]; -- it's not to be found d _ AddToCache[tuple]; END }; ReadDomain: PUBLIC PROC[d: Domain] = { d.index _ CopyTupleHandle[GetTupleField[d.tupleSet, indexHandle]]; d.entityNameHandle _ DBModelPrivate.GetFieldField[d.tupleSet, nameHandleHandle]; d.detailsKnown _ TRUE }; CheckForNull: PUBLIC PROC[t: TupleHandle] = { IF DBStorage.NullTuple[t] THEN DB.Error[NullifiedArgument] }; CopyTupleHandle: PUBLIC PROC[t: TupleHandle] RETURNS[new: TupleHandle] = { new _ DBStorage.ConsSystemTupleObject[]; new.tid _ t.tid; new.cacheHint _ t.cacheHint }; EmptyTupleSet: PUBLIC PROC[ts: DBStorage.TuplesetHandle] RETURNS[yes: BOOL] = { yes _ DBStorage.EmptyTupleSet[ts] }; GetNamedTuple: PUBLIC PROC[index: DBStorage.IndexHandle, name: ROPE] RETURNS[tuple: TupleHandle] = { tuple _ DBStorage.TupleForKey[index, name] }; SetTupleField: PUBLIC PROC[t: TupleHandle, f: DBStorage.FieldHandle, val: TupleHandle] = { DBStorage.SetTupleField[t, f, val] }; GetTupleField: PUBLIC PROC[t: TupleHandle, f: DBStorage.FieldHandle] RETURNS[val: TupleHandle] = { val _ DBStorage.ReadTID[t, f] }; NullifyTupleField: PUBLIC PROC[t: TupleHandle, f: DBStorage.FieldHandle] = { DBStorage.WriteTIDNil[t, f] }; GetRopeField: PUBLIC PROC[t: TupleHandle, f: DBStorage.FieldHandle] RETURNS[val: Rope.ROPE] = { val _ DBStorage.ReadVarByte[t, f] }; SetRopeField: PUBLIC PROC[t: TupleHandle, f: DBStorage.FieldHandle, val: Rope.ROPE] = { IF val = NIL THEN val _ ""; DBStorage.WriteVarByte[t, f, val] }; CheckDomainKey: PUBLIC PROC[d: Domain] = { sh: SegmentHandle = DBModelPrivate.SegmentToHandle[d.segment]; IF sh.key # d.key THEN ERROR DB.Error[IllegalDomain] }; CompatibleTypes: PUBLIC PROC[d: Domain, type: TypeCode] RETURNS[yes: BOOL] = { WHILE TRUE DO IF d.tupleSet.tid = type.code THEN RETURN[TRUE]; IF NOT d.superTypeKnown THEN SetSuperType[d]; IF d.superType = NIL THEN RETURN[FALSE]; -- d has no super type d _ d.superType -- go up the chain ENDLOOP }; SetSuperType: PROC[d: REF DomainObject] = { superTuple: TupleHandle = GetTupleField[d.tupleSet, superHandle]; d.superType _ IF superTuple = NIL THEN NIL ELSE TupleToDomain[superTuple, d.segment]; d.superTypeKnown _ TRUE }; TupleToDomain: PUBLIC PROC[t: TupleHandle, segment: Segment, name: Rope.ROPE _ NIL] RETURNS[d: Domain] = { IF t=NIL THEN RETURN[NIL]; BEGIN sh: SegmentHandle = DBModelPrivate.SegmentToHandle[segment]; AddToCache: PROC[tuple: TupleHandle] RETURNS[d: Domain] = { cachedTuple: TupleHandle = DBModelPrivate.CopyTupleHandle[tuple]; domainEntry: REF DomainObject = NEW[DomainObject _ [key: sh.key, segment: segment, name: name, tupleSet: cachedTuple]]; d _ domainEntry; [] _ SymTab.Store[x: sh.domainTable, key: name, val: domainEntry]; [] _ CardTable.Store[x: sh.domainsByTID, key: t.tid, val: domainEntry]; RETURN[d] }; d _ NARROW[CardTable.Fetch[sh.domainsByTID, t.tid].val]; IF d # NIL THEN RETURN; IF name = NIL THEN name _ GetRopeField[t, nameHandle]; d _ AddToCache[t] END }; DestroyDomain: PUBLIC PROC [d: Domain] = { IF d = NIL THEN RETURN; CheckDomainKey[d]; IF NOT d.detailsKnown THEN ReadDomain[d]; BEGIN subs: DomainSet = SubTypes[d]; IF NextDomain[subs] # NIL THEN { ReleaseDomainSet[subs]; ERROR DB.Error[NotImplemented] }; -- must destroy the domain's subdomains first! ReleaseDomainSet[subs] END; BEGIN segmentHandle: SegmentHandle = DBModelPrivate.SegmentToHandle[d.segment]; TID: DBCommon.TID = d.tupleSet.tid; d.superType _ NIL; NullifyTupleField[d.tupleSet, superHandle]; BEGIN scanHandle: DBStorage.TuplesetScanHandle = DBStorage.OpenScanTupleset[d.tupleSet, First]; FOR t: TupleHandle _ DBStorage.NextScanTupleset[scanHandle], DBStorage.NextScanTupleset[scanHandle] UNTIL t = NIL DO DBModelPrivate.Unlink[t, d]; SetRopeField[t, d.entityNameHandle, NIL]; DBStorage.DestroyTuple[t] ENDLOOP; DBStorage.CloseScanTupleset[scanHandle] END; BEGIN DBStorage.DestroyIndex[d.index]; DBStorage.DestroyTuple[d.index] END; DBModelPrivate.DestroyStoredRelations[d]; DBModelPrivate.DestroySurrogates[d]; DBStorage.DeleteFromIndex[segmentHandle.indices[DBCommon.domainIndex], d.name, d.tupleSet]; DBStorage.DestroyTuple[d.tupleSet]; segmentHandle.schemaUpdated _ TRUE; [] _ SymTab.Delete[segmentHandle.domainTable, d.name]; [] _ CardTable.Delete[segmentHandle.domainsByTID, TID]; d.key _ 0; -- this entry should no longer be used END }; DomainsByName: PUBLIC PROC [segment: Segment, lowName, highName: ROPE, start: FirstLast] RETURNS[ds: DomainSet] = { iScan: DBStorage.IndexHandle = DBModelPrivate.SegmentToHandle[segment].indices[DBCommon.domainIndex]; IF highName = NIL THEN highName _ lowName; ds _ NEW[DomainSetObject _ [segment: segment, variant: index[scanHandle: DBStorage.OpenScanIndex[iScan, [lowerBound: lowName, upperBound: highName, includeLowerBound: TRUE, includeUpperBound: TRUE, lowerBoundInfinity: lowName = NIL, upperBoundInfinity: highName = NIL], start]]]]; RETURN[ds] }; typeTuple: TupleHandle _ DBStorage.ConsSystemTupleObject[]; TypeToDomain: PUBLIC PROC[type: DBDefs.TypeCode, segment: Segment] RETURNS[d: Domain] = { typeTuple.tid _ type.code; typeTuple.cacheHint _ NIL; d _ TupleToDomain[typeTuple, segment] }; NameFromIndexKey: PUBLIC PROC[key: DBCommon.IndexKey] RETURNS[name: Rope.ROPE] = TRUSTED { IF key = NIL OR key.length = 0 THEN RETURN[NIL]; BEGIN indexValue: Rope.Text _ Rope.NewText[key.length]; FOR i: CARDINAL IN [0..key.length) DO indexValue.text[i] _ key.text[i] ENDLOOP; indexValue.length _ key.length; RETURN[indexValue] END }; NextDomain: PUBLIC PROC [ds: DomainSet] RETURNS [d: Domain] = TRUSTED { IF ds = NIL THEN RETURN[NIL]; WITH ds: ds SELECT FROM index => BEGIN name: Rope.ROPE = NameFromIndexKey[DBStorage.NextScanKey[ds.scanHandle]]; tuple: DBCommon.TupleHandle = IF name # NIL THEN DBStorage.ThisScanTuple[ds.scanHandle] ELSE NIL; IF tuple # NIL THEN d _ TupleToDomain[tuple, ds.segment, name] END; group => { tuple: DBCommon.TupleHandle = DBStorage.NextInGroup[ds.scanHandle]; IF tuple # NIL THEN d _ TupleToDomain[tuple, ds.segment] } ENDCASE }; PrevDomain: PUBLIC PROC [ds: DomainSet] RETURNS [d: Domain] = TRUSTED { IF ds = NIL THEN RETURN[NIL]; WITH ds: ds SELECT FROM index => BEGIN name: Rope.ROPE = NameFromIndexKey[DBStorage.PrevScanKey[ds.scanHandle]]; tuple: DBCommon.TupleHandle = IF name # NIL THEN DBStorage.ThisScanTuple[ds.scanHandle] ELSE NIL; IF tuple # NIL THEN d _ TupleToDomain[tuple, ds.segment, name] END; group => { tuple: DBCommon.TupleHandle = DBStorage.PrevInGroup[ds.scanHandle]; IF tuple # NIL THEN d _ TupleToDomain[tuple, ds.segment] } ENDCASE }; ReleaseDomainSet: PUBLIC PROC [ds: DomainSet] = TRUSTED { IF ds = NIL THEN RETURN; WITH ds: ds SELECT FROM index => { DBStorage.CloseScanIndex[ds.scanHandle]; ds.scanHandle _ NIL }; group => { DBStorage.CloseScanGroup[ds.scanHandle]; ds.scanHandle _ NIL } ENDCASE }; EmptyDomain: PROC[d: Domain] RETURNS[ yes: BOOL ] = { scanHandle: DBStorage.TuplesetScanHandle = DBStorage.OpenScanTupleset[d.tupleSet, First]; nextTuple: TupleHandle = DBStorage.NextScanTupleset[scanHandle]; DBStorage.CloseScanTupleset[scanHandle]; RETURN[nextTuple = NIL] }; DeclareSubType: PUBLIC PROC [of, is: Domain] = { sh: SegmentHandle = DBModelPrivate.SegmentToHandle[of.segment]; CheckDomainKey[of]; CheckDomainKey[is]; IF of.segment # is.segment THEN ERROR DB.Error[IllegalSuperType]; IF NOT is.superTypeKnown THEN SetSuperType[is]; IF is.superType # NIL THEN IF Rope.Equal[is.superType.name, of.name] THEN RETURN ELSE ERROR DB.Error[IllegalSuperType]; IF CompatibleTypes[is, TypeForDomain[of]] THEN ERROR DB.Error[IllegalSuperType]; IF NOT EmptyDomain[of] THEN ERROR DB.Error[NotImplemented]; SetTupleField[is.tupleSet, superHandle, of.tupleSet]; is.superType _ of; sh.schemaUpdated _ TRUE; }; DestroySubType: PUBLIC PROC [of, is: Domain] = { sh: SegmentHandle = DBModelPrivate.SegmentToHandle[of.segment]; CheckDomainKey[of]; CheckDomainKey[is]; IF of.segment # is.segment THEN ERROR DB.Error[IllegalSuperType]; IF NOT is.superTypeKnown THEN SetSuperType[is]; IF is.superType = NIL OR is.superType # of THEN ERROR DB.Error[IllegalSuperType]; IF NOT EmptyDomain[is] THEN ERROR DB.Error[NotImplemented]; NullifyTupleField[is.tupleSet, superHandle]; is.superType _ NIL; sh.schemaUpdated _ TRUE }; SuperType: PUBLIC PROC [d: Domain] RETURNS [super: Domain] = { CheckDomainKey[d]; IF NOT d.superTypeKnown THEN SetSuperType[d]; super _ d.superType }; SubTypes: PUBLIC PROC [d: Domain] RETURNS[subs: DomainSet] = { CheckDomainKey[d]; BEGIN scanHandle: DBStorage.GroupScanHandle = DBStorage.OpenScanGroup[d.tupleSet, superHandle, First]; subs _ NEW[DomainSetObject _ [segment: d.segment, variant: group[scanHandle]]] END }; NoSubtypes: PUBLIC PROC[d: Domain] RETURNS[yes: BOOL] = { yes _ DBStorage.TupleForField[d.tupleSet, superHandle] = NIL }; TypeForDomain: PUBLIC PROC[d: Domain] RETURNS[type: TypeCode] = { CheckDomainKey[d]; RETURN[[code: d.tupleSet.tid]] }; DeclareEntity: PUBLIC PROC[d: Domain, name: ROPE, newOnly: BOOL _ FALSE] RETURNS [e: Entity] = BEGIN CheckDomainKey[d]; e _ LookupEntity[d, name]; IF e # NIL THEN IF newOnly THEN ERROR DB.Error[AlreadyExists] ELSE RETURN[e]; BEGIN tuple: TupleHandle = DBStorage.CreateTuple[x: d.tupleSet]; DBStorage.InsertIntoIndex[d.index, name, tuple]; DBStorage.WriteVarByte[tuple, d.entityNameHandle, name]; e _ NEW[EntityObject _ [name: name, domain: d, tuple: tuple]] END END; LookupEntity: PUBLIC PROC[d: Domain, name: ROPE] RETURNS [e: Entity] = BEGIN tuple: DBCommon.TupleHandle; IF NOT d.detailsKnown THEN ReadDomain[d]; tuple _ GetNamedTuple[d.index, name]; IF tuple = NIL THEN RETURN[NIL]; RETURN[NEW[EntityObject _ [name: name, domain: d, tuple: tuple]]] END; DomainSubset: PUBLIC PROCEDURE[d: Domain, lowName, highName: ROPE, start: FirstLast] RETURNS [es: EntitySet] = BEGIN CheckDomainKey[d]; IF NOT d.detailsKnown THEN ReadDomain[d]; BEGIN -- Search using index IF highName = NIL THEN highName _ lowName; es _ NEW[EntitySetObject _ [domain: d, scanHandle: DBStorage.OpenScanIndex[d.index, [lowerBound: lowName, upperBound: highName, includeLowerBound: TRUE, includeUpperBound: TRUE, lowerBoundInfinity: lowName = NIL, upperBoundInfinity: highName = NIL], start]]]; END END; NextEntity: PUBLIC PROCEDURE[es: EntitySet] RETURNS[e: Entity] = TRUSTED { IF es=NIL THEN RETURN[NIL]; CheckDomainKey[es.domain]; BEGIN name: Rope.ROPE = NameFromIndexKey[DBStorage.NextScanKey[es.scanHandle]]; tuple: TupleHandle = IF name # NIL THEN DBStorage.ThisScanTuple[es.scanHandle] ELSE NIL; IF tuple = NIL THEN RETURN[NIL]; RETURN[NEW[ EntityObject _ [domain: es.domain, name: name, tuple: tuple]]] END }; PrevEntity: PUBLIC PROCEDURE[es: EntitySet] RETURNS[e: Entity] = TRUSTED { IF es=NIL THEN RETURN[NIL]; CheckDomainKey[es.domain]; BEGIN name: Rope.ROPE = NameFromIndexKey[DBStorage.PrevScanKey[es.scanHandle]]; tuple: TupleHandle = IF name # NIL THEN DBStorage.ThisScanTuple[es.scanHandle] ELSE NIL; IF tuple = NIL THEN RETURN[NIL]; RETURN[NEW[ EntityObject _ [domain: es.domain, name: name, tuple: tuple]]] END }; ReleaseEntitySet: PUBLIC PROCEDURE[es: EntitySet] = BEGIN IF es=NIL THEN RETURN; IF es.scanHandle # NIL THEN { DBStorage.CloseScanIndex[es.scanHandle]; es.scanHandle _ NIL }; END; DestroyEntity: PUBLIC PROC[e: Entity] = BEGIN CheckDomainKey[e.domain]; -- make sure it's a legal entity first CheckForNull[e.tuple]; DBModelPrivate.Unlink[e.tuple, e.domain]; -- destroy all relationships referring to the entity DBStorage.DeleteFromIndex[e.domain.index, e.name, e.tuple]; SetRopeField[e.tuple, e.domain.entityNameHandle, NIL]; DBStorage.DestroyTuple[e.tuple]; END; CopyEntity: PUBLIC PROC[e: Entity] RETURNS[Entity] = { IF e = NIL THEN RETURN[NIL]; RETURN[NEW[EntityObject _ [domain: e.domain, name: e.name, tuple: CopyTupleHandle[e.tuple]]]] }; DomainEq: PUBLIC PROC [d1, d2: Domain] RETURNS[BOOL] = { IF d1 = NIL THEN RETURN[d2 = NIL]; IF d2 = NIL THEN RETURN[FALSE]; CheckDomainKey[d1]; CheckDomainKey[d2]; RETURN[d1^ = d2^] }; NullDomain: PUBLIC PROC[d: Domain] RETURNS[BOOLEAN] = { IF d = NIL THEN RETURN[TRUE]; BEGIN sh: SegmentHandle = DBModelPrivate.SegmentToHandle[d.segment]; RETURN[d.key # sh.key] END }; NullEntity: PUBLIC PROC[e: Entity] RETURNS[yes: BOOL] = { IF e = NIL THEN RETURN[TRUE]; IF DBStorage.NullTuple[e.tuple] THEN RETURN[TRUE]; BEGIN d: Domain = e.domain; sh: SegmentHandle = DBModelPrivate.SegmentToHandle[d.segment]; RETURN[d.key # sh.key] END }; EntityEq: PUBLIC PROC[e1: Entity, e2: Entity] RETURNS[yes: BOOL] = { IF NullEntity[e1] THEN RETURN[NullEntity[e2]]; IF NullEntity[e2] THEN RETURN[NullEntity[e1]]; RETURN[DomainEq[e1.domain, e2.domain] AND e1.tuple.tid = e2.tuple.tid] }; EntityInfo: PUBLIC PROC [e: Entity] RETURNS [name: ROPE, domain: Domain] = { IF e = NIL THEN RETURN; CheckDomainKey[e.domain]; RETURN[e.name, e.domain] }; ToUnderType: PUBLIC PROC[e: Entity] = { IF e = NIL THEN RETURN; CheckDomainKey[e.domain]; CheckForNull[e.tuple]; BEGIN domaintuple: TupleHandle = DBStorage.ReadTupleset[e.tuple]; IF domaintuple.tid = e.domain.tupleSet.tid THEN RETURN; e.domain _ TupleToDomain[domaintuple, e.domain.segment] END }; ChangeName: PUBLIC PROC [of: Entity, to: Rope.ROPE] ~ { IF of = NIL THEN RETURN; IF to = NIL THEN ERROR DB.Error[NILArgument]; CheckDomainKey[of.domain]; CheckForNull[of.tuple]; BEGIN d: Domain = of.domain; IF GetNamedTuple[d.index, to] # NIL THEN DB.Error[AlreadyExists]; DBStorage.DeleteFromIndex[d.index, of.name, of.tuple]; DBStorage.InsertIntoIndex[d.index, to, of.tuple]; DBStorage.WriteVarByte[of.tuple, d.entityNameHandle, to]; of.name _ to END }; END. ¨File: DBModelDomainImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Contents: Implementation of global operations for Model level Last edited by: Eric Bier on August 6, 1981 17:10:15 Rick Cattell on January 4, 1984 10:36 am Willie-Sue on February 22, 1985 9:21:53 am PST Donahue, August 7, 1986 12:00:34 pm PDT Widom, September 9, 1985 5:06:22 pm PDT Definition of the structure of Domains in the Database The DomainDomain tuples are tuplesets with the following additional fields: 1. the name of the domain 2. the index ID of the index on the names of entities in the domain 3. the superType of the domain (a TID that may be empty), 4. the field handle to be used when accessing entities in the tupleset The DomainDomain Field Handles and Group Field Descriptors The field handles for entities in the DomainDomain. The nameHandle extracts the name of the domain, indexHandle the index for the domain, superHandle the supertype of the domain, and nameHandleHandle the handle to get the field handle to read the name field of tuples stored in the tupleset for the domain Operations on Domains Creates a domain of this name or fetches it if it already exists. Create a new domain. Add the tuple to the domain cache for the segment create the name field for the entities of this domain See if you can find it in the index for the DomainDomain It's in the database, but not in the cache. Cache it; none of the details of the entry are computed yet is the subtype the type we're looking for? Compute the SuperType of the domain d Destroys a domain, all its entities, and all relationships that reference entities in d. To destroy a domain, we remove it from the domain from the SubType list of its SuperType, destroy all of the entities in the domain and then destroy all of the relations that had fields of the domain type If d still has remaining subtypes, then it cannot be destroyed remove connection to any supertype Destroy all of the entities in the domain Destroy the index on the domain Destroy all of the relations that reference the domain and the domain tuple itself Finally, remove the information from the cache and remember that the schema has been updated Provides a domain set that enumerates domains in the given segment. If lowName and highName are non-NIL, enumerates only those domains whose name is lexicographically >=lowName and <=highName. If only highName is NIL, it defaults to lowName, i.e. we will search for the domain whose name exactly equals lowName. Turn the TID into a tuple handle and use TupleToDomain Should be called when client is finished with a DomainSet. Check that sub (is) does not already have a supertype, that the supertype isn't compatible with the subtype (i.e., you're not about to introduce a cycle) and that supertype is empty. Currently can't define subdomain if super already has entries Set the supertype of the domain is to be the domain of and add the domain is to the subtype list of domain of Record the fact that the schema has been changed Returns the subtypes of a given domain (if any have been previously defined using DeclareSubType) This quickly checks for no subtypes Operations on Entities Checks to see if the entity already exists. If so, it returns it, if not, it returns NIL. Used with NextEntity to index through entities in a domain. If lowName or highName are non-NIL, enumerates only those entities whose name is lexicographically >= lowName and <= highName, and the enumeration is sorted. In this case, we create an "index" variant of EntitySetObject. If both are NIL, we create an unindexed (tupleSet variant) EntitySet. Destroy the name index entry Destroy the entity by setting the name field to NIL and then destroying the tuple Κ˜šœ™Jšœ Οmœ1™<—Jšœ=™=šœ™Jšœ%™%Jšœ(™(Jšœ.™.Icode™'K™'J˜—šΟk ˜ J˜ J˜ J˜ J˜Jšžœ˜J˜J˜J˜J˜J˜—šœžœž˜ Jšžœžœ˜>Jšžœ˜Jšžœ˜ J˜—Jšžœžœ˜head1šœ6™6Jšœ žœžœ žœ ˜GJ™Jš œžœžœžœžœ˜Jšœžœ˜Jšžœžœžœžœ˜šž˜Jšœ8™8Jšœ6˜6Jš žœ žœžœžœžœΟc˜9Jšœh™hJšœ˜Jšžœ˜——J˜šŸ œž œ˜&JšœB˜BJšœP˜PJšœž˜J˜—J˜šŸ œžœžœ˜-Jšžœžœžœ˜=—J™šŸœž œžœ˜JJ˜(J˜/—J˜š Ÿ œžœžœžœžœ˜OJšœ$˜$—J˜Jš Ÿ œžœžœ%žœžœF˜’J˜šŸ œž œA˜[Jšœ%˜%—J˜JšŸ œžœžœ+žœ7˜ƒJ˜šŸœžœžœ.˜LJšœ˜—J˜Jš Ÿ œžœžœ+žœ žœ*˜„J˜šŸ œžœžœ5žœ˜XJšžœžœžœ ˜Jšœ$˜$—J˜šŸœž œ˜*Jšœ>˜>Jšžœžœžœžœ˜7—J˜š Ÿœžœžœžœžœ˜Nšžœžœž˜ šžœžœžœžœ˜0Jšœ*™*—Jšžœžœžœ˜.Jš žœžœžœžœžœ‘˜?Jšœ‘˜"Jšžœ˜ ——J™šŸ œžœžœ˜+J™%JšœA˜AJš œžœžœžœžœžœ&˜UJšœž˜J˜—J˜š Ÿ œž œ.žœžœžœ˜jJš žœžœžœžœžœ˜šž˜Jšœ<˜<šŸ œžœžœ˜;JšœA˜AJšœ žœžœT˜wJšœ˜JšœB˜BJšœG˜GJšžœ˜ Jšœ˜—Jšœžœ.˜8Jšžœžœžœžœ˜Jšžœžœžœ$˜6J˜Jšž˜—Jšœ˜—J˜šŸ œžœžœ˜*Jšœ¦™¦Jšžœžœžœžœ˜J˜Jšžœžœžœ˜)Jšœ>™>šž˜J˜šžœžœžœ˜ J˜Jšžœžœ‘.˜P—J˜Jšžœ˜—šž˜JšœI˜IJšžœ žœ˜#šœ"™"Jšœžœ-˜>—Jšœ)™)šž˜JšœY˜Yšžœažœžœž˜tJšœ˜Jšœ$žœ˜)Jšœ˜Jšžœ˜—Jšœ'˜'Jšžœ˜—Jšœ™šž˜Jšœ ˜ Jšœ˜Jšžœ˜—™RJ˜)J˜$Jšœ[˜[Jšœ#˜#—™\Jšœžœ˜#Jšœ6˜6Jšœ2žœ˜7Jšœ ‘&˜2Jšž˜——Jšœ˜—J™š Ÿ œžœžœ'žœžœ˜sJšœΊ™ΊJšœe˜eJšžœ žœžœ˜*Jš œžœŸžœžœ žœ!žœ ˜˜Jšžœ˜ —J˜J˜;J˜šŸ œžœžœ*žœ˜YJšœ6™6Jšœ1žœ˜5Jšœ%˜%Jšœ˜—J˜š Ÿœž œžœ žœžœ˜ZJš žœžœžœžœžœžœ˜0šž˜Jšœ1˜1Jš žœžœžœžœ"žœ˜OJšœ˜Jšžœ ˜Jšž˜—J˜—J˜š Ÿ œžœžœžœžœ˜GJš žœžœžœžœžœ˜šžœžœž˜˜šž˜Jšœ žœ:˜IJš œžœžœžœ(žœžœ˜aJšžœ žœžœ+˜>Jšžœ˜——šœ ˜ JšœC˜CJšžœ žœžœ'˜:——Jšžœ˜ —J˜š Ÿ œžœžœžœžœ˜GJš žœžœžœžœžœ˜šžœžœž˜˜šž˜Jšœ žœ:˜IJš œžœžœžœ(žœžœ˜aJšžœ žœžœ+˜>Jšžœ˜——šœ ˜ JšœC˜CJšžœ žœžœ'˜:—Jšžœ˜ ——J˜šŸœžœžœžœ˜9Jšœ:™:Jšžœžœžœžœ˜šžœžœž˜JšœDžœ˜JJšœDžœ˜IJšžœ˜ ——J˜šŸ œžœ žœžœ˜5JšœY˜YJ˜@J˜(Jšžœ žœ˜—J˜šŸœžœžœ˜0JšœΆ™ΆJ˜?Jšœ'˜'Jšžœžœžœžœ˜AJšžœžœžœ˜/šžœžœž˜Jšžœ(žœž˜5Jšžœžœžœ˜&—Jšžœ(žœžœžœ˜Pš žœžœžœžœžœ˜;Jšœ=™=—Jšœm™mJ˜5Jšœ˜Jšœ0™0Jšœžœ˜Jšœ˜—J˜šŸœžœžœ˜0J˜?Jšœ'˜'Jšžœžœžœžœ˜AJšžœžœžœ˜/Jš žœžœžœžœžœžœ˜QJš žœžœžœžœžœ˜;Jšœ,˜,Jšœžœ˜Jšœžœ˜—J˜šŸ œžœžœ žœ˜>Jšœ˜Jšžœžœžœ˜-Jšœ˜—J˜šŸœžœžœ žœ˜>Jšœa™aJšœ˜šž˜J˜`JšœžœD˜NJšžœ˜——J˜š Ÿ œžœžœ žœžœ˜9Jšœ#™#Jšœ9žœ˜?—J˜šŸ œžœžœ žœ˜AJ˜Jšžœ˜!——™šŸ œžœžœžœ žœžœžœ˜^Jšž˜Jšœ˜Jšœ˜Jšžœžœžœžœ žœžœžœžœžœ˜Mšž˜Jšœ:˜:Jšœ0˜0Jšœ8˜8Jšœžœ6˜=Jšž˜—Jšžœ˜—J˜š Ÿ œžœžœžœžœ˜FJšœY™YJšž˜J˜Jšžœžœžœ˜)Jšœ%˜%Jš žœ žœžœžœžœ˜ Jšžœžœ7˜AJšžœ˜—J˜š Ÿ œžœž œžœžœ˜nJšœί™ίJšž˜Jšœ˜Jšžœžœžœ˜)šžœ‘˜Jšžœ žœžœ˜*Jš œžœ‹žœžœ žœ!žœ ˜ƒJšž˜—Jšžœ˜J˜—š Ÿ œžœž œžœžœ˜JJš žœžœžœžœžœ˜J˜šž˜Jšœ žœ:˜IJš œžœžœžœ(žœžœ˜XJš žœ žœžœžœžœ˜ Jšžœžœ@˜JJšžœ˜——J˜š Ÿ œžœž œžœžœ˜JJš žœžœžœžœžœ˜J˜šž˜Jšœ žœ:˜IJš œžœžœžœ(žœžœ˜XJš žœ žœžœžœžœ˜ Jšžœžœ@˜JJšžœ˜——J˜šŸœžœž œ˜3Jšž˜Jšžœžœžœžœ˜šžœžœžœ˜Jšœ9žœ˜?—Jšžœ˜—J˜šŸ œžœžœ ˜'Jšž˜Jšœ‘&˜@J˜Jšœ*‘4˜^™Jšœ;˜;—šœQ™QJšœ1žœ˜6Jšœ ˜ —Jšžœ˜—J˜šŸ œžœžœ žœ ˜6Jš žœžœžœžœžœ˜JšžœžœV˜`—J˜š Ÿœžœžœžœžœ˜8Jš žœžœžœžœžœ˜"Jš žœžœžœžœžœ˜Jšœ'˜'Jšžœ˜—J˜š Ÿ œžœžœ žœžœ˜7Jš žœžœžœžœžœ˜šž˜Jšœ>˜>Jšžœ˜Jšžœ˜——J˜š Ÿ œžœžœ žœžœ˜9Jš žœžœžœžœžœ˜Jšžœžœžœžœ˜2šž˜J˜Jšœ>˜>Jšžœ˜Jšžœ˜——J˜š Ÿœžœžœžœžœ˜DJšžœžœžœ˜.Jšžœžœžœ˜.Jšžœ žœ˜FJšœ˜—J˜š Ÿ œžœžœ žœžœ˜LJšžœžœžœžœ˜Jšœ˜Jšžœ˜—J˜šŸ œžœžœ˜'Jšžœžœžœžœ˜Jšœ˜J˜šž˜Jšœ;˜;Jšžœ)žœžœ˜7Jšœ7˜7Jšžœ˜——J˜šŸ œžœžœžœ˜7Kšžœžœžœžœ˜Kš žœžœžœžœžœ˜-Jšœ˜Jšœ˜šž˜J˜Jšžœžœžœžœ˜AJšœ6˜6Jšœ1˜1Jšœ9˜9J˜ Jšž˜—K˜—J˜—Jšžœ˜J˜J˜J˜J˜—…—Djh.