Foreign Key Constraint Failed on Index Field Prisma Delete - postgresql

I'm getting an error when I'm trying to delete all items from a table using postgres + prisma
I have the following schema:
model Profile {
id String #id #default(cuid())
projects Project[]
}
model Project {
id String #id #default(cuid())
profile Profile #relation(fields: [profile_email], references: [email], onDelete: NoAction)
profile_email String
}
Here's the code with the client:
const { PrismaClient } = require("#prisma/client");
const prisma = new PrismaClient();
(async () => {
await prisma.profile.deleteMany({});
await prisma.project.deleteMany({});
})();
The error I get is this -
Invalid `prisma.profile.deleteMany()` invocation in
clear.js:6:24
3 const prisma = new PrismaClient();
4
5 (async () => {
→ 6 await prisma.profile.deleteMany(
Foreign key constraint failed on the field: `Project_profile_email_fkey (index)`
How can we solve this? Thanks in advance.

When you try to delete a profile, there might be projects with a foreign key that references a profile. Because of this relation, you will get an error when trying to delete a profile. You can use referential actions. In your case, replace "OnDelete: NoAction with OnDelete: Cascade" inside the relation field in the Project model. (EDIT: Make sure to update your database as well with the new constraint)
You can read more about it here:
Referential actions | Prisma docs

You use "profile" and "project", instead use "Profile" and "Project" with first letter uppercase, or use ##map for change the name of your model. (The models are crated with same name from model or the name you set in ##map)
https://www.prisma.io/docs/concepts/components/prisma-schema/data-model#introspection-and-migration

Related

Prisma, how to preserve foreign data?

It's been a few months since I started prisma and I'm still confused.
In a normal database, foreign key data also exists in table data. However, according to the prisma document, in prisma, the data does not exist at the database level.
So where is it stored? It seems that the things I do "connect:id:1" are stored in the Prisma client. If I delete the prisma dependency and install it again with npm install, will all these relational data be deleted too?? How can I make it as safe as possible????
And it seems too dangerous when I migrate later. what am I misunderstanding?
ADDED
const user = await prisma.user.create({
data: {
email: 'vlad#prisma.io',
posts: {
connect: [{ id: 8 }, { id: 9 }, { id: 10 }],
},
},
include: {
posts: true, // Include all posts in the returned object
},
})
in this case, id 8, id 9, id 10, Where are all these stored? Is there any way to check other than prisma studio or select query? I don't know where it is physically stored. It's not even in the planet scale database.
// In the workbench, the foriegn key is actually saved and can be exported. I don't know how it's not at the database level, but where it is referenced and stored.
Considering this Schema:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int #id #default(autoincrement())
name String
email String #unique
posts Post[]
}
model Post {
id Int #id #default(autoincrement())
title String
published Boolean #default(true)
author User #relation(fields: [authorId], references: [id])
authorId Int
}
There is a one-to-many relationship between User and Posts.
according to the prisma document, in prisma, the data does not exist
at the database level.
Only the relation fields do not exist at the database level, so in this case posts in User model and author in Post model would not exist at database level. But the foreign key exists at the database level, so in this case authorId is actually stored in the database.
Based on the create query you have shared:
in this case, id 8, id 9, id 10, Where are all these stored?
The connect statement in create query is essentially linking the records.
So to elaborate Posts with id 8,9,10 would have the authorId value of the new user record which is created.
So the data is stored in database, you can always check which posts are created by a specific author. You just need to query all the posts which has authorId set to the id which you are querying for.

I can't manually add foreign keys in golang gorm

I am trying to add a foreign key manually in gorm but i get this error
db.Model(&models.Business{}).AddForeignKey undefined (type *gorm.DB has no field or method AddForeignKey)
am using postgres
i have tried
db.Model(&Business{}).AddForeignKey("cust_id", "customers(cust_id)", "CASCADE", "CASCADE")
you can do it with two solution that i know in GORM
#1
when you create model you do it like below:
type Business struct {
Name string
CustomersID int
Customers Customers `gorm:"foreignKey:CustomersID"` // use CustomersID as foreign key
}
type Customers struct {
ID int
Name string
}
#2
every time you want you can add foreign key like below
Client.Exec("ALTER TABLE business ADD FOREIGN KEY (cust_id)" +
"REFERENCES customers (id) ON DELETE CASCADE ON UPDATE CASCADE;")

knex.js migrations create tables with relationship between each other fails

I've looked all over the place, there are quite a few examples, but nothing complete or working.
Use case:
Simple database structure, a few tables and some relationships. Set up node, knex and pg - in a docker container.
All works well.
Created the migration file for the first table (table A) - ok.
Added the second table (table B) and a 1:n relationship from table B to A. All good.
Added a 1:n relationship from table A to table B. And the script errored out.
table info:
exports.up = function(knex) {
return knex.schema
.createTable('user', t => {
t.uuid('user_id').primary()
t.string('name', 100).notNullable()
t.string('surname', 100)
t.string('email').notNullable().unique()
t.string('password')
t
.boolean('email_confirmed')
.notNullable()
.defaultTo(false)
t
.datetime('last_login', { precision: 6 })
.defaultTo(knex.fn.now(6))
t.string('language')
t.string('newsletter')
t.timestamps(true, true)
t
.uuid('company_id')
.references('company_id')
.inTable('company')
})
.createTable('company', t => {
t.uuid('company_id').primary()
t.string('address_id')
t.string('name', 100).notNullable()
t.string('phone')
t.timestamps(true, true)
t
.uuid('owner_user_id')
.references('user_id')
.inTable('user')
})
}
error:
migration failed with error: alter table "user" add constraint
"user_company_uuid_foreign" foreign key ("company_uuid") references
"company" ("company_id") - relation "company" does not exist
I'd say it tries to create a table and add the foreign key before creating the second table (which the FK references).
Any idea on how to solve this.
it is not a m:n relationship really. A company can and should only have 1 owner. A user has to belong to a company, otherwise it can't exist. If this is not solvable I can have the user.company_id field as a simple string w/o any relationship.
Having a different table for user_companies would be overkill.
Thanks!
You are correct that it is trying to create the reference before the table it is referencing exists. The easiest way would probably be to simply delay the creation of the foreign key until after the companies table has been created. i.e.
exports.up = async function(knex) {
await knex.schema.createTable('user', t => {
t.uuid('user_id').primary()
t.string('name', 100).notNullable()
t.string('surname', 100)
t.string('email').notNullable().unique()
t.string('password')
t.boolean('email_confirmed')
.notNullable()
.defaultTo(false)
t.datetime('last_login', { precision: 6 })
.defaultTo(knex.fn.now(6))
t.string('language')
t.string('newsletter')
t.timestamps(true, true)
t.uuid('company_id')
});
await knex.schema.createTable('company', t => {
t.uuid('company_id').primary()
t.string('address_id')
t.string('name', 100).notNullable()
t.string('phone')
t.timestamps(true, true)
t.uuid('owner_user_id')
.references('user_id')
.inTable('user')
});
await knex.schema.table('user', t => {
t.foreign('company_id')
.references('company_id')
.inTable('company')
});
}

After upgrading to Prisma2 should Psima1 still be able to create relation in nested create?

I'm attempting to upgrade Prisma from 1 to 2, opting to run prisma1 (1.34.12) along-side Prisma2 (3.4.1)
My problem is that after upgrading the MySQL DB and schema, my prisma1 queries are failing when trying to create nested creates in relation tables.
Example (paraphrased) Prisma2 schema:
model User {
id String #id #default(cuid()) #db.Char(30)
email String #db.MediumText
admin Admin?
}
model Admin {
id String #id #default(cuid()) #db.Char(30)
name String #db.MediumText
userId String #db.Char(30)
user User #relation(fields: [userId], references: [id], onUpdate: Restrict)
}
Example (paraphrased) Prisma1 query:
mutation ($data: UserCreateInput!) {
createuser(data: $data) {
id
email
}
}
variables
{
"data" {
"email": "diety#supremebeing.org"
"admin": {
"create": {
"name": "me"
}
}
}
}
The (paraphrased) error I get:
(conn=3216) Field 'userId' doesn't have a default value
This section of the schema-incompatibilities prisma-upgrade doc seems to indicate that, after updating the schema and MySQL DB via the directions in the work-around, prisma1 should stick the userId into that Admin table based on the foreign key constraint, shouldn't it?
https://www.prisma.io/docs/guides/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgres#all-non-inline-relations-are-recognized-as-m-n
How might I get my prisma1 queries/mutations to play in the Prisma2-upgraded DB?
Thank you!

Invalid `prisma.mytable.create()` invocation: Foreign key constraint failed on the field: `(not available)` when using cockroachdb

I'm attempting to use Prisma with Cockroachdb locally. I understand that official support for CockroachDB is in the works.
I have a parallel local PostgreSQL database where everything is working correctly and I am able to generate Prisma migrations to run manually against Cockroachdb. All of this works and I end up with two apparently identical schemas.
However, any create operation in Prisma using the connect feature is failing with the following error:
Invalid `prisma.mylinkedtable.create()` invocation:
Foreign key constraint failed on the field: `(not available)`
Here are key parts of my schema.prisma:
datasource db {
provider = "postgresql"
url = "postgresql://user:pass#localhost:26257/mydb"
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["cockroachdb"]
}
model MyLinkedEntity {
id Int #id #default(autoincrement())
myEntity MyEntity #relation(fields: [myEntityId], references: [id])
myEntityId Int
// ...
}
model MyEntity {
id Int #id #default(autoincrement())
// ...
}
The code that is triggering the foreign key constraint:
const entity = await prisma.myEntity.findFirst({})
await prisma.myLinkedEntity.create({
data: {
myEntityId: entity.id,
// ...
}
}
If I go about it slightly diffently and try to link using the connect feature:
await prisma.myLinkedEntity.create({
data: {
myEntity: {
connect: {
id: entity.id
}
},
// ...
}
}
I get a different error:
Invalid `prisma.myLinkedEntity.create()` invocation:
An operation failed because it depends on one or more records that were required but not found. No 'MyEntity' record(s) (needed to inline the relation on 'MyLinkedEntity' record(s)) was found for a nested connect on one-to-many relation 'MyEntityToMyLinkedEntity'.
What gives?
It looks like the related rows are not being created first.
Could you try using connectOrCreate instead? https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#connect-or-create-a-record
It could also be something wrong with the Prisma model. I'm not not sure if order matters, but I notice you have the relation defined before the ID it's referencing.
One final, unrelated, point: you should not use auto incrementing ints as keys in CockroachDB. See https://www.cockroachlabs.com/docs/v21.2/schema-design-table#primary-key-best-practices