Introspection can't get composite primary key for partitioned table
See original GitHub issueBug description
Hello 👋🏻 I’m trying to add Prisma to existing project and it fails on introspection step. We have partitioned table with composite keys and prisma can’t understand what primary key is in the original table. The fun fact is that it successfully introspected the same primary key for partitions themselves.
*** WARNING ***
The following models were commented out as they do not have a valid unique identifier or id. This is currently not supported by the Prisma Client.
- "blocks"
- "comments"
- "reactions"
Blocks, comments and reactions are tables with partitions
How to reproduce
- Create a partitioned table with composite id. For example here is sql to create our
blocks
table:
-- Table: public.blocks
CREATE TABLE IF NOT EXISTS public.blocks
(
id uuid NOT NULL,
account text COLLATE pg_catalog."default" NOT NULL,
holder_type_id uuid NOT NULL,
holder_entity_id uuid NOT NULL,
block_source_id uuid,
type block_type NOT NULL,
kind block_kind NOT NULL,
created_by uuid NOT NULL,
created_at timestamp without time zone NOT NULL DEFAULT now(),
modified_at timestamp without time zone NOT NULL DEFAULT now(),
rank integer NOT NULL,
link_comment text COLLATE pg_catalog."default",
content jsonb NOT NULL,
is_deleted boolean NOT NULL DEFAULT false,
CONSTRAINT blocks_pkey PRIMARY KEY (account, id),
CONSTRAINT block_source_block_fk FOREIGN KEY (block_source_id, account)
REFERENCES public.blocks (id, account) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE,
CONSTRAINT blocks_account_block_source_id_fkey FOREIGN KEY (block_source_id, account)
REFERENCES public.blocks_p2_0 (id, account) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE,
CONSTRAINT blocks_account_block_source_id_fkey1 FOREIGN KEY (block_source_id, account)
REFERENCES public.blocks_p2_1 (id, account) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE,
) PARTITION BY HASH (account);
ALTER TABLE IF EXISTS public.blocks
OWNER to postgres;
-- Index: entity_blocks_idx
CREATE INDEX IF NOT EXISTS entity_blocks_idx
ON public.blocks USING btree
(account COLLATE pg_catalog."default" ASC NULLS LAST, holder_type_id ASC NULLS LAST, holder_entity_id ASC NULLS LAST)
;
-- Partitions SQL
CREATE TABLE public.blocks_p2_0 PARTITION OF public.blocks
FOR VALUES WITH (modulus 2, remainder 0);
ALTER TABLE IF EXISTS public.blocks_p2_0
OWNER to postgres;
CREATE TABLE public.blocks_p2_1 PARTITION OF public.blocks
FOR VALUES WITH (modulus 2, remainder 1);
ALTER TABLE IF EXISTS public.blocks_p2_1
OWNER to postgres;
- run
npx prisma db pull
Expected behavior
Primary key should be introspected correctly for partitioned table. Now it prevents me from using Prisma completely since I can’t generate a client
Prisma information
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
/// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by the Prisma Client.
model blocks {
id String @db.Uuid
account String
holder_type_id String @db.Uuid
holder_entity_id String @db.Uuid
block_source_id String? @db.Uuid
type block_type
kind block_kind
created_by String @db.Uuid
created_at DateTime @default(now()) @db.Timestamp(6)
modified_at DateTime @default(now()) @db.Timestamp(6)
rank Int
link_comment String?
content Json
is_deleted Boolean @default(false)
blocks blocks? @relation("blocksToblocks_account_block_source_id", fields: [account, block_source_id], references: [account, id], onDelete: Cascade, onUpdate: NoAction, map: "block_source_block_fk")
blocks_p2_0_blocks_account_block_source_idToblocks_p2_0 blocks_p2_0? @relation("blocks_account_block_source_idToblocks_p2_0", fields: [account, block_source_id], references: [account, id], onDelete: Cascade, onUpdate: NoAction)
blocks_p2_1_blocks_account_block_source_idToblocks_p2_1 blocks_p2_1? @relation("blocks_account_block_source_idToblocks_p2_1", fields: [account, block_source_id], references: [account, id], onDelete: Cascade, onUpdate: NoAction, map: "blocks_account_block_source_id_fkey1")
other_blocks blocks[] @relation("blocksToblocks_account_block_source_id")
blocks_p2_0_blocksToblocks_p2_0_account_block_source_id blocks_p2_0[] @relation("blocksToblocks_p2_0_account_block_source_id")
blocks_p2_1_blocksToblocks_p2_1_account_block_source_id blocks_p2_1[] @relation("blocksToblocks_p2_1_account_block_source_id")
@@ignore
}
model blocks_p2_0 {
id String @db.Uuid
account String
holder_type_id String @db.Uuid
holder_entity_id String @db.Uuid
block_source_id String? @db.Uuid
type block_type
kind block_kind
created_by String @db.Uuid
created_at DateTime @default(now()) @db.Timestamp(6)
modified_at DateTime @default(now()) @db.Timestamp(6)
rank Int
link_comment String?
content Json
is_deleted Boolean @default(false)
blocks_blocksToblocks_p2_0_account_block_source_id blocks? @relation("blocksToblocks_p2_0_account_block_source_id", fields: [account, block_source_id], references: [account, id], onDelete: Cascade, onUpdate: NoAction, map: "block_source_block_fk") @ignore
blocks_blocks_account_block_source_idToblocks_p2_0 blocks[] @relation("blocks_account_block_source_idToblocks_p2_0") @ignore
@@id([account, id])
@@index([account, holder_type_id, holder_entity_id])
}
model blocks_p2_1 {
id String @db.Uuid
account String
holder_type_id String @db.Uuid
holder_entity_id String @db.Uuid
block_source_id String? @db.Uuid
type block_type
kind block_kind
created_by String @db.Uuid
created_at DateTime @default(now()) @db.Timestamp(6)
modified_at DateTime @default(now()) @db.Timestamp(6)
rank Int
link_comment String?
content Json
is_deleted Boolean @default(false)
blocks_blocksToblocks_p2_1_account_block_source_id blocks? @relation("blocksToblocks_p2_1_account_block_source_id", fields: [account, block_source_id], references: [account, id], onDelete: Cascade, onUpdate: NoAction, map: "block_source_block_fk") @ignore
blocks_blocks_account_block_source_idToblocks_p2_1 blocks[] @relation("blocks_account_block_source_idToblocks_p2_1") @ignore
comments comments[] @ignore
reactions reactions[] @ignore
@@id([account, id])
@@index([account, holder_type_id, holder_entity_id])
}
enum block_kind {
field
native
link
transclusion
}
enum block_type {
file
view
rich_text @map("rich-text")
}
Environment & setup
- OS: MacOs Monterey 12.0.1
- Database: PostgreSQL 13.3 (Debian 13.3-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
- Node.js version: v16.13.1
Prisma Version
prisma : 3.7.0
@prisma/client : Not found
Current platform : darwin
Query Engine (Node-API) : libquery-engine 8746e055198f517658c08a0c426c7eec87f5a85f (at node_modules/@prisma/engines/libquery_engine-darwin.dylib.node)
Migration Engine : migration-engine-cli 8746e055198f517658c08a0c426c7eec87f5a85f (at node_modules/@prisma/engines/migration-engine-darwin)
Introspection Engine : introspection-core 8746e055198f517658c08a0c426c7eec87f5a85f (at node_modules/@prisma/engines/introspection-engine-darwin)
Format Binary : prisma-fmt 8746e055198f517658c08a0c426c7eec87f5a85f (at node_modules/@prisma/engines/prisma-fmt-darwin)
Default Engines Hash : 8746e055198f517658c08a0c426c7eec87f5a85f
Studio : 0.445.0
Issue Analytics
- State:
- Created 2 years ago
- Comments:10 (3 by maintainers)
Top Results From Across the Web
Primary Key Index not getting picked on Partitioned Table
This table is range partitioned on account_id. There is composite primary key (account_id, b_key) on this table.
Read more >Composite Primary Key on partitioned tables, and Foreign Keys
Create a table with a PRIMARY KEY that references the partition scheme. ... I cannot decide whether to use composite FKs, referencing both ......
Read more >Composite primary key declaration through Convention for ...
I need to use Fluent-nHibernate against a table with a composite primary key (Azure Table, primary keys being ...
Read more >Partition Data to Enable Joins - ksqlDB Documentation
Tables are always partitioned by their PRIMARY KEY , and ksqlDB doesn't allow repartitioning of tables, meaning you can only use a table's...
Read more >Schema design best practices | Cloud Spanner
The following table definition that uses a timestamp-based primary key as the ... The hotspot is created because a single Spanner server will...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
We have adopted prisma in a very large postgres database that syncs integration data and want to partition some tables. I’d be very excited to have a way (even if suboptimal) to achieve partitioning. We already write many manual migrations that cannot be expressed in prisma as it is. I don’t mind doing that for partitions, but the composite key issue is a blocker.
if someone could point me to where the inference of the partitioned table needs to be fixed, I can have a look, but this codebase is very large and I would need some guidance to tackle this, but I can give it a shot