Schema design hints
ODABA supports a degree of complexity, which sometimes may cause unpredictable reactions. Thus, In order to reduce the risk for such problems, it is suggested to follow some rules listed below.
The generalization of a complex data type might be defined as exclusive or shared base instance. Shared base instances slow down the performance and should be used only, whenseveral instances may inherit from a base instance.
When defining shared inheritance, the base type should get an inverse reference, always.
When a general data type might be specialized to only one of the defined specializations, exclusive inheritance should be defined. In order to get a collection with all instances of the generalization, one may define a weak typed extent, which might be the base extent for the typed extent for all specializations.
A Person, which might be an Employee, a Student and a Patient at the same time. Thus, Person should be defined as shared generalisation of the other complex data types.
In case, that a berson might specialized to only ome of the listed types, the specialisations shuold inherit exclusively.
When not using inverse references for shared base types, remaing instances will cause problems, when renaming the base type instance.
Usually, it is suggested using owning relationships rather than references. The only useful case for using references are large text or binary objects (MEMO and BLOBs) or complex data types, which rarely appear and are really considered as part of the owning object instance.
Typically, addresses of a person or organisation might be stored as reference.
Using references is, usually faster, since the database system supposes, that references are accessible via the owning instance, only. Thus, references and its indexes will not be locked when being accessed (the owning instance is locked instead). This may cause problems, when the referenced instance refers to other instances via relationsips, which may provide other non-exclusive access paths.
There are many different ways of defining indexes in order to provide fast access for large collections and for defining unique or no-empty constraints. Usually, indexes do not cause problems, but in some cases,
For each collection (reference, relationship or global extents) one or more indexes might be defined based on the key definitions for the referenced data type. One of the indexes is considered as main index, which will be activated automatically, when accessing the index. By default, the main index is the index referring to the primary key (identifying key). When this key is not used as index, the first persistent and unique index in the list is the main index. Beside, one may mark any index explicitly as main index.
It is suggested to use the primary index as main index in any case. This is not necessary, when the collection is an owning collection, but it helps avoiding conflicts in set hierarchies.
When defining base collections (super sets) the main index must have been defined in all indexes in the set hierarchy. Otherwise, instance look-up may fail, when trying to locate an instance in the super set, e.g. when inserting an instance by key to the collection.
When indexes do not match in a set hierarchy, the application must ensure, that instances are inserted to the collection only by instance with properly set key component attributes for all indexes in the hierarchy. Otherwise, insertion may fail or new instances with partially empty key component values will be created.
Avoid using relationships in complex data types used as reference collection type. This is not forbidden, since the complex data type might be used in other relationships an no warning is issued when checking the type.
The ODABA system model uses DSC_Topic objects for documentation. Those are, typically linked to resources (SDB_ResourceRef). On the other hand, a DSC_Topic might get any number of subtopics (reference collection). Those subtopics must not contain links to e.g. concepts (relationship descriptors).
Using relationships in references may cause problems, when importing instances, since several import procedures do noot check for relationships when importing references (e.g. OIF import). Moreover, in some cases collection indexes might be damaged.
Inverse relationships are not mandatory, since in some situation, inverse relationships might be very disturbing. When not defining inverse relationships, the relationship should not contain an ordered index (singular or unordered collection), since modifications in the instances referenced in the relationship cannot be maintained automatically.
Moreover, the application has to make sure, that instances referenced in the relationship are removed from the collection before being deleted. This is not a problem, when the relationship is the instance owner and the only relationship referring to the instance.
In some cases, it might be, however, better not to define inverse references (see example below from the ODABA system model)
// this shows the problem, but the real definition is more difficult
SDB_Structure ... // complex data type
RELATIONSHIP {
SET<SDB_Member> members owner INVERSE structure ...; // all data type members
SET<SDB_Attribute> smcepdde BASED_ON .members ...; // attributes (no inverse, but based on members)
SET<SDB_Reference> smcepref BASED_ON .members ...; // references (no inverse, but based on members)
....
};
The consequence from missing inverse definitions are index problems when changing the referenced instances from other references than the relationship or invalid instance pointers after deleting a referenced instance.