<> <> <> <> <> <> <> <> <> DIRECTORY AlpineEnvironment, Atom, DB, DBExtras, DBCommon, DBDefs, DBModel, DBStats, Rope; DBImpl: CEDAR MONITOR IMPORTS DBModel, DBStats, DB, DBDefs EXPORTS DB, DBExtras = BEGIN ROPE: TYPE = Rope.ROPE; <> Initialize: PUBLIC ENTRY PROC[nCachePages: NAT, cacheFileName: ROPE] = { ENABLE UNWIND => NULL; DBModel.Initialize[nCachePages, cacheFileName]; RETURN}; OpenTransaction: PUBLIC ENTRY PROC[segment: DB.Segment, useTrans: DB.TransactionHandle] RETURNS[trans: DB.TransactionHandle, schemaInvalid: BOOL] = { ENABLE UNWIND => DBStats.Stopping[OpenTransaction]; DBStats.Starting[OpenTransaction]; [trans, schemaInvalid] _ DBModel.OpenTransaction[segment, useTrans]; DBStats.Stopping[OpenTransaction] }; MarkTransaction: PUBLIC ENTRY PROC[trans: DB.TransactionHandle] = { ENABLE UNWIND => DBStats.Stopping[MarkTransaction]; DBModel.MarkTransaction[trans]; DBStats.Stopping[MarkTransaction] }; AbortTransaction: PUBLIC ENTRY PROC[trans: DB.TransactionHandle] = { ENABLE UNWIND => DBStats.Stopping[AbortTransaction]; DBModel.AbortTransaction[trans]; DBStats.Stopping[AbortTransaction] }; CloseTransaction: PUBLIC ENTRY PROC[trans: DB.TransactionHandle] = { ENABLE UNWIND => DBStats.Stopping[CloseTransaction]; DBModel.CloseTransaction[trans]; DBStats.Stopping[CloseTransaction] }; MakeTransHandle: PUBLIC PROC[trans: DBCommon.Transaction] RETURNS[handle: DB.TransactionHandle] = { RETURN[NEW[DBCommon.TransactionObject _ [trans: trans, segments: NIL]]] }; DeclareSegment: PUBLIC ENTRY PROC[filePath: ROPE, segment: DB.Segment, number: DB.SegmentIndex, lock: AlpineEnvironment.LockOption, readonly: BOOL, createIfNotFound: BOOL, nPagesInitial, nPagesPerExtent: INT] = { ENABLE UNWIND => NULL; DBModel.DeclareSegment[filePath, segment, number, lock, readonly, createIfNotFound, nPagesInitial, nPagesPerExtent] }; EraseSegment: PUBLIC ENTRY PROC[segment: DB.Segment, useTrans: DB.TransactionHandle] RETURNS [trans: DB.TransactionHandle] = <> { ENABLE UNWIND => NULL; RETURN[DBModel.OpenTransaction[segment: segment, useTrans: useTrans, eraseAfterOpen: TRUE].trans] }; GetSegmentInfo: PUBLIC ENTRY PROC[segment: DB.Segment] RETURNS [filePath: ROPE, readOnly: BOOL] = { ENABLE UNWIND => NULL; [filePath, readOnly] _ DBModel.GetSegmentInfo[segment] }; SegmentsForTransaction: PUBLIC PROC[trans: DB.TransactionHandle] RETURNS [segments: DB.SegmentList] = { segments _ IF trans = NIL THEN NIL ELSE trans.segments }; <> DeclareDomain: PUBLIC ENTRY PROC [name: ROPE, segment: DB.Segment] RETURNS [d: DB.Domain] = { ENABLE UNWIND => DBStats.Stopping[DeclareDomain]; IF NOT DBModel.initialized THEN ERROR Error[DatabaseNotInitialized]; d _ DBModel.DeclareDomain[name, segment]; DBStats.Stopping[DeclareDomain] }; LookupDomain: PUBLIC ENTRY PROC [name: ROPE, segment: DB.Segment] RETURNS [d: DB.Domain] = { ENABLE UNWIND => DBStats.Stopping[LookupDomain]; IF NOT DBModel.initialized THEN ERROR Error[DatabaseNotInitialized]; d _ DBModel.LookupDomain[name, segment]; DBStats.Stopping[LookupDomain] }; DestroyDomain: PUBLIC ENTRY PROC [d: DB.Domain] = { ENABLE UNWIND => DBStats.Stopping[DestroyDomain]; DBModel.DestroyDomain[d]; DBStats.Stopping[DestroyDomain] }; DomainInfo: PUBLIC ENTRY PROC[d: DB.Domain] RETURNS[name: ROPE, segment: DB.Segment] = TRUSTED { ENABLE UNWIND => NULL; IF d.key # DBModel.CacheKey[d.segment] THEN ERROR Error[IllegalDomain]; segment _ d.segment; name _ d.name }; DomainsByName: PUBLIC ENTRY PROC [segment: DB.Segment, lowName, highName: ROPE, start: DB.FirstLast] RETURNS[ds: DB.DomainSet] = { ENABLE UNWIND => NULL; ds _ DBModel.DomainsByName[segment, lowName, highName, start] }; NextDomain: PUBLIC ENTRY PROC [ds: DB.DomainSet] RETURNS [d: DB.Domain] = { ENABLE UNWIND => NULL; d _ DBModel.NextDomain[ds] }; PrevDomain: PUBLIC ENTRY PROC [ds: DB.DomainSet] RETURNS [d: DB.Domain] = { ENABLE UNWIND => NULL; d _ DBModel.PrevDomain[ds] }; ReleaseDomainSet: PUBLIC ENTRY PROC [ds: DB.DomainSet] = { ENABLE UNWIND => NULL; DBModel.ReleaseDomainSet[ds] }; DeclareSubType: PUBLIC ENTRY PROC [of, is: DB.Domain] = { ENABLE UNWIND => NULL; DBModel.DeclareSubType[of, is] }; DestroySubType: PUBLIC ENTRY PROC [of, is: DB.Domain] = { ENABLE UNWIND => NULL; DBModel.DestroySubType[of, is] }; SuperType: PUBLIC ENTRY PROC [d: DB.Domain] RETURNS[super: DB.Domain] = { ENABLE UNWIND => NULL; RETURN[DBModel.SuperType[d]] }; SubTypes: PUBLIC ENTRY PROC [d: DB.Domain] RETURNS[subs: DB.DomainSet] = { ENABLE UNWIND => NULL; RETURN[DBModel.SubTypes[d]] }; TypeForDomain: PUBLIC PROC[d: DB.Domain] RETURNS[type: DB.TypeCode] = { ENABLE UNWIND => NULL; RETURN[DBModel.TypeForDomain[d]] }; TypeToDomain: PUBLIC ENTRY PROC[type: DB.TypeCode, segment: DB.Segment] RETURNS[d: DB.Domain] = { ENABLE UNWIND => NULL; IF DBDefs.IsPrimitive[type] THEN ERROR DB.Error[IllegalDomain]; RETURN[DBModel.TypeToDomain[type, segment]] }; DeclareRelation: PUBLIC ENTRY PROC [name: ROPE, segment: DB.Segment, fields: DB.FieldSpec] RETURNS [r: DB.Relation] = { ENABLE UNWIND => DBStats.Stopping[DeclareRelation]; DBStats.Starting[DeclareRelation]; r _ DBModel.DeclareRelation[name, segment, fields, FALSE]; DBStats.Stopping[DeclareRelation] }; DeclareProperty: PUBLIC ENTRY PROC [name: ROPE, segment: DB.Segment, fields: DB.FieldSpec] RETURNS [r: DB.Relation] = { ENABLE UNWIND => DBStats.Stopping[DeclareRelation]; DBStats.Starting[DeclareRelation]; r _ DBModel.DeclareRelation[name, segment, fields, TRUE]; DBStats.Stopping[DeclareRelation] }; LookupRelation: PUBLIC ENTRY PROC [name: ROPE, segment: DB.Segment] RETURNS [r: DB.Relation] = { ENABLE UNWIND => DBStats.Stopping[LookupRelation]; DBStats.Starting[LookupRelation]; r _ DBModel.LookupRelation[name, segment]; DBStats.Stopping[LookupRelation] }; DestroyRelation: PUBLIC ENTRY PROC [r: DB.Relation] = { ENABLE UNWIND => DBStats.Stopping[DestroyRelation]; DBStats.Starting[DestroyRelation]; DBModel.DestroyRelation[r]; DBStats.Stopping[DestroyRelation] }; RelationInfo: PUBLIC ENTRY PROC [r: DB.Relation] RETURNS[name: ROPE, segment: DB.Segment] = TRUSTED { ENABLE UNWIND => NULL; IF r.key # DBModel.CacheKey[r.segment] THEN ERROR Error[IllegalRelation]; segment _ r.segment; name _ r.name }; RelationsByName: PUBLIC ENTRY PROC [segment: DB.Segment, lowName, highName: ROPE, start: DB.FirstLast] RETURNS[rs: DB.RelationSet] = { ENABLE UNWIND => NULL; rs _ DBModel.RelationsByName[segment, lowName, highName, start] }; NextRelation: PUBLIC ENTRY PROC [rs: DB.RelationSet] RETURNS [r: DB.Relation] = { ENABLE UNWIND => NULL; r _ DBModel.NextRelation[rs] }; PrevRelation: PUBLIC ENTRY PROC [rs: DB.RelationSet] RETURNS [r: DB.Relation] = { ENABLE UNWIND => NULL; r _ DBModel.PrevRelation[rs] }; ReleaseRelationSet: PUBLIC ENTRY PROC [rs: DB.RelationSet] = { ENABLE UNWIND => NULL; DBModel.ReleaseRelationSet[rs] }; NameToField: PUBLIC ENTRY PROC [r: DB.Relation, name: ROPE] RETURNS[exists: BOOL, pos: CARDINAL] = { ENABLE UNWIND => NULL; [exists, pos] _ DBModel.NameToField[r: r, name: name] }; FieldCount: PUBLIC ENTRY PROC[r: DB.Relation] RETURNS[count: CARDINAL] = { ENABLE UNWIND => NULL; count _ DBModel.FieldCount[r: r] }; Fields: PUBLIC ENTRY PROC[r: DB.Relation] RETURNS[fields: DB.FieldSpec] = { ENABLE UNWIND => NULL; fields _ DBModel.Fields[r] }; RelationType: PUBLIC ENTRY PROC[r: DB.Relation] RETURNS[fields: DB.FieldSpec, isProperty: BOOL] = { ENABLE UNWIND => NULL; fields _ DBModel.Fields[r]; isProperty _ r.isProperty }; FieldDescription: PUBLIC ENTRY PROC [r: DB.Relation, pos: CARDINAL] RETURNS [field: DB.Field] = { ENABLE UNWIND => NULL; field _ DBModel.FieldDescription[r, pos] }; DeclareIndex: PUBLIC ENTRY PROC [r: DB.Relation, fields: DB.FieldSequence] RETURNS[index: DB.Index] = { ENABLE UNWIND => DBStats.Stopping[DeclareIndex]; DBStats.Starting[DeclareIndex]; index _ DBModel.DeclareIndex[r: r, fields: fields, isKey: FALSE]; DBStats.Stopping[DeclareIndex] }; DeclareKeyIndex: PUBLIC ENTRY PROC [r: DB.Relation, fields: DB.FieldSequence] RETURNS[index: DB.Index] = { ENABLE UNWIND => DBStats.Stopping[DeclareIndex]; DBStats.Starting[DeclareIndex]; index _ DBModel.DeclareIndex[r: r, fields: fields, isKey: TRUE]; DBStats.Stopping[DeclareIndex] }; DestroyIndex: PUBLIC ENTRY PROC [r: DB.Relation, index: DB.Index] = { ENABLE UNWIND => DBStats.Stopping[DestroyIndex]; DBStats.Starting[DestroyIndex]; DBModel.DestroyIndex[r, index]; DBStats.Stopping[DestroyIndex] }; KeyIndices: PUBLIC ENTRY PROC[r: DB.Relation] RETURNS[keyIndices: LIST OF DB.Index] = { keyIndices _ DBModel.Keys[r] }; OtherIndices: PUBLIC ENTRY PROC[r: DB.Relation] RETURNS[indices: LIST OF DB.Index] = { indices _ DBModel.Indices[r] }; <> DeclareEntity: PUBLIC ENTRY PROC[d: DB.Domain, name: ROPE, newOnly: BOOL _ FALSE] RETURNS[e: DB.Entity] = { ENABLE UNWIND => DBStats.Stopping[DeclareEntity]; DBStats.Starting[DeclareEntity]; e _ DBModel.DeclareEntity[d, name, newOnly]; DBStats.Stopping[DeclareEntity]}; LookupEntity: PUBLIC ENTRY PROC[d: DB.Domain, name: ROPE] RETURNS[e: DB.Entity] = { ENABLE UNWIND => DBStats.Stopping[LookupEntity]; DBStats.Starting[LookupEntity]; e _ DBModel.LookupEntity[d, name]; DBStats.Stopping[LookupEntity] }; CreateRelship: PUBLIC ENTRY PROC[r: DB.Relation, init: DB.ValueSequence] RETURNS[t: DB.Relship] = { ENABLE UNWIND => DBStats.Stopping[CreateRelship]; DBStats.Starting[CreateRelship]; t _ DBModel.CreateRelship[r, init]; DBStats.Stopping[CreateRelship] }; LookupRelship: PUBLIC ENTRY PROC[r: DB.Relation, keyIndex: DB.Index, key: DB.ValueSequence] RETURNS[t: DB.Relship] = { ENABLE UNWIND => DBStats.Stopping[LookupRelship]; DBStats.Starting[LookupRelship]; t _ DBModel.LookupRelship[r, keyIndex, key]; DBStats.Stopping[LookupRelship] }; oneLittleValueSequence: DB.ValueSequence _ NEW[DBDefs.ValueSequenceObject[1]]; LookupWithSimpleKey: PUBLIC ENTRY PROC[r: DB.Relation, keyIndex: DB.Index, key: DB.Value] RETURNS[t: DB.Relship] = TRUSTED { ENABLE UNWIND => DBStats.Stopping[LookupRelship]; DBStats.Starting[LookupRelship]; IF keyIndex.fields.count # 1 THEN ERROR DB.Error[MismatchedAttributeValueType]; oneLittleValueSequence[0] _ key; t _ DBModel.LookupRelship[r, keyIndex, oneLittleValueSequence]; DBStats.Stopping[LookupRelship] }; LookupProperty: PUBLIC ENTRY PROC[r: DB.Relation, e: DB.Entity] RETURNS[relship: DB.Relship] = { ENABLE UNWIND => DBStats.Stopping[LookupProperty]; DBStats.Starting[LookupProperty]; relship _ DBModel.LookupProperty[r, e]; DBStats.Stopping[LookupProperty] }; FirstRelship: PUBLIC ENTRY PROC[r: DB.Relation] RETURNS[relship: DB.Relship] = { ENABLE UNWIND => DBStats.Stopping[LookupRelship]; DBStats.Starting[LookupRelship]; relship _ DBModel.FirstRelship[r]; DBStats.Stopping[LookupRelship] }; DestroyEntity: PUBLIC ENTRY PROC[e: DB.Entity] = { ENABLE UNWIND => DBStats.Stopping[DestroyEntity]; DBStats.Starting[DestroyEntity]; DBModel.DestroyEntity[e]; DBStats.Stopping[DestroyEntity] }; CopyEntity: PUBLIC ENTRY PROC[e: DB.Entity] RETURNS[DB.Entity] = { RETURN[DBModel.CopyEntity[e]] }; DestroyRelship: PUBLIC ENTRY PROC[t: DB.Relship] = { ENABLE UNWIND => DBStats.Stopping[DestroyRelship]; DBStats.Starting[DestroyRelship]; DBModel.DestroyRelship[t]; DBStats.Stopping[DestroyRelship] }; CopyRelship: PUBLIC ENTRY PROC[t: DB.Relship] RETURNS[DB.Relship] = { RETURN[DBModel.CopyRelship[t]] }; SetF: PUBLIC ENTRY PROC[t: DB.Relship, field: CARDINAL, v: DB.Value] = { ENABLE UNWIND => DBStats.Stopping[SetF]; DBStats.Starting[SetF]; DBModel.SetF[t, field, v]; DBStats.Stopping[SetF] }; GetF: PUBLIC ENTRY PROC[t: DB.Relship, field: CARDINAL] RETURNS [v: DB.Value _ [null[]]] = TRUSTED { ENABLE UNWIND => DBStats.Stopping[GetF]; DBStats.Starting[GetF]; v _ DBModel.GetF[t, field]; DBStats.Stopping[GetF] }; SetP: PUBLIC ENTRY PROC[e: DB.Entity, r: DB.Relation, field: CARDINAL, v: DB.Value] = { ENABLE UNWIND => DBStats.Stopping[SetP]; DBStats.Starting[SetP]; DBModel.SetP[e, r, field, v]; DBStats.Stopping[SetP] }; GetP: PUBLIC ENTRY PROC[e: DB.Entity, r: DB.Relation, field: CARDINAL] RETURNS[v: DB.Value _ [null[]]] = TRUSTED { ENABLE UNWIND => DBStats.Stopping[GetP]; DBStats.Starting[GetP]; v _ DBModel.GetP[e, r, field]; DBStats.Stopping[GetP] }; DomainEq: PUBLIC PROC [d1, d2: DB.Domain] RETURNS[BOOL] = { RETURN[DBModel.DomainEq[d1, d2]] }; RelationEq: PUBLIC PROC [r1, r2: DB.Relation] RETURNS[BOOL] = { RETURN[DBModel.RelationEq[r1, r2]] }; NullDomain: PUBLIC PROC [d: DB.Domain] RETURNS[BOOLEAN] = { RETURN[DBModel.NullDomain[d]] }; NullRelation: PUBLIC PROC [r: DB.Relation] RETURNS[BOOLEAN] = { RETURN[DBModel.NullRelation[r]] }; EntityInfo: PUBLIC ENTRY PROC [e: DB.Entity] RETURNS [name: ROPE, domain: DB.Domain] = { ENABLE UNWIND => NULL; [name, domain] _ DBModel.EntityInfo[e] }; NullEntity: PUBLIC PROC[e: DB.Entity] RETURNS[BOOL] = { RETURN[DBModel.NullEntity[e]]}; EntityEq: PUBLIC PROC[e1: DB.Entity, e2: DB.Entity] RETURNS[BOOL] = { RETURN[DBModel.EntityEq[e1, e2]] }; ToUnderType: PUBLIC ENTRY PROC [e: DB.Entity] = { ENABLE UNWIND => NULL; DBModel.ToUnderType[e] }; ChangeName: PUBLIC ENTRY PROC [of: DB.Entity, to: Rope.ROPE] = { ENABLE UNWIND => NULL; DBModel.ChangeName[of, to] }; RelationOf: PUBLIC ENTRY PROC[t: DB.Relship] RETURNS [DB.Relation] = { ENABLE UNWIND => NULL; RETURN[DBModel.RelationOf[t]] }; RelshipEq: PUBLIC ENTRY PROC[r1: DB.Relship, r2: DB.Relship] RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN[DBModel.RelshipEq[r1, r2]] }; NullRelship: PUBLIC ENTRY PROC[r: DB.Relship] RETURNS [BOOL] = { ENABLE UNWIND => NULL; RETURN[DBModel.NullRelship[r]] }; <> RelationSubset: PUBLIC ENTRY PROC[r: DB.Relation, index: DB.Index, constraint: DB.Constraint, start: DB.FirstLast] RETURNS [rs: DB.RelshipSet] = { ENABLE UNWIND => DBStats.Stopping[RelationSubset]; DBStats.Starting[RelationSubset]; rs _ DBModel.RelationSubset[r, index, constraint, start]; DBStats.Stopping[RelationSubset] }; NextRelship: PUBLIC ENTRY PROC[rs: DB.RelshipSet] RETURNS [t: DB.Relship] = { ENABLE UNWIND => DBStats.Stopping[NextRelship]; DBStats.Starting[NextRelship]; t _ DBModel.NextRelship[rs]; DBStats.Stopping[NextRelship] }; PrevRelship: PUBLIC ENTRY PROC[rs: DB.RelshipSet] RETURNS [t: DB.Relship] = { ENABLE UNWIND => DBStats.Stopping[PrevRelship]; DBStats.Starting[PrevRelship]; t _ DBModel.PrevRelship[rs]; DBStats.Stopping[PrevRelship] }; ReleaseRelshipSet: PUBLIC ENTRY PROC [rs: DB.RelshipSet] = {ENABLE UNWIND => NULL; DBModel.ReleaseRelshipSet[rs]}; DomainSubset: PUBLIC ENTRY PROC[d: DB.Domain, lowName, highName: ROPE, start: DB.FirstLast] RETURNS [es: DB.EntitySet] = { ENABLE UNWIND => DBStats.Stopping[DomainSubset]; DBStats.Starting[DomainSubset]; es _ DBModel.DomainSubset[d, lowName, highName, start]; DBStats.Stopping[DomainSubset]; RETURN[es] }; NextEntity: PUBLIC ENTRY PROC[es: DB.EntitySet] RETURNS [e: DB.Entity] = { ENABLE UNWIND => DBStats.Stopping[NextEntity]; DBStats.Starting[NextEntity]; e _ DBModel.NextEntity[es]; DBStats.Stopping[NextEntity]; }; PrevEntity: PUBLIC ENTRY PROC[es: DB.EntitySet] RETURNS [e: DB.Entity] = { ENABLE UNWIND => DBStats.Stopping[PrevEntity]; DBStats.Starting[PrevEntity]; e _ DBModel.PrevEntity[es]; DBStats.Stopping[PrevEntity]; }; ReleaseEntitySet: PUBLIC ENTRY PROC[es: DB.EntitySet] = { ENABLE UNWIND => NULL; DBModel.ReleaseEntitySet[es]}; RelshipsForEntity: PUBLIC ENTRY PROC [e: DB.Entity] RETURNS [rs: DB.RelshipSet] = { ENABLE UNWIND => NULL; RETURN[DBModel.RelshipsForEntity[e]] }; RelshipsWithEntityField: PUBLIC ENTRY PROC[r: DB.Relation, field: CARDINAL, val: DB.Entity] RETURNS[rs: DB.RelshipSet] = { ENABLE UNWIND => NULL; RETURN[DBModel.RelshipsWithEntityField[r, field, val]] }; RelationsOf: PUBLIC ENTRY PROC[d: DB.Domain] RETURNS[rs: DB.RelationSet] = { ENABLE UNWIND => NULL; rs _ DBModel.RelationsOf[d] }; <> L2VS: PUBLIC PROC[vals: LIST OF DB.Value] RETURNS[seq: DB.ValueSequence] = TRUSTED { length: CARDINAL _ 0; IF vals = NIL THEN RETURN[NIL]; FOR vL: LIST OF DB.Value _ vals, vL.rest UNTIL vL = NIL DO length _ length + 1 ENDLOOP; seq _ NEW[DBDefs.ValueSequenceObject[length]]; length _ 0; FOR vL: LIST OF DB.Value _ vals, vL.rest UNTIL vL = NIL DO seq[length] _ vL.first; length _ length + 1 ENDLOOP }; L2FS: PUBLIC PROC[vals: LIST OF DB.Field] RETURNS[seq: DB.FieldSpec] = TRUSTED { length: CARDINAL _ 0; IF vals = NIL THEN RETURN[NIL]; FOR vL: LIST OF DB.Field _ vals, vL.rest UNTIL vL = NIL DO length _ length + 1 ENDLOOP; seq _ NEW[DB.FieldSpecObject[length]]; length _ 0; FOR vL: LIST OF DB.Field _ vals, vL.rest UNTIL vL = NIL DO seq[length] _ vL.first; length _ length + 1 ENDLOOP }; L2F: PUBLIC PROC[vals: LIST OF CARDINAL] RETURNS[seq: DB.FieldSequence] = TRUSTED { length: CARDINAL _ 0; IF vals = NIL THEN RETURN[NIL]; FOR vL: LIST OF CARDINAL _ vals, vL.rest UNTIL vL = NIL DO length _ length + 1 ENDLOOP; seq _ NEW[DBDefs.FieldSequenceObject[length]]; length _ 0; FOR vL: LIST OF CARDINAL _ vals, vL.rest UNTIL vL = NIL DO seq[length] _ vL.first; length _ length + 1 ENDLOOP }; L2C: PUBLIC PROC[vals: LIST OF DB.ValueConstraint] RETURNS[seq: DB.Constraint] = TRUSTED { length: CARDINAL _ 0; IF vals = NIL THEN RETURN[NIL]; FOR vL: LIST OF DBDefs.ValueConstraint _ vals, vL.rest UNTIL vL = NIL DO length _ length + 1 ENDLOOP; seq _ NEW[DBDefs.ConstraintObject[length]]; length _ 0; FOR vL: LIST OF DBDefs.ValueConstraint _ vals, vL.rest UNTIL vL = NIL DO seq[length] _ vL.first; length _ length + 1 ENDLOOP }; <> Error: PUBLIC SIGNAL [code: DB.ErrorCode] = CODE; Aborted: PUBLIC ERROR = CODE; Failure: PUBLIC ERROR [what: ATOM, info: ROPE] = CODE; InternalError: PUBLIC ERROR = CODE; <> { DBStats.Initialize[] } END.