Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to delete Obj1 if Obj2 references it with Action: SetNull #14271

Closed
Tracked by #11441
baconcheese113 opened this issue Jul 13, 2022 · 10 comments
Closed
Tracked by #11441

Unable to delete Obj1 if Obj2 references it with Action: SetNull #14271

baconcheese113 opened this issue Jul 13, 2022 · 10 comments
Labels
bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: broken query topic: referential actions topic: relationMode formerly `referentialIntegrity` topic: relations

Comments

@baconcheese113
Copy link

baconcheese113 commented Jul 13, 2022

Bug description

When using the Action: SetNull referential action for a model relationship the deletion fails and throws an error about violating a foreign key constraint:

Invalid `prisma.hub.delete()` invocation:\n\n\n  Foreign key constraint failed on the field: `BatteryLevel_hubId_fkey (index)`

When I update the set the field with the foreign key to be null ahead of the deletion it works:

await prisma.batteryLevel.updateMany({ where: { hubId: id }, data: { hubId: null } })

How to reproduce

  1. Use the Action: SetNull Cascade option for a model relationship
  2. Create a field of both objects
  3. Try to delete the parent object

Expected behavior

The foreign key field should be set to null and the deletion should succeed

Prisma information

model Hub {
  id                    Int                    @id @default(autoincrement())
  createdAt             DateTime               @default(now())
  updatedAt             DateTime               @default(now()) @updatedAt
  name                  String
  batteryLevels         BatteryLevel[]
}
model BatteryLevel {
  id        Int      @id @default(autoincrement())
  volts     Float
  percent   Float
  hubId     Int?
  hub       Hub?     @relation(fields: [hubId], references: [id], onDelete: SetNull)
  createdAt DateTime @default(now())
}

Environment & setup

  • OS: Windows 10
  • Database: PostgreSQL
  • Node.js version: v16.14.2

Prisma Version

prisma                  : 3.15.2
@prisma/client          : 3.15.2
Current platform        : windows
Query Engine (Node-API) : libquery-engine 461d6a05159055555eb7dfb337c9fb271cbd4d7e (at node_modules\@prisma\engines\query_engine-windows.dll.node)
Migration Engine        : migration-engine-cli 461d6a05159055555eb7dfb337c9fb271cbd4d7e (at node_modules\@prisma\engines\migration-engine-windows.exe)
Introspection Engine    : introspection-core 461d6a05159055555eb7dfb337c9fb271cbd4d7e (at node_modules\@prisma\engines\introspection-engine-windows.exe)
Format Binary           : prisma-fmt 461d6a05159055555eb7dfb337c9fb271cbd4d7e (at node_modules\@prisma\engines\prisma-fmt-windows.exe)
Default Engines Hash    : 461d6a05159055555eb7dfb337c9fb271cbd4d7e
Studio                  : 0.462.0
@baconcheese113 baconcheese113 added the kind/bug A reported bug. label Jul 13, 2022
@pimeys pimeys added topic: broken query topic: relations team/schema Issue for team Schema. team/client Issue for team Client. topic: referential actions topic: relationMode formerly `referentialIntegrity` process/candidate bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Jul 13, 2022
@janpio janpio mentioned this issue Jul 13, 2022
35 tasks
@matthewmueller
Copy link
Contributor

matthewmueller commented Jul 15, 2022

Can you share your full Prisma Schema including datasource and generator? We're wondering what your referentialIntegrity settings are.

@baconcheese113
Copy link
Author

baconcheese113 commented Jul 15, 2022

Pretty minimal, you can see the schema/datasource/generator here and the mutation here

@jkomyno jkomyno self-assigned this Jul 21, 2022
@jkomyno
Copy link
Contributor

jkomyno commented Jul 21, 2022

Hi, could you please try again with Prisma 4.1.0? We tried reproducing this issue, but we observed the proper behavior: deleting 1 hub row results in setting all the related batteryLevel's hubIds to NULL.

