tbdb 0.0.0 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -0
- package/dist/adapter/IndexedDB/IndexedDBAdapter.d.ts +29 -0
- package/dist/adapter/IndexedDB/index.d.ts +1 -0
- package/dist/adapter/IndexedDB/test/indexeddb.test.d.ts +1 -0
- package/dist/adapter/SQLite/SQLiteAdapter.d.ts +137 -15
- package/dist/adapter/SQLite/benchmark/query_analysis.bench.d.ts +1 -0
- package/dist/adapter/SQLite/benchmark/sqlite-extended.bench.d.ts +9 -0
- package/dist/adapter/SQLite/benchmark/sqlite.bench.d.ts +1 -0
- package/dist/adapter/SQLite/driver/BetterSqlite3Driver.d.ts +27 -0
- package/dist/adapter/SQLite/driver/BunSqliteDriver.d.ts +68 -0
- package/dist/adapter/SQLite/driver/NodeSqliteDriver.d.ts +60 -0
- package/dist/adapter/SQLite/driver/index.d.ts +51 -0
- package/dist/adapter/SQLite/driver/test/driver.test.d.ts +6 -0
- package/dist/adapter/SQLite/driver/types.d.ts +106 -0
- package/dist/adapter/SQLite/index.d.ts +3 -0
- package/dist/adapter/SQLite/test/dirty-tracking-bugs.test.d.ts +24 -0
- package/dist/adapter/SQLite/test/dirty-tracking-production.test.d.ts +11 -0
- package/dist/adapter/SQLite/test/side-table-bug-verify.test.d.ts +14 -0
- package/dist/adapter/SQLite/test/side-table-bugs.test.d.ts +17 -0
- package/dist/adapter/SQLite/test/side-table-edge-cases.test.d.ts +15 -0
- package/dist/adapter/SQLite/test/sqlite-datatypes.test.d.ts +5 -0
- package/dist/adapter/SQLite/test/sqlite-multi-driver.test.d.ts +6 -0
- package/dist/adapter/SQLite/test/sqlite-query-ops.test.d.ts +4 -0
- package/dist/adapter/SQLite/utils/mongoToSql.d.ts +4 -1
- package/dist/adapter/SQLite/utils/projection.d.ts +16 -0
- package/dist/adapter/SQLite/utils/queryAnalysis.d.ts +54 -0
- package/dist/adapter/SQLite/utils/serializer.d.ts +19 -2
- package/dist/adapter/SQLite/utils/zstdHelper.d.ts +2 -2
- package/dist/adapter/adapter.d.ts +62 -3
- package/dist/benchmark/dist/base.try.d.ts +1 -0
- package/dist/core/Table.d.ts +15 -9
- package/dist/core/defineTable.d.ts +10 -4
- package/dist/core/event.d.ts +24 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/extension/tree/TableTree.d.ts +49 -0
- package/dist/extension/tree/core/copyNodes.d.ts +36 -0
- package/dist/extension/tree/core/createNodes.d.ts +33 -0
- package/dist/extension/tree/core/deleteNodes.d.ts +33 -0
- package/dist/extension/tree/core/listNodes.d.ts +32 -0
- package/dist/extension/tree/core/listNodesByCursor.d.ts +31 -0
- package/dist/extension/tree/core/moveNodes.d.ts +25 -0
- package/dist/extension/tree/core/preOverwriteNodes.d.ts +41 -0
- package/dist/extension/tree/core/presyncNodes.d.ts +30 -0
- package/dist/extension/tree/core/setNodes.d.ts +49 -0
- package/dist/extension/tree/core/unDeleteNodes.d.ts +28 -0
- package/dist/extension/tree/core/updateNodes.d.ts +29 -0
- package/dist/extension/tree/demo/dist-web/assets/index-DT1zZc4B.d.ts +1 -0
- package/dist/extension/tree/demo/src/main.d.ts +1 -0
- package/dist/extension/tree/demo/src/server.d.ts +1 -0
- package/dist/extension/tree/demo/vite.config.d.ts +2 -0
- package/dist/extension/tree/index.d.ts +1 -0
- package/dist/extension/tree/test/benchmark/ManyMany.bench.d.ts +1 -0
- package/dist/extension/tree/test/benchmark/table-tree.bench.d.ts +1 -0
- package/dist/extension/tree/test/gemini/table-tree-gemini-TableTree.test.d.ts +1 -0
- package/dist/extension/tree/test/human/table-tree-humam.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-clearDeadNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-copyNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-createNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-deleteNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-fs-comb.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-index-comb.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-listNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-metadata-comb.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-moveNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-multi-user-comb.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-preOverwriteNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-presyncNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-setNdoes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree-updateNodes.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree.test.d.ts +1 -0
- package/dist/extension/tree/test/table-tree.try.d.ts +1 -0
- package/dist/extension/tree/tool/clearDeadNodes.d.ts +22 -0
- package/dist/extension/tree/tool/refreshTreeMetadata.d.ts +9 -0
- package/dist/extension/tree/tree.types.d.ts +111 -0
- package/dist/extension/tree/util/applyTreeMetadataDelta.d.ts +29 -0
- package/dist/extension/tree/util/assertTreeParent.d.ts +8 -0
- package/dist/extension/tree/util/collectAncestorIds.d.ts +4 -0
- package/dist/extension/tree/util/collectDescendantNodes.d.ts +10 -0
- package/dist/extension/tree/util/collectExistingParentIds.d.ts +9 -0
- package/dist/extension/tree/util/collectTopSelectedNodes.d.ts +10 -0
- package/dist/extension/tree/util/getNodeValueByPath.d.ts +2 -0
- package/dist/extension/tree/util/getUniqueFileNames.d.ts +13 -0
- package/dist/extension/tree/util/groupNodesByParentId.d.ts +8 -0
- package/dist/extension/tree/util/newEmptyNode.d.ts +2 -0
- package/dist/extension/tree/util/newNodeId.d.ts +2 -0
- package/dist/extension/tree/util/normalizeWritableNode.d.ts +9 -0
- package/dist/extension/tree/util/rebalanceTreeIndexes.d.ts +11 -0
- package/dist/extension/tree/util/refreshTreeMetadata.d.ts +16 -0
- package/dist/extension/tree/util/repairDuplicatedSiblingConflicts.d.ts +4 -0
- package/dist/extension/tree/util/repairDuplicatedSiblingNames.d.ts +4 -0
- package/dist/extension/tree/util/repairTreeOverwriteConflicts.d.ts +10 -0
- package/dist/extension/tree/util/resolveOverwriteNodes.d.ts +26 -0
- package/dist/extension/tree/util/resolveTreeIndex.d.ts +4 -0
- package/dist/extension/tree/util/setTreeNumberStat.d.ts +9 -0
- package/dist/extension/tree/util/stripTreeManagedFields.d.ts +5 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4017 -1188
- package/dist/test/auto-metadata.test.d.ts +1 -0
- package/dist/test/getTestTable.d.ts +3 -1
- package/dist/test/globals.d.ts +1 -0
- package/dist/test/table-event.test.d.ts +1 -0
- package/dist/test/table-index.test.d.ts +1 -0
- package/dist/test/table-type.test.d.ts +1 -0
- package/dist/test/try/doc.try.d.ts +1 -1
- package/dist/test/try/getTestUserTable.d.ts +1 -1
- package/dist/test/try/insert.try.d.ts +1 -1
- package/dist/test/try/mongodb-try/id-test.d.ts +1 -0
- package/dist/test/try//345/210/233/345/273/272350/344/270/207/346/225/260/346/215/256.d.ts +1 -1
- package/dist/test/try//346/223/215/344/275/234350/344/270/207/346/225/260/346/215/256.d.ts +1 -1
- package/package.json +26 -8
- package/dist/rslib-runtime.js +0 -18
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs-src/logo/tbdb-logo.png" alt="TableDB Logo" height="128" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# TableDB
|
|
6
|
+
|
|
7
|
+
A very simple NoSQL database abstraction layer that provides MongoDB-like CRUD APIs, supporting multiple backends including SQLite, MongoDB and IndexedDB.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
> 这个世界上复杂的数据库和 ORM 已经够多了,而我们只想简单地存个东西。
|
|
12
|
+
|
|
13
|
+
一个非常简单却实用的 NoSQL 数据库抽象层,提供类似 MongoDB 的增删改查 API,支持多种存储后端(SQLite, MongoDB, IndexedDB)。
|
|
14
|
+
|
|
15
|
+
- **完全兼容 JavaScript 数据类型**\
|
|
16
|
+
直接存入 `Date`, `Map`, `RegExp`, `ArrayBuffer`,`Unint8Array`, `Blob`, `File` 等 JavaScript 类型,取出后数据类型不变,不用额外考虑数据库类型问题。
|
|
17
|
+
- **类似 MongoDB 的 NoSQL API**\
|
|
18
|
+
增删改查的接口遵照 MongoDB 设计,例如 `findOne()`, `updateMany()`,易于上手,可以平滑的从 MongoDB 迁移。
|
|
19
|
+
- **切换不同数据库后端**\
|
|
20
|
+
提供 SQLite, MongoDB 等多种数据库适配器,可以方便的切换不同的数据库存储后端。
|
|
21
|
+
并且可以在不同数据库间迁移数据,让你可以从 SQLite 开始,当规模变大时迁移到 MongoDB。
|
|
22
|
+
|
|
23
|
+
- **集成实用方法**\
|
|
24
|
+
内置 “分页”、“游标分页”、“批量遍历”等实用功能。
|
|
25
|
+
|
|
26
|
+
- **可选功能**:
|
|
27
|
+
- `autoMetadata` 自动元数据(创建时间,修改时间)
|
|
28
|
+
- `markDelete` 标记删除
|
|
29
|
+
- `tree` 目录树存储
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## 安装
|
|
35
|
+
|
|
36
|
+
```sh [npm]
|
|
37
|
+
$ npm add -D tbdb fzz
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
> `fzz` 是 TableDB 使用的数据类型定义库 `dto` 的依赖,可选安装,如果你不需要通过定义 Schema 获得更好的 TypeScript 类型提示,可以不安装。
|
|
41
|
+
|
|
42
|
+
## 快速开始
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { defineTable, SQLiteAdapter } from "tbdb"
|
|
46
|
+
|
|
47
|
+
// 1. 定义 Table,并得到 useTable 函数
|
|
48
|
+
let useMemberTable = defineTable({
|
|
49
|
+
name: "Member",
|
|
50
|
+
adapter: SQLiteAdapter({ filename: "./member.sqlite" }),
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// 2.使用 useTable 创建 Table 实例
|
|
54
|
+
let memberTable = await useMemberTable()
|
|
55
|
+
|
|
56
|
+
// 3.使用 Table 实例进行数据操作
|
|
57
|
+
await memberTable.insertMany([
|
|
58
|
+
{
|
|
59
|
+
id: "member1",
|
|
60
|
+
name: "Alice",
|
|
61
|
+
age: 30,
|
|
62
|
+
},
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
let members = await memberTable.findMany({ age: { $gt: 20 } })
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 项目目录结构
|
|
69
|
+
|
|
70
|
+
- 接口定义:`./core/types.ts`, `./adapter/adapter.ts`
|
|
71
|
+
- 核心实现:`./core/Table.ts`
|
|
72
|
+
- 适配器实现:`./adapter/`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ITableDBAdapter } from "../adapter";
|
|
2
|
+
/**
|
|
3
|
+
* IndexedDBAdapter 机制说明
|
|
4
|
+
* ===============================================
|
|
5
|
+
*
|
|
6
|
+
* 核心设计目标:
|
|
7
|
+
* 在浏览器环境下提供高性能的 MongoDB 风格文档数据库体验。
|
|
8
|
+
*
|
|
9
|
+
* 关键机制:
|
|
10
|
+
* 1. 动态 Schema 管理:
|
|
11
|
+
* IndexedDB 只能在 onupgradeneeded 事件中修改 ObjectStore 和 Index。
|
|
12
|
+
* 当调用 defineIndexes 时,如果发现需要创建新索引,会关闭当前数据库连接,
|
|
13
|
+
* 增加版本号并重新打开。
|
|
14
|
+
*
|
|
15
|
+
* 2. 多表与并发升级支持:
|
|
16
|
+
* - 适配器在获取 Store 前会自动检查表是否存在,如果不存在则触发数据库升级。
|
|
17
|
+
* - 通过监听 onversionchange 事件,当其他实例请求升级时主动关闭连接,防止死锁和超时。
|
|
18
|
+
*
|
|
19
|
+
* 3. 混合查询策略:
|
|
20
|
+
* - 尽可能利用 IndexedDB 索引进行范围查询 (IDBKeyRange)。(待进一步优化)
|
|
21
|
+
* - 对于复杂查询,使用游标 (Cursor) 遍历并在内存中进行 matches 匹配。
|
|
22
|
+
*
|
|
23
|
+
* 4. 兼容性:
|
|
24
|
+
* - _id: 为每个文档维护一个虚拟的 _id,以兼容核心层对 _id 的依赖(如游标分页)。
|
|
25
|
+
* - undefined 规范化: 将 undefined 转换为 null,保持与其他适配器行为一致。
|
|
26
|
+
*/
|
|
27
|
+
export declare function IndexedDBAdapter(config: {
|
|
28
|
+
dbName: string;
|
|
29
|
+
}): ITableDBAdapter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./IndexedDBAdapter";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "fake-indexeddb/auto";
|
|
@@ -1,31 +1,120 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ITableDBAdapterInstance, ITableDBAdapter, ITableDefineIndexesOptions, ITableDeletedResult, ITableDeleteOptions, ITableDoc, ITableFindOptions, ITableIndexConfig, ITableInsertResult, ITableSetOptions, ITableSetResult, ITableUpdateOptions, ITableUpdateResult } from "../adapter";
|
|
1
|
+
import { ITableDBAdapterInstance, ITableDBAdapter, ITableDefineIndexesOptions, ITableDeletedResult, ITableDeleteOptions, ITableDoc, ITableFindOptions, ITableIndexConfig, ITableInsertResult, ITableSetOptions, ITableSetResult, ITableUpdateOptions, ITableUpdateResult, ITableDebugResult } from "../adapter";
|
|
3
2
|
import { ITableFilter, ITableUpdateOp } from "../../core/types";
|
|
4
|
-
|
|
3
|
+
import { ISqliteDatabase, SqliteDriverType } from "./driver";
|
|
4
|
+
/**
|
|
5
|
+
* SQLiteAdapter 机制说明文档
|
|
6
|
+
* ===============================================
|
|
7
|
+
*
|
|
8
|
+
* 核心设计目标:
|
|
9
|
+
* 在 SQLite 上提供高性能、全功能的 MongoDB 风格文档数据库体验。
|
|
10
|
+
*
|
|
11
|
+
* 关键机制 (Key Mechanisms):
|
|
12
|
+
*
|
|
13
|
+
* 1. 侧表倒排索引 (Side Table Inverted Index):
|
|
14
|
+
* - 问题: 对于数组字段查询 (e.g. { tags: "A" }),SQLite 原生 JSON 函数需要全表扫描。
|
|
15
|
+
* - 解决: 为数组字段创建辅助表 `_idx_{tableName}_{field}`,存储 `(val, id)` 对。
|
|
16
|
+
* - 实现: 使用 SQLite Triggers 自动维护侧表数据(Insert/Update/Delete 时自动触发)。
|
|
17
|
+
* - 效果: 将 Array Containment 查询转化为高效的 SQL `EXISTS` 子查询。
|
|
18
|
+
*
|
|
19
|
+
* 2. 脏字段检测与查询优化 ( Dirty Tracking & Query Optimization):
|
|
20
|
+
* - 问题: 混合模式 (Hybrid Mode) 虽然万能但较慢,纯 SQL 模式快但可能语义不准确(特别是数组隐式包含)。
|
|
21
|
+
* - 解决: 维护 `_schema_dirty_{tableName}` 表,记录哪些字段曾经存储过数组或特殊值 (NaN/Null)。
|
|
22
|
+
* - 策略:
|
|
23
|
+
* - 如果某字段以前从未存过数组,那么 `{ field: "A" }` 可以安全视为 SQL 相等比较。
|
|
24
|
+
* - 如果存过数组,则必须回退到 JsMatch 或使用侧表。
|
|
25
|
+
*
|
|
26
|
+
* 3. 混合查询执行 (Hybrid Query Execution):
|
|
27
|
+
* - 纯 SQL 模式 (SQL Mode): 当 Filter 可以完全无损映射为 SQL 时使用,性能最高。
|
|
28
|
+
* - 混合模式 (Hybrid Mode): `SELECT ... WHERE (SQL_PreFilter) AND JsMatch(data, filter)`
|
|
29
|
+
* - 利用 SQL 索引进行粗筛。
|
|
30
|
+
* - 利用自定义 SQLite 函数 `JsMatch` 在内存中运行 JS 逻辑进行精确匹配。
|
|
31
|
+
* - 保证了 MongoDB 语义的 100% 兼容性 (Regular Expressions, $where, complex logic)。
|
|
32
|
+
*
|
|
33
|
+
* 4. 批量操作优化:
|
|
34
|
+
* - 批量插入优化: 临时禁用侧表 Trigger -> 批量插入数据 -> 批量 Rebuild 侧表 -> 恢复 Trigger。
|
|
35
|
+
* - 批量更新优化 (bulkUpdateSync): 在单个事务中执行所有操作,减少 I/O 和上下文切换。
|
|
36
|
+
*
|
|
37
|
+
* 5. 多驱动支持 (Multi-Driver Support):
|
|
38
|
+
* - 支持 better-sqlite3 和 node:sqlite (Node.js 22.5+) 两种驱动
|
|
39
|
+
* - 通过 Driver 抽象层统一 API 差异
|
|
40
|
+
* - 可通过 config.driver 指定驱动类型,或使用 "auto" 自动选择
|
|
41
|
+
*/
|
|
42
|
+
/** SQLiteAdapter 配置选项 */
|
|
43
|
+
export interface SQLiteAdapterConfig {
|
|
44
|
+
/** 数据库文件路径,":memory:" 表示内存数据库 */
|
|
5
45
|
filename: string;
|
|
46
|
+
/**
|
|
47
|
+
* 安全模式配置
|
|
48
|
+
* - false/undefined: synchronous=OFF,性能最高但系统崩溃可能丢数据
|
|
49
|
+
* - true: synchronous=NORMAL,平衡性能和安全
|
|
50
|
+
* - "full": synchronous=FULL,最安全,每次写入都落盘
|
|
51
|
+
*/
|
|
6
52
|
safe?: boolean | "full";
|
|
53
|
+
/** 是否启用 ZSTD 压缩(打开文件前解压,关闭文件时压缩) */
|
|
7
54
|
zstd?: boolean;
|
|
8
|
-
|
|
55
|
+
/**
|
|
56
|
+
* 多进程访问模式
|
|
57
|
+
* 使用 WAL 模式和适当的同步设置,SQLite 可以支持多个进程同时访问同一个数据库文件。
|
|
58
|
+
* 启用 multi 模式后,SQLiteAdapter 将自动配置数据库连接以支持多进程访问:
|
|
59
|
+
* - PRAGMA journal_mode=WAL
|
|
60
|
+
* - PRAGMA busy_timeout=15000
|
|
61
|
+
* 可以与 `safe:true` 一起使用
|
|
62
|
+
*/
|
|
63
|
+
multi?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* SQLite 驱动类型
|
|
66
|
+
* - "better-sqlite3": 使用 better-sqlite3(需要安装依赖,兼容性好,支持自定义函数)
|
|
67
|
+
* - "node:sqlite": 使用 Node.js 内置模块(Node.js 22.5+ 无需安装依赖,支持自定义函数)
|
|
68
|
+
* - "bun:sqlite": 使用 Bun 内置模块(仅 Bun 运行时,不支持自定义函数,无法使用混合查询模式)
|
|
69
|
+
* - "auto": 自动选择(Bun 环境用 bun:sqlite,Node 环境优先 better-sqlite3 > node:sqlite)
|
|
70
|
+
*
|
|
71
|
+
* 注意:bun:sqlite 不支持自定义函数,因此无法使用 JsMatch/JsPatch 混合查询模式
|
|
72
|
+
*
|
|
73
|
+
* @default "auto"
|
|
74
|
+
*/
|
|
75
|
+
driver?: SqliteDriverType | "auto";
|
|
76
|
+
}
|
|
77
|
+
export declare function SQLiteAdapter(config: SQLiteAdapterConfig): ITableDBAdapter;
|
|
9
78
|
export declare class SQLiteAdapterInstance implements ITableDBAdapterInstance {
|
|
10
79
|
private db;
|
|
11
80
|
private tableName;
|
|
12
81
|
private config;
|
|
82
|
+
private driverType;
|
|
13
83
|
name: string;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
84
|
+
private statementCache;
|
|
85
|
+
private indexedFields;
|
|
86
|
+
private dirtyFieldCache;
|
|
87
|
+
private supportsCustomFunctions;
|
|
88
|
+
constructor(db: ISqliteDatabase, tableName: string, config: SQLiteAdapterConfig, driverType?: SqliteDriverType);
|
|
89
|
+
private loadDirtyFields;
|
|
90
|
+
/**
|
|
91
|
+
* 检查查询是否可以使用纯 SQL 模式
|
|
92
|
+
*
|
|
93
|
+
* 如果当前驱动不支持自定义函数(如 bun:sqlite),则强制返回 true,
|
|
94
|
+
* 使用纯 SQL 模式(可能会有语义差异,但至少不会报错)
|
|
95
|
+
*/
|
|
96
|
+
private isQueryCompatible;
|
|
97
|
+
private markFieldDirty;
|
|
19
98
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
99
|
+
* 扫描文档并标记脏字段
|
|
100
|
+
* 在写入文档前调用,用于更新 Schema 统计信息
|
|
101
|
+
*/
|
|
102
|
+
private scanAndMarkDirty;
|
|
103
|
+
private loadExistingIndexes;
|
|
104
|
+
private getStatement;
|
|
105
|
+
/**
|
|
106
|
+
* 数据规范化:处理 undefined 和特殊对象类型
|
|
107
|
+
* - undefined -> null (JSON 标准)
|
|
108
|
+
* - 保留 Map, Set, Date, BigInt, Blob 等特殊类型 (Serializer 会处理)
|
|
22
109
|
*/
|
|
23
110
|
private normalizeUndefined;
|
|
24
111
|
get(id: any): Promise<ITableDoc | void>;
|
|
25
112
|
set(id: any, value: ITableDoc): Promise<void>;
|
|
26
113
|
delete(id: any): Promise<void>;
|
|
27
114
|
has(id: any): Promise<boolean>;
|
|
28
|
-
count(filter?: ITableFilter
|
|
115
|
+
count(filter?: ITableFilter, options?: {
|
|
116
|
+
debug?: ITableDebugResult;
|
|
117
|
+
}): Promise<number>;
|
|
29
118
|
clear(): Promise<void>;
|
|
30
119
|
clearAll(): Promise<void>;
|
|
31
120
|
drop(): Promise<void>;
|
|
@@ -37,13 +126,46 @@ export declare class SQLiteAdapterInstance implements ITableDBAdapterInstance {
|
|
|
37
126
|
filter: ITableFilter;
|
|
38
127
|
updateOp: ITableUpdateOp<ITableDoc>;
|
|
39
128
|
options?: ITableUpdateOptions;
|
|
40
|
-
}[]
|
|
129
|
+
}[], options?: {
|
|
130
|
+
debug?: ITableDebugResult;
|
|
131
|
+
}): Promise<ITableUpdateResult>;
|
|
132
|
+
bulkUpdateSync(updates: {
|
|
133
|
+
filter: ITableFilter;
|
|
134
|
+
updateOp: ITableUpdateOp<ITableDoc>;
|
|
135
|
+
options?: ITableUpdateOptions;
|
|
136
|
+
}[], options?: {
|
|
137
|
+
debug?: ITableDebugResult;
|
|
138
|
+
}): Promise<ITableUpdateResult>;
|
|
41
139
|
updateOne(filter: ITableFilter, updateOp: ITableUpdateOp<ITableDoc>, options?: ITableUpdateOptions): Promise<ITableUpdateResult>;
|
|
42
|
-
|
|
140
|
+
private static BULK_IMPORT_THRESHOLD;
|
|
141
|
+
insertMany(docs: ITableDoc[], options?: {
|
|
142
|
+
debug?: ITableDebugResult;
|
|
143
|
+
}): Promise<ITableInsertResult>;
|
|
144
|
+
/**
|
|
145
|
+
* 默认批量插入实现
|
|
146
|
+
* 使用标准事务通过 INSERT 语句逐条插入
|
|
147
|
+
*/
|
|
148
|
+
private insertManyDefault;
|
|
149
|
+
/**
|
|
150
|
+
* 高性能批量插入实现
|
|
151
|
+
*
|
|
152
|
+
* 优化机制:
|
|
153
|
+
* 1. 禁用 Trigger: 临时禁用侧表维护触发器。
|
|
154
|
+
* 2. 批量写入: 执行纯数据插入。
|
|
155
|
+
* 3. 批量重建 (Rebuild): 插入完成后,rebuildSideTableIndexes 一次性回填。
|
|
156
|
+
*/
|
|
157
|
+
private insertManyOptimized;
|
|
43
158
|
setMany(docs: Partial<ITableDoc>[], options?: ITableSetOptions): Promise<ITableSetResult>;
|
|
44
|
-
deleteMany(filter: ITableFilter): Promise<ITableDeletedResult>;
|
|
159
|
+
deleteMany(filter: ITableFilter, options?: ITableDeleteOptions): Promise<ITableDeletedResult>;
|
|
45
160
|
deleteOne(filter: ITableFilter, options?: ITableDeleteOptions): Promise<ITableDeletedResult>;
|
|
46
161
|
defineIndexes(indexes: ITableIndexConfig[], options?: ITableDefineIndexesOptions): Promise<void>;
|
|
162
|
+
private getSideTableName;
|
|
163
|
+
private createSideTableIndex;
|
|
164
|
+
private dropSideTableIndex;
|
|
165
|
+
disableSideTableTriggers(): Promise<void>;
|
|
166
|
+
enableSideTableTriggers(): Promise<void>;
|
|
167
|
+
private createSideTableTriggersOnly;
|
|
168
|
+
rebuildSideTableIndexes(): Promise<void>;
|
|
47
169
|
dropIndexes(): Promise<void>;
|
|
48
170
|
compact(): Promise<void>;
|
|
49
171
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BetterSqlite3Driver - better-sqlite3 的 Driver 实现
|
|
3
|
+
*
|
|
4
|
+
* 包装 better-sqlite3 以符合 ISqliteDatabase 接口
|
|
5
|
+
*/
|
|
6
|
+
import type Database from "better-sqlite3";
|
|
7
|
+
import type { ISqliteDatabase, ISqliteStatement, ISqliteTransactionFn, ISqliteDriverConfig } from "./types";
|
|
8
|
+
/**
|
|
9
|
+
* 包装 better-sqlite3 Database
|
|
10
|
+
*/
|
|
11
|
+
export declare class BetterSqlite3Driver implements ISqliteDatabase {
|
|
12
|
+
private db;
|
|
13
|
+
private stmtCache;
|
|
14
|
+
constructor(config: ISqliteDriverConfig);
|
|
15
|
+
get isOpen(): boolean;
|
|
16
|
+
prepare(sql: string): ISqliteStatement;
|
|
17
|
+
exec(sql: string): void;
|
|
18
|
+
function(name: string, fn: (...args: any[]) => any): void;
|
|
19
|
+
transaction<T extends (...args: any[]) => any>(fn: T): ISqliteTransactionFn<T>;
|
|
20
|
+
checkpoint(mode?: "PASSIVE" | "FULL" | "RESTART" | "TRUNCATE"): void;
|
|
21
|
+
close(): void;
|
|
22
|
+
/**
|
|
23
|
+
* 获取原始的 better-sqlite3 Database 实例
|
|
24
|
+
* 用于需要直接访问底层 API 的场景(如 zstd 压缩)
|
|
25
|
+
*/
|
|
26
|
+
getRawDatabase(): Database.Database;
|
|
27
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BunSqliteDriver - bun:sqlite 的 Driver 实现
|
|
3
|
+
*
|
|
4
|
+
* 包装 Bun 内置的 bun:sqlite 模块以符合 ISqliteDatabase 接口
|
|
5
|
+
*
|
|
6
|
+
* 注意事项:
|
|
7
|
+
* 1. bun:sqlite 仅在 Bun 运行时可用
|
|
8
|
+
* 2. bun:sqlite 不支持自定义函数 (db.function),会抛出错误
|
|
9
|
+
* 3. 因此使用此驱动时,无法使用依赖 JsMatch/JsPatch 的混合查询模式
|
|
10
|
+
*/
|
|
11
|
+
import type { ISqliteDatabase, ISqliteStatement, ISqliteTransactionFn, ISqliteDriverConfig } from "./types";
|
|
12
|
+
interface BunSqliteStatement {
|
|
13
|
+
all(...params: any[]): any[];
|
|
14
|
+
get(...params: any[]): any;
|
|
15
|
+
run(...params: any[]): {
|
|
16
|
+
changes: number | bigint;
|
|
17
|
+
lastInsertRowid: number | bigint;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
interface BunSqliteDatabase {
|
|
21
|
+
query(sql: string): BunSqliteStatement;
|
|
22
|
+
exec(sql: string): void;
|
|
23
|
+
close(): void;
|
|
24
|
+
transaction<T>(fn: () => T): () => T;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 包装 bun:sqlite Database
|
|
28
|
+
*
|
|
29
|
+
* 主要差异处理:
|
|
30
|
+
* 1. bun:sqlite 使用 query() 而不是 prepare()
|
|
31
|
+
* 2. bun:sqlite 不支持自定义函数 function()
|
|
32
|
+
* 3. bun:sqlite 没有 isOpen 属性
|
|
33
|
+
* 4. bun:sqlite 的 transaction() API 不同于 better-sqlite3
|
|
34
|
+
*/
|
|
35
|
+
export declare class BunSqliteDriver implements ISqliteDatabase {
|
|
36
|
+
private db;
|
|
37
|
+
private stmtCache;
|
|
38
|
+
private _isOpen;
|
|
39
|
+
constructor(config: ISqliteDriverConfig);
|
|
40
|
+
get isOpen(): boolean;
|
|
41
|
+
prepare(sql: string): ISqliteStatement;
|
|
42
|
+
exec(sql: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* bun:sqlite 不支持自定义函数
|
|
45
|
+
*
|
|
46
|
+
* 这意味着使用 BunSqliteDriver 时:
|
|
47
|
+
* - 无法使用 JsMatch 进行混合模式查询
|
|
48
|
+
* - 无法使用 JsPatch 进行内存更新
|
|
49
|
+
* - 所有查询必须使用纯 SQL 模式
|
|
50
|
+
*
|
|
51
|
+
* @throws Error 始终抛出错误
|
|
52
|
+
*/
|
|
53
|
+
function(_name: string, _fn: (...args: any[]) => any): void;
|
|
54
|
+
/**
|
|
55
|
+
* 包装 bun:sqlite 的 transaction() 方法
|
|
56
|
+
*
|
|
57
|
+
* bun:sqlite 的 transaction() 签名: transaction<T>(fn: () => T): () => T
|
|
58
|
+
* better-sqlite3 的 transaction() 签名: transaction<T>(fn: T): T & { immediate, exclusive, deferred }
|
|
59
|
+
*/
|
|
60
|
+
transaction<T extends (...args: any[]) => any>(fn: T): ISqliteTransactionFn<T>;
|
|
61
|
+
checkpoint(mode?: "PASSIVE" | "FULL" | "RESTART" | "TRUNCATE"): void;
|
|
62
|
+
close(): void;
|
|
63
|
+
/**
|
|
64
|
+
* 获取原始的 bun:sqlite Database 实例
|
|
65
|
+
*/
|
|
66
|
+
getRawDatabase(): BunSqliteDatabase;
|
|
67
|
+
}
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NodeSqliteDriver - node:sqlite 的 Driver 实现
|
|
3
|
+
*
|
|
4
|
+
* 包装 Node.js 22+ 内置的 node:sqlite 模块以符合 ISqliteDatabase 接口
|
|
5
|
+
*
|
|
6
|
+
* 注意事项:
|
|
7
|
+
* 1. node:sqlite 从 Node.js 22.5.0 开始可用
|
|
8
|
+
* 2. node:sqlite 不支持 db.transaction(),需要手动实现
|
|
9
|
+
* 3. pragma 需要通过 db.exec() 执行
|
|
10
|
+
*/
|
|
11
|
+
import type { ISqliteDatabase, ISqliteStatement, ISqliteTransactionFn, ISqliteDriverConfig } from "./types";
|
|
12
|
+
interface NodeSqliteStatement {
|
|
13
|
+
all(...params: any[]): any[];
|
|
14
|
+
get(...params: any[]): any;
|
|
15
|
+
run(...params: any[]): {
|
|
16
|
+
changes: number | bigint;
|
|
17
|
+
lastInsertRowid: number | bigint;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
interface NodeSqliteDatabase {
|
|
21
|
+
isOpen: boolean;
|
|
22
|
+
prepare(sql: string): NodeSqliteStatement;
|
|
23
|
+
exec(sql: string): void;
|
|
24
|
+
function(name: string, options: {
|
|
25
|
+
varargs?: boolean;
|
|
26
|
+
}, fn: (...args: any[]) => any): void;
|
|
27
|
+
function(name: string, fn: (...args: any[]) => any): void;
|
|
28
|
+
close(): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 包装 node:sqlite Database
|
|
32
|
+
*
|
|
33
|
+
* 主要差异处理:
|
|
34
|
+
* 1. transaction() 需要手动实现(使用 BEGIN/COMMIT/ROLLBACK)
|
|
35
|
+
* 2. function() 的签名略有不同
|
|
36
|
+
* 3. isOpen 属性名称相同
|
|
37
|
+
*/
|
|
38
|
+
export declare class NodeSqliteDriver implements ISqliteDatabase {
|
|
39
|
+
private db;
|
|
40
|
+
private stmtCache;
|
|
41
|
+
constructor(config: ISqliteDriverConfig);
|
|
42
|
+
get isOpen(): boolean;
|
|
43
|
+
prepare(sql: string): ISqliteStatement;
|
|
44
|
+
exec(sql: string): void;
|
|
45
|
+
function(name: string, fn: (...args: any[]) => any): void;
|
|
46
|
+
/**
|
|
47
|
+
* 模拟 better-sqlite3 的 transaction() 行为
|
|
48
|
+
*
|
|
49
|
+
* better-sqlite3 的 transaction() 返回一个函数,调用时会自动包装在事务中
|
|
50
|
+
* node:sqlite 没有这个 API,需要手动实现
|
|
51
|
+
*/
|
|
52
|
+
transaction<T extends (...args: any[]) => any>(fn: T): ISqliteTransactionFn<T>;
|
|
53
|
+
checkpoint(mode?: "PASSIVE" | "FULL" | "RESTART" | "TRUNCATE"): void;
|
|
54
|
+
close(): void;
|
|
55
|
+
/**
|
|
56
|
+
* 获取原始的 node:sqlite Database 实例
|
|
57
|
+
*/
|
|
58
|
+
getRawDatabase(): NodeSqliteDatabase;
|
|
59
|
+
}
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Driver 统一导出
|
|
3
|
+
*
|
|
4
|
+
/**
|
|
5
|
+
* SQLite Driver 统一导出
|
|
6
|
+
*
|
|
7
|
+
* 提供 better-sqlite3 和 node:sqlite 两种驱动的统一接口
|
|
8
|
+
*/
|
|
9
|
+
export * from "./types";
|
|
10
|
+
export { BetterSqlite3Driver } from "./BetterSqlite3Driver";
|
|
11
|
+
export { NodeSqliteDriver } from "./NodeSqliteDriver";
|
|
12
|
+
export { BunSqliteDriver } from "./BunSqliteDriver";
|
|
13
|
+
import type { ISqliteDatabase, ISqliteDriverConfig, SqliteDriverType } from "./types";
|
|
14
|
+
/**
|
|
15
|
+
* 创建 SQLite Driver 实例
|
|
16
|
+
*
|
|
17
|
+
* @param type 驱动类型: "better-sqlite3" 或 "node:sqlite"
|
|
18
|
+
* @param config 驱动配置
|
|
19
|
+
* @returns SQLite 数据库实例
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* // 使用 better-sqlite3(默认,兼容性更好)
|
|
24
|
+
* const db = createSqliteDriver("better-sqlite3", { filename: "test.db" })
|
|
25
|
+
*
|
|
26
|
+
* // 使用 node:sqlite(Node.js 22.5+ 内置,无需安装依赖)
|
|
27
|
+
* const db = createSqliteDriver("node:sqlite", { filename: "test.db" })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function createSqliteDriver(type: SqliteDriverType, config: ISqliteDriverConfig): ISqliteDatabase;
|
|
31
|
+
/**
|
|
32
|
+
* 自动检测并创建可用的 SQLite Driver
|
|
33
|
+
*
|
|
34
|
+
* 选择逻辑:
|
|
35
|
+
* 1. Bun 环境:直接使用 bun:sqlite
|
|
36
|
+
* 2. Node 环境:
|
|
37
|
+
* - 优先使用环境变量 TABLEDB_SQLITE_DRIVER 指定的驱动
|
|
38
|
+
* - 其次使用 better-sqlite3
|
|
39
|
+
* - 如果 better-sqlite3 不可用,退回 node:sqlite
|
|
40
|
+
*
|
|
41
|
+
* @param config 驱动配置
|
|
42
|
+
* @returns SQLite 数据库实例和使用的驱动类型
|
|
43
|
+
*/
|
|
44
|
+
export declare function createAutoSqliteDriver(config: ISqliteDriverConfig): {
|
|
45
|
+
db: ISqliteDatabase;
|
|
46
|
+
type: SqliteDriverType;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* 检查指定的 SQLite 驱动是否可用
|
|
50
|
+
*/
|
|
51
|
+
export declare function isSqliteDriverAvailable(type: SqliteDriverType): boolean;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Driver 抽象层类型定义
|
|
3
|
+
*
|
|
4
|
+
* 提供统一的接口让 better-sqlite3 和 node:sqlite 可以互换使用
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* SQLite Statement 抽象接口
|
|
8
|
+
* 对应 better-sqlite3 的 Statement 和 node:sqlite 的 StatementSync
|
|
9
|
+
*/
|
|
10
|
+
export interface ISqliteStatement {
|
|
11
|
+
/**
|
|
12
|
+
* 执行语句并返回所有结果行
|
|
13
|
+
*/
|
|
14
|
+
all(...params: any[]): any[];
|
|
15
|
+
/**
|
|
16
|
+
* 执行语句并返回第一行结果
|
|
17
|
+
*/
|
|
18
|
+
get(...params: any[]): any;
|
|
19
|
+
/**
|
|
20
|
+
* 执行语句(用于 INSERT/UPDATE/DELETE)
|
|
21
|
+
* @returns 包含 changes 和 lastInsertRowid 的对象
|
|
22
|
+
*/
|
|
23
|
+
run(...params: any[]): ISqliteRunResult;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Statement.run() 的返回值
|
|
27
|
+
*/
|
|
28
|
+
export interface ISqliteRunResult {
|
|
29
|
+
/** 受影响的行数 */
|
|
30
|
+
changes: number | bigint;
|
|
31
|
+
/** 最后插入行的 rowid */
|
|
32
|
+
lastInsertRowid: number | bigint;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* SQLite 事务函数类型
|
|
36
|
+
* better-sqlite3 使用 db.transaction() 返回一个可调用函数
|
|
37
|
+
* node:sqlite 需要手动管理 BEGIN/COMMIT
|
|
38
|
+
*/
|
|
39
|
+
export type ISqliteTransactionFn<T extends (...args: any[]) => any> = T & {
|
|
40
|
+
/** 立即执行事务 */
|
|
41
|
+
immediate: T;
|
|
42
|
+
/** 独占执行事务 */
|
|
43
|
+
exclusive: T;
|
|
44
|
+
/** 延迟执行事务 */
|
|
45
|
+
deferred: T;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* SQLite Database 抽象接口
|
|
49
|
+
* 统一 better-sqlite3 和 node:sqlite 的 API 差异
|
|
50
|
+
*/
|
|
51
|
+
export interface ISqliteDatabase {
|
|
52
|
+
/**
|
|
53
|
+
* 数据库是否已打开
|
|
54
|
+
*/
|
|
55
|
+
readonly isOpen: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* 准备 SQL 语句
|
|
58
|
+
* @param sql SQL 语句
|
|
59
|
+
* @returns 预编译的语句对象
|
|
60
|
+
*/
|
|
61
|
+
prepare(sql: string): ISqliteStatement;
|
|
62
|
+
/**
|
|
63
|
+
* 执行 SQL 语句(不返回结果)
|
|
64
|
+
* @param sql SQL 语句
|
|
65
|
+
*/
|
|
66
|
+
exec(sql: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* 注册自定义函数
|
|
69
|
+
* @param name 函数名
|
|
70
|
+
* @param fn 函数实现
|
|
71
|
+
*/
|
|
72
|
+
function(name: string, fn: (...args: any[]) => any): void;
|
|
73
|
+
/**
|
|
74
|
+
* 创建事务
|
|
75
|
+
* @param fn 事务函数
|
|
76
|
+
* @returns 可调用的事务函数
|
|
77
|
+
*/
|
|
78
|
+
transaction<T extends (...args: any[]) => any>(fn: T): ISqliteTransactionFn<T>;
|
|
79
|
+
/**
|
|
80
|
+
* 执行 WAL checkpoint
|
|
81
|
+
* 用于在压缩数据库文件前确保所有 WAL 数据已写入主文件
|
|
82
|
+
* @param mode checkpoint 模式,默认 "TRUNCATE"
|
|
83
|
+
*/
|
|
84
|
+
checkpoint(mode?: "PASSIVE" | "FULL" | "RESTART" | "TRUNCATE"): void;
|
|
85
|
+
/**
|
|
86
|
+
* 关闭数据库连接
|
|
87
|
+
*/
|
|
88
|
+
close(): void;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* SQLite Driver 工厂配置
|
|
92
|
+
*/
|
|
93
|
+
export interface ISqliteDriverConfig {
|
|
94
|
+
/** 数据库文件路径,":memory:" 表示内存数据库 */
|
|
95
|
+
filename: string;
|
|
96
|
+
/** 是否启用 WAL 模式 */
|
|
97
|
+
walMode?: boolean;
|
|
98
|
+
/** 数据库繁忙时的等待时间,单位毫秒 */
|
|
99
|
+
busyTimeout?: number;
|
|
100
|
+
/** 同步模式: "OFF" | "NORMAL" | "FULL" */
|
|
101
|
+
synchronous?: "OFF" | "NORMAL" | "FULL";
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* SQLite Driver 类型枚举
|
|
105
|
+
*/
|
|
106
|
+
export type SqliteDriverType = "better-sqlite3" | "node:sqlite" | "bun:sqlite";
|
|
@@ -1 +1,4 @@
|
|
|
1
1
|
export { SQLiteAdapter } from "./SQLiteAdapter";
|
|
2
|
+
export type { SQLiteAdapterConfig } from "./SQLiteAdapter";
|
|
3
|
+
export { createSqliteDriver, createAutoSqliteDriver, isSqliteDriverAvailable, BetterSqlite3Driver, NodeSqliteDriver, } from "./driver";
|
|
4
|
+
export type { ISqliteDatabase, ISqliteStatement, ISqliteRunResult, ISqliteDriverConfig, SqliteDriverType, } from "./driver";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 脏字段检测 (Dirty Tracking) 机制测试
|
|
3
|
+
*
|
|
4
|
+
* ✅ 已修复的 BUG:
|
|
5
|
+
*
|
|
6
|
+
* 1. [已修复] NaN 值查询返回 0 条结果
|
|
7
|
+
* - 根因:mongoToSql.ts 对 NaN 生成错误的类型检查
|
|
8
|
+
* - 修复:检测 NaN 并生成 `json_type = 'object'` 条件
|
|
9
|
+
*
|
|
10
|
+
* 2. [已修复] Infinity 值查询返回 0 条结果
|
|
11
|
+
* - 根因:同上
|
|
12
|
+
* - 修复:同上
|
|
13
|
+
*
|
|
14
|
+
* 测试覆盖:
|
|
15
|
+
* 1. 字段类型变化追踪
|
|
16
|
+
* 2. clearAll 后缓存一致性
|
|
17
|
+
* 3. 嵌套路径追踪
|
|
18
|
+
* 4. 特殊值 (NaN, Infinity, null) 追踪和查询
|
|
19
|
+
* 5. 批量操作追踪
|
|
20
|
+
* 6. 更新操作追踪(包括 upsert)
|
|
21
|
+
* 7. 查询策略验证
|
|
22
|
+
* 8. 并发写入追踪
|
|
23
|
+
*/
|
|
24
|
+
export {};
|