Type API

select ๋ฐ insert ์ฟผ๋ฆฌ๋ฅผ ์œ„ํ•ด ํ…Œ์ด๋ธ” ์Šคํ‚ค๋งˆ์—์„œ ํƒ€์ž…์„ ๊ฒ€์ƒ‰ํ•˜๋ ค๋ฉด ํƒ€์ž… ํ—ฌํผ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PostgreSQL
MySQL
SQLite
SingleStore
import { serial, text, pgTable } from 'drizzle-orm/pg-core';
import { type InferSelectModel, type InferInsertModel } from 'drizzle-orm'

const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
});

type SelectUser = typeof users.$inferSelect;
type InsertUser = typeof users.$inferInsert;
// or
type SelectUser = typeof users._.$inferSelect;
type InsertUser = typeof users._.$inferInsert;
// or
type SelectUser = InferSelectModel<typeof users>;
type InsertUser = InferInsertModel<typeof users>;

๋กœ๊น…

๊ธฐ๋ณธ ์ฟผ๋ฆฌ ๋กœ๊น…์„ ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด drizzle ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜์— { logger: true }๋ฅผ ์ „๋‹ฌํ•˜์„ธ์š”:

import { drizzle } from 'drizzle-orm/...'; // driver specific

const db = drizzle({ logger: true });

DefaultLogger ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ปค์Šคํ…€ writer๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๋กœ๊ทธ ๋Œ€์ƒ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

import { DefaultLogger, LogWriter } from 'drizzle-orm/logger';
import { drizzle } from 'drizzle-orm/...'; // driver specific

class MyLogWriter implements LogWriter {
  write(message: string) {
    // Write to file, stdout, etc.
  }
}

const logger = new DefaultLogger({ writer: new MyLogWriter() });
const db = drizzle({ logger });

์ปค์Šคํ…€ ๋กœ๊ฑฐ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

import { Logger } from 'drizzle-orm/logger';
import { drizzle } from 'drizzle-orm/...'; // driver specific

class MyLogger implements Logger {
  logQuery(query: string, params: unknown[]): void {
    console.log({ query, params });
  }
}

const db = drizzle({ logger: new MyLogger() });

๋ฉ€ํ‹ฐ ํ”„๋กœ์ ํŠธ ์Šคํ‚ค๋งˆ

Table creator API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ด๋ธ” ์ด๋ฆ„์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ์˜ ์Šคํ‚ค๋งˆ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

PostgreSQL
MySQL
SQLite
SingleStore
import { serial, text, pgTableCreator } from 'drizzle-orm/pg-core';

const pgTable = pgTableCreator((name) => `project1_${name}`);

const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
});
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  schema: "./src/schema/*",
  out: "./drizzle",
  dialect: "mysql", 
  dbCredentials: {
    url: process.env.DATABASE_URL,
  }
  tablesFilter: ["project1_*"],
});

์—ฌ๋Ÿฌ ๊ฐœ์˜ or ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

tablesFilter: ["project1_*", "project2_*"]

SQL ์ฟผ๋ฆฌ ์ถœ๋ ฅ

db ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ **standalone query builder**๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ SQL ์ฟผ๋ฆฌ๋ฅผ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const query = db
  .select({ id: users.id, name: users.name })
  .from(users)
  .groupBy(users.id)
  .toSQL();
// query:
{
  sql: 'select 'id', 'name' from 'users' group by 'users'.'id'',
  params: [],
}

Raw SQL ์ฟผ๋ฆฌ ์‹คํ–‰

์‹คํ–‰ํ•ด์•ผ ํ•  ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์žˆ๊ณ  drizzle-orm์ด ์•„์ง ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ, db.execute ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ raw parametrized ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PostgreSQL
MySQL
SQLite
SingleStore
const statement = sql`select * from ${users} where ${users.id} = ${userId}`;
const res: postgres.RowList<Record<string, unknown>[]> = await db.execute(statement)

Standalone query builder

Drizzle ORM์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ ๋„ ์ฟผ๋ฆฌ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ์ƒ์„ฑ๋œ SQL์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” standalone query builder๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

PostgreSQL
MySQL
SQLite
SingleStore
import { QueryBuilder } from 'drizzle-orm/pg-core';

const qb = new QueryBuilder();

const query = qb.select().from(users).where(eq(users.name, 'Dan'));
const { sql, params } = query.toSQL();

ํƒ€์ž…์ด ์ง€์ •๋œ ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ๊ฐ€์ ธ์˜ค๊ธฐ

ํƒ€์ž…์ด ์ง€์ •๋œ ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ ๋งต์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์„ ํƒ ์‹œ ํŠน์ • ์ปฌ๋Ÿผ์„ ์ƒ๋žตํ•ด์•ผ ํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

PostgreSQL
MySQL
SQLite
SingleStore
index.ts
schema.ts
import { getTableColumns } from "drizzle-orm";
import { user } from "./schema";

const { password, role, ...rest } = getTableColumns(user);

await db.select({ ...rest }).from(users);

ํ…Œ์ด๋ธ” ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

PostgreSQL
MySQL
SQLite
SingleStore
import { getTableConfig, pgTable } from 'drizzle-orm/pg-core';

export const table = pgTable(...);

const {
  columns,
  indexes,
  foreignKeys,
  checks,
  primaryKeys,
  name,
  schema,
} = getTableConfig(table);

๊ฐ์ฒด ํƒ€์ž… ๋น„๊ต (instanceof ๋Œ€์•ˆ)

is() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๊ฐ€ ํŠน์ • Drizzle ํƒ€์ž…์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Drizzle์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ํƒ€์ž…๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

IMPORTANT

instanceof ๋Œ€์‹  ํ•ญ์ƒ is()๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

๋ช‡ ๊ฐ€์ง€ ์˜ˆ์ œ

import { Column, is } from 'drizzle-orm';

if (is(value, Column)) {
  // value's type is narrowed to Column
}

Mock Driver

์ด API๋Š” Drizzle ํ…Œ์ŠคํŠธ์—์„œ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ–ˆ์œผ๋ฉฐ ์™ธ๋ถ€ ๊ฐœ๋ฐœ์ž์—๊ฒŒ๋Š” ๊ฑฐ์˜ ๊ถŒ์žฅํ•˜์ง€ ์•Š์•˜๋˜ undefined drizzle({} as any) API์˜ ํ›„์† ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.

์ ์ ˆํ•œ API๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ๋…ธ์ถœํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์œผ๋ฉฐ, ์ด์ œ ๋ชจ๋“  drizzle ๋“œ๋ผ์ด๋ฒ„์— drizzle.mock()์ด ์žˆ์Šต๋‹ˆ๋‹ค:

import { drizzle } from "drizzle-orm/node-postgres";

const db = drizzle.mock();

ํƒ€์ž…์— ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์Šคํ‚ค๋งˆ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

import { drizzle } from "drizzle-orm/node-postgres";
import * as schema from "./schema"

const db = drizzle.mock({ schema });