Opened 6 years ago
Closed 6 years ago
#30883 closed Bug (invalid)
select_for_update doesn't include submodels in PostgreSQL
| Reported by: | Abhijeet Viswa | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 2.2 |
| Severity: | Normal | Keywords: | psql, select_for_update, transactions |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Consider the following line of code:
order = Order.objects.filter(uuid=order_uuid).prefetch_related(
Prefetch(
lookup='items',
queryset=items
)
).select_related('outlet').select_related('user').select_related('outlet__group') \
.select_for_update(of=('self', 'outlet'))
Here, outlet is a relation defined as:
outlet = models.ForeignKey(Outlet, on_delete=models.PROTECT, related_name="orders")
Here the Order and Outlet models are sub-models to Transaction and Shop models respectively (which are situated in another Django app)
The former models reside in an app called cashless while the latter reside in payment_gateway.
I logged the PSQL output and this is the resultant query for the above line of code:
SELECT
"payment_gateway_transaction"."uuid",
"payment_gateway_transaction"."ref_number",
"payment_gateway_transaction"."shop_id",
"payment_gateway_transaction"."user_id",
"payment_gateway_transaction"."timestamp",
"payment_gateway_transaction"."amount",
"payment_gateway_transaction"."payment_method",
"payment_gateway_transaction"."transaction_status",
"payment_gateway_transaction"."service",
"cashless_order"."transaction_ptr_id", "cashless_order"."token",
"cashless_order"."outlet_id", "cashless_order"."order_status",
"cashless_order"."order_start_time", "cashless_order"."order_end_time",
"cashless_order"."order_collect_time", "cashless_order"."order_review",
"cashless_order"."order_ratings", "authentication_user"."id",
"authentication_user"."password", "authentication_user"."last_login",
"authentication_user"."is_superuser", "authentication_user"."email",
"authentication_user"."student_id", "authentication_user"."first_name",
"authentication_user"."last_name", "authentication_user"."date_joined",
"authentication_user"."ip_address", "authentication_user"."mac_address",
"authentication_user"."location", "authentication_user"."phone_number",
"authentication_user"."total_spent", "authentication_user"."is_banned",
"authentication_user"."needs_student_id",
"authentication_user"."generated_at", "authentication_user"."verify_token",
"authentication_user"."is_active", "payment_gateway_shop"."uuid",
"payment_gateway_shop"."name", "payment_gateway_shop"."location_id",
"payment_gateway_shop"."location_coords",
"payment_gateway_shop"."tax_applicable",
"payment_gateway_shop"."percentage_tax",
"payment_gateway_shop"."gst_number", "payment_gateway_shop"."open",
"payment_gateway_shop"."active", "payment_gateway_shop"."group_id",
"cashless_outlet"."shop_ptr_id", "cashless_outlet"."start_time",
"cashless_outlet"."end_time", "cashless_outlet"."break_start_time",
"cashless_outlet"."break_end_time", "cashless_outlet"."items_limit",
"cashless_outlet"."image", "cashless_outlet"."description",
"cashless_outlet"."on_cashless", "cashless_outlet"."ratings",
"cashless_outlet"."latest_token", "auth_group"."id", "auth_group"."name"
FROM "cashless_order"
INNER JOIN "payment_gateway_transaction" ON ("cashless_order"."transaction_ptr_id" = "payment_gateway_transaction"."uuid")
INNER JOIN "authentication_user" ON ("payment_gateway_transaction"."user_id" = "authentication_user"."id")
INNER JOIN "cashless_outlet" ON ("cashless_order"."outlet_id" = "cashless_outlet"."shop_ptr_id")
INNER JOIN "payment_gateway_shop" ON ("cashless_outlet"."shop_ptr_id" = "payment_gateway_shop"."uuid")
INNER JOIN "auth_group" ON ("payment_gateway_shop"."group_id" = "auth_group"."id")
WHERE "cashless_order"."transaction_ptr_id" = '6e413b2e8f07-4452-8cd2-5bc186e7ffcb'::uuid
FOR UPDATE OF "payment_gateway_transaction", "payment_gateway_shop"
As seen from the SQL query, only the rows of tables payment_gateway_transaction and payment_gateway_model (Transaction and Shop models respectively) are being locked for update. This is despite the fact that the original Queryset references Order (a submodel of Transaction).
Since the of parameter provides no way of specifying the Models/tables that we would want to lock, there is no way around this problem.