Drizzle ORM
PetraDB 通过 @petradb/drizzle 包提供 Drizzle ORM 驱动。它实现了自定义 PostgreSQL 方言驱动 — Drizzle 生成 PostgreSQL 方言的 SQL,PetraDB 在进程内执行,无需线协议。该驱动与 drizzle-orm/node-postgres 完全功能对等,包括 db.transaction()、所有变更操作的 returning(),以及关系查询。
npm install @petradb/drizzle drizzle-orm @petradb/engineimport { Session } from "@petradb/engine";import { drizzle } from "@petradb/drizzle";
const session = new Session({ storage: "memory" });const db = drizzle(session);// 内存模式(默认)new Session({ storage: "memory" })
// 文件持久化存储new Session({ storage: "persistent", path: "./mydb.petra" })使用 Drizzle 的 pgTable 定义表:
import { pgTable, serial, text, integer, boolean } from "drizzle-orm/pg-core";
const users = pgTable("users", { id: serial("id").primaryKey(), name: text("name").notNull(), email: text("email").notNull(), age: integer("age"), active: boolean("active").default(true),});通过 session 创建表,或使用迁移配合 drizzle-kit generate + migrate():
await session.execute(` CREATE TABLE users ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT NOT NULL, age INTEGER, active BOOLEAN DEFAULT true )`);// 单行await db.insert(users).values({ name: "Alice", email: "alice@example.com", age: 30,});
// 多行await db.insert(users).values([ { name: "Bob", email: "bob@example.com", age: 25 }, { name: "Charlie", email: "charlie@example.com", age: 35 },]);
// 带 returningconst [inserted] = await db .insert(users) .values({ name: "Diana", email: "diana@example.com", age: 28 }) .returning();console.log(inserted.id); // 自动生成的序列号import { eq, gt } from "drizzle-orm";
// 所有行const allUsers = await db.select().from(users);
// WHERE 子句const alice = await db.select().from(users).where(eq(users.name, "Alice"));
// 条件const older = await db.select().from(users).where(gt(users.age, 28));
// 指定列const names = await db .select({ name: users.name, email: users.email }) .from(users);
// 限制const first = await db.select().from(users).limit(1);// 更新行await db.update(users).set({ age: 31 }).where(eq(users.name, "Alice"));
// 带 returningconst [updated] = await db .update(users) .set({ active: false }) .where(eq(users.name, "Bob")) .returning();// 删除行await db.delete(users).where(eq(users.name, "Charlie"));
// 带 returningconst [deleted] = await db .delete(users) .where(eq(users.name, "Diana")) .returning();使用 Drizzle 的 db.transaction() API 实现自动提交/回滚:
// 自动提交const result = await db.transaction(async (tx) => { const [inserted] = await tx .insert(users) .values({ name: "Eve", email: "eve@example.com", age: 22 }) .returning(); return inserted;});
// 错误时自动回滚await db.transaction(async (tx) => { await tx.insert(users).values({ name: "Frank", email: "frank@example.com" }); throw new Error("something went wrong"); // Frank 不会被插入 — 事务已回滚});
// 显式回滚await db.transaction(async (tx) => { await tx.insert(users).values({ name: "Grace", email: "grace@example.com" }); tx.rollback(); // 抛出 TransactionRollbackError});你也可以使用 db.$session 进行手动事务控制:
await db.$session.execute("BEGIN");await db.insert(users).values({ name: "Hank", email: "hank@example.com" });await db.$session.execute("COMMIT");PetraDB 返回原生 JS 类型 — 无需字符串转换:
| Drizzle 类型 | PetraDB 列 | JS 类型 |
|---|---|---|
serial() | SERIAL | number |
integer() | INTEGER | number |
text() | TEXT | string |
boolean() | BOOLEAN | boolean |
numeric() | NUMERIC | string |
可空列在没有值时返回 null。
使用 migrate() 函数应用 Drizzle Kit 迁移:
import { migrate } from "@petradb/drizzle";
await migrate(db, { migrationsFolder: "./drizzle" });这会读取由 drizzle-kit generate 生成的迁移日志和 SQL 文件,按顺序执行,并在 drizzle.__drizzle_migrations 表中跟踪已应用的迁移(自动创建)。
典型工作流:
# 从模式更改生成迁移npx drizzle-kit generate
# 启动时应用迁移import { Session } from "@petradb/engine";import { drizzle, migrate } from "@petradb/drizzle";
const session = new Session({ storage: "memory" });const db = drizzle(session);
await migrate(db, { migrationsFolder: "./drizzle" });// 表已创建 — 正常使用 dbawait session.close();