drizzle-team / drizzle-kit-mirror

Docs and issues repository for drizzle-kit
289 stars 17 forks source link

Instrospect misses to wrap database default values in sql #232

Open subzero79 opened 11 months ago

subzero79 commented 11 months ago

Hi there,

I use hasura for managing my db schema handling the migrations using their cli tooling. Then i've been playing around in a pet project using kisely and genql for db queries.

I decided to give drizzle a try by pulling the existing schema from the db, I just noticed that when it comes to default values of columns that could be text, or postgres function(like gen_random_uuid()) these are not parsed correctly into the typescript schema file. Below is a sample of the schema output.

In the default function there are postgres functions that should not be put in javascript as normal functions, as i understand they should be wrapped like

sql`gen_random_uuid())`

from what i've seen in the docs.

The drizzle-kit version is 0.20.1

import { pgTable, pgSchema, text, boolean, foreignKey, unique, uuid, bigint, timestamp, integer } from "drizzle-orm/pg-core"

import { sql } from "drizzle-orm"

export const auth = pgSchema("auth");

export const user = auth.table("User", {
    id: text("id").primaryKey().notNull(),
    email: text("email"),
    emailVerified: boolean("email_verified").default(false),
    username: text("username"),
    image: text("image"),
});

export const key = auth.table("Key", {
    id: text("id").default(gen_random_uuid()).primaryKey().notNull(),
    userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade", onUpdate: "restrict" } ),
    hashedPassword: text("hashed_password"),
});

export const verificationCode = auth.table("VerificationCode", {
    id: uuid("id").defaultRandom().primaryKey().notNull(),
    userId: text("user_id").notNull(),
    code: text("code").notNull(),
    // You can use { mode: "bigint" } if numbers are exceeding js number limitations
    expires: bigint("expires", { mode: "number" }).notNull(),
},
(table) => {
    return {
        verificationCodeUserIdKey: unique("VerificationCode_user_id_key").on(table.userId),
    }
});

export const competition = pgTable("Competition", {
    id: text("id").default(ksuid_pgcrypto('comp_'::text)).primaryKey().notNull(),
    name: text("name").notNull(),
    createdAt: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
    updatedAt: timestamp("updated_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(),
    level: integer("level").default(100),
    slug: text("slug").notNull(),
    orgId: text("orgId").references(() => organization.id, { onDelete: "cascade", onUpdate: "restrict" } ),
});

image

pfurini commented 8 months ago

Same here.. just introspected a basic PG schema with default timestamp values, and the result is:

createdAt: timestamp("created_at", { withTimezone: true, mode: 'string' }).default(timezone('utc'::text, now())).notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true, mode: 'string' }).default(timezone('utc'::text, now())).notNull(),

instead of

createdAt: timestamp("created_at", { withTimezone: true, mode: 'string' }).default(sql`timezone('utc'::text, now())`).notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true, mode: 'string' }).default(sql`timezone('utc'::text, now())`).notNull(),

plus relations are not scripted in the schema file (see #83 ). My feeling around Drizzle so far is aligned to my general feeling towards ORMs... better avoiding them. SQL generators, maybe. But I want to finish the first beta of my product before a final judgement, let's see how it goes.

arxpoetica commented 5 months ago

Sames:

export const gateway_users = pgTable("gateway_users", {
    id: serial("id").primaryKey().notNull(),
    created_at: timestamp("created_at", { mode: 'string' }).default(timezone('utc'::text, now())),
    updated_at: timestamp("updated_at", { mode: 'string' }).default(timezone('utc'::text, now())),
    username: varchar("username").notNull(),
    password: varchar("password").notNull(),
    salt: varchar("salt").notNull(),
    role: varchar("role").notNull(),
    first: varchar("first"),
    last: varchar("last"),
    asset_id: integer("asset_id").references(() => meta_assets.id, { onDelete: "set null" } ),
});

uh oh, what's this about:

timezone('utc'::text, now())