ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

使用 @tursodatabase/database 在 Node.js 中运行 Turso 嵌入式数据库:官方示例 database-node 全解析

使用 @tursodatabase/database 在 Node.js 中运行 Turso 嵌入式数据库:官方示例 database-node 全解析 使用 tursodatabase/database 在 Node.js 中运行 Turso 嵌入式数据库官方示例 database-node 全解析【免费下载链接】tursoA SQL database in Rust: SQLite-compatible, now also speaking Postgres (experimental). The LLVM of databases.项目地址: https://gitcode.com/GitHub_Trending/tu/turso本文以 Turso 仓库中官方最小示例 database-node 为主线系统讲解如何在 Node.js 应用中通过tursodatabase/database包创建本地文件型数据库、执行建表与索引 DDL、使用预处理语句绑定参数完成写入与查询。读完本文你将掌握connect / exec / prepare / run / all / get的完整用法理解timeout等连接选项的底层语义并能对照源码定位每个 API 的实现位置快速上手基于 Turso 嵌入式引擎的应用开发。示例项目概览一个只依赖数据库包的 Node 最小工程官方示例 database-node 目录结构非常精简共 4 个文件README.md使用说明即本文讲解的关联文档index.mjs全部演示逻辑以 ES Module 方式编写package.json声明唯一运行时依赖tursodatabase/databasepackage-lock.json锁定依赖版本。从 package.json 可以看到示例通过本地路径../../../bindings/javascript/packages/native直接链接到仓库内的 native 包也就是说示例代码与你 clone 下来的源码树实时对应不会出现版本漂移。该包在 bindings/javascript/packages/native/package.json 中发布名为tursodatabase/database当前仓库锁定版本为0.8.0-pre.11license 为 MITexports同时提供./dist/promise.js主入口与./compat兼容入口。npm install node index.mjs这两条命令就是 README 给出的全部运行步骤先安装依赖再直接以 Node.js 运行index.mjs。由于示例没有第三方工具链依赖安装后即可执行。连接数据库connect()与timeout选项示例的第一行代码从包中导入connect并打开本地数据库文件import { connect } from tursodatabase/database; const db await connect(local.db, { timeout: 1000, // busy timeout for handling high-concurrency write cases });connect的签名在 promise.ts 中有明确定义async function connect(path: string, opts: DatabaseOpts {}): PromiseDatabase { const db new Database(path, opts); await db.connect(); return db; }它内部构造Database实例后异步调用connect()因此返回的是一个PromiseDatabase这也是示例中所有调用都需要await的原因。path传普通文件路径即创建/打开文件型数据库传:memory:则创建纯内存数据库native 包 README 与 promise.test.ts 中的in-memory-db-async测试均验证了该用法。DatabaseOpts支持哪些选项完整的连接选项定义在 index.d.ts该文件由 NAPI-RS 自动生成与 better-sqlite3 的选项对齐选项类型含义readonlyboolean只读模式打开数据库timeoutnumberbusy timeout单位毫秒用于高并发写场景下等待锁释放defaultQueryTimeoutnumber语句默认查询超时fileMustExistboolean文件不存在时报错而非自动创建tracingstring语句追踪配置experimentalstring[]需要开启的实验特性列表encryptionEncryptionOpts本地数据库加密配置cipher hexkey示例使用的timeout: 1000正是 busy timeout当多个连接并发写入、目标连接持锁未释放时当前连接会重试等待最长等待 1000ms。这一语义在 promise.test.ts 中有专门的测试佐证conn1开启事务写锁后不提交conn2以timeout: 200写入时会在约 200ms 预算内不断重试随后抛出locked错误——既不会快速失败也不会无限挂起另一个测试进一步验证等待期间通过STEP_SLEEP让出事件循环不会阻塞 Node.js 主线程。执行 DDLexec()一次运行多条语句连接建立后示例用exec一次性执行建表和建索引两条语句await db.exec( CREATE TABLE IF NOT EXISTS guestbook (comment TEXT, created_at DEFAULT (unixepoch())); CREATE INDEX IF NOT EXISTS guestbook_idx ON guestbook (created_at); );exec适合只需要执行到完成、不关心返回值的语句DDL、批量 INSERT 等支持以分号分隔的多条 SQL。created_at使用 SQLite 内置的unixepoch()函数生成秒级时间戳作为默认值再为该列建索引以加速后续按时间倒序的查询——这为后面ORDER BY created_at DESC的读取做好了铺垫。从 common/promise.ts 的源码结构看Database类内部维护了一把execLock异步锁所有语句执行都在其上串行化保证同一连接上并发调用不会出现交叉污染。预处理语句与参数绑定prepare()run()/all()/get()接下来是示例的核心演示——预处理语句与占位符绑定// use prepared statements and bind args to placeholders later const insert db.prepare(INSERT INTO guestbook(comment) VALUES (?)); // use run(...) method if query only need to be executed till completion await insert.run([hello, turso at ${Math.floor(Date.now() / 1000)}]); const select db.prepare(SELECT * FROM guestbook ORDER BY created_at DESC LIMIT ?); // use all(...) or get(...) methods to get all or one row from the query console.info(await select.all([5]));这里展示的是完整的数据访问模式db.prepare(sql)预编译一条 SQL 语句返回Statement实例。SQL 中的?是位置占位符运行时再绑定具体值避免字符串拼接带来的注入风险同时语句只解析编译一次、可重复执行。stmt.run(...args)执行只求完成不求结果的语句INSERT/UPDATE/DELETE 等参数以数组或展开形式传入。stmt.all(...args)执行查询并返回所有匹配行stmt.get(...args)则只取第一行。示例中select.all([5])即查询按时间倒序的最新 5 条留言结果以对象数组形式打印到控制台。此外native 包 README 还展示了run()的返回值用法const result await insertPost.run(Hello World, ...)之后可以通过result.lastInsertRowid拿到刚插入行的 rowid。与之对应的底层能力在 index.d.ts 中均有暴露Database.lastInsertRowid()、changes()、totalChanges()以及Statement上的parameterCount()、parameterName(index)、bindAt()、columns()等元信息与绑定 API。Statement还支持raw()/pluck()两种展示模式切换以及safeIntegers()控制大整数是否以安全整数返回setQueryTimeout()为单条语句设置超时用完可调用finalize()显式释放。事务transactionAsync()保证原子性虽然index.mjs示例本身没有演示事务但这是嵌入式数据库使用中不可或缺的一环native 包 README 给出了完整示例import { connect } from tursodatabase/database; const db await connect(transactions.db); // Using transactions for atomic operations const transaction db.transactionAsync(async (txn, users) { const insert await txn.prepare(INSERT INTO users (name, email) VALUES (?, ?)); for (const user of users) { await insert.run(user.name, user.email); } }); // Execute transaction await transaction([ { name: Alice, email: aliceexample.com }, { name: Bob, email: bobexample.com } ]);transactionAsync(fn)接受一个异步回调回调首个参数是Transaction句柄内部的prepare/exec/run都必须在txn上调用后续参数由调用方传入。其实现位于 common/promise.ts执行前先获取execLock回调体前后分别执行BEGIN与COMMIT/ROLLBACK从而把整段逻辑包进一个原子事务锁在事务提交/回滚后才释放避免其他语句穿插进事务区间。旧的transaction()同步包装已被标记为 deprecated新代码应统一使用transactionAsync。进阶能力内存数据库、加密与兼容层结合 native 包 README 与源码还可以看到示例之外的几类进阶用法内存数据库const db await connect(:memory:); await db.exec(CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)); const users await db.prepare(SELECT * FROM users).all();适合测试与临时计算场景数据随连接关闭即消失。Database类型上对应的memory、readonly、open、path属性在 index.d.ts 中均有声明可用于运行时自检。本地加密promise.ts中Database构造器会把字符串形式的 cipher 名称映射为 native 枚举值后传入底层支持aes128gcm、aes256gcm、aegis256、aegis256x2、aegis128l、aegis128x2、aegis128x4七种算法配合 hex 编码密钥使用const db await connect(encrypted.db, { encryption: { cipher: aes256gcm, hexkey: ... }, });若当前构建的 native 模块未启用加密会在映射时直接抛出 Encryption is not supported in this build 错误。仓库内另有 examples/javascript/encryption 专门演示这一能力。兼容层与生态集成包入口还导出了./compat兼容模块对应compat.ts提供贴近 better-sqlite3 风格的同步式 API便于存量代码迁移。原生异步 API 则可通过 promise.test.ts 中drizzle-orm的集成测试看到生态适配情况drizzle(conn)包装连接后即可执行 ORM 风格的db.run/db.all测试中 1234 条并发 INSERT 全部成功并正确计数。底层原理NAPI-RS 原生绑定与异步 I/O 循环tursodatabase/database并不是一个纯 JS 实现而是通过 NAPI-RS 将仓库根目录 Cargo.toml 下用 Rust 编写的 Turso 嵌入式引擎编译为原生模块napi build产物JS 层只是薄封装。从 bindings/javascript/packages/native/package.json 的napi.targets可以看出官方预编译的四个平台目标x86_64-unknown-linux-gnu、x86_64-pc-windows-msvc、aarch64-apple-darwin、aarch64-unknown-linux-gnu即覆盖主流 Linux/macOS/Windows 的 x86_64 与 arm64 架构。异步模型上底层Database暴露了ioLoopSync()/ioLoopAsync()Statement.stepSync()每次步进返回[step, sleepMs]step取值 1有行可读、2执行完毕、3需要 I/O、4请求休眠sleepMs仅在STEP_SLEEP时非零。JS 层据此实现需要 I/O 就让出事件循环、需要等待锁就定时唤醒的非阻塞执行策略——这正是上文 busy timeout 测试中等待期间不阻塞事件循环的机制来源。此外classifySql()可将任意 SQL 归类为read / write / begin / commit / rollback供执行策略与锁管理参考。需要更完整的 API 说明时可查阅仓库内的 JavaScript API ReferenceSQLite 语法与文件格式兼容状态见 COMPAT.md。小结官方 database-node 示例以不足 30 行代码覆盖了嵌入式数据库使用的全部核心链路connect建连并配置 busy timeout →exec执行多语句 DDL →prepare预编译 占位符绑定 →run写入 →all读取。以此为基础再结合transactionAsync事务、内存库、加密与兼容层等进阶能力即可在 Node.js 应用中快速获得一个进程内运行、SQLite 兼容、具备并发写保护与事务能力的本地数据库引擎。所有 API 的精确行为都可在 bindings/javascript/packages/native 与 bindings/javascript/packages/common 的源码及测试中找到对应实现便于你按需深入。【免费下载链接】tursoA SQL database in Rust: SQLite-compatible, now also speaking Postgres (experimental). The LLVM of databases.项目地址: https://gitcode.com/GitHub_Trending/tu/turso创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表