<> <> <> <> <> <> <> <> <> DIRECTORY Basics USING [LowHalf], DBCommon, DBStorage, DBDefs, DB, DBModelPrivate, Rope USING [ROPE, Concat]; DBModelSystemImpl: CEDAR PROGRAM IMPORTS DB, DBStorage, DBModelPrivate, Basics, Rope EXPORTS DBDefs, DBModelPrivate = BEGIN OPEN DBStorage, DBCommon, DBDefs, DBModelPrivate; ROPE: TYPE = Rope.ROPE; MaxVTID: CARDINAL = DBStorage.MaxSystemTupleID; Property: TYPE = Attribute; <> AnyDomainType, BoolType, IntType, TimeType, RopeType: PUBLIC DataType; RecordType: PUBLIC DataType; <> DomainTSID: LONG CARDINAL = 1; RelationTSID: LONG CARDINAL = 2; AttributeTSID: LONG CARDINAL = 3; DataTypeTSID: LONG CARDINAL = 4; IndexTSID: LONG CARDINAL = 5; IndexFactorTSID: LONG CARDINAL = 6; aRelationTSID: LONG CARDINAL = 7; aTypeTSID: LONG CARDINAL = 8; aUniquenessTSID: LONG CARDINAL = 9; aLengthTSID: LONG CARDINAL = 10; aLinkTSID: LONG CARDINAL = 11; aDomainTSID: LONG CARDINAL = 12; aUnlinkedTSID: LONG CARDINAL = 13; ifIndexTSID: LONG CARDINAL = 14; ifOrdinalPositionTSID: LONG CARDINAL = 15; ifAttributeTSID: LONG CARDINAL = 16; dSubTypeTSID: LONG CARDINAL = 17; DummyID: LONG CARDINAL = 19; -- used for one fake relation RopeTypeID: LONG CARDINAL = 20; IntTypeID: LONG CARDINAL = 21; TimeTypeID: LONG CARDINAL = 22; BoolTypeID: LONG CARDINAL = 23; RecordTypeID: LONG CARDINAL = 24; AnyDomainTypeID: LONG CARDINAL = 25; <> STSVecType: TYPE = ARRAY[1..MaxVTID] OF TupleHandle; <> systemTupleVec: PUBLIC REF STSVecType _ NEW[STSVecType_ ALL[NIL]]; attributeIDCount: LONG CARDINAL_ 0; <> <> <> <> <> <> DomainDomain: PUBLIC Domain; -- one element per client-defined domain dHandleProp: PUBLIC Property; -- the storage level tupleset handle dIndexProp: PUBLIC Property; -- the storage level index handle for this domain dSubType: PUBLIC Relation; -- one element per direct sub-super type relationship dSubTypeOf: PUBLIC Attribute; -- domain: the super-type dSubTypeIs: PUBLIC Attribute; -- domain: the sub-type RelationDomain: PUBLIC Domain; -- one element per client-defined relation rHandleProp: PUBLIC Property; -- the storage level tupleset handle r1to1Prop: PUBLIC Property; -- TRUE iff this relation is a surrogate relation AttributeDomain: PUBLIC Domain; -- one element per client-defined attribute aHandleProp: PUBLIC Property; -- the storage level handle for this field aTypeCodeProp: PUBLIC Property; -- tid of the type entity, or zero if domain-valued aTypeEntityProp: PUBLIC Property; -- the domain this attribute refs, or NIL if datum-valued aRelation: PUBLIC Relation; -- one element per client-defined attribute aRelationOf: PUBLIC Attribute; -- the attribute aRelationIs: PUBLIC Attribute; -- relation of the attribute aType: PUBLIC Relation; -- one element per client-defined attribute aTypeOf: PUBLIC Attribute; -- the attribute aTypeIs: PUBLIC Attribute; -- domain or datatype of the attribute aUniqueness: PUBLIC Relation; -- one element per client-defined attribute aUniquenessOf: PUBLIC Attribute; -- the attribute aUniquenessIs: PUBLIC Attribute; -- INT corresponding to its uniqueness aLength: PUBLIC Relation; -- one element per client-defined attribute aLengthOf: PUBLIC Attribute; -- the attribute aLengthIs: PUBLIC Attribute; -- INT corresponding to attribute's length aLink: PUBLIC Relation; -- one element per client-defined attribute aLinkOf: PUBLIC Attribute; -- the attribute aLinkIs: PUBLIC Attribute; -- INT corresponding to its LinkType. aDomain: PUBLIC Relation; -- exported to DBModelPrivate: one elt per client-defined attribute aDomainOf: PUBLIC Attribute; -- the attribute aDomainIs: PUBLIC Attribute; -- non-NIL only if this is the first (targetted) attribute of <> <> aUnlinked: PUBLIC Relation; -- exported to DBModelPrivate: one elt per client-defined attribute aUnlinkedOf: PUBLIC Attribute; -- the attribute aUnlinkedIs: PUBLIC Attribute; -- non-NIL only if this attribute is NOT linked, in which <> DataTypeDomain: PUBLIC Domain; -- RopeTypeEntity, BoolTypeEntity, etc. are of this domain <> RopeTypeEntity, IntTypeEntity, TimeTypeEntity, BoolTypeEntity, RecordTypeEntity, AnyDomainTypeEntity: PUBLIC Entity; IndexDomain: PUBLIC Domain; -- one element per client-defined index iHandleProp: PUBLIC Property; -- index handle, set by storage level IndexFactorDomain: PUBLIC Domain; -- one element per attribute in an index ifIndex: PUBLIC Relation; -- one element per attribute in an index (an "index factor") ifIndexOf: PUBLIC Attribute; -- the index factor ifIndexIs: PUBLIC Attribute; -- the index this index factor belongs to ifOrdinalPosition: PUBLIC Relation; -- one element per index factor ifOrdinalPositionOf: PUBLIC Attribute; -- the index factor ifOrdinalPositionIs: PUBLIC Attribute; -- the position of this index factor in the ordering ifAttribute: PUBLIC Relation; -- one element per index factor ifAttributeOf: PUBLIC Attribute; -- the index factor ifAttributeIs: PUBLIC Attribute; -- the attribute this index factor indexes <> defaultNameHandle, attributeNameHandle, tupleSetNameHandle: PUBLIC DBStorage.FieldHandle; defaultNameAttribute: PUBLIC Attribute; DefaultNameSize: CARDINAL = 20; <> minfString: ROPE _ ""; -- less than any other string infString: ROPE _ "\177"; -- greater than any other string InitializeSystemTuples: PUBLIC PROC = TRUSTED BEGIN dNameProp, rNameProp, aNameProp: Property; -- only need temporarily DBStorage.SetSystemTupleTable[systemTupleVec]; <> DomainDomain_ DefineSystemDomain[DomainTSID, "Domain"]; RelationDomain_ DefineSystemDomain[RelationTSID, "Relation"]; AttributeDomain_ DefineSystemDomain[AttributeTSID, "Attribute"]; DataTypeDomain_ DefineSystemDomain[DataTypeTSID, "DataType"]; IndexDomain_ DefineSystemDomain[IndexTSID, "Index"]; IndexFactorDomain_ DefineSystemDomain[IndexFactorTSID, "IndexFactor"]; <> RopeType_ $ROPE; IntType_ $INT; TimeType_ $GMT; BoolType_ $BOOL; AnyDomainType_ $ANY; RecordType_ $RECORD; <> RopeTypeEntity _ DefineSystemEntity[RopeTypeID, DataTypeDomain, "ROPE"]; IntTypeEntity _ DefineSystemEntity[IntTypeID, DataTypeDomain, "INT"]; TimeTypeEntity _ DefineSystemEntity[TimeTypeID, DataTypeDomain, "GMT"]; BoolTypeEntity _ DefineSystemEntity[BoolTypeID, DataTypeDomain, "BOOL"]; RecordTypeEntity _ DefineSystemEntity[RecordTypeID, DataTypeDomain, "RECORD"]; AnyDomainTypeEntity _ DefineSystemEntity[AnyDomainTypeID, DataTypeDomain, "ANY"]; FakeTheNameHandle[]; -- must call after RopeType defined but before any real entities <> dHandleProp_ DefinePrivateProperty[ DomainDomain, "dHandleProp", RecordType, DBStorage.TuplesetObjectSize]; <> dNameProp_ DefinePrivateProperty[DomainDomain, "dName", RopeType, DefaultNameSize]; tupleSetNameHandle_ dNameProp.fh; dIndexProp_ DefinePrivateProperty[DomainDomain, "dIndexProp", $IndexDomain]; rHandleProp_ DefinePrivateProperty[ RelationDomain, "rHandleProp", RecordType, DBStorage.TuplesetObjectSize]; <> rNameProp_ DefinePrivateProperty[ RelationDomain, "rNameProp", RopeType, DefaultNameSize]; <> r1to1Prop_ DefinePrivateProperty[RelationDomain, "r1to1", BoolType]; aHandleProp_ DefinePrivateProperty[ AttributeDomain, "aHandleProp", RecordType, DBStorage.FieldObjectSize]; <> aNameProp_ DefinePrivateProperty[AttributeDomain, "aName", RopeType]; attributeNameHandle_ aNameProp.fh; aTypeCodeProp_ DefinePrivateProperty[ AttributeDomain, "aTypeCodeProp", IntType]; aTypeEntityProp_ DefinePrivateProperty[ AttributeDomain, "aTypeEntityProp", $DataTypeDomain]; iHandleProp_ DefinePrivateProperty[ IndexDomain, "iHandleProp", RecordType, DBStorage.IndexObjectSize]; <> <> FakeTheTypeAndLinkRelations[]; [aRelation, aRelationOf, aRelationIs]_ DefineSystemBinary[ id: aRelationTSID, name: "aRelation", of: $AttributeDomain, is: $RelationDomain]; [aUniqueness, aUniquenessOf, aUniquenessIs]_ DefineSystemBinary[ id: aUniquenessTSID, name: "aUniqueness", of: $AttributeDomain, is: IntType]; [aLength, aLengthOf, aLengthIs]_ DefineSystemBinary[ id: aLengthTSID, name: "aLength", of: $AttributeDomain, is: IntType]; [aDomain, aDomainOf, aDomainIs]_ DefineSystemBinary[ id: aDomainTSID, name: "aDomain", of: $AttributeDomain, is: $DomainDomain]; [aUnlinked, aUnlinkedOf, aUnlinkedIs]_ DefineSystemBinary[ id: aUnlinkedTSID, name: "aUnlinked", of: $AttributeDomain, is: $DomainDomain]; [ifIndex, ifIndexOf, ifIndexIs]_ DefineSystemBinary[ id: ifIndexTSID, name: "ifIndex", of: $IndexFactorDomain, is: $IndexDomain]; [ifOrdinalPosition, ifOrdinalPositionOf, ifOrdinalPositionIs]_ DefineSystemBinary[ id: ifOrdinalPositionTSID, name: "ifOrdinalPosition", of: $IndexFactorDomain, is: IntType]; [ifAttribute, ifAttributeOf, ifAttributeIs]_ DefineSystemBinary[ id: ifAttributeTSID, name: "ifAttribute", of: $IndexFactorDomain, is: $AttributeDomain]; [dSubType, dSubTypeOf, dSubTypeIs]_ DefineSystemBinary[ id: dSubTypeTSID, name: "dSubType", of: $DomainDomain, is: $DomainDomain, is1to1: FALSE]; END; FakeTheNameHandle: PROC = <> <> BEGIN fakeReln: Relation_ DefineSystemRelation[DummyID, "fakeReln", FALSE]; defaultNameAttribute_ DefineSystemField[fakeReln.systemTupleSet, "defaultNameAttribute", RopeType]; defaultNameAttribute.relation _ fakeReln; defaultNameHandle_ defaultNameAttribute.fh; END; FakeTheTypeAndLinkRelations: PROC = <> <> <> <> <> <<(1) If aTypeEntityProp=NIL, then we have a non-entity-valued attribute, and the>> <> <<(2) If aTypeEntityProp#NIL, then it references the domain that is the type of the>> <> <> <> <> <> <> <> BEGIN aType_ DefineSystemRelation[ id: aTypeTSID, name: "aType", is1to1: TRUE]; aTypeOf_ DefineSystemFieldObject["aTypeOf", $AttributeDomain].a; aTypeOf.relation _ aType; aTypeIs_ DefineSystemField[aType.systemTupleSet, "aTypeIs", $DataTypeDomain]; aTypeIs.relation _ aType; aTypeIs.fh_ aTypeEntityProp.fh; -- so group scans work on type aTypeOf.relation_ aTypeIs.relation_ aType; aType.attributes_ LIST[aTypeOf, aTypeIs]; aLink_ DefineSystemRelation[ id: aLinkTSID, name: "aLink", is1to1: TRUE]; aLinkOf_ DefineSystemFieldObject["aLinkOf", $AttributeDomain].a; aLinkOf.relation _ aLink; aLinkIs_ DefineSystemField[aLink.systemTupleSet, "aLinkIs", IntType]; aLinkIs.relation _ aLink; aLink.attributes_ LIST[aLinkOf, aLinkIs]; aLinkOf.relation_ aLinkIs.relation_ aLink; END; DefineSystemBinary: PROC [ id: LONG CARDINAL, name: ROPE, of: DataType, is: DataType, is1to1: BOOL_ TRUE] RETURNS [r: Relation, rOf, rIs: Attribute] = <> <> <> <> <> <> BEGIN r_ DefineSystemRelation[id, name, is1to1]; IF is1to1 THEN <> BEGIN ofDomain: Domain _ SystemDataTypeToDomain[of]; rOf_ DefineSystemFieldObject[Rope.Concat[name, "Of"], of].a; rOf.relation _ r; rIs_ DefineSystemField[ofDomain.systemTupleSet, Rope.Concat[name, "Is"], is, DefaultNameLength]; rIs.relation _ r; END ELSE <> BEGIN rOf_ DefineSystemField[r.systemTupleSet, Rope.Concat[name, "Of"], of]; rOf.relation _ r; rIs_ DefineSystemField[r.systemTupleSet, Rope.Concat[name, "Is"], is, DefaultNameLength]; rIs.relation _ r; END; r.attributes_ LIST[rOf, rIs]; rOf.relation_ rIs.relation_ r; END; SystemDataTypeToDomain: PROC[type: DataType] RETURNS [d: Domain] = BEGIN SELECT type FROM $DomainDomain => RETURN[DomainDomain]; $RelationDomain => RETURN[RelationDomain]; $AttributeDomain => RETURN[AttributeDomain]; $DataTypeDomain => RETURN[DataTypeDomain]; $IndexDomain => RETURN[IndexDomain]; $IndexFactorDomain => RETURN[IndexFactorDomain]; ENDCASE => ERROR DB.InternalError; END; DefineSystemRelation: PROC[id: LONG CARDINAL, name: ROPE, is1to1: BOOL] RETURNS[Relation] = TRUSTED <> BEGIN r: Relation _ NEW[RelationObject]; t: TupleHandle _ DBStorage.ConsSystemTupleObject[]; IF id>MaxVTID THEN ERROR DB.InternalError; t.tid_ id; t.name _ name; r.name _ name; r.isSystem _ TRUE; r.is1to1 _ is1to1; r.systemTupleSet _ DBStorage.CreateSystemTupleset[id]; systemTupleVec[Basics.LowHalf[id]]_ t; r.tuple _ t; RETURN[r]; END; DefineSystemDomain: PROC[id: LONG CARDINAL, name: ROPE] RETURNS[Domain] = TRUSTED <> BEGIN d: Domain _ NEW[DomainObject]; t: TupleHandle _ DBStorage.ConsSystemTupleObject[]; IF id>MaxVTID THEN ERROR DB.InternalError; t.tid_ id; t.name _ name; d.isSystem _ TRUE; d.name _ name; d.systemTupleSet _ DBStorage.CreateSystemTupleset[id]; systemTupleVec[Basics.LowHalf[id]]_ t; d.tuple _ t; RETURN[d]; END; DefineSystemField: PROC[ ts: DBStorage.SystemTuplesetHandle, name: ROPE, type: DataType, length: CARDINAL_ 0] RETURNS[Attribute] = TRUSTED <> <> BEGIN f: Attribute; t: TupleHandle; [f, t] _ DefineSystemFieldObject[name, type]; <> f.fh_ DBStorage.AddSystemField[ts, MakeFD[type, length,, t]]; RETURN[f] END; DefineSystemFieldObject: PROC[ name: ROPE, type: DataType] RETURNS[a: Attribute, t: TupleHandle] = TRUSTED <> <> BEGIN a _ NEW[AttributeObject]; t _ DBStorage.ConsSystemTupleObject[]; t.tid_ FirstAttributeID + attributeIDCount; t.name _ name; a.isSystem _ TRUE; a.name _ name; a.type _ type; attributeIDCount_ attributeIDCount+1; IF FirstAttributeID+attributeIDCount>MaxVTID THEN ERROR DB.InternalError; systemTupleVec[Basics.LowHalf[attributeIDCount+FirstAttributeID-1]]_ t; a.tuple _ t; RETURN[a, t] END; DefineSystemEntity: PROC[ id: LONG CARDINAL, d: Domain, name: ROPE] RETURNS [Entity] = TRUSTED <> BEGIN t: TupleHandle _ DBStorage.ConsSystemTupleObject[]; t.tid_ id; t.name _ name; systemTupleVec[Basics.LowHalf[id]]_ t; RETURN[t] END; DefinePrivateProperty: PROC [ d: Domain, name: ROPE, type: DataType, length: INT_ 0] RETURNS [Property] = <> <> <> <> <> <> <> <> BEGIN fakeAttribute: Attribute; fakeAttribute_ DefineSystemField[d.systemTupleSet, name, type, length]; fakeAttribute.domain _ d; d.attributes_ CONS[fakeAttribute, d.attributes]; fakeAttribute.domain_ d; RETURN[fakeAttribute] END; <> SystemDomainSubset: PUBLIC PROC[d: Domain, lowName, highName: ROPE, segment: SegmentHandle, es: EntitySet] RETURNS [EntitySet] = TRUSTED <> <> <> <> <> <> BEGIN MakeIndexScan: PROC[indexToScan: DBStorage.IndexHandle] RETURNS[EntitySet] = TRUSTED BEGIN tsScan: DBStorage.IndexScanHandle; [lowName, highName]_ NCodeAndDefaultLimits[lowName, highName]; tsScan_ DBStorage.OpenScanIndex[indexToScan, [lowName, highName, TRUE, TRUE], First ]; es.scan _ index; es.indexScanHandle _ tsScan; RETURN[es]; END; SELECT d FROM DomainDomain => es_ MakeIndexScan[GetDomainIndex[segment]]; RelationDomain => es_ MakeIndexScan[GetRelationIndex[segment]]; ENDCASE => ERROR DB.Error[NotImplemented]; RETURN[es]; END; NCodeAndDefaultLimits: PROC [low, high: ROPE] RETURNS [newLow, newHigh: ROPE] = TRUSTED <> <> <<(2) if just the high limit is NIL, it defaults to the low limit, (3) any any case, we>> <> BEGIN IF high=NIL THEN IF low=NIL THEN {low_ minfString; high_ infString} ELSE {low_ NCode[DB.S2V[low]]; high_ low} ELSE {low_ NCode[DB.S2V[low]]; high_ NCode[DB.S2V[high]]}; RETURN[low, high] END; END.