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.
Default value is null