Could you also please try running prisma db pull --force? We suspect the onDelete: SetNull might have been added after pushing your schema to the database, hence Postgres might not be aware of it.

@jkomyno jkomyno added bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Jul 21, 2022
jkomyno added a commit that referenced this issue Jul 21, 2022
@baconcheese113
Copy link
Author

Interesting, so when I did prisma db pull --force the schema reflected not having any Cascade option set, yet my BatteryLevel_hubid_fkey is set up as
image

@janpio
Copy link
Member

janpio commented Jul 28, 2022

That is unfortunate. Can you maybe share the CREATE TABLE/DDL for this table via DBeaver? (You should be able to right click the table name in the schema view, and then choose Generate SQL -> DDL)

@baconcheese113
Copy link
Author

-- public."BatteryLevel" definition

-- Drop table

-- DROP TABLE public."BatteryLevel";

CREATE TABLE public."BatteryLevel" (
	id serial4 NOT NULL,
	"hubId" int4 NULL,
	"createdAt" timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
	volts float8 NOT NULL,
	"percent" float8 NOT NULL,
	CONSTRAINT "BatteryLevel_pkey" PRIMARY KEY (id)
);


-- public."BatteryLevel" foreign keys

ALTER TABLE public."BatteryLevel" ADD CONSTRAINT "BatteryLevel_hubId_fkey" FOREIGN KEY ("hubId") REFERENCES public."Hub"(id) ON DELETE SET NULL ON UPDATE CASCADE;

@janpio janpio added bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. process/candidate and removed bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. labels Aug 4, 2022
@janpio janpio removed the team/schema Issue for team Schema. label Aug 4, 2022
@jkomyno
Copy link
Contributor

jkomyno commented Aug 10, 2022

I'm currently re-working on a reproduction of this issue, but the fact that no onUpdate: Cascade is reflected in the schema is expected.
In fact, the default referential action for update rules is Cascade, and Prisma introspection doesn't render default values in the schema.prisma file.

From the docs:

The schema does not explicitly define referential actions on the mandatory author relation field, which means that the default referential actions of Restrict for onDelete and Cascade for onUpdate apply.

@jkomyno
Copy link
Contributor

jkomyno commented Aug 10, 2022

After trying to reproduce this issue with prisma@3.15.2, prisma@4.2.0, Postgres 10, Postgres 14, I confirm that we're not observing any anomalous behavior. May you please share a minimal reproduction like the following so we can follow along?

Schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgres"
  url      = env("DATABASE_URL")
}

model Hub {
  id                    Int                    @id @default(autoincrement())
  name                  String
  batteryLevels         BatteryLevel[]
}

model BatteryLevel {
  id        Int      @id @default(autoincrement())
  hubId     Int?

  // recall that `onUpdate: Cascade` is implicit
  hub       Hub?     @relation(fields: [hubId], references: [id], onDelete: SetNull)
}

Reproduction

// 'hub-1' has batteryLevels with ids in [1, 2]
await prisma.hub.create({
  data: {
    id: 1,
    name: 'hub-1',
    batteryLevels: {
      createMany: {
        data: [
          { id: 1 },
          { id: 2 },
        ]
      }
    }
  },
})

// 'hub-2' has batteryLevels with ids in [3, 4]
await prisma.hub.create({
  data: {
    id: 2,
    name: 'hub-2',
    batteryLevels: {
      createMany: {
        data: [
          { id: 3 },
          { id: 4 },
        ]
      }
    }
  },
})

// we get rid of 'hub-2'
await prisma.hub.delete({ where: { id: 2 } })

const hubs = await prisma.hub.findMany({
  include: { batteryLevels: true },
  orderBy: { id: 'asc' },
})
expect(hubs).toMatchObject([
  id: 1,
  name: 'hub-1',
  batteryLevels: [ { id: 1, hubId: 1 }, { id: 2, hubId: 1 } ],
])

