For a field that uses
includeFrom, specifies which
foreignKey field should be used to find records in the related DataSource.
includeVia only needs to be set when you have more than one foreignKey to the same related DataSource. If you have multiple foreignKeys to multiple different DataSources, there is no need to set includeVia.
For example, perhaps you have a DataSource "moneyTransfer" where each record represents a money transfer, where the source and payment currencies are different, and the list of currencies is stored in a related DataSource "currency". Each "moneyTransfer" record is linked to 2 "currency" records, through two different foreignKey fields, "sourceCurrencyId" and "paymentCurrencyId".
The following declarations would be required to use includeFrom to get a include the field "currencySymbol" from each of the two related "currency" records.
<field name="sourceCurrencyId" foreignKey="currency.id"/>
<field name="paymentCurrencyId" foreignKey="currency.id"/>
<field name="sourceCurrencySymbol" includeFrom="currency.currencySymbol" includeVia="sourceCurrencyId"/>
<field name="paymentCurrencySymbol" includeFrom="currency.currencySymbol" includeVia="paymentCurrencyId"/>
SQL Templating and includeVia
The includeVia feature uses SQL table aliases in the generated SQL when generating multiple SQL joins to the same SQL table. When using SQL Templating, it's sometimes necessary to know the names of the aliases in the generated SQL. The table alias used can be configured via setting relatedTableAlias on the foreignKey field, for example, using the declarations below, aliases "source" and "payment" would be used for the two "currency" tables.
<field name="sourceCurrencyId" foreignKey="currency.id" relatedTableAlias="source"/>
<field name="paymentCurrencyId" foreignKey="currency.id" relatedTableAlias="payment"/>
<field name="sourceCurrencySymbol" includeFrom="currency.currencySymbol" includeVia="sourceCurrencyId"/>
<field name="paymentCurrencySymbol" includeFrom="currency.currencySymbol" includeVia="paymentCurrencyId"/>
Multiple indirection and relatedTableAlias
General rule is that if relatedTableAlias is present it is used as alias or its segment, otherwise foreignKey field name linked by includeVia is used instead. See the "Automatically generated table aliases" section of the SQL Templating for the complete set of general rules how aliases are generated. Also, see some samples below.
Sometimes you may have two includeFrom fields that include a field which is itself included from another DataSource, for example:
<field name="sourceCurId" nativeName="sourceCurrencyId" foreignKey="currency.id" relatedTableAlias="source"/>
<field name="sourceCurrencySymbol" includeFrom="currency.currencySymbol" includeVia="sourceCurId"/>
<field name="sourceCurrencyGroup" includeFrom="currency.groupName" includeVia="sourceCurId"/>
<field name="paymentCurId" nativeName="paymentCurrencyId" foreignKey="currency.id" relatedTableAlias="payment"/>
<field name="paymentCurrencySymbol" includeFrom="currency.currencySymbol" includeVia="paymentCurId"/>
<field name="paymentCurrencyGroup" includeFrom="currency.groupName" includeVia="paymentCurId"/>
.. where the "currency" DataSource used above is related to the "currencyGroup" DataSource via fields:
<field name="groupId" type="integer" foreignKey="currencyGroup.id" relatedTableAlias="group"/>
<field name="groupName" type="text" includeFrom="currencyGroup.groupName"/>
Fields "sourceCurrencyGroup" and "paymentCurrencyGroup" include a field that is itself an included field. In this case "currencyGroup" table will be referenced two times, and its
relatedTableAlias defined in "currency" DataSource will be prefixed with the referenced by
includeVia field's
relatedTableAlias value to make aliases unique in generated SQL: "source_group" and "payment_group".
The same aliases would be used if "sourceCurrencyGroup" and "paymentCurrencyGroup" fields were to include "currencyGroup.groupName" indirectly:
<field name="sourceCurrencyGroup" includeFrom="currency.currencyGroup.groupName" includeVia="sourceCurId"/>
<field name="paymentCurrencyGroup" includeFrom="currency.currencyGroup.groupName" includeVia="paymentCurId"/>
This works the same for more complex relationships. If we add a "moneyTransferDetail" DataSource to the sample above which has multiple references to "moneyTransfer" DataSource and would include fields from "currency" and "currencyGroup" DataSources:
<field name="mtId" nativeName="moneyTransferId" type="integer" foreignKey="moneyTransfer.id" relatedTableAlias="main" />
<field name="mainTransferName" includeFrom="moneyTransfer.name" includeVia="mtId" />
<field name="mainSourceSymbol" includeFrom="moneyTransfer.sourceCurrencySymbol" includeVia="mtId" />
<field name="mainSourceGroup" includeFrom="moneyTransfer.sourceCurrencyGroup" includeVia="mtId" />
<field name="mainPaymentSymbol" includeFrom="moneyTransfer.paymentCurrencySymbol" includeVia="mtId" />
<field name="mainPaymentGroup" includeFrom="moneyTransfer.paymentCurrencyGroup" includeVia="mtId" />
<field name="mtPrevId" nativeName="moneyTransferPreviousId" type="integer" foreignKey="moneyTransfer.id" relatedTableAlias="prev" />
<field name="previousTransferName" includeFrom="moneyTransfer.name" includeVia="mtPrevId" />
<field name="previousSourceSymbol" includeFrom="moneyTransfer.sourceCurrencySymbol" includeVia="mtPrevId" />
<field name="previousSourceGroup" includeFrom="moneyTransfer.sourceCurrencyGroup" includeVia="mtPrevId" />
<field name="previousPaymentSymbol" includeFrom="moneyTransfer.paymentCurrencySymbol" includeVia="mtPrevId" />
<field name="previousPaymentGroup" includeFrom="moneyTransfer.paymentCurrencyGroup" includeVia="mtPrevId" />
In this scenario the "currencyGroup" table will be joined 4 times - for all main/prev transfer and payment/source currency combinations. So, aliases will be prefixed with both intermediate
relatedTableAlias values: "main_source_group", "main_payment_group", "prev_source_group", "prev_payment_group".
It is also allowed to specify a series of FK fields in includeVia, for example "moneyTransferDetail" could declare:
<field name="mainSourceCurrencyGroup" includeFrom="moneyTransfer.currency.currencyGroup.groupName" includeVia="mtId.sourceCurId"/>
<field name="mainPaymentCurrencyGroup" includeFrom="moneyTransfer.currency.currencyGroup.groupName" includeVia="mtId.paymentCurId"/>
In this case the prefix used for table aliases will be the same, cause relations referenced in
includeVia are the same as in previous example: "main_source_group" and "main_payment_group".
Note that if related table alias are completely missing then, according to general rule, foreignKey field names will be used in aliases: "mtId_sourceCurId_groupId" and "mtId_paymentCurId_groupId".
Ambiguous includeFrom definitions and logging
Considering the flexibility and complexity of configuring relationships between Datasources, it is important to be aware of certain limitations. Specifically, when multiple fields attempt to include the same field from the same related Datasource via the same (default or specified) foreign key, such configurations are not permitted and may result in unpredictable behavior. This scenario is detected and reported as a warning in the server logs during both DataSource loading and DSRequest execution.
In example below, fields "sourceCurrencySymbol", "currency" and "currencySymbol" include the same "currencySymbol" field from the same "currency" DataSource via the same "currencyId" foreign key field. So, for the fields "currency" and "currencySymbol" warnings will be logged as they include the same value as does the "sourceCurrencySymbol" field.
<field name="currencyId" foreignKey="currency.id"/>
<field name="sourceCurrencySymbol" includeFrom="currency.currencySymbol" />
<field name="currency" includeFrom="currency.currencySymbol" />
<field includeFrom="currency.currencySymbol" />
Additionally there are two server logging categories that may be set to DEBUG level to log details of the entire
includeFrom setup. Specifically
com.isomorphic.sql.SQLDataSource.Alias category enables logging for all fields with
includeFrom, exact direct or indirect include path to the target field, includeVia/aliases used and
com.isomorphic.sql.SQLDataSource.FK category additionally enables logging for the foreign key fields relations are based on.
Extended includeVia syntax
In complex cases involving composite foreign keys or indirect relation chains (multi-step paths across multiple DataSources),
includeVia supports an extended syntax that allows explicit control over how relationships are resolved. See
IncludeViaSyntax for more details.
Default value is null