<> <> <> <> <> <> <> <> DIRECTORY DBCommon, DBStats USING [Inc], DBStorage, DBDefs, DB, DBModel, DBModelPrivate, DBModelSchema, Rope; DBModelSetImpl: CEDAR PROGRAM IMPORTS DBStats, DBStorage, DB, DBDefs, DBModel, DBModelPrivate, DBModelSchema, Rope EXPORTS DBModel, DBModelPrivate = BEGIN OPEN DB, DBCommon, DBDefs, DBModel, DBModelPrivate; ROPE: TYPE = Rope.ROPE; <> numberOfEntitySetObjects: CARDINAL = 4; numberOfRelshipSetObjects: CARDINAL = 4; numberOfDomainSetObjects: CARDINAL = 2; numberOfRelationSetObjects: CARDINAL = 2; eSetList: ARRAY [0..numberOfEntitySetObjects) OF EntitySet; rSetList: ARRAY [0..numberOfRelshipSetObjects) OF RelshipSet; dSetList: ARRAY [0..numberOfDomainSetObjects) OF DomainSet; rnSetList: ARRAY [0..numberOfRelationSetObjects) OF RelationSet; eSetFree: PACKED ARRAY [0..numberOfEntitySetObjects) OF BOOLEAN _ ALL[TRUE]; rSetFree: PACKED ARRAY [0..numberOfRelshipSetObjects) OF BOOLEAN _ ALL[TRUE]; dSetFree: PACKED ARRAY [0..numberOfDomainSetObjects) OF BOOLEAN _ ALL[TRUE]; rnSetFree: PACKED ARRAY [0..numberOfRelationSetObjects) OF BOOLEAN _ ALL[TRUE]; firstFreeESet: [0..numberOfEntitySetObjects] _ 0; firstFreeRSet: [0..numberOfRelshipSetObjects] _ 0; firstFreeDSet: [0..numberOfDomainSetObjects] _ 0; firstFreeRnSet: [0..numberOfRelationSetObjects] _ 0; <> QDomainSubset: PUBLIC PROCEDURE[ d: Domain, lowName, highName: ROPE_ NIL, start: FirstLast_ First, es: EntitySet, searchSubDomains: BOOL _ TRUE] RETURNS [EntitySet] = <> <> <> <> <> <= lowName and <=highName, and the enumeration is sorted.>> <> <> <> <> BEGIN dl: LIST OF Domain; dt: TupleHandle; IF QNullDomain[d] THEN RETURN[NIL]; IF DBModelSchema.InvalidDomain[d] THEN ERROR Error[InvalidSchema]; IF d.isSystem THEN ERROR Error[NotImplemented]; dt _ DBModelSchema.GetDomainTuple[d]; IF searchSubDomains AND (dl_ QSubTypes[d])#NIL THEN <> BEGIN -- Nested search of d and its subdomains es.scan _ nested; es.previousDomains _ IF start=Last THEN CONS[d, dl] ELSE NIL; es.remainingDomains _ IF start=First THEN Reverse[CONS[d, dl]] ELSE NIL; es.lowName _ lowName; es.highName _ highName; es.start _ start; es.currentEntitySet _ NIL; RETURN[es] END; IF lowName#NIL THEN BEGIN -- Search using index nameIndex: Index _ PV2E[SafeGetP[dt, dIndexProp]]; lowName_ NCode[S2V[lowName]]; highName_ IF highName=NIL THEN lowName ELSE NCode[S2V[highName]]; es.scan _ index; es.indexScanHandle _ DBStorage.OpenScanIndex[nameIndex, [lowName, highName, TRUE, TRUE], start ]; END ELSE { <> es.scan _ tupleSet; es.tSetScanHandle _ DBStorage.OpenScanTupleset[dt, start] }; RETURN[es]; END; Reverse: PROC [list: LIST OF Domain] RETURNS [val: LIST OF Domain] = { val _ NIL; UNTIL list = NIL DO val _ CONS[list.first, val]; list _ list.rest; ENDLOOP; RETURN[val]; }; QRelationSubset: PUBLIC PROCEDURE[ r: Relation, constraint: AttributeValueList, start: FirstLast_ First, rs: RelshipSet] RETURNS [RelshipSet] = <> <> <> <<(1) Is r a surrogate relation? If so, will be doing index, group, or tupleset scan on domain.>> <<(2) Special-case r surrogate with first attribute constraint on entity in r's target domain.>> <<(3) Is there a useful index on r? This can be true whether r is surrogate or not.>> <<(4) Is one of the constraints entity-valued (group-scannable)? r can be surrogate or not.>> <<(5) If all else fails, use a tupleset scan (even if r is surrogage), NextRelship will filter.>> <> <> <> <> <> <> <> <> <> <> BEGIN surrogateR: Relation; -- NIL if not surrogate relation targetAttr: Attribute; -- target attribute if surrogate relation targetTupleset: DBStorage.TuplesetHandle; -- target domain if r is surrogate relation, else r entityConstraint: AttributeValue _ [NIL, [null[]], [null[]]]; -- entity-valued constraint if group scannable reducedList: AttributeValueList; -- remainder of constraint if group or index scannable recVal: DBStorage.FieldHandle; -- handle to pass to storage level for group scans groupScannable: BOOL; indexScan: DBStorage.IndexScanHandle; <<(0) Check that valid parameters>> IF QNullRelation[r] THEN RETURN[NIL]; IF DBModelSchema.InvalidRelation[r] THEN ERROR Error[InvalidSchema]; IF CheckAVList[constraint] THEN { rs.scan _ empty; RETURN[rs] }; IF RelationEq[r, dSubType] AND constraint=NIL THEN ERROR Error[NotImplemented]; <<(1) Determine whether surrogate or normal relation>> IF r.is1to1 THEN <> BEGIN surrogateR_ r; targetAttr_ GetFirstAttribute[r] END ELSE -- normal relation surrogateR_ NIL; <<(2) Try for one-element scan on the target attribute if a surrogate relation>> IF surrogateR#NIL AND constraint#NIL AND QAttributeEq[constraint.first.attribute, targetAttr] THEN BEGIN -- no search necessary, want tuple that corresponds to one entity in targetDomain t: SurrogateRelshipHandle_ SurrogateCreateRelship[r]; t.entity_ V2E[constraint.first.lo]; IF constraint.rest=NIL OR MatchingRelship[t, constraint.rest] THEN { rs.scan _ justOne; rs.hereItIs _ t } ELSE rs.scan _ empty; RETURN[rs] END; <<(3) Try for index scan>> [indexScan, reducedList]_ FindIndexedConstraint[r, constraint, start]; IF indexScan#NIL THEN BEGIN rs.serialCheck _ reducedList; rs.scan _ index; rs.indexScanHandle _ indexScan; rs.surrogate _ surrogateR; RETURN[rs]; END; <<(4) Try for group scan>> [entityConstraint, reducedList, groupScannable]_ FindEntityConstraint[constraint]; IF groupScannable THEN BEGIN recVal _ entityConstraint.attribute.fh; rs.serialCheck _ reducedList; rs.scan _ group; rs.groupScanHandle _ DBStorage.OpenScanGroup[V2E[entityConstraint.lo], recVal, start]; rs.surrogate _ surrogateR; RETURN[rs] END <<(5) Resort to scanning the whole tupleset, either the relation r or if r is surrogate then the>> <> ELSE BEGIN rs.serialCheck _ constraint; rs.scan _ tupleSet; IF r.is1to1 THEN targetTupleset_ DataTypeToEntity[targetAttr.type, r.segment] ELSE targetTupleset_ DBModelSchema.GetRelationTuple[r]; rs.tSetScanHandle _ DBStorage.OpenScanTupleset[targetTupleset, start]; rs.surrogate _ surrogateR; RETURN[rs] END; END; FindEntityConstraint: PROC [constraint: AttributeValueList] RETURNS [con: AttributeValue _ [NIL, [null[]]], reducedList: AttributeValueList, found: BOOLEAN] = <> <> <> BEGIN reducedList_ NIL; found_ FALSE; FOR conL: AttributeValueList_ constraint, conL.rest UNTIL conL = NIL DO a: Attribute = conL.first.attribute; link: LinkType; -- whether it is linked IF a.isSystem THEN link_ Linked ELSE link _ a.link; IF IsDomainType[a.type] AND (link=Linked OR link=Colocated) THEN {con_ conL.first; GOTO Found} ELSE reducedList_ CONS[conL.first, reducedList]; REPEAT Found => BEGIN found_ TRUE; FOR conT: AttributeValueList_ conL.rest, conT.rest UNTIL conT = NIL DO reducedList_ CONS[conT.first, reducedList]; ENDLOOP END; FINISHED => con_ [NIL, [null[]]]; -- return found=FALSE and dummy values. ENDLOOP; RETURN END; FindIndexedConstraint: PROC[r: Relation, constraint: AttributeValueList, start: FirstLast] RETURNS [is: DBStorage.IndexScanHandle, reducedList: AttributeValueList] = <> <> <> <> <> BEGIN i: Index; ifs: LIST OF IndexFactor; lowKey, highKey: ROPE; IF constraint=NIL OR r.isSystem THEN RETURN[NIL, constraint]; ifs_ VL2TL[QGetPList[DBModelSchema.GetAttributeTuple[constraint.first.attribute], ifAttributeOf]]; FOR ifs_ ifs, ifs.rest UNTIL ifs=NIL DO i_ PV2E[SafeGetP[ifs.first, ifIndexIs]]; SELECT CanUseIndex[i, constraint] FROM different => NULL; identical => { lowKey_ NCodeForTupleMatch[constraint, i, low]; highKey_ NCodeForTupleMatch[constraint, i, high]; reducedList_ NIL; GO TO FoundAnIndex; }; indexSuperset => { lowKey_ NCodeForTupleMatch[constraint, i, low]; highKey_ NCodeForTupleMatch[constraint, i, high]; reducedList_ NIL; GO TO FoundAnIndex; }; matchSuperset => { lowKey_ NCodeForTupleMatch[constraint, i, low]; highKey_ NCodeForTupleMatch[constraint, i, high]; reducedList_ constraint; GO TO FoundAnIndex; }; ENDCASE => ERROR; REPEAT FoundAnIndex => RETURN[DBStorage.OpenScanIndex[i, [lowKey, highKey, TRUE, TRUE], start], reducedList]; FINISHED => RETURN[NIL, constraint]; ENDLOOP; END; CanUseIndex: PROCEDURE[i: Index, tm: AttributeValueList] RETURNS[{different, identical, indexSuperset, matchSuperset}] = <> <> <> <> <> BEGIN if: IndexFactor; count: INT_ 0; ifs: LIST OF IndexFactor_ VL2TL[QGetPList[i, ifIndexOf]]; FOR tmL: AttributeValueList_ tm, tmL.rest UNTIL tmL=NIL DO IF ifs=NIL AND count>0 THEN RETURN[matchSuperset]; if_ ifs.first; ifs_ ifs.rest; IF count#PV2I[SafeGetP[if, ifOrdinalPositionIs]] THEN ERROR InternalError; IF NOT EntityEq[PV2E[SafeGetP[if, ifAttributeIs]], DBModelSchema.GetAttributeTuple[tmL.first.attribute]] THEN RETURN[different]; count_ count+1; ENDLOOP; IF ifs=NIL THEN RETURN[identical] ELSE RETURN[indexSuperset]; END; QGetAllRefAttributes: PUBLIC PROCEDURE[e: Entity] RETURNS[al: LIST OF Attribute] = <> <> <> <> <> <> <> <> <> BEGIN al1, al2, al3: LIST OF Attribute _ NIL; IF NOT IsSystem[e] THEN { d: Domain _ GetCachedEntityInfo[SegmentOf[e], e].domain; dt: TupleHandle _ DBModelSchema.GetDomainTuple[d]; al1_ GetDomainUnlinkedRefAttributes[dt]; al2_ GetDomainSurrogateRefAttributes[dt] }; al3 _ TL2AHL[DBStorage.GetGroupIDs[e]]; RETURN[Nconc[Nconc[al1, al2], al3]]; END; QGetDomainRefAttributes: PUBLIC PROC[d: Domain] RETURNS[al: LIST OF Attribute] = <> <> BEGIN IF QNullDomain[d] THEN RETURN[NIL]; IF DBModelSchema.InvalidDomain[d] THEN ERROR Error[InvalidSchema]; IF d.isSystem THEN ERROR Error[NotImplemented]; al_ GetDomainDirectRefAttributes[d]; FOR dl: LIST OF Domain_ FindSuperDomains[d], dl.rest UNTIL dl=NIL DO al_ Nconc[al, GetDomainDirectRefAttributes[dl.first]] ENDLOOP; RETURN[al] END; FindSuperDomains: PROC[d: Domain] RETURNS [LIST OF Domain] = <> {RETURN[TransitiveClosure[DBModelSchema.GetDomainTuple[d], dSubTypeIs, dSubTypeOf]]}; GetDomainDirectRefAttributes: PROC[d: Domain] RETURNS[al: LIST OF Attribute] = <> <> {RETURN[VL2AHL[QGetPList[DBModelSchema.GetDomainTuple[d], aTypeOf]]]}; GetDomainSurrogateRefAttributes: PROC[d: TupleHandle] RETURNS[al: LIST OF Attribute] = <> {RETURN[VL2AHL[QGetPList[d, aDomainOf]]]}; GetDomainUnlinkedRefAttributes: PROC[d: TupleHandle] RETURNS[al: LIST OF Attribute] = <> {RETURN[VL2AHL[QGetPList[d, aUnlinkedOf]]]}; <> QNextEntity: PUBLIC PROCEDURE[es: EntitySet] RETURNS[e: Entity] = <> <> <> <<(1) tupleSet scan simply chaining through ALL entities in a domain,>> <<(2) nested scan through currentEntitySet till exhausted, then next in remainingDomains>> <<(3) segment scan through currentEntitySet till exhausted, then next in remainingSegments >> <<(4) group scan finds all entities reffing some entity (used on surrogate fields)>> <<(5) attributeSet goes through all relations, and all attributes for each>> <<(6) system scan follows linked list through system entities>> <<(7) empty scan always returns NIL (used for some special cases)>> <> <> BEGIN QNextEntityRec: PROCEDURE[es: EntitySet, esi: CARDINAL] RETURNS[e: Entity] = { IF es=NIL THEN RETURN[NIL]; TRUSTED { SELECT es.scan FROM tupleSet => e_ DBStorage.NextScanTupleset[es.tSetScanHandle]; nested => { DO IF (e_ QNextEntityRec[es.currentEntitySet, esi])#NIL THEN { QReleaseEntitySet[es.currentEntitySet]; ReturnEntitySet[esi]; RETURN[e] }; IF es.remainingDomains=NIL THEN { QReleaseEntitySet[es.currentEntitySet]; ReturnEntitySet[esi]; RETURN[NIL] }; QReleaseEntitySet[es.currentEntitySet]; -- all done with this, get next ReturnEntitySet[esi]; [es.currentEntitySet, esi] _ GetNewEntitySet[]; es.currentEntitySet_ QDomainSubset[ es.remainingDomains.first, es.lowName, es.highName, es.start, es.currentEntitySet, FALSE]; es.previousDomains_ CONS[es.remainingDomains.first, es.previousDomains]; es.remainingDomains_ es.remainingDomains.rest; ENDLOOP }; index => e_ DBStorage.NextScanIndex[es.indexScanHandle]; empty => e_ NIL; ENDCASE => ERROR InternalError; } }; RETURN[QNextEntityRec[es, numberOfEntitySetObjects]]; END; QPrevEntity: PUBLIC PROCEDURE[es: EntitySet] RETURNS[e: Entity] = <> BEGIN QPrevEntityRec: PROCEDURE[es: EntitySet, esi: CARDINAL] RETURNS[e: Entity] = { IF es=NIL THEN RETURN[NIL]; TRUSTED { SELECT es.scan FROM tupleSet => e_ DBStorage.PrevScanTupleset[es.tSetScanHandle]; nested => { <> <> <> <> <> DO IF (e_ QPrevEntityRec[es.currentEntitySet, esi])#NIL THEN { QReleaseEntitySet[es.currentEntitySet]; ReturnEntitySet[esi]; RETURN[e] }; <> <> IF es.previousDomains=NIL THEN { QReleaseEntitySet[es.currentEntitySet]; ReturnEntitySet[esi]; RETURN[NIL] }; QReleaseEntitySet[es.currentEntitySet]; ReturnEntitySet[esi]; <> es.remainingDomains_ CONS[es.previousDomains.first, es.remainingDomains]; es.previousDomains_ es.previousDomains.rest; <> IF es.previousDomains=NIL THEN { QReleaseEntitySet[es.currentEntitySet]; ReturnEntitySet[esi]; RETURN[NIL] }; [es.currentEntitySet, esi] _ GetNewEntitySet[]; es.currentEntitySet_ QDomainSubset[ es.previousDomains.first, es.lowName, es.highName, Last, es.currentEntitySet, FALSE]; ENDLOOP }; index => e_ DBStorage.PrevScanIndex[es.indexScanHandle]; empty => e_ NIL; ENDCASE => ERROR InternalError; } }; RETURN[QPrevEntityRec[es, numberOfEntitySetObjects]]; END; QNextRelship: PUBLIC PROCEDURE[rs: RelshipSet] RETURNS[t: Relship] = <> <> <> <> <> <> <> BEGIN ConsSurrogate: PROC[r: Relation] RETURNS [newT: SurrogateRelshipHandle] = { IF QNullRelation[r] THEN ERROR Error[IllegalRelation]; IF DBModelSchema.InvalidRelation[r] THEN ERROR Error[InvalidSchema]; newT _ SurrogateCreateRelship[r]; newT.entity_ NARROW[t]; RETURN[newT] }; IF rs=NIL THEN RETURN[NIL]; TRUSTED { SELECT rs.scan FROM tupleSet => WHILE (t_ DBStorage.NextScanTupleset[rs.tSetScanHandle])#NIL DO IF rs.surrogate#NIL THEN t_ ConsSurrogate[rs.surrogate]; IF MatchingRelship[t, rs.serialCheck] THEN RETURN ENDLOOP; group => WHILE (t_ DBStorage.NextInGroup[rs.groupScanHandle])#NIL DO IF rs.surrogate#NIL THEN t_ ConsSurrogate[rs.surrogate]; IF MatchingRelship[t, rs.serialCheck] THEN RETURN ENDLOOP; index => WHILE (t_ DBStorage.NextScanIndex[rs.indexScanHandle])#NIL DO IF rs.surrogate#NIL THEN t_ ConsSurrogate[rs.surrogate]; IF MatchingRelship[t, rs.serialCheck] THEN RETURN ENDLOOP; justOne => IF rs.hereItIs#NIL THEN {t_ rs.hereItIs; rs.hereItIs_ NIL; RETURN[t]}; empty => RETURN[NIL]; ENDCASE => ERROR InternalError; }; <> <> RETURN[NIL]; END; QPrevRelship: PUBLIC PROCEDURE[rs: RelshipSet] RETURNS[t: Relship] = <> BEGIN ConsSurrogate: PROC[r: Relation] RETURNS [newT: SurrogateRelshipHandle] = { IF QNullRelation[r] THEN ERROR Error[IllegalRelation]; IF DBModelSchema.InvalidRelation[r] THEN ERROR Error[InvalidSchema]; newT _ SurrogateCreateRelship[r]; newT.entity_ NARROW[t]; RETURN[newT] }; IF rs=NIL THEN RETURN[NIL]; TRUSTED { SELECT rs.scan FROM tupleSet => WHILE (t_ DBStorage.PrevScanTupleset[rs.tSetScanHandle])#NIL DO IF rs.surrogate#NIL THEN t_ ConsSurrogate[rs.surrogate]; IF MatchingRelship[t, rs.serialCheck] THEN RETURN ENDLOOP; group => WHILE (t_ DBStorage.PrevInGroup[rs.groupScanHandle])#NIL DO IF rs.surrogate#NIL THEN t_ ConsSurrogate[rs.surrogate]; IF MatchingRelship[t, rs.serialCheck] THEN RETURN ENDLOOP; index => WHILE (t_ DBStorage.PrevScanIndex[rs.indexScanHandle])#NIL DO IF rs.surrogate#NIL THEN t_ ConsSurrogate[rs.surrogate]; IF MatchingRelship[t, rs.serialCheck] THEN RETURN ENDLOOP; justOne => ERROR Error[NotImplemented]; empty => RETURN[NIL]; ENDCASE => ERROR InternalError; }; <> <> RETURN[NIL]; END; <> MatchingRelship: PROCEDURE[rel: Relship, alh: AttributeValueList] RETURNS[BOOLEAN] = <> --INLINE-- BEGIN FOR alhL: AttributeValueList_ alh, alhL.rest UNTIL alhL=NIL DO IF NOT MatchingAttribute[rel, alhL.first] THEN RETURN[FALSE] ENDLOOP; RETURN[TRUE] END; MatchingAttribute: PROCEDURE[rel: Relship, alh: AttributeValue] RETURNS[ans: BOOLEAN] = <> --INLINE-- TRUSTED BEGIN s: ROPE_ NCode[QGetF[rel, alh.attribute]]; low: ROPE_ NCode[alh.lo]; high: ROPE_ IF NullValue[alh.hi] THEN low ELSE NCode[alh.hi]; ans_ GreaterEqString[s, low] AND GreaterEqString[high, s]; END; QReleaseEntitySet: PUBLIC PROCEDURE[es: EntitySet] = BEGIN IF es=NIL THEN RETURN; TRUSTED { SELECT es.scan FROM nested => {QReleaseEntitySet[es.currentEntitySet]; es.currentEntitySet_ NIL}; index => { IF es.indexScanHandle # NIL THEN { DBStorage.CloseScanIndex[es.indexScanHandle]; es.indexScanHandle_ NIL}}; tupleSet => { IF es.tSetScanHandle # NIL THEN { DBStorage.CloseScanTupleset[es.tSetScanHandle]; es.tSetScanHandle_ NIL}}; empty => NULL; ENDCASE => ERROR; }; es.scan _ empty; END; QReleaseRelshipSet: PUBLIC PROCEDURE[rs: RelshipSet] = BEGIN IF rs=NIL THEN RETURN; TRUSTED { SELECT rs.scan FROM group => { IF rs.groupScanHandle # NIL THEN { DBStorage.CloseScanGroup[rs.groupScanHandle]; rs.groupScanHandle_ NIL}}; tupleSet => { IF rs.tSetScanHandle # NIL THEN { DBStorage.CloseScanTupleset[rs.tSetScanHandle]; rs.tSetScanHandle_ NIL}}; index => { IF rs.indexScanHandle # NIL THEN { DBStorage.CloseScanIndex[rs.indexScanHandle]; rs.indexScanHandle_ NIL}}; justOne => NULL; empty => NULL; ENDCASE => ERROR; }; rs.scan _ empty; END; <> QEntitySetToList: PUBLIC PROC[es: EntitySet] RETURNS [el: LIST OF Entity] = BEGIN e: Entity_ QNextEntity[es]; IF e=NIL THEN {QReleaseEntitySet[es]; RETURN[NIL]} ELSE RETURN[CONS[e, QEntitySetToList[es]]]; END; QRelshipSetToList: PUBLIC PROC[rs: RelshipSet] RETURNS [el: LIST OF Relship] = BEGIN r: Relship_ QNextRelship[rs]; IF r=NIL THEN {QReleaseRelshipSet[rs]; RETURN[NIL]} ELSE RETURN[CONS[r, QRelshipSetToList[rs]]]; END; CheckAVList: PROC[avl: AttributeValueList] RETURNS [abort: BOOL] = <> <> <> TRUSTED BEGIN FOR avlT: AttributeValueList_ avl, avlT.rest UNTIL avlT=NIL DO alh: AttributeValue = avl.first; WITH v: alh.lo SELECT FROM <> entity => IF IsSystem[v.value] THEN RETURN[TRUE]; ENDCASE; ENDLOOP; RETURN[FALSE] END; NCodeForTupleMatch: PROCEDURE[ tm: AttributeValueList, i: Index, extreme: {high, low}] RETURNS[ROPE] = <> <> <> <> <> <> <> <> BEGIN count: INT_ 0; s: ROPE_ ""; if: IndexFactor; ifType: DataType; ifs: LIST OF IndexFactor_ VL2TL[QGetPList[i, ifIndexOf]]; FOR tmL: AttributeValueList_ tm, tmL.rest UNTIL tmL=NIL DO <> IF ifs=NIL THEN <> <> RETURN[s]; if_ ifs.first; ifs_ ifs.rest; IF NOT EntityEq[PV2E[SafeGetP[if, ifAttributeIs]], DBModelSchema.GetAttributeTuple[tmL.first.attribute]] THEN ERROR InternalError; -- CanUseIndex only succeeds if same order as index factors IF count#PV2I[SafeGetP[if, ifOrdinalPositionIs]] THEN ERROR InternalError; { v: Value _ IF extreme=low OR NullValue[tmL.first.hi] THEN tmL.first.lo ELSE tmL.first.hi; s _ Rope.Cat[s, NCode[v], "\000"] }; count_ count+1; ENDLOOP; IF extreme=high THEN { <> FOR ifs_ ifs, ifs.rest UNTIL ifs=NIL DO if_ ifs.first; ifType _ DBModelSchema.TupleToAttribute[PV2E[SafeGetP[if, ifAttributeIs]]].type; IF ifType=IntType OR ifType=TimeType THEN s_ s.Concat["\377\377\377\377"] ELSE -- RopeType or entity name s_ s.Concat["\377"]; ENDLOOP }; RETURN[s]; END; NullValue: PROC[v: Value] RETURNS[BOOLEAN] = TRUSTED { WITH v SELECT FROM null => RETURN[TRUE]; ENDCASE => RETURN[FALSE] }; GreaterEqString: PROC[s1, s2: ROPE] RETURNS[BOOLEAN] = <> BEGIN RETURN[Rope.Compare[s1, s2] # less] END; Nconc: PROC[l1, l2: LIST OF Attribute] RETURNS [LIST OF Attribute] = BEGIN lp: LIST OF Attribute _ l1; IF l1=NIL THEN RETURN[l2]; FOR lp_ l1, lp.rest UNTIL lp.rest=NIL DO ENDLOOP; lp.rest_ l2; RETURN[l1]; END; GetNewEntitySet: PUBLIC PROC[] RETURNS [es: EntitySet, esi: CARDINAL] = { <> IF firstFreeESet = numberOfEntitySetObjects THEN { DBStats.Inc[EntitySetObjectAllocation]; RETURN[NEW[EntitySetObject], numberOfEntitySetObjects] }; es _ eSetList[firstFreeESet]; esi _ firstFreeESet; eSetFree[firstFreeESet] _ FALSE; UNTIL (firstFreeESet _ firstFreeESet + 1) = numberOfEntitySetObjects OR eSetFree[firstFreeESet] DO ENDLOOP; RETURN[es, esi] }; GetNewRelshipSet: PUBLIC PROC[] RETURNS [rs: RelshipSet, rsi: CARDINAL] = { <> IF firstFreeRSet = numberOfRelshipSetObjects THEN { DBStats.Inc[RelshipSetObjectAllocation]; RETURN[NEW[RelshipSetObject], numberOfRelshipSetObjects] }; rs _ rSetList[firstFreeRSet]; rsi _ firstFreeRSet; rSetFree[firstFreeRSet] _ FALSE; UNTIL (firstFreeRSet _ firstFreeRSet + 1) = numberOfRelshipSetObjects OR rSetFree[firstFreeRSet] DO ENDLOOP; RETURN[rs, rsi] }; GetNewDomainSet: PUBLIC PROC[] RETURNS [ds: DomainSet, dsi: CARDINAL] = { <> IF firstFreeDSet = numberOfDomainSetObjects THEN { DBStats.Inc[DomainSetObjectAllocation]; RETURN[NEW[DomainSetObject], numberOfDomainSetObjects] }; ds _ dSetList[firstFreeDSet]; dsi _ firstFreeDSet; dSetFree[firstFreeDSet] _ FALSE; UNTIL (firstFreeDSet _ firstFreeDSet + 1) = numberOfDomainSetObjects OR dSetFree[firstFreeDSet] DO ENDLOOP; RETURN[ds, dsi] }; GetNewRelationSet: PROC[] RETURNS [rs: RelationSet, rsi: CARDINAL] = { <> IF firstFreeRnSet = numberOfRelationSetObjects THEN { DBStats.Inc[RelationSetObjectAllocation]; RETURN[NEW[RelationSetObject], numberOfRelationSetObjects] }; rs _ rnSetList[firstFreeRnSet]; rsi _ firstFreeRnSet; rnSetFree[firstFreeRnSet] _ FALSE; UNTIL (firstFreeRnSet _ firstFreeRnSet + 1) = numberOfRelationSetObjects OR rnSetFree[firstFreeRnSet] DO ENDLOOP; RETURN[rs, rsi] }; ReturnEntitySet: PUBLIC PROC[i: CARDINAL] = { <= numberOfEntitySetObjects then the EntitySetObject was newly allocated>> IF i < numberOfEntitySetObjects THEN { eSetList[i].scan _ empty; eSetFree[i] _ TRUE; IF i < firstFreeESet THEN firstFreeESet _ i } }; ReturnRelshipSet: PUBLIC PROC[i: CARDINAL] = { <= numberOfRelshipSetObjects then the RelshipSetObject was newly allocated>> IF i < numberOfRelshipSetObjects THEN { rs: RelshipSet _ rSetList[i]; rs.scan _ empty; rs.surrogate _ NIL; rSetFree[i] _ TRUE; IF i < firstFreeRSet THEN firstFreeRSet _ i } }; ReturnDomainSet: PUBLIC PROC[i: CARDINAL] = { <= numberOfDomainSetObjects then the DomainSetObject was newly allocated>> IF i < numberOfDomainSetObjects THEN { dSetFree[i] _ TRUE; IF i < firstFreeDSet THEN firstFreeDSet _ i } }; ReturnRelationSet: PROC[i: CARDINAL] = { <= numberOfRelationSetObjects then the RelationSetObject was newly allocated>> IF i < numberOfRelationSetObjects THEN { rnSetFree[i] _ TRUE; IF i < firstFreeRnSet THEN firstFreeRnSet _ i } }; InitializeSetObjects: PUBLIC PROC[] = { <> i: CARDINAL; FOR i IN [0..numberOfEntitySetObjects) DO eSetList[i] _ NEW[EntitySetObject]; ENDLOOP; FOR i IN [0..numberOfRelshipSetObjects) DO rSetList[i] _ NEW[RelshipSetObject]; ENDLOOP; FOR i IN [0..numberOfDomainSetObjects) DO dSetList[i] _ NEW[DomainSetObject]; ENDLOOP; FOR i IN [0..numberOfRelationSetObjects) DO rnSetList[i] _ NEW[RelationSetObject]; ENDLOOP }; TL2AHL: PUBLIC PROC[tl: LIST OF TupleHandle] RETURNS [LIST OF Attribute] = { IF tl = NIL THEN RETURN[NIL] ELSE RETURN[CONS[DBModelSchema.TupleToAttribute[tl.first], TL2AHL[tl.rest]]] }; VL2AHL: PUBLIC PROC[vl: LIST OF Value] RETURNS [LIST OF Attribute] = { IF vl = NIL THEN RETURN[NIL] ELSE RETURN[CONS[DBModelSchema.TupleToAttribute[V2E[vl.first]], VL2AHL[vl.rest]]] }; END.