-- File: DBModelPrivate.mesa -- Contents: Internal data structures and types for Model Level modules of Cedar DB. -- File created by Rick Cattell, September 1980 -- Last edited by: -- Cattell on: April 28, 1983 11:56 am -- Willie-Sue on January 27, 1983 2:04 pm DIRECTORY Convert, DB, DBStorage, DBModel, DBTuplesConcrete, DBEnvironment, Rope; DBModelPrivate: DEFINITIONS IMPORTS Convert, DB, DBStorage, DBModel, Rope SHARES DBModel = BEGIN OPEN DB, DBTuplesConcrete; -- Types ROPE: TYPE = Rope.ROPE; TupleHandle: TYPE = REF TupleObject; TupleObject: TYPE = DBTuplesConcrete.TupleObject; TupleSet, Attribute, Index, IndexFactor: TYPE = TupleHandle; Value: TYPE = REF ANY; AttributeValueList: TYPE = LIST OF AttributeValue; AttributeValue: TYPE = DB.AttributeValue; AttributeList: TYPE = DB.AttributeList; -- Global variables and constants MaxVTID: CARDINAL = DBStorage.MaxSystemTupleID; MaxIndexKeyLength: CARDINAL = 200; DefaultNameLength: INT = 12; infString, minfSting: ROPE; desperate: BOOL; -- Set to press on in spite of internal inconsistencies -- Counts for balancing Subset/Release calls: entitySetCount: PUBLIC INT; relshipSetCount: PUBLIC INT; defaultNameHandle: DBStorage.FieldHandle; -- name handle used for all domains w/ default naming: always first field, 18 chars tupleSetNameHandle: DBStorage.FieldHandle; -- this one is used only for tuplesets (whose handle, not name, is first field) attributeNameHandle: DBStorage.FieldHandle; -- this one is used only for attributes (whose name is first field, but is system tuple) defaultNameAttribute: Attribute; -- fake attribute, not really used for much -- Private system properties and relations, used internally and not exported to DB dHandleProp: PUBLIC Attribute; dIndexProp: PUBLIC Attribute; rHandleProp: PUBLIC Attribute; r1to1Prop: PUBLIC Attribute; aHandleProp: PUBLIC Attribute; aTypeCodeProp: PUBLIC Attribute; aTypeEntityProp: PUBLIC Attribute; aDomain: PUBLIC Relation; -- used to form group of attributes targetted to domain by surrogates aDomainOf: PUBLIC Attribute; aDomainIs: PUBLIC Attribute; aUnlinked: PUBLIC Relation; -- used to form group of attributes that reference domain w/o link aUnlinkedOf: PUBLIC Attribute; aUnlinkedIs: PUBLIC Attribute; ifOrdinalPosition: PUBLIC Relation; -- one element per index factor ifOrdinalPositionOf: PUBLIC Attribute; -- the index factor ifOrdinalPositionIs: PUBLIC Attribute; -- INT: ordinal position in indexing -- Definitions of system tuple (virtual) tids NoTID: LONG CARDINAL = 0; -- used in tuple handles nullified by storage level 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 StringTypeID: LONG CARDINAL = 20; IntTypeID: LONG CARDINAL = 21; TimeTypeID: LONG CARDINAL = 22; BoolTypeID: LONG CARDINAL = 23; RecordTypeID: LONG CARDINAL = 24; AnyDomainTypeID: LONG CARDINAL = 25; SurrogateRelshipID: LONG CARDINAL = 31; -- used for surrogate relships FirstAttributeID: LONG CARDINAL = 32; -- system attribute ids are 32, 33, ... -- Checking procedures IsSystem: PROC[t: TupleHandle] RETURNS[BOOL] = INLINE {RETURN[t.tid<=DBStorage.MaxSystemTupleID AND t.tid#SurrogateRelshipID] }; IsSurrogate: PROC[t: TupleHandle] RETURNS[BOOL] = INLINE {RETURN[t.tid=SurrogateRelshipID] }; IsData: PROC[t: TupleHandle] RETURNS[BOOL] = INLINE BEGIN IF t.tid<MaxVTID THEN RETURN[FALSE]; -- system tuple RETURN[T2CT[DBStorage.ReadTupleset[LOOPHOLE[t]]].tid>=MaxVTID]; END; IsDictionary: PROC[t: TupleHandle] RETURNS[BOOL] = INLINE BEGIN IF t.tid<MaxVTID THEN RETURN[FALSE]; RETURN[T2CT[DBStorage.ReadTupleset[LOOPHOLE[t]]].tid<MaxVTID]; END; IsDomainType: PROC [vt: DataType] RETURNS [b: BOOL]; -- Returns TRUE iff vt is a domain or AnyDomainType CheckEntity: PROC [t: TupleHandle]; -- SIGNALS if t not an Entity CheckRelship: PROC [t: TupleHandle]; -- SIGNALS if t not a Relship CheckDomain: PROC [d: Domain]; -- Is d really a domain? SIGNAL if not. CheckRelation: PROC [r: Relation]; -- Is r really a relation? SIGNAL if not. CheckAttribute: PUBLIC PROC [a: Attribute]; -- Is a really an attribute? SIGNAL if not. CheckNIL: PROC[p: REF] = INLINE { -- Use for ROPEs and Values only. IF p=NIL THEN SIGNAL DB.Error[NILArgument] }; CheckNullified: PROC [p: TupleHandle] = INLINE { -- Use for Entities and Relships IF p=NIL THEN SIGNAL DB.Error[NILArgument] ELSE IF p.tid=NoTID THEN SIGNAL DB.Error[NullifiedArgument] }; CompatibleType: PROC [v: Value, t: DataType, fh: DBStorage.FieldHandle← NIL] RETURNS [BOOL]; -- Returns TRUE if v's type is a built-in datatype identical to t or is a -- domain identical to t or a sub-domain of t. -- Takes the optional argument fh so can special-case aTypeProp. CompatibleDomain: PUBLIC PROC [sub, super: Domain] RETURNS [BOOL]; -- Returns TRUE iff sub=super or sub is related through transitive closure of -- SubType relations to super. Should work with system sub or super. IsKeyAttribute: PUBLIC PROC [a: Attribute] RETURNS [BOOL]; EmptyDomain: PUBLIC PROC [d: Domain] RETURNS [BOOLEAN]; EmptyRelation: PUBLIC PROC [r: Relation] RETURNS [BOOLEAN]; -- String manipulation procedures ConvertToUpper: PUBLIC PROC[s: ROPE] RETURNS [ROPE]; StringToValue: PROC[s: ROPE, a: Attribute] RETURNS[v: Value]; -- Converts a string to a value of the type required by a, doing the appropriate -- string conversion or a Fetch if dt is a Domain. ParseSegmentName: PUBLIC PROC[path: ROPE] RETURNS [name, ext, server: ROPE]; -- Separates [server]name.ext, and checks that name contains directory if non-local server NCode: PUBLIC PROC[v: Value] RETURNS[ROPE]; -- Converts value to encoded rope suitable for index lookup or matching. CheckForNulls: PROC[s: ROPE] = INLINE BEGIN i: LONG CARDINAL← 0; last: LONG CARDINAL← Rope.Size[s]; WHILE (i← i+1) < last DO IF Rope.Fetch[s,i]=0C OR Rope.Fetch[s,i]=377C THEN ERROR DB.Error[IllegalString] ENDLOOP; END; MakeNullValueOfType: PUBLIC PROC [vt: DataType] RETURNS[Value]; -- Caching procedures. These are designed to essentially all accesses to the data schema once -- a database application is in some loop; the caches must be big enough to accomplish this -- (see DBModelPrivateImpl), with considerable performance degradation if not. GetCachedAttributeInfo: PUBLIC PROC[x: Attribute] RETURNS[ relation: Relation, type: DataType, handle: DBStorage.FieldHandle, uniqueness: Uniqueness, link: LinkType, indexFactors: LIST OF IndexFactor]; -- Returns all info set by DeclareAttribute, and also index factors x is connected to. GetCachedRelationInfo: PUBLIC PROC[ x: Relation] RETURNS[first, second: Attribute, indexes: LIST OF Index]; -- Returns first and second attribute of x, and also any indexes on x. GetCachedDomainInfo: PUBLIC PROC [x: Domain] RETURNS [ surrogates, indexedSurrogates: LIST OF Relation, nameIndex: Index, subDomains: LIST OF Domain]; -- Returns surrogate relations targetted to x, the subset of those that are indexed, -- the name index for x, and the subdomains of x. GetCachedTupleTS: PUBLIC PROC[ x: TupleHandle] RETURNS[TupleSet]; -- Returns domain of entity or relation of relship. FlushCaches: PROC; -- Flushes attribute, relation, tuple caches of info. Must do if schema changes -- or transaction closed or aborted. FlushTSCache: PROC; -- Just flushes the tupleset cache; should be called when tuple or entity destroyed. -- Basic and Set operations on surrogates, system tuples (exported by Basic Impl) SurrogateGetF: PROC[t: Relship, a: Attribute, string: BOOL] RETURNS [v: Value]; -- Called by GetF to handle the surrogate relships. If string=TRUE then fetch as StringType -- regardless of actual type. SurrogateSetF: PROC[t: Relship, a: Attribute, v: Value]; -- Called by SetF to handle the surrogate relships. SurrogateCreateRelship: PROC[r: Relation, init: AttributeValueList← NIL] RETURNS[t: Relship]; -- Creates a new surrogate relship in R, must set 1st attribute before others SurrogateDestroyRelship: PROC [t: Relship]; -- Destroys a surrogate relship (ie removes a property from an entity tuple) SystemGetP: PROC[e: Entity, aIs: Attribute] RETURNS [v: Value]; -- Call to handle system entities. SafeGetP: PROC[e: Entity, aIs: Attribute] RETURNS [v: Value]; -- Faster version of GetP which need not do type checking, for internal use only. SafeSetP: PROC [e: Entity, aIs: Attribute, v: Value, aOf: Attribute← NIL] RETURNS[Relship]; -- Same as SetP but doesn't do checking and works on dictionary entities. -- May return NIL for dictionary entities, for efficiency (client can't call, so doesn't matter). SafeSetF: PROC [t: Relship, a: Attribute, v: Value]; -- Same as SetF but doesn't do checking and works on dictionary relships. SetValFromHandle: PROC [ t: Relship, fh: DBStorage.FieldHandle, ft: DataType, fl: LinkType← None, v: Value]; -- Low level routine for actually doing field store (in BasicImpl) -- System tuple operations (exported by System Impl) SystemDomainSubset: PUBLIC PROC[ d: Domain, lowName, highName: ROPE, segment: Segment] RETURNS [es: EntitySet]; -- Call to handle system domains (RelationDomain or DomainDomain). SystemRelationSubset: PUBLIC PROC[ r: Relation, avl: AttributeValueList] RETURNS [rs: RelshipSet]; -- Call to handle system relations. -- Index- and link- related procedures (exported by Private Impl) GetDomainIndex: PROC[s: Segment] RETURNS [Index]; -- Returns the domain index for the segment GetRelationIndex: PROC[s: Segment] RETURNS [Index]; -- Returns the relation index for the segment CreateEntityIndexEntries: PUBLIC PROC [e: Entity]; -- Finds the name index for e's Domain and insert e into it. -- Also creates index entries for any surrogate relations that are actually stored in e. DestroyEntityIndexEntries: PUBLIC PROC [e: Entity]; -- Find the name index for e's Domain and remove e from it. -- Also destroys any surrogate relation index entries. DestroyVariableFieldsOf: PUBLIC PROC[t: Relship]; DestroyLinksTo: PUBLIC PROC[e: Entity]; DestroyLinksFrom: PUBLIC PROC[t: Relship]; DestroyIndexEntries: PUBLIC PROC [t: Relship, changed: Attribute]; DestroyAllIndexEntries: PUBLIC PROC [t: Relship]; CreateIndexEntries: PUBLIC PROC [t: Relship, changed: Attribute]; CreateAllIndexEntries: PUBLIC PROC [t: Relship]; GetTypeAndLink: PUBLIC PROC [a: Attribute] RETURNS [type: Entity, link: LinkType]; -- To get the type and link fields of an attribute, which are not stored explicitly. SetTypeAndLink: PUBLIC PROC [a: Attribute, type: Entity, link: LinkType]; -- To set the type and link fields of an attribute, which are not stored explicitly. -- List and Set procedures (exported by Private Impl) SearchEntityList: PROC [ el: LIST OF Entity, test: PROC[Entity] RETURNS[BOOL]] RETURNS [Entity]; TransitiveClosure: PROC[e: Entity, from, to: Attribute] RETURNS [LIST OF Entity]; -- Find all entities referenced by relships via the to attribute whose from attribute refns e, -- then all entities referenced by relships via the to attribute whose from -- attribute reference one of those, and so on, return the result as a list. Nconc: PROC[l1, l2: LIST OF Entity] RETURNS [LIST OF Entity]; -- Concatenates lists l1 and l2 -- Miscellaneous declarations (exported by Private Impl) V2Rec: PROC[v: Value] RETURNS [r: POINTER TO UNSPECIFIED]; -- a hack for now *** T2CT: PROC[t: REF DBEnvironment.TupleObject] RETURNS [DBTuplesConcrete.TupleHandle] = INLINE BEGIN RETURN[LOOPHOLE[t]] END; MakeFD: PROC [ vt: DataType, length: INT← 0, link: BOOL← TRUE, a: Attribute← NIL] RETURNS [DBStorage.FieldDescriptor]; systemTupleVec: REF STSVecType; STSVecType: TYPE = ARRAY[1..MaxVTID] OF TupleHandle; -- passed to storage level so that proper tuple can be returned when a GetF is done and the tid is < SL.MaxSystemTupleID. SameSegment: PROC [x, y: DBStorage.TupleHandle] RETURNS [BOOL] = INLINE {RETURN[DBStorage.SegmentIDFromTuple[x]=DBStorage.SegmentIDFromTuple[y]]}; TranslateToSegment: PROC[e: Entity, of: TupleHandle] RETURNS[Entity]; -- Returns e if it is already in the same segment as "of". Otherwise, generates error, for now. -- In future this proc may automatically create an entity in the to segment. InitializeSystemTuples: PROC; -- System relations are documented in DB. NumberOfAttributes: PROC [r: Relation] RETURNS [n: CARDINAL]; -- Returns the number of attributes r has. GetFirstAttribute: PROC [ of: Relation, notCounting: Attribute← NIL] RETURNS [a: Attribute]; -- Returns the first attribute of relation "of" except for "notCounting". Uses -- GetCacheRelationInfo to get attributes, unless "of" is a system relation. FindSuperDomains: PROC[d: Domain] RETURNS [LIST OF Domain]; -- Returns all super-Domains of d but not d itself. Use GetCachedDomainInfo for sub-domains. END. Fix/extension records since 24-Nov-81: Rick on 24-Nov-81 17:34:31: IsSurrogate[rel] returns FALSE because said tid=0 instead of SurrogateRelshipID. Rick on 26-Nov-81 15:32:00: RopeToInt always returned an error, don't know why removed signed branch of case. Rick on 29-Dec-81 14:47:31: Added TransitiveClosure and CompatibleType, removed TypeOf and some procs already in DBView. Rick on April 28, 1982 9:54 am: Removed NCodeName, added NCode Rick on May 22, 1982 6:56 pm: Added SafeSetP. Added SetValFromHandle for DBViewGlobalImpl. Rick on June 24, 1982 11:58 am: made FindSubDomains and FindSuperDomains non-inlines, changed FindSubDomains to work on AnyDomainType. Rick on October 22, 1982 11:27 am: Changes for new properties and system relations. Rick on December 19, 1982 12:58 pm: Re-organized and expanded, added DBModelPrivateImpl, new segment stuff, etc. Added aDomain, aLink, aUnlinked, TranslateToSegment, many procedures previously in DBViewBasicImpl. Rick on March 14, 1983 2:04 pm: expanded domain caching to include index & subdomains.