What you did
A belongs_to relationship is loaded with a separate SQL SELECT when either eager-loaded or used with .include() if toasty::Deferred wrapped in a BEGIN/COMMIT block on at least PostgreSQL.
So querying a single (child) table row via get_by_id() with the parent relationship included is issuing something like this to the database:
BEGIN;
SELECT
tbl_0_0."id" AS column1,
tbl_0_0."parent_id" AS column2,
tbl_0_0."name" AS column3
FROM "child_table" AS tbl_0_0
WHERE tbl_0_0."id" = $1;
SELECT
tbl_0_0."id" AS column1,
tbl_0_0."parent_name" AS column2
FROM "parent_table" AS tbl_0_0
WHERE EXISTS (SELECT $2 AS column1 FROM (VALUES ($1)) AS tbl_1_0 WHERE tbl_1_0.column1 = tbl_0_0."id");
COMMIT;
This doesn't actually guarantee data consistency because the SELECTs happen at a different time. Transactions with the default isolation level does not make the separate SELECTs see the data from the same point of time - if something else updates data (and commits it if using explicit transactions) inbetween the separate SELECT calls issued here database connection roundtrips, then the data will not be consistent. This is very bad in my book.
The correct way to do this is to JOIN (the appropriate type, e.g. LEFT JOIN if the relationship is nullable or that just in case) or some other CTE thing as to do this in a single statement.
What you expected
I expected the ORM to issue a query more like this:
SELECT
tbl_0_0."id" AS column1,
tbl_0_0."parent_id" AS column2,
tbl_0_0."name" AS column3,
tbl_1_0."id" AS column4,
tbl_1_0."parent_name" AS column5
FROM "child_table" AS tbl_0_0
LEFT JOIN "parent_table" AS tbl_1_0
ON tbl_1_0."id" = tbl_0_0."parent_id"
WHERE tbl_0_0."id" = $1;
This is safe in terms of data consistency, so we won't at least have the child and parent models in application logic seen from a different point of time.
What actually happened
No response
Minimal reproducer
Database driver
PostgreSQL
Toasty version
0.9.0
Additional context
No response
What you did
A belongs_to relationship is loaded with a separate SQL SELECT when either eager-loaded or used with
.include()iftoasty::Deferredwrapped in a BEGIN/COMMIT block on at least PostgreSQL.So querying a single (child) table row via get_by_id() with the parent relationship included is issuing something like this to the database:
This doesn't actually guarantee data consistency because the SELECTs happen at a different time. Transactions with the default isolation level does not make the separate SELECTs see the data from the same point of time - if something else updates data (and commits it if using explicit transactions) inbetween the separate SELECT calls issued here database connection roundtrips, then the data will not be consistent. This is very bad in my book.
The correct way to do this is to JOIN (the appropriate type, e.g. LEFT JOIN if the relationship is nullable or that just in case) or some other CTE thing as to do this in a single statement.
What you expected
I expected the ORM to issue a query more like this:
This is safe in terms of data consistency, so we won't at least have the child and parent models in application logic seen from a different point of time.
What actually happened
No response
Minimal reproducer
Database driver
PostgreSQL
Toasty version
0.9.0
Additional context
No response