// the batteryLevels that were linked to 'hub-2' have `hubId: null` now
const batteryLevels = await prisma.batteryLevel.findMany({ orderBy: { id: 'asc' } })
expect(batteryLevels).toMatchObject([
  { id: 1, hubId: 1 },
  { id: 2, hubId: 1 },
  { id: 3, hubId: null },
  { id: 4, hubId: null }
])

@jkomyno jkomyno added bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. and removed bug/1-unconfirmed Bug should have enough information for reproduction, but confirmation has not happened yet. labels Aug 10, 2022
@baconcheese113
Copy link
Author

baconcheese113 commented Aug 13, 2022

After upgrading to Prisma 4.2.1 and migrating from Nexus + Nexus-prisma-plugin to Pothos, and Node version 18.7.0 I'm no longer experiencing this issue 👍 Appreciate all the assistance!

@janpio
Copy link
Member

janpio commented Aug 15, 2022

Thanks for the update @baconcheese113. If anyone ever hits this issue again, please let us know via a comment here or open a new one. Thanks!

@janpio janpio closed this as not planned Won't fix, can't repro, duplicate, stale Aug 15, 2022
Jolg42 added a commit that referenced this issue Oct 13, 2022
…tabases (#14221)

* test(client): prototype referential integrity tests

Related: #10806

Test Suites: 1 failed, 1 total
Tests:       3 failed, 45 passed, 48 total
Snapshots:   0 total
Time:        9.838 s

* exclude mongodb to see if types tests fail like locally

* wip rewrite with Alberto

* chore: update tests

* chore: used .rejects.toThrowError

* chore: started adding ref actions

* chore: mongodb only supports 'referentialIntegrity: prisma'

* chore: added support for conditional error messages

* wip

reorg with describe
revert matrix and schema changes
beforeEach check and create users with profiles

* fix referentialIntegrityLine

* add skeleton for 1:n and m:n tests

* chore: highlighted some test errors with mongodb

* chore: added create tests for 1:n relationship

* chore: added TODO comment

* WIP m:n for SQL databases

* ci: try running github actions matrix with our tests only

* ci: remove needs: detect_jobs_to_run

* ci: fix os matrix

* ci: small CI env var tweak

* ci: fix bash line

* chore: added some update/delete tests for 1:n

* chore: added comments to _matrix.ts

* postgresql m:n all referential actions

* merge main

* DEFAULT, exclude Restrict from SQL Server, fix tests

* add mongodb tests for m:n

* chore: added some additional ref actions, added support for SQL Server

* chore: fixed bug with DEFAULT not tested, added upsert test, fixed some conditional errors, found panic on SQLServer with SetDefault

* reuse sql schema for mongodb 1:1 1:n

* 1:1 test all referral actions for onDelete & clean

* chore: improved ref actions, fixed failing tests

* chore: reproduced issue #14271

* chore: split relationships in separate files

* split m:n mongodb tests into its own file

* add `enabled Boolean?` on 1-to-n

It's a reproduction of #13766

* m:n add comments where RI=prisma - Cascade resolves instead of failing in update and create

* add `published   Boolean?` to MongoDB and update tests

* 1:1 add `enabled Boolean?` and MongoDB update tests

* add `published   Boolean?` to m:n with update tests

* chore: updated sql server tests

* add comments to m:n

[skip ci]

* add a mongodb test for immutable _id

* full database matrix for CI

* split schemas into simple files

* m to n MongoDB: change tests to match current implementation expectations

* chore: add JSON support to getTestSuiteFullName

* chore: moved ref integrity utils to its own folder. Added builder pattern to conditional error. Added matrix generation. Extracted self-contained utilities out of _schema.ts file.

* chore: added sqlite support and referentialIntegrity=prisma snapshots to 1:1 and 1:n relations

* chore: pnpm-lock

* chore: removed temp folder that wasn't supposed to be committed

* chore: imported right 'checkIfEmpty' util for m:n relation

* clean and add sqlite on m to n

* m to n add RI=Prisma messages as comments + small edits

add expectation even for `toThrowError()` cases

* m:n: split 1 test for prisma/foreignKeys

* chore: added prisma snapshots and errors as comments in m:n relation (no MongoDB yet)

* chore: added mongodb and comments to _matrix

* fix: moved _referential-integrity-utils to _utils/referential-integrity to support  ERR_PNPM_NO_SCRIPT  Missing script: test:functional-code command

* update matrix for MongoDB: add SetNull

* chore: added comments to m:n

* m to n: small edits for RI=prisma

* test 1:1 / 1:n add expects for expected throws and fix some RI=prisma messages

* chore: prettier

* 1:1 handle error messages depending on RI=prisma/foreignKeys

* * simplify conditionals

* m to n: change expectations to match current state

* chore: comment skipped test

* sqlite: skip createMany in 1:n relations

* chore: added missing sqlite snapshots to 1:n relation

* 1:n add missing delete action variants

* 1:n simplify and handle expected RI=prisma tests that should succeed

* chore: added reproduction of issue #10000

* chore: updated reproduction of issue #10000

* chore: reproduce issue #12378

* 1:1 separate onUpdate: Restrict, NoAction

* 1:1 fix create test from should throw to should succeed

* ci: separate action test for each relation / file

* ci: continue-on-error: true

* fix: referential actions test params

* fix ts checks

* only run pnpm run test:functional:code filename

* fix Cannot destructure property 'onDelete' of 'suiteConfig.referentialActions' as it is undefined.

* chore: added reproduction of issue #12557

* chore: add assertions to nested child connect in 1:1

* chore: clean unused code and better describe title

* test: add test about NO ACTION behavior with DEFERRABLE constraint

* manually bump engines

* chore: rename referentialIntegrity datasource property to relationMode

* fix github actions

* fix test about 14759 and RELATION_MODE env var

* cleanup some reproduce-x test cases

* add sqlite error snapshot

* remove continue-on-error

* remove outdated comments

* ci: remove last continue-on-error: true

* test: add `SetNull` to the matrix only for relationMode=prisma

* ci: add continue-on-error: true to run all tests

* fix snapshot with lowerace table name and run SQL Server

* exclude SQL Server / SetNull when relationMode !== prisma

* fix computeMatrix for SQL Server Restrict emulation which is not implemented

* change failing tests (issue 15683) to use .failing

* fix SQL Server test

* test(reproductions): fix empty test name

* fix relationMode = prisma SQL Server error snapshot

* fix relationMode = prisma SQL Server error snapshot

* fix relationMode = prisma SQL Server error snapshot

* comment vitess docker image (unused) and put back timeout to 60s

* test: fix snapshots for field-reference

* test: fix snapshot and getTestSuiteParametersString

* ignore expected type errors

* add note about SetNull is not run for foreignKeys in the test suite

* test: tweak comment and fix 1:1 test snapshots

* Unused '@ts-expect-error' directive.

* add `--relation-mode-tests-only` to unblock merge

* test: skip NoAction for PostgreSQL and SQLite

Related prisma/prisma-engines#3274

* fix relationMode value

* fix test name + comments

* cleanup matrix and move reproduce tests to issues directory

* add test for referentialIntegrity="prisma"

Closes #15736

* cleanup comments and misleading `toThrowError()` for expected to fail tests

* chore: removed useless comment

* chore: removed useless comments

* fix imports for moved tests in issues directory

Co-authored-by: jkomyno <skiabo97@gmail.com>
Co-authored-by: Alberto Schiabel <jkomyno@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug/0-unknown Bug is new, does not have information for reproduction or reproduction could not be confirmed. kind/bug A reported bug. team/client Issue for team Client. topic: broken query topic: referential actions topic: relationMode formerly `referentialIntegrity` topic: relations
Projects
None yet
Development

No branches or pull requests

5 participants