Drizzle ORM dialect for the CUBRID database — TypeScript-first, type-safe schema definition and query builder for Node.js.
Drizzle ORM is a modern TypeScript ORM with a SQL-like query API, zero dependencies, and first-class type inference. Until now, there was no Drizzle dialect for CUBRID.
drizzle-cubrid bridges that gap:
- Type-safe queries — Full TypeScript inference from schema to query results
- Drizzle query API —
select(),insert(),update(),delete()with the familiar Drizzle chain syntax - CUBRID-specific types —
SET,MULTISET,SEQUENCE,MONETARYas native column builders - Transactions with savepoints — Nested transaction support via CUBRID savepoints
- Relations — Drizzle relational query API (
db.query.users.findMany({ with: { posts: true } })) - 99%+ test coverage — 52 offline tests, no database required for CI
flowchart TD
A[Application] --> B[Drizzle ORM]
B --> C[drizzle-cubrid dialect<br/>CubridDialect]
C --> D[cubrid-client]
D --> E[CUBRID Server]
npm install drizzle-cubrid drizzle-orm cubrid-client| Package | Purpose |
|---|---|
drizzle-cubrid |
CUBRID dialect for Drizzle (this package) |
drizzle-orm |
Drizzle ORM core |
cubrid-client |
TypeScript CUBRID driver |
Requirements: Node.js 18+, CUBRID 10.2+
// schema.ts
import { cubridTable, int, varchar, timestamp } from "drizzle-cubrid";
export const users = cubridTable("users", {
id: int("id").primaryKey().autoincrement(),
name: varchar("name", { length: 100 }).notNull(),
email: varchar("email", { length: 200 }).notNull().unique(),
created_at: timestamp("created_at").defaultNow(),
});// app.ts
import { createClient } from "cubrid-client";
import { drizzle } from "drizzle-cubrid";
import { eq } from "drizzle-cubrid";
import { users } from "./schema";
const client = createClient({
host: "localhost",
port: 33000,
database: "demodb",
user: "dba",
});
const db = drizzle(client);
// Insert
await db.insert(users).values({
name: "Alice",
email: "alice@example.com",
});
// Select with type-safe results
const allUsers = await db.select().from(users);
// allUsers: { id: number; name: string; email: string; created_at: Date | null }[]
// Where clause
const alice = await db
.select()
.from(users)
.where(eq(users.name, "Alice"));
// Update
await db
.update(users)
.set({ name: "Alicia" })
.where(eq(users.id, 1));
// Delete
await db.delete(users).where(eq(users.id, 1));
// Close connection
await client.close();Beyond standard SQL types, CUBRID has collection types and a monetary type:
import { cubridTable, int, varchar } from "drizzle-cubrid";
import { cubridSet, cubridMultiset, cubridSequence, monetary } from "drizzle-cubrid";
export const products = cubridTable("products", {
id: int("id").primaryKey().autoincrement(),
name: varchar("name", { length: 100 }),
// SET — unordered unique values → SET(VARCHAR(50))
tags: cubridSet("tags", { element: varchar("tag_item", { length: 50 }) }),
// MULTISET — unordered, allows duplicates → MULTISET(VARCHAR(50))
categories: cubridMultiset("categories", { element: varchar("category_item", { length: 50 }) }),
// SEQUENCE — ordered, allows duplicates → SEQUENCE(INTEGER)
rankings: cubridSequence("rankings", { element: int("rank_item") }),
// MONETARY — CUBRID native monetary type → MONETARY
price: monetary("price"),
});// Insert with collection values
await db.insert(products).values({
name: "Widget",
tags: ["sale", "new"], // string[] → SET
categories: ["electronics"], // string[] → MULTISET
rankings: ["1", "3", "5"], // string[] → SEQUENCE
});
// Select — collections return string[]
const rows = await db.select().from(products);
console.log(rows[0].tags); // ["sale", "new"]await db.transaction(async (tx) => {
await tx.insert(users).values({ name: "Alice", email: "a@example.com" });
await tx.insert(users).values({ name: "Bob", email: "b@example.com" });
// Auto-committed on success, auto-rolled back on error
});await db.transaction(async (tx) => {
await tx.insert(users).values({ name: "Alice", email: "a@example.com" });
try {
await tx.transaction(async (tx2) => {
// SAVEPOINT sp1
await tx2.insert(users).values({ name: "Bob", email: "b@example.com" });
throw new Error("rollback inner only");
// ROLLBACK TO SAVEPOINT sp1
});
} catch {
// Inner rolled back, outer continues
}
await tx.insert(users).values({ name: "Charlie", email: "c@example.com" });
// Alice + Charlie committed, Bob rolled back
});import { cubridTable, int, varchar } from "drizzle-cubrid";
import { relations } from "drizzle-orm";
export const users = cubridTable("users", {
id: int("id").primaryKey().autoincrement(),
name: varchar("name", { length: 100 }).notNull(),
});
export const posts = cubridTable("posts", {
id: int("id").primaryKey().autoincrement(),
title: varchar("title", { length: 200 }).notNull(),
author_id: int("author_id").notNull(),
});
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.author_id],
references: [users.id],
}),
}));import * as schema from "./schema";
const db = drizzle(client, { schema, mode: "default" });
const usersWithPosts = await db.query.users.findMany({
with: { posts: true },
});Errors propagate from cubrid-client with structured error types:
import { ConnectionError, QueryError, TransactionError } from "cubrid-client";
try {
await db.select().from(users);
} catch (error) {
if (error instanceof QueryError) {
console.error("Query failed:", error.message);
console.error("Cause:", error.cause);
}
}| Feature | Status | Notes |
|---|---|---|
INSERT ... RETURNING |
❌ Not supported | Use separate SELECT after INSERT |
| Streaming / iterators | ❌ Not supported | Use LIMIT/OFFSET for pagination |
| JSON columns | ❌ Not supported | Use VARCHAR with manual serialization |
| Native BOOLEAN | ❌ Not supported | Mapped to SMALLINT (0/1) |
| Sequences | ❌ Not supported | Use AUTO_INCREMENT |
| Document | Description |
|---|---|
| Schema Guide | Column types, CUBRID types, relations, custom types |
| Queries Guide | SELECT, INSERT, UPDATE, DELETE, joins, aggregations, raw SQL |
| Troubleshooting | Common errors, TypeScript issues, performance tips |
| Migration Example | Drizzle Kit config, schema, and CUBRID migration notes |
git clone https://github.com/cubrid-labs/drizzle-cubrid.git
cd drizzle-cubrid
npm install
npm run build # TypeScript compilation
npm run check # Lint + type-check + test
npm test # Run tests| Package | Description |
|---|---|
| cubrid-client | TypeScript CUBRID driver |
| drizzle-cubrid | Drizzle ORM dialect (this package) |
See ROADMAP.md for this project's direction and next milestones.
For the ecosystem-wide view, see the CUBRID Labs Ecosystem Roadmap and Project Board.
MIT — see LICENSE.