TupleIn lookup uses tuple containment even if the supports_tuple_lookups feature is disabled for right-hand-side subqueries
Refer to this support request from the SQL Server third-party backends maintainers.
The problem can be triggered directly when doing filter(pk__in=queryset)
or indirectly when doing updates that involve related tables as we've not implemented UPDATE FROM
yet and it is simulated by doing UPDATE table SET ... WHERE (pk_field0, ..., pk_fieldn) IN (SELECT ... FROM other_table)
.
The latter can be observed in the SQL generated by the composite_pk.test_update.CompositePKUpdateTests.test_update_token_by_tenant_name
even when supports_tuple_lookups
is off
UPDATE "composite_pk_token"
SET "secret" = 'bar'
WHERE ("composite_pk_token"."tenant_id",
"composite_pk_token"."id") IN
(SELECT U0."tenant_id",
U0."id"
FROM "composite_pk_token" U0
INNER JOIN "composite_pk_tenant" U1 ON (U0."tenant_id" = U1."id")
WHERE U1."name" = 'A')
Which can be emulated by using EXISTS
instead
UPDATE "composite_pk_token"
SET "secret" = 'bar'
WHERE EXISTS
(SELECT 1 AS "a"
FROM "composite_pk_token" U0
INNER JOIN "composite_pk_tenant" U1 ON (U0."tenant_id" = U1."id")
WHERE (U1."name" = 'A'
AND "composite_pk_token"."tenant_id" = (U0."tenant_id")
AND "composite_pk_token"."id" = (U0."id"))
LIMIT 1)
Note that we didn't run into issues before because even if we have test coverage for this case the sole backend we test against that has supports_tuple_lookups
disabled (Oracle < 23.4) happens to support tuple comparisons for subqueries. It feels like it should nonetheless be solved in Django itself.
Change History
(14)
Triage Stage: |
Unreviewed → Accepted
|
Cc: |
composite primary key added
|
Summary: |
TupleIn lookup uses tuple comparision even if the supports_tuple_lookups feature is disable for right-hand-side subqueries → TupleIn lookup uses tuple containment even if the supports_tuple_lookups feature is disabled for right-hand-side subqueries
|
Cc: |
composite primary key removed
|
Keywords: |
composite primary key added
|
Keywords: |
composite, primary, key → composite primary key
|
Needs tests: |
unset
|
Triage Stage: |
Accepted → Ready for checkin
|
Patch needs improvement: |
set
|
Triage Stage: |
Ready for checkin → Accepted
|
Patch needs improvement: |
unset
|
Triage Stage: |
Accepted → Ready for checkin
|
Resolution: |
→ fixed
|
Status: |
assigned → closed
|
Keywords: |
CompositePrimaryKey added; composite primary key removed
|
I'm assuming we'll want some sort of low-level test against the compiled SQL when the feature flag is false as modeled in the report.