)
Drizzle ORM 0.37.0 版本詳解SingleStore 新方言與 SQLite Durable Objects 驅動實戰(zhàn)【免費下載鏈接】drizzle-ormORM項目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm本篇基于 Drizzle ORM 0.37.0 版本的官方變更記錄深入解讀該版本的三項核心更新全新的 SingleStore 方言、SQLite Durable ObjectsCloudflare DO驅動以及兩個關鍵 Bug 修復。讀者讀完本文后將掌握 SingleStore 數據庫在 Drizzle 中的接入方式、在 Cloudflare Durable Objects 中構建同步 SQLite 數據層的完整流程并能理解withReplicas與 Neon$withAuth兩個修復背后的實現原理。版本概覽0.37.0 帶來了什么Drizzle ORM 0.37.0 是一次以新數據庫接入能力為主的版本迭代主要變化集中在三方面新增 SingleStore 方言支持在 Drizzle 中以類型安全的方式操作 MySQL 兼容的 SingleStore 數據庫新增 SQLite Durable Objects 驅動允許在 Cloudflare Durable Objects 的DurableObjectStorage之上直接執(zhí)行同步 SQLite 查詢修復兩處已知缺陷withReplicas中$with未定義以及 Neon serverless 驅動$withAuth不接受 Promise 類型 token。下文分別展開。一、SingleStore 方言MySQL 兼容體系的新成員1.1 能力來源與定位SingleStore原 MemSQL是一款同時支持行存與列存的分布式數據庫其協議與 MySQL 高度兼容。0.37.0 版本中SingleStore 團隊為 Drizzle 提交了 PR完成了對 SingleStore 中MySQL 兼容部分的完整支持使得 Drizzle 的全部核心能力類型安全的表定義、查詢構建、關系查詢等可以直接作用于 SingleStore 實例。從倉庫源碼結構看SingleStore 支持被拆分為兩層與 MySQL/PostgreSQL 的既有架構完全一致singlestore-core目錄與方言無關的核心層包含表定義、列構建器、查詢構建器、方言、會話抽象等singlestore目錄基于mysql2驅動的實現層包含驅動、會話與遷移器。singlestore-core的公開入口 index.ts 統(tǒng)一導出了singlestoreTable、全部列構建器、SingleStoreDialect、索引、主鍵、唯一約束、視圖等符號說明 SingleStore 從第一天起就享受與 MySQL 同等的完整能力面。1.2 快速上手示例以下是官方變更記錄給出的最小可用示例它完整覆蓋了定義表結構 → 建立連接 → 發(fā)起查詢三步import { int, singlestoreTable, varchar } from drizzle-orm/singlestore-core; import { drizzle } from drizzle-orm/singlestore; export const usersTable singlestoreTable(users_table, { id: int().primaryKey(), name: varchar({ length: 255 }).notNull(), age: int().notNull(), email: varchar({ length: 255 }).notNull().unique(), }); // ... 其余代碼 const db drizzle(process.env.DATABASE_URL!); db.select()...幾個值得注意的細節(jié)singlestoreTable與sqliteTable、pgTable一樣接收表名與列定義對象列構建器int、varchar等從drizzle-orm/singlestore-core導入與驅動實現解耦drizzle()直接接收連接字符串DATABASE_URL內部會自動創(chuàng)建連接池。1.3 連接初始化字符串、PoolOptions 與回調客戶端官方文檔只展示了傳入連接字符串的最簡形式。從 singlestore/driver.ts 的源碼可以看到drizzle()實際支持三種調用形態(tài)調用形態(tài)說明drizzle(connectionString)傳入連接字符串內部調用createPool({ uri, connectAttributes })創(chuàng)建回調風格連接池并自動轉為 Promise 風格drizzle(connectionString, config)連接字符串 Drizzle 配置logger、cache、schema、casingdrizzle({ connection \| client, ...config })傳入PoolOptions對象或直接傳入已有的mysql2客戶端Pool/Connection/ 回調版本其中SingleStoreDriverOptions源碼支持兩個可選字段logger傳入自定義Logger實例或設為true使用內置DefaultLoggercache傳入緩存實例用于查詢結果緩存且連接池會自動附帶_connector_name: SingleStore Drizzle ORM Driver與_connector_version兩個連接屬性源碼便于 SingleStore 側識別 Drizzle 客戶端。此外drizzle.mock()源碼同樣適用于 SingleStore 驅動可在不連接真實數據庫的情況下構建查詢、進行類型與 SQL 斷言測試。1.4 完整的列類型體系SingleStore 方言并非只支持int與varchar。查看 singlestore-core/columns/all.ts共注冊了 28 種列構建器覆蓋數值、字符串、時間、二進制、JSON 與向量等類型數值bigint、int、tinyint、smallint、mediumint、decimal、double、float、real、serial、year字符串varchar、char、text、tinytext、mediumtext、longtext、binary、varbinary時間date、datetime、time、timestamp其他boolean、json、singlestoreEnum、customType、vector其中特別值得一提的是vector列vector.ts其構建器接收dimensions與elementType配置底層數據類型為Arraynumber、驅動參數為字符串——這為在 SingleStore 上構建向量檢索場景預留了直接的類型支持是 MySQL 方言所不具備的 SingleStore 特色能力。1.5 遷移與測試支持集成測試目錄 integration-tests/tests/singlestore/ 中包含了常規(guī)、自定義類型、前綴表名、代理proxy等全套測試用例drizzle-kit 的遷移快照目錄 integration-tests/drizzle2/singlestore/ 下存在meta/0000_snapshot.json與_journal.json說明drizzle-kit的 generate/push/migrate 流程對 SingleStore 已可用關系查詢測試relational/singlestore.test.ts與副本讀寫測試replicas/singlestore.test.ts也一并就緒。注意本版本先支持 SingleStore 與 MySQL 兼容的部分。SingleStore 官方團隊將持續(xù)迭代后續(xù)版本會逐步引入更多 SingleStore 特有的能力。二、SQLite Durable Objects 驅動在 Cloudflare DO 中直接查詢 SQLite2.1 什么是 SQLite Durable ObjectsCloudflare Durable ObjectsDO是 Workers 平臺提供的強一致性狀態(tài)存儲原語每個 DO 擁有一個DurableObjectStorage實例。0.37.0 之前開發(fā)者需要自行在 SQL 與 DO Storage API 之間做適配0.37.0 起Drizzle 直接提供了drizzle-orm/durable-sqlite驅動把 DO 的存儲層封裝為同步 SQLite 會話開發(fā)者可以直接用 Drizzle 的類型安全 API 讀寫數據。2.2 官方示例一個完整的 Durable Object以下代碼來自官方變更記錄展示了一個完整的 DO 類——在構造函數中通過drizzle(this.storage)建立數據庫實例并對外暴露migrate、insert、select三個方法/// reference typescloudflare/workers-types / import { drizzle, DrizzleSqliteDODatabase } from drizzle-orm/durable-sqlite; import { DurableObject } from cloudflare:workers import { migrate } from drizzle-orm/durable-sqlite/migrator; import migrations from ../drizzle/migrations; import { usersTable } from ./db/schema; export class MyDurableObject1 extends DurableObject { storage: DurableObjectStorage; db: DrizzleSqliteDODatabaseany; constructor(ctx: DurableObjectState, env: Env) { super(ctx, env); this.storage ctx.storage; this.db drizzle(this.storage, { logger: false }); } async migrate() { migrate(this.db, migrations); } async insert(user: typeof usersTable.$inferInsert) { await this.db.insert(usersTable).values(user); } async select() { return this.db.select().from(usersTable); } } export default { /** * This is the standard fetch handler for a Cloudflare Worker * * param request - The request submitted to the Worker from the client * param env - The interface to reference bindings declared in wrangler.toml * param ctx - The execution context of the Worker * returns The response to be sent back to the client */ async fetch(request: Request, env: Env): PromiseResponse { const id: DurableObjectId env.MY_DURABLE_OBJECT1.idFromName(durable-object); const stub env.MY_DURABLE_OBJECT1.get(id); await stub.migrate(); await stub.insert({ name: John, age: 30, email: johnexample.com, }) console.log(New user created!) const users await stub.select(); console.log(Getting all users from the database: , users) return new Response(); } }示例中的關鍵信息入口類型DrizzleSqliteDODatabase與工廠函數drizzle均從drizzle-orm/durable-sqlite導入遷移器從drizzle-orm/durable-sqlite/migrator導入migrations是 drizzle-kit 生成后編譯進 Worker 的遷移對象Worker 的fetch處理器通過env.MY_DURABLE_OBJECT1.idFromName(...)獲取 DO stub隨后依次執(zhí)行遷移、插入與查詢。2.3 驅動實現原理同步會話與底層存儲從源碼看這個驅動的設計非??酥扑耆珡陀昧?SQLite 同步方言只是替換了會話層。driver.ts 中drizzle(client, config)接收DurableObjectStorage作為客戶端構造SQLiteSyncDialect與SQLiteDOSession并支持config.schema關系查詢、config.casing、config.loggertrue時使用DefaultLogger等標準 Drizzle 配置同時把原始客戶端掛載到$client上session.ts 中的SQLiteDOPreparedQuery是核心執(zhí)行單元run/all/get/values四個方法最終都落到this.client.sql.exec(...)上——即 DO 存儲層內置的 SQLite 執(zhí)行引擎并且全部為同步 API返回SqlStorageCursor后再經toArray()/mapResultRow映射為行對象事務能力由SQLiteDOTransaction提供session.ts底層調用client.transactionSync(() ...)保證事務原子性并支持嵌套事務nestedIndex 1。2.4 遷移器__drizzle_migrations表與斷點執(zhí)行durable-sqlite/migrator.ts 中的migrate(db, config)實現了與 SQLite 其他驅動一致的遷移協議讀取journal.entries按序號拼接出每個遷移的 SQL鍵名規(guī)則為m 4 位零填充序號如m0000按-- statement-breakpoint將每個遷移文件拆分為多條語句在事務內創(chuàng)建__drizzle_migrations記錄表id、hash、created_at讀取最近一條已應用遷移的時間戳僅執(zhí)行比它更新的遷移并逐條寫入記錄。由于遷移文件最終會被打包進 Worker bundle示例中的import migrations from ../drizzle/migrations這套機制讓 DO 在首次初始化時即可自動完成建表。2.5 集成測試佐證倉庫中 integration-tests/tests/sqlite/durable-objects/index.ts 是一份超過 3600 行的 DO 集成測試覆蓋了 DO 場景下的完整 Drizzle 能力面遷移流程migrate1、插入/自增/默認值$default全字段/部分字段/原始 SQL/類型化 SQL 查詢inArray、notInArray、selectDistinct、returning、JOIN 與aliasblob的 JSON 與 bigint 模式、timestamp 模式等類型映射。該測試文件同時配有 wrangler.toml 配置說明整個 DO 數據層是通過真實 Cloudflare 運行環(huán)境驗證的。三、Bug 修復兩處一致性缺陷的源碼級解讀3.1 修復一withReplicas中$with未定義問題背景對應 issue #1834withReplicas(primary, replicas)用于構建主庫寫入、從庫讀取的副本分離實例。此前其返回對象缺失$with/withCTE 構建入口導致在副本分離場景下使用 CTE 時拋出$with is undefined。修復方式在 mysql-core/db.ts 的withReplicas實現中新增了$with與with的轉發(fā)const $with: Q[with] (...args: []) getReplica(replicas).with(...args); // ... return { ...primary, select, selectDistinct, $count, with: $with, // 只讀查詢轉發(fā)到副本 // ... };與select、selectDistinct、$count一樣CTE 構建被歸類為只讀操作因此統(tǒng)一轉發(fā)到隨機挑選的副本上執(zhí)行而update、insert、delete、execute、transaction依舊路由到主庫。同樣的修復模式也存在于pg-core、gel-core與singlestore-core各自的withReplicas實現中可從各目錄的db.ts中檢索withReplicas確認。3.2 修復二Neon$withAuth的 token 類型對齊問題背景對應 issue #3597Neon serverless 驅動的連接選項中authToken支持傳入 Promise但數據庫實例上的$withAuth()方法此前只接受字符串造成類型不一致與使用困惑。修復方式在 neon-http/driver.ts 中NeonHttpDatabase.$withAuth的入參類型被改為與HTTPQueryOptions[authToken]保持一致$withAuth( token: ExcludeHTTPQueryOptionstrue, true[authToken], undefined, ): Omitthis, /* 保留查詢相關方法 */ { ... }同時該方法內部通過 Proxy 包裝wrap(this, token, ...)實現 token 的透傳對with等鏈式返回的中間對象也會遞歸包裹確保后續(xù)所有查詢都攜帶新 token。修復后$withAuth返回的類型被收窄為僅包含$count、delete、select、selectDistinct、selectDistinctOn、update、insert、with、query、execute、refreshMaterializedView等查詢方法的實例避免誤用其他實例 API。四、升級與使用建議升級drizzle-orm至 0.37.0 或更高版本即可獲得上述能力配套使用drizzle-kit時SingleStore 項目的生成/推送流程可參考 drizzle2/singlestore 遷移快照 作為輸出形態(tài)參考SingleStore 場景下建議優(yōu)先從drizzle-orm/singlestore-core導入表與列定義、從drizzle-orm/singlestore導入drizzle保持核心層與驅動層的清晰邊界Durable Objects 場景下需在tsconfig中引入cloudflare/workers-types示例頂部有/// reference typescloudflare/workers-types /且注意該驅動當前為同步 API不適合在需要異步游標流式讀取的超大結果集場景使用若使用了withReplicas或 Neon$withAuth本次兩個修復為向后兼容的缺陷修復升級后無需改動業(yè)務代碼直接獲得正確的$with行為與 Promise token 類型支持。結語0.37.0 通過 SingleStore 方言與 SQLite Durable Objects 驅動將 Drizzle 的類型安全查詢體驗擴展到了分布式分析型數據庫與邊緣狀態(tài)存儲兩個新領域同時以兩個針對性的 Bug 修復收緊了副本分離與 Neon 認證的類型邊界。對希望在 Cloudflare Workers 上構建本地優(yōu)先local-first應用的團隊而言durable-sqlite驅動提供了一條把 SQLite 遷移、CRUD 與關系查詢全部納入類型系統(tǒng)的捷徑?!久赓M下載鏈接】drizzle-ormORM項目地址: https://gitcode.com/gh_mirrors/dr/drizzle-orm創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考