-- 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: November 8, 1983 11:10 am
-- Willie-Sue on January 27, 1983 2:04 pm
DIRECTORY
DB,
DBStorage,
DBModel,
DBTuplesConcrete,
DBEnvironment,
Rope;
DBModelPrivate: DEFINITIONS
IMPORTS
DB,
DBStorage,
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
RopeTypeID: 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[x: REF ANY] RETURNS [DBStorage.FieldHandle] = INLINE
{RETURN[LOOPHOLE[x]]}; -- Can't do narrow because it's an opaque type!
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.