SectorLabs/django-postgres-extra

Empty savepoint being inserted

snuderl opened this issue · 1 comments

We see an empty save point being inserted if we specfify on_conflict target as relation name and not column name.

See the example bellow, the difference is in the on_conflict parameter. I will provide more details soon, but wanted to flag this as this is a relatively big issue for as as we are trying to get rid of savepoints in the first place and other people might get burned too.

In [4]: with atomic(savepoint=False):
   ...:     Asset.objects.on_conflict(["asset_contract", "token_identifier"], ConflictAction.NOTHING).insert_and_get(asset_contract_id=1, token_identi
   ...: fier="1234568912", collection_id=1, chain_id=1)
SAVEPOINT "s4371727744_x1"

Execution time: 0.004372s [Database: default]
RELEASE SAVEPOINT "s4371727744_x1"

Execution time: 0.001503s [Database: default]
INSERT INTO "api_asset" ("created_date", "modified_date", "hidden", "asset_contract_id", "collection_id", "token_identifier", "image_url", "favorite_count", "favorite_weight", "raw_data", "staleness", "num_sales", "is_curated", "is_delisted", "is_nsfw", "is_frozen", "is_trading_disabled", "rarity_data", "should_scrape_spot_price", "chain_id")
VALUES ('2022-06-24T13:00:23.451374'::timestamp, '2022-06-24T13:00:23.452275'::timestamp, false, 1, 1, '1234568912', '', 0, 0, '{}', 0, 0, false, false, false, false, false, '{}', false, 1)
    ON
CONFLICT ("asset_contract_id", "token_identifier") DO NOTHING RETURNING *

Execution time: 0.002252s [Database: default]

In [5]:                                                                                                                                               

In [5]: with atomic(savepoint=False):
   ...:     Asset.objects.on_conflict(["asset_contract_id", "token_identifier"], ConflictAction.NOTHING).insert_and_get(asset_contract_id=1, token_ide
   ...: ntifier="1234568912", collection_id=1, chain_id=1)
INSERT INTO "api_asset" ("created_date", "modified_date", "hidden", "asset_contract_id", "collection_id", "token_identifier", "image_url", "favorite_count", "favorite_weight", "raw_data", "staleness", "num_sales", "is_curated", "is_delisted", "is_nsfw", "is_frozen", "is_trading_disabled", "rarity_data", "should_scrape_spot_price", "chain_id")
VALUES ('2022-06-24T13:00:42.484742'::timestamp, '2022-06-24T13:00:42.484750'::timestamp, false, 1, 1, '1234568912', '', 0, 0, '{}', 0, 0, false, false, false, false, false, '{}', false, 1)
    ON
CONFLICT ("asset_contract_id","token_identifier") DO NOTHING RETURNING *

Execution time: 0.002528s [Database: default]

I don't think this is from djang-postgres-extra, it doesn't manage transactions anywhere. Have you tried to verify this behaviour by ensuring your atomic block is the most outer one?

with atomic(durable=True, savepoint=False):
  ...