SelectBuilder makes assumptions about join conditions being "trivial" #995
Labels
in: selectbuilder
SelectBuilder stands for the complete API for creating SQL statements programmatically.
type: enhancement
A general enhancement
Milestone
Hi,
Like with #968, I have a case where I want to delegate the SELECT query generation to Spring to leverage Spring's support for different dialects (giving me support for different databases "out of the box"). Unfortunately, I am faced with a non-trivial join where I need to go beyond Spring's current assumptions for how JOIN works.
My two key issues:
selectBuilder.join(...)
), the parameter is assumed to be aTable
(possible via String which is immediately passed toTable.create
). However, SQL supports joining on a "subselect" (LEFT OUTER JOIN (SELECT ... ) AS alias ON alias.X = other_table.Y
). This is now tracked in Add support for join with subselect #1003x.A = y.B [AND z.C = Y.D ...]
formatted conditions. However, other formats can be used - such asOR
'ing conditions. This is tracked as this issue.The concrete example
The example I am working on is a bit complex, but I have attempted to reduce it to these model classes:
What I want to do is to generate an SQL query that maps up a
TransportLocationTO
from a single SELECT statement. TheVehicle
entity comes via theTransport
entity on eitherpickupLocationId
ordeliveryLocationId
. Some additional context:The
TransportLocation
can be on "either side" of theTransport
. Often it will appear in thepickupLocationId
of one Transport anddeliveryLocationId
of another. This happens if theTransportLocation
is a "middle stops" in the route.id
of theTransportLocation
depends implicit on theVehicle
due to business rules (that are not reflected in this example) - but SQL-wise the link between the two goes viaTransport
. This is why it is "fine" in this case for the JOIN to use anOR
(with a DISTINCT). But on the flip side, if I only use one of them then the join will fail for either very first or the very lastTransportLocation
.The API has
TransportLocationTO
has a "primary entity" - as in "GET /transport-locations" + "GET /transport-locations/{ID}" are defined endpoints and they want to include theVehicle
entity.I will be passing the generated SQL to Spring R2DBC's
DatabaseClient
in case that bit will matter (I do not think it will, but mentioning it for completeness).Version used
In case it matters, I am currently using:
I am not entirely sure which version of spring-data-jdbc + spring-r2dbc that implies.
Solutions / work arounds
As far as I have gathered, the "optimal" solution is to use JOIN + sub-select as this avoids the need for DISTINCT, but this is not possible at all.
An alternative in my case is to use the
JOIN ... ON A=B OR A=C
+ DISTINCT. I will test whether the code accepts the variant ofJOIN ... ON (A=B OR A=C) = TRUE
, which is at best a rewrite of questionable readability and at worst might neuter some database/query planner optimizations.Sadly changing the datamodel is not an option for me (political decision that I cannot change).
The text was updated successfully, but these errors were encountered: