This class is used to generate and manage SQL projections of iKnow data structures for a
particular domain. The easiest way to generate these SQL projections is by setting the objectsPackage
attribute on the <domain> element in a Domain Definition.
These projections can be customized in any of the following ways:
- New properties for metadata can be added to any table. they can be either writeable properties (such as source-level metadata) or computed/calculated fields to denormalize the schema. Non-computed fields should be set using regular UPDATE calls in SQL or set commands in COS. Computed fields (with the SqlComputed flag on) will be populated automatically when either of the following conditions is met:
- The computed property has the SqlComputeOnChange attribute set to one or more custom fields: the value is updated when one of those is updated
- The computed property is based on built-in fields (for example to denormalize the schema, such as adding a SourceId property to the Parts table): the value is updated (set) automatically when the domain is being built. Note that computed fields are built in a specific order and particular dependencies may not be satisfied, in which case the condition below applies. The build order is Sources, [EntityUnique, StemUnique, CrcUnique, CcUniqe], Sentence, Path, Part, CrcOccurrence, with the  indicating that these are built in parallel.
- The table's %BuildCustomFields() method is called. Note that this is called automatically as part of loading / updating a domain. Iow, this method only needs to be called explicitly when a computed property depends on a custom field and its SqlComputeOnChange is not set appropriately, or when it has non-trivial dependencies on other tables and the automated call to %BuildCustomFields() does not cover them.
- Existing properties (created as part of the default mapping) that are marked as Calculated and SqlComputed can be marked SqlComputed only (not Calculated). These properties' values will then be persisted rather than calculated on-the-fly, which may benefit query performance. See above for the policy on when computed fields' values are updated.
- New indices can be added on existing or custom properties, regardless of whether their values are simply persisted, computed-persisted or calculated. These indices will be updated automatically when loading/updating a domain or when updating writeable fields as added in option 1.
- Custom methods, optionally serving to populate indices (like *BuildValueArray()) can be added to the existing tables.
The CustomAnnotations table is special in the sense that it's the only table that can be written to directly. It allows users to specify custom annotations for specific sentence parts (Part table), which will be available through the Annotations property of that Part table, next to attributes and matching results.
The following modifications are NOT supported:
- modifying the definition of any property marked as ReadOnly, other than turning calculated fields into computed ones as described above.
- modifying the definition of any index or foreign key whose name starts with a % sign
- modifying or overriding any *Get() or *BuildValueArray() method for a ReadOnly property provided in the generated classes or its superclasses
- dropping any of the generated tables
- INSERT and DELETE operations on any of the generated tables, except CustomAnnotations. Note that there are triggers that should prevent this.
- UPDATE operations on any non-custom fields. Note that this should be prevented by the ReadOnly attributes of those fields.
These table projections and any associated data will be dropped when dropping the domain.
It is important to note that the generated projections include a number of denormalizations, such as calculated fields providing convenience access to data stored in another table. For example, the EntityValue property of the Part table is a calculated field based on the string value of the corresponding EntityUnique record. This means filtering or grouping by such denormalized columns directly may lead to valid but not necessarily efficient SQL. Therefore, it is recommend to check query plans and, when adopting the queries for production use (or when implementing a query generation utility), ensure appropriate indices will be used, either custom (as explained earlier) or default ones by adding a query subclause.
When generating these tables, the actual classes, properties and indices generated will be based on the Build Flag settings and some domain parameters (most importantly $$$IKPSTEMMING). If these would change (which already assumes the domain is empty), the GenerateDomainTables() method should be re-invoked.
classmethod DropDomainTables(pPackageName As %String) as %Status
Creates a set of tables representing the data in domain pDomainId in package pPackageName. If pOverWrite=1, existing table definitions will be overwritten, which may therefore no longer preserve non-calculated custom field values.
If pRefClass is non-null, a "Ref" property of that type will be added to the Source class, initialized with the value of its LocalReference property (ie, the ID field used when loading from a SQL table).
Any metadata fields referenced in pMetadata will be added to the Source class as calculated fields, along with indices mapping the corresponding iKnow data structures where possible.
A list of additional indices to be created can be supplied through pIndices in the following format:pIndices("TableName", "idx", "IndexName") = $lb("Properties", "IndexType")For the Source table, these can be references to pRefClass columns by using arrow syntax.
Drops any classes generated by CreateDomainTables in package pPackageName and associated customization data (field values & indices) classmethod SyncCustomizations(pDomainId As %Integer = "", pPackageName As %String = "", pAutoPurge As %Boolean = 1, pStartSrcId As %Integer = "", pEndSrcId As %Integer = "", ByRef pRanges) as %Status
Either pDomainId or pPackageName has to be passed in, or both if they are known classmethod SyncDictionaryMatchCustomizations(pDomainId As %Integer = "", pPackageName As %String = "", pAutoPurge As %Boolean = 1, pStartSrcId As %Integer = "", pEndSrcId As %Integer = "", pFilter As %iKnow.Filters.Filter = "") as %Status