drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
24.16k stars 617 forks source link

[BUG]: Drizzkle kit generate wrong SQL for Postgres enum arrays and double precision array. #1680

Open Hebilicious opened 10 months ago

Hebilicious commented 10 months ago

What version of drizzle-orm are you using?

0.29.1

What version of drizzle-kit are you using?

0.20.7

Describe the Bug

Hello there, just finished migrating a big~ish project from prisma to drizzle (prisma.schema was 800lines) and I encountered this bug :

error: type "notificationtype[]" does not exist
 code: "42704"
error: type "double precision[]" does not exist
 code: "42704"

SQL line generated :

"disabledNotificationTypes" NotificationType[],
ALTER TABLE "VidStat" ADD COLUMN "watchHours" "double precision"[];

correct line

"disabledNotificationTypes" "NotificationType"[],
ALTER TABLE "VidStat" ADD COLUMN "watchHours" double precision[];

Manually editing the quotes in the sql file works.

I tried to generate them in isolation and got the same result :

ALTER TABLE "UserNotificationSetting" ADD COLUMN "disabledNotificationTypes" NotificationType[];--> statement-breakpoint
ALTER TABLE "UserNotificationSetting" ADD COLUMN "disabledEmailTypes" EmailTypes[];--> statement-breakpoint
ALTER TABLE "VidStat" ADD COLUMN "watchHours" "double precision"[];

For reference this is the TS code :

export const notificationType = pgEnum('NotificationType', ["foo", "bar"]);

const somethingLikeThis = {
    disabledNotificationTypes: notificationType('disabledNotificationTypes').array(),
    watchHours: doublePrecision('watchHours').array(),
}

Expected behavior

I expect the SQL to be generated correctly.

Environment & setup

node --version v20.5.0 macos

Hebilicious commented 10 months ago

@Angelelz Investigating this a little I think it might be because of the fact that I'm using camelCase / pascalCase and drizzle incorrectly quote things in this scenario.

Angelelz commented 10 months ago

Can you show what the statement that got generated by the pgEnum?

Hebilicious commented 10 months ago

Can you show what the statement that got generated by the pgEnum?

--> statement-breakpoint
DO $$ BEGIN
 CREATE TYPE "EmailTypes" AS ENUM('WEEKLY_DIGEST', 'IMPORTANT_UPDATES', 'PROMOTIONS_DISCOUNTS_OFFERS', 'FEEDBACK_SURVEY', 'SUBSCRIPTION_UPDATES');
EXCEPTION
 WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
 CREATE TYPE "NotificationType" AS ENUM('NEW_COURSE', 'NEW_INSTRUCTOR_ANNOUNCEMENTS', 'COMMUNITY_ENGAGEMENT', 'ACHIEVEMENT_CELEBRATIONS');
EXCEPTION
 WHEN duplicate_object THEN null;
END $$;

These 2 statements.

risen228 commented 9 months ago

I also encountered this. Maybe this issue should be created in the drizzle-kit-mirror repository? It would be great if the problem was resolved soon, I really don't want to change name case everywhere =(

Hebilicious commented 9 months ago

I also encountered this. Maybe this issue should be created in the drizzle-kit-mirror repository? It would be great if the problem was resolved soon, I really don't want to change name case everywhere =(

As a workaround you can fix the generated migration manually. Only need to be done once.

dalechyn commented 9 months ago

Also hit this, yet not with double precision array, but with a enum of strings.

SiNONiMiTY commented 8 months ago

I am hitting this issue with an enum of strings

pnpm drizzle-kit -v
drizzle-kit: v0.20.14
drizzle-orm: v0.29.4
gunhaxxor commented 5 months ago

Also stumbled upon this issue with doublePrecison('columnName').array() generating the following sql "columnName" "double precision[]", In my case i can simply use real instead of doublePrecision as a workaround.

jperezr21 commented 5 months ago

Same issue here: doublePrecision("embedding").array() gets converted to "embedding" "double precision[]" which fails with the following error:

error: type "double precision[]" does not exist

Can't use real for embeddings, since the precision is needed.

jperezr21 commented 5 months ago

Solved the issue by implementing a float8 column builder:

float8-pg-column-builder.ts ```typescript import type { ColumnBaseConfig, ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig, } from "drizzle-orm"; import { PgColumn, PgColumnBuilder, type AnyPgTable, } from "drizzle-orm/pg-core"; export type PgFloat8BuilderInitial = PgFloat8Builder<{ name: TName; dataType: "number"; columnType: "PgFloat8"; data: number; driverParam: string | number; enumValues: undefined; }>; const entityKind: unique symbol = Symbol("entityKind"); export class PgFloat8Builder< T extends ColumnBuilderBaseConfig<"number", "PgFloat8">, > extends PgColumnBuilder { static readonly [entityKind]: string = "PgFloat8Builder"; constructor(name: T["name"]) { super(name, "number", "PgFloat8"); } /** @internal */ build( table: AnyPgTable<{ name: TTableName }>, ): PgFloat8> { return new PgFloat8>( table, this.config as ColumnBuilderRuntimeConfig, // eslint-disable-line ); } } export class PgFloat8< T extends ColumnBaseConfig<"number", "PgFloat8">, > extends PgColumn { static readonly [entityKind]: string = "PgFloat8"; getSQLType(): string { return "float8"; } override mapFromDriverValue(value: string | number): number { if (typeof value === "string") { return Number.parseFloat(value); } return value; } } export function float8( name: TName, ): PgFloat8BuilderInitial { return new PgFloat8Builder(name); } ```