drizzle-cubrid
v0.2.1
Published
Drizzle ORM dialect for CUBRID database
Maintainers
Readme
drizzle-cubrid
Drizzle ORM dialect for the CUBRID database — TypeScript-first, type-safe schema definition and query builder for Node.js.
Why drizzle-cubrid?
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
Installation
npm install drizzle-cubrid drizzle-orm cubrid-client node-cubrid| Package | Purpose |
|---------|---------|
| drizzle-cubrid | CUBRID dialect for Drizzle (this package) |
| drizzle-orm | Drizzle ORM core |
| cubrid-client | TypeScript CUBRID driver |
| node-cubrid | Low-level CUBRID protocol driver |
Requirements: Node.js 18+, CUBRID 10.2+
Quick Start
1. Define Your Schema
// 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(),
});2. Connect and Query
// 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: "[email protected]",
});
// 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();CUBRID-Specific Column Types
Beyond standard SQL types, CUBRID has collection types and a monetary type:
import { cubridTable, int, varchar } from "drizzle-cubrid";
import { set, multiset, sequence, 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: set("tags", { type: "VARCHAR", length: 50 }),
// MULTISET — unordered, allows duplicates → MULTISET(VARCHAR(50))
categories: multiset("categories", { type: "VARCHAR", length: 50 }),
// SEQUENCE — ordered, allows duplicates → SEQUENCE(INTEGER)
rankings: sequence("rankings", { type: "INTEGER" }),
// 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"]Transactions
Automatic (Recommended)
await db.transaction(async (tx) => {
await tx.insert(users).values({ name: "Alice", email: "[email protected]" });
await tx.insert(users).values({ name: "Bob", email: "[email protected]" });
// Auto-committed on success, auto-rolled back on error
});Nested Transactions (Savepoints)
await db.transaction(async (tx) => {
await tx.insert(users).values({ name: "Alice", email: "[email protected]" });
try {
await tx.transaction(async (tx2) => {
// SAVEPOINT sp1
await tx2.insert(users).values({ name: "Bob", email: "[email protected]" });
throw new Error("rollback inner only");
// ROLLBACK TO SAVEPOINT sp1
});
} catch {
// Inner rolled back, outer continues
}
await tx.insert(users).values({ name: "Charlie", email: "[email protected]" });
// Alice + Charlie committed, Bob rolled back
});Relations
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 },
});Error Handling
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);
}
}CUBRID Limitations
| 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 |
Documentation
| 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 |
Development
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 testsEcosystem
| Package | Description | |---------|-------------| | cubrid-client | TypeScript CUBRID driver | | drizzle-cubrid | Drizzle ORM dialect (this package) | | pycubrid | Python DB-API 2.0 driver | | sqlalchemy-cubrid | SQLAlchemy 2.0 dialect | | cubrid-go | Go database/sql driver + GORM | | cubrid-cookbook | Framework integration examples |
License
MIT — see LICENSE.
