DrizzleORM v0.32.0 릴리스
Jul 10, 2024

drizzle-orm@0.32.0drizzle-kit@0.23.0 릴리스 노트

두 패키지를 모두 업그레이드할 필요는 없지만, 쿼리와 마이그레이션 모두에서 새로운 기능을 사용하려면 두 패키지를 모두 업그레이드해야 합니다

새로운 기능

🎉 MySQL $returningId() 함수

MySQL은 INSERTRETURNING을 기본적으로 지원하지 않습니다. autoincrement (또는 serial) 타입을 가진 primary keys에 대해서만 insertIdaffectedRows 필드에 접근할 수 있는 방법이 있습니다. Drizzle에서는 이러한 경우를 자동으로 처리하여 삽입된 모든 ID를 별도의 객체로 자동으로 받을 수 있는 방법을 준비했습니다

import { boolean, int, text, mysqlTable } from 'drizzle-orm/mysql-core';

const usersTable = mysqlTable('users', {
  id: int('id').primaryKey(),
  name: text('name').notNull(),
  verified: boolean('verified').notNull().default(false),
});


const result = await db.insert(usersTable).values([{ name: 'John' }, { name: 'John1' }]).$returningId();
//    ^? { id: number }[]

또한 Drizzle에서는 런타임에 커스텀 primary key를 생성하는 $default 함수를 사용하여 primary key를 지정할 수 있습니다. $returningId() 호출에서 생성된 키도 반환됩니다

import { varchar, text, mysqlTable } from 'drizzle-orm/mysql-core';
import { createId } from '@paralleldrive/cuid2';

const usersTableDefFn = mysqlTable('users_default_fn', {
  customId: varchar('id', { length: 256 }).primaryKey().$defaultFn(createId),
  name: text('name').notNull(),
});


const result = await db.insert(usersTableDefFn).values([{ name: 'John' }, { name: 'John1' }]).$returningId();
//  ^? { customId: string }[]

primary key가 없는 경우 타입은 {}[]가 됩니다

🎉 PostgreSQL 시퀀스

이제 PostgreSQL에서 필요한 모든 스키마 내에서 시퀀스를 지정하고 사용 가능한 모든 속성을 정의할 수 있습니다

예제
import { pgSchema, pgSequence } from "drizzle-orm/pg-core";

// No params specified
export const customSequence = pgSequence("name");

// Sequence with params
export const customSequence = pgSequence("name", {
      startWith: 100,
      maxValue: 10000,
      minValue: 100,
      cycle: true,
      cache: 10,
      increment: 2
});

// Sequence in custom schema
export const customSchema = pgSchema('custom_schema');

export const customSequence = customSchema.sequence("name");

🎉 PostgreSQL Identity 컬럼

출처: 언급했듯이 PostgreSQL의 serial 타입은 구식이며 사용하지 않는 것이 좋습니다. 이상적으로는 사용하지 말아야 합니다. Identity 컬럼은 스키마에서 시퀀스를 지정하는 권장 방법이며, 이것이 바로 identity columns 기능을 도입하는 이유입니다

예제
import { pgTable, integer, text } from 'drizzle-orm/pg-core' 

export const ingredients = pgTable("ingredients", {
  id: integer("id").primaryKey().generatedAlwaysAsIdentity({ startWith: 1000 }),
  name: text("name").notNull(),
  description: text("description"),
});

.generatedAlwaysAsIdentity() 함수에서 시퀀스에 사용 가능한 모든 속성을 지정할 수 있습니다. 또한 이러한 시퀀스의 커스텀 이름을 지정할 수도 있습니다

PostgreSQL 문서 참조.

🎉 PostgreSQL 생성 컬럼

이제 PostgreSQL에서 생성 컬럼을 사용할 수 있도록 지원하는 모든 컬럼에 생성 컬럼을 지정할 수 있습니다

tsvector를 위한 생성 컬럼 예제

참고: 최신 릴리스 전에 tsVector 컬럼 타입을 추가할 예정입니다

import { SQL, sql } from "drizzle-orm";
import { customType, index, integer, pgTable, text } from "drizzle-orm/pg-core";

const tsVector = customType<{ data: string }>({
  dataType() {
    return "tsvector";
  },
});

export const test = pgTable(
  "test",
  {
    id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
    content: text("content"),
    contentSearch: tsVector("content_search", {
      dimensions: 3,
    }).generatedAlwaysAs(
      (): SQL => sql`to_tsvector('english', ${test.content})`
    ),
  },
  (t) => ({
    idx: index("idx_content_search").using("gin", t.contentSearch),
  })
);

테이블의 컬럼을 참조할 필요가 없는 경우 sql 템플릿 또는 string만 사용할 수 있습니다

export const users = pgTable("users", {
  id: integer("id"),
  name: text("name"),
  generatedName: text("gen_name").generatedAlwaysAs(sql`hello world!`),
  generatedName1: text("gen_name1").generatedAlwaysAs("hello world!"),
}),

🎉 MySQL 생성 컬럼

이제 MySQL에서 생성 컬럼을 사용할 수 있도록 지원하는 모든 컬럼에 생성 컬럼을 지정할 수 있습니다

storedvirtual 옵션을 모두 지정할 수 있으며, 자세한 정보는 MySQL 문서를 확인하세요

또한 MySQL은 이러한 컬럼 사용에 몇 가지 제한이 있으며, 이는 여기에 설명되어 있습니다

Drizzle Kit의 push 명령에도 제한사항이 있습니다:

  1. push를 사용하여 생성 제약조건 표현식과 타입을 변경할 수 없습니다. Drizzle-kit은 이 변경사항을 무시합니다. 이를 적용하려면 컬럼 삭제, push, 그리고 새 표현식으로 컬럼 추가를 해야 합니다. 이는 데이터베이스 측의 복잡한 매핑으로 인해 스키마 표현식이 데이터베이스 측에서 수정되고 introspection 시 다른 문자열을 얻게 되기 때문입니다. 이 표현식을 변경했는지 또는 데이터베이스에서 변경 및 포맷했는지 확신할 수 없습니다. 이러한 컬럼이 생성 컬럼이고 push는 주로 로컬 데이터베이스에서 프로토타이핑에 사용되므로, 생성 컬럼을 삭제하고 생성하는 것은 빨라야 합니다. 이러한 컬럼이 생성되므로 모든 데이터가 복원됩니다

  2. generate에는 제한이 없어야 합니다

예제
export const users = mysqlTable("users", {
  id: int("id"),
  id2: int("id2"),
  name: text("name"),
  generatedName: text("gen_name").generatedAlwaysAs(
    (): SQL => sql`${schema2.users.name} || 'hello'`,
    { mode: "stored" }
  ),
  generatedName1: text("gen_name1").generatedAlwaysAs(
    (): SQL => sql`${schema2.users.name} || 'hello'`,
    { mode: "virtual" }
  ),
}),

테이블의 컬럼을 참조할 필요가 없는 경우 .generatedAlwaysAs()에서 sql 템플릿 또는 string만 사용할 수 있습니다

🎉 SQLite 생성 컬럼

이제 SQLite에서 생성 컬럼을 사용할 수 있도록 지원하는 모든 컬럼에 생성 컬럼을 지정할 수 있습니다

storedvirtual 옵션을 모두 지정할 수 있으며, 자세한 정보는 SQLite 문서를 확인하세요

또한 SQLite는 이러한 컬럼 사용에 몇 가지 제한이 있으며, 이는 여기에 설명되어 있습니다

Drizzle Kit의 pushgenerate 명령에도 제한사항이 있습니다:

  1. 기존 테이블에서 stored 타입의 생성 제약조건 표현식을 변경할 수 없습니다. 이 테이블을 삭제하고 다시 생성해야 합니다. 이는 SQLite의 이러한 작업에 대한 제한 때문입니다. 향후 릴리스에서 이 경우를 처리할 예정입니다 (데이터 마이그레이션과 함께 새 테이블 생성 포함).

  2. 위와 동일한 이유로 기존 컬럼에 stored 생성 표현식을 추가할 수 없습니다. 하지만 기존 컬럼에 virtual 표현식은 추가할 수 있습니다.

  3. 위와 동일한 이유로 기존 컬럼에서 stored 생성 표현식을 변경할 수 없습니다. 하지만 virtual 표현식은 변경할 수 있습니다.

  4. 위와 동일한 이유로 생성 제약조건 타입을 virtual에서 stored로 변경할 수 없습니다. 하지만 stored에서 virtual로는 변경할 수 있습니다.

새로운 Drizzle Kit 기능

🎉 모든 새로운 ORM 기능에 대한 마이그레이션 지원

모든 dialect에 대한 PostgreSQL 시퀀스, identity 컬럼 및 생성 컬럼 지원

🎉 drizzle-kit push를 위한 새로운 플래그 --force

push 명령을 사용하여 모든 데이터 손실 문을 자동으로 승인할 수 있습니다. CLI 매개변수에서만 사용할 수 있습니다. 데이터베이스에서 데이터 손실 문을 실행해도 괜찮다면 항상 이 플래그를 사용하세요

🎉 새로운 migrations 플래그 prefix

이제 마이그레이션 파일 접두사를 사용자 정의하여 마이그레이션 도구에 적합한 형식으로 만들 수 있습니다:

예제: Supabase 마이그레이션 형식
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  dialect: "postgresql",
  migrations: {
    prefix: 'supabase'
  }
});