@yydb/light-db 0.0.0

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.
Files changed (150) hide show
  1. package/dist/api/LightDB.d.ts +194 -0
  2. package/dist/api/LightDB.d.ts.map +1 -0
  3. package/dist/api/LightDB.js +299 -0
  4. package/dist/api/LightDB.js.map +1 -0
  5. package/dist/api/Transaction.d.ts +100 -0
  6. package/dist/api/Transaction.d.ts.map +1 -0
  7. package/dist/api/Transaction.js +263 -0
  8. package/dist/api/Transaction.js.map +1 -0
  9. package/dist/api/index.d.ts +24 -0
  10. package/dist/api/index.d.ts.map +1 -0
  11. package/dist/api/index.js +54 -0
  12. package/dist/api/index.js.map +1 -0
  13. package/dist/api/types.d.ts +154 -0
  14. package/dist/api/types.d.ts.map +1 -0
  15. package/dist/api/types.js +7 -0
  16. package/dist/api/types.js.map +1 -0
  17. package/dist/collection/Collection.d.ts +235 -0
  18. package/dist/collection/Collection.d.ts.map +1 -0
  19. package/dist/collection/Collection.js +671 -0
  20. package/dist/collection/Collection.js.map +1 -0
  21. package/dist/collection/QueryBuilder.d.ts +225 -0
  22. package/dist/collection/QueryBuilder.d.ts.map +1 -0
  23. package/dist/collection/QueryBuilder.js +475 -0
  24. package/dist/collection/QueryBuilder.js.map +1 -0
  25. package/dist/collection/QueryParser.d.ts +117 -0
  26. package/dist/collection/QueryParser.d.ts.map +1 -0
  27. package/dist/collection/QueryParser.js +438 -0
  28. package/dist/collection/QueryParser.js.map +1 -0
  29. package/dist/collection/index.d.ts +42 -0
  30. package/dist/collection/index.d.ts.map +1 -0
  31. package/dist/collection/index.js +41 -0
  32. package/dist/collection/index.js.map +1 -0
  33. package/dist/collection/types.d.ts +365 -0
  34. package/dist/collection/types.d.ts.map +1 -0
  35. package/dist/collection/types.js +7 -0
  36. package/dist/collection/types.js.map +1 -0
  37. package/dist/constants/index.d.ts +51 -0
  38. package/dist/constants/index.d.ts.map +1 -0
  39. package/dist/constants/index.js +68 -0
  40. package/dist/constants/index.js.map +1 -0
  41. package/dist/errors/index.d.ts +69 -0
  42. package/dist/errors/index.d.ts.map +1 -0
  43. package/dist/errors/index.js +132 -0
  44. package/dist/errors/index.js.map +1 -0
  45. package/dist/index.d.ts +220 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +729 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/indexes/BPlusTree.d.ts +181 -0
  50. package/dist/indexes/BPlusTree.d.ts.map +1 -0
  51. package/dist/indexes/BPlusTree.js +528 -0
  52. package/dist/indexes/BPlusTree.js.map +1 -0
  53. package/dist/indexes/IndexManager.d.ts +236 -0
  54. package/dist/indexes/IndexManager.d.ts.map +1 -0
  55. package/dist/indexes/IndexManager.js +502 -0
  56. package/dist/indexes/IndexManager.js.map +1 -0
  57. package/dist/indexes/PrimaryIndex.d.ts +240 -0
  58. package/dist/indexes/PrimaryIndex.d.ts.map +1 -0
  59. package/dist/indexes/PrimaryIndex.js +354 -0
  60. package/dist/indexes/PrimaryIndex.js.map +1 -0
  61. package/dist/indexes/SecondaryIndex.d.ts +204 -0
  62. package/dist/indexes/SecondaryIndex.d.ts.map +1 -0
  63. package/dist/indexes/SecondaryIndex.js +480 -0
  64. package/dist/indexes/SecondaryIndex.js.map +1 -0
  65. package/dist/indexes/errors.d.ts +66 -0
  66. package/dist/indexes/errors.d.ts.map +1 -0
  67. package/dist/indexes/errors.js +117 -0
  68. package/dist/indexes/errors.js.map +1 -0
  69. package/dist/indexes/index.d.ts +52 -0
  70. package/dist/indexes/index.d.ts.map +1 -0
  71. package/dist/indexes/index.js +131 -0
  72. package/dist/indexes/index.js.map +1 -0
  73. package/dist/indexes/types.d.ts +246 -0
  74. package/dist/indexes/types.d.ts.map +1 -0
  75. package/dist/indexes/types.js +30 -0
  76. package/dist/indexes/types.js.map +1 -0
  77. package/dist/performance/BatchWALWriter.d.ts +185 -0
  78. package/dist/performance/BatchWALWriter.d.ts.map +1 -0
  79. package/dist/performance/BatchWALWriter.js +490 -0
  80. package/dist/performance/BatchWALWriter.js.map +1 -0
  81. package/dist/performance/ColumnarStorage.d.ts +138 -0
  82. package/dist/performance/ColumnarStorage.d.ts.map +1 -0
  83. package/dist/performance/ColumnarStorage.js +875 -0
  84. package/dist/performance/ColumnarStorage.js.map +1 -0
  85. package/dist/performance/LazyQuery.d.ts +307 -0
  86. package/dist/performance/LazyQuery.d.ts.map +1 -0
  87. package/dist/performance/LazyQuery.js +588 -0
  88. package/dist/performance/LazyQuery.js.map +1 -0
  89. package/dist/performance/OptimizedBuffer.d.ts +375 -0
  90. package/dist/performance/OptimizedBuffer.d.ts.map +1 -0
  91. package/dist/performance/OptimizedBuffer.js +730 -0
  92. package/dist/performance/OptimizedBuffer.js.map +1 -0
  93. package/dist/performance/RWLock.d.ts +260 -0
  94. package/dist/performance/RWLock.d.ts.map +1 -0
  95. package/dist/performance/RWLock.js +570 -0
  96. package/dist/performance/RWLock.js.map +1 -0
  97. package/dist/performance/index.d.ts +41 -0
  98. package/dist/performance/index.d.ts.map +1 -0
  99. package/dist/performance/index.js +162 -0
  100. package/dist/performance/index.js.map +1 -0
  101. package/dist/performance/types.d.ts +247 -0
  102. package/dist/performance/types.d.ts.map +1 -0
  103. package/dist/performance/types.js +26 -0
  104. package/dist/performance/types.js.map +1 -0
  105. package/dist/storage/Checkpoint.d.ts +128 -0
  106. package/dist/storage/Checkpoint.d.ts.map +1 -0
  107. package/dist/storage/Checkpoint.js +251 -0
  108. package/dist/storage/Checkpoint.js.map +1 -0
  109. package/dist/storage/LightFile.d.ts +227 -0
  110. package/dist/storage/LightFile.d.ts.map +1 -0
  111. package/dist/storage/LightFile.js +526 -0
  112. package/dist/storage/LightFile.js.map +1 -0
  113. package/dist/storage/Recovery.d.ts +172 -0
  114. package/dist/storage/Recovery.d.ts.map +1 -0
  115. package/dist/storage/Recovery.js +399 -0
  116. package/dist/storage/Recovery.js.map +1 -0
  117. package/dist/storage/SHMFile.d.ts +243 -0
  118. package/dist/storage/SHMFile.d.ts.map +1 -0
  119. package/dist/storage/SHMFile.js +436 -0
  120. package/dist/storage/SHMFile.js.map +1 -0
  121. package/dist/storage/StorageEngine.d.ts +146 -0
  122. package/dist/storage/StorageEngine.d.ts.map +1 -0
  123. package/dist/storage/StorageEngine.js +353 -0
  124. package/dist/storage/StorageEngine.js.map +1 -0
  125. package/dist/storage/WALFile.d.ts +248 -0
  126. package/dist/storage/WALFile.d.ts.map +1 -0
  127. package/dist/storage/WALFile.js +597 -0
  128. package/dist/storage/WALFile.js.map +1 -0
  129. package/dist/storage/index.d.ts +10 -0
  130. package/dist/storage/index.d.ts.map +1 -0
  131. package/dist/storage/index.js +153 -0
  132. package/dist/storage/index.js.map +1 -0
  133. package/dist/types/index.d.ts +220 -0
  134. package/dist/types/index.d.ts.map +1 -0
  135. package/dist/types/index.js +7 -0
  136. package/dist/types/index.js.map +1 -0
  137. package/dist/utils/binary.d.ts +271 -0
  138. package/dist/utils/binary.d.ts.map +1 -0
  139. package/dist/utils/binary.js +454 -0
  140. package/dist/utils/binary.js.map +1 -0
  141. package/dist/utils/file.d.ts +166 -0
  142. package/dist/utils/file.d.ts.map +1 -0
  143. package/dist/utils/file.js +346 -0
  144. package/dist/utils/file.js.map +1 -0
  145. package/dist/utils/index.d.ts +6 -0
  146. package/dist/utils/index.d.ts.map +1 -0
  147. package/dist/utils/index.js +39 -0
  148. package/dist/utils/index.js.map +1 -0
  149. package/package.json +37 -0
  150. package/readme.md +124 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * LightDB 二级索引实现
3
+ * 使用 Map<索引值, Set<主键>> 结构,支持高效的等值查询
4
+ */
5
+ import type { IndexKey, IndexValue, IndexStats, EqualityCondition } from "./types";
6
+ import { IndexType } from "./types";
7
+ /**
8
+ * 二级索引配置
9
+ */
10
+ export interface SecondaryIndexConfig {
11
+ /** 索引名称 */
12
+ name: string;
13
+ /** 字段名 */
14
+ fieldName: string;
15
+ /** 是否唯一索引 */
16
+ unique?: boolean;
17
+ /** 是否稀疏索引(不索引 null/undefined 值) */
18
+ sparse?: boolean;
19
+ }
20
+ /**
21
+ * 二级索引
22
+ * 使用 Map + Set 结构实现,支持等值查询和范围查询
23
+ */
24
+ export declare class SecondaryIndex {
25
+ private readonly index;
26
+ private readonly config;
27
+ private keyCount;
28
+ /**
29
+ * 创建二级索引实例
30
+ * @param config 索引配置
31
+ */
32
+ constructor(config: SecondaryIndexConfig);
33
+ /**
34
+ * 获取索引名称
35
+ */
36
+ get Name(): string;
37
+ /**
38
+ * 获取字段名
39
+ */
40
+ get FieldName(): string;
41
+ /**
42
+ * 获取索引类型
43
+ */
44
+ get Type(): IndexType.Secondary | IndexType.Unique;
45
+ /**
46
+ * 获取是否唯一索引
47
+ */
48
+ get IsUnique(): boolean;
49
+ /**
50
+ * 获取是否稀疏索引
51
+ */
52
+ get IsSparse(): boolean;
53
+ /**
54
+ * 获取索引中的键数量
55
+ */
56
+ get Size(): number;
57
+ /**
58
+ * 获取索引值数量
59
+ */
60
+ get ValueCount(): number;
61
+ /**
62
+ * 检查索引是否为空
63
+ */
64
+ isEmpty(): boolean;
65
+ /**
66
+ * 插入索引条目
67
+ * @param value 索引值
68
+ * @param primaryKey 主键
69
+ * @param throwOnDuplicate 如果是唯一索引且值已存在是否抛出异常
70
+ * @returns 是否插入成功
71
+ */
72
+ insert(value: IndexValue, primaryKey: IndexKey, throwOnDuplicate?: boolean): boolean;
73
+ /**
74
+ * 删除索引条目
75
+ * @param value 索引值
76
+ * @param primaryKey 主键
77
+ * @returns 是否删除成功
78
+ */
79
+ delete(value: IndexValue, primaryKey: IndexKey): boolean;
80
+ /**
81
+ * 更新索引条目
82
+ * @param oldValue 旧索引值
83
+ * @param newValue 新索引值
84
+ * @param primaryKey 主键
85
+ * @param throwOnDuplicate 如果是唯一索引且新值已存在是否抛出异常
86
+ * @returns 是否更新成功
87
+ */
88
+ update(oldValue: IndexValue, newValue: IndexValue, primaryKey: IndexKey, throwOnDuplicate?: boolean): boolean;
89
+ /**
90
+ * 等值查询
91
+ * @param value 索引值
92
+ * @returns 匹配的主键集合
93
+ */
94
+ find(value: IndexValue): Set<IndexKey>;
95
+ /**
96
+ * 检查索引值是否存在
97
+ * @param value 索引值
98
+ */
99
+ has(value: IndexValue): boolean;
100
+ /**
101
+ * 检查索引值和主键组合是否存在
102
+ * @param value 索引值
103
+ * @param primaryKey 主键
104
+ */
105
+ hasEntry(value: IndexValue, primaryKey: IndexKey): boolean;
106
+ /**
107
+ * 条件查询
108
+ * @param condition 查询条件
109
+ * @returns 匹配的主键集合
110
+ */
111
+ query(condition: EqualityCondition<IndexValue>): Set<IndexKey>;
112
+ /**
113
+ * 范围查询
114
+ * @param start 起始值
115
+ * @param end 结束值
116
+ * @param includeStart 是否包含起始值
117
+ * @param includeEnd 是否包含结束值
118
+ * @returns 匹配的主键集合
119
+ */
120
+ range(start?: IndexValue, end?: IndexValue, includeStart?: boolean, includeEnd?: boolean): Set<IndexKey>;
121
+ /**
122
+ * 获取所有索引值
123
+ */
124
+ values(): IndexValue[];
125
+ /**
126
+ * 获取所有主键
127
+ */
128
+ keys(): IndexKey[];
129
+ /**
130
+ * 获取所有条目
131
+ */
132
+ entries(): Array<{
133
+ value: IndexValue;
134
+ keys: Set<IndexKey>;
135
+ }>;
136
+ /**
137
+ * 清空索引
138
+ */
139
+ clear(): void;
140
+ /**
141
+ * 获取索引统计信息
142
+ */
143
+ getStats(): IndexStats;
144
+ /**
145
+ * 批量插入
146
+ * @param entries 条目数组
147
+ * @param throwOnDuplicate 如果是唯一索引且值已存在是否抛出异常
148
+ */
149
+ insertBatch(
150
+ entries: Array<{
151
+ value: IndexValue;
152
+ primaryKey: IndexKey;
153
+ }>,
154
+ throwOnDuplicate?: boolean,
155
+ ): {
156
+ success: number;
157
+ failed: number;
158
+ errors: Array<{
159
+ primaryKey: IndexKey;
160
+ error: string;
161
+ }>;
162
+ };
163
+ /**
164
+ * 批量删除
165
+ * @param entries 条目数组
166
+ */
167
+ deleteBatch(
168
+ entries: Array<{
169
+ value: IndexValue;
170
+ primaryKey: IndexKey;
171
+ }>,
172
+ ): {
173
+ success: number;
174
+ failed: number;
175
+ };
176
+ /**
177
+ * 将索引值转换为存储键
178
+ */
179
+ private valueToKey;
180
+ /**
181
+ * 将存储键转换为索引值
182
+ */
183
+ private keyToValue;
184
+ /**
185
+ * 比较两个索引值
186
+ */
187
+ private compareValues;
188
+ /**
189
+ * 获取排序后的条目
190
+ */
191
+ private getSortedEntries;
192
+ /**
193
+ * 估算内存使用
194
+ */
195
+ private estimateMemoryUsage;
196
+ /**
197
+ * 验证索引一致性
198
+ */
199
+ validate(): {
200
+ valid: boolean;
201
+ errors: string[];
202
+ };
203
+ }
204
+ //# sourceMappingURL=SecondaryIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SecondaryIndex.d.ts","sourceRoot":"","sources":["../../src/indexes/SecondaryIndex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,480 @@
1
+ "use strict";
2
+ /**
3
+ * LightDB 二级索引实现
4
+ * 使用 Map<索引值, Set<主键>> 结构,支持高效的等值查询
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SecondaryIndex = void 0;
8
+ const types_1 = require("./types");
9
+ const errors_1 = require("./errors");
10
+ /**
11
+ * 二级索引
12
+ * 使用 Map + Set 结构实现,支持等值查询和范围查询
13
+ */
14
+ class SecondaryIndex {
15
+ /**
16
+ * 创建二级索引实例
17
+ * @param config 索引配置
18
+ */
19
+ constructor(config) {
20
+ this.keyCount = 0;
21
+ this.config = {
22
+ name: config.name,
23
+ fieldName: config.fieldName,
24
+ unique: config.unique ?? false,
25
+ sparse: config.sparse ?? false,
26
+ };
27
+ this.index = new Map();
28
+ }
29
+ /**
30
+ * 获取索引名称
31
+ */
32
+ get Name() {
33
+ return this.config.name;
34
+ }
35
+ /**
36
+ * 获取字段名
37
+ */
38
+ get FieldName() {
39
+ return this.config.fieldName;
40
+ }
41
+ /**
42
+ * 获取索引类型
43
+ */
44
+ get Type() {
45
+ return this.config.unique ? types_1.IndexType.Unique : types_1.IndexType.Secondary;
46
+ }
47
+ /**
48
+ * 获取是否唯一索引
49
+ */
50
+ get IsUnique() {
51
+ return this.config.unique;
52
+ }
53
+ /**
54
+ * 获取是否稀疏索引
55
+ */
56
+ get IsSparse() {
57
+ return this.config.sparse;
58
+ }
59
+ /**
60
+ * 获取索引中的键数量
61
+ */
62
+ get Size() {
63
+ return this.keyCount;
64
+ }
65
+ /**
66
+ * 获取索引值数量
67
+ */
68
+ get ValueCount() {
69
+ return this.index.size;
70
+ }
71
+ /**
72
+ * 检查索引是否为空
73
+ */
74
+ isEmpty() {
75
+ return this.keyCount === 0;
76
+ }
77
+ /**
78
+ * 插入索引条目
79
+ * @param value 索引值
80
+ * @param primaryKey 主键
81
+ * @param throwOnDuplicate 如果是唯一索引且值已存在是否抛出异常
82
+ * @returns 是否插入成功
83
+ */
84
+ insert(value, primaryKey, throwOnDuplicate = false) {
85
+ if (value === null || value === undefined) {
86
+ if (this.config.sparse) {
87
+ return true;
88
+ }
89
+ }
90
+ const valueKey = this.valueToKey(value);
91
+ if (this.config.unique) {
92
+ const existing = this.index.get(valueKey);
93
+ if (existing && existing.size > 0) {
94
+ if (throwOnDuplicate) {
95
+ throw new errors_1.DuplicateKeyError(this.config.name, value);
96
+ }
97
+ return false;
98
+ }
99
+ }
100
+ let keySet = this.index.get(valueKey);
101
+ if (!keySet) {
102
+ keySet = new Set();
103
+ this.index.set(valueKey, keySet);
104
+ }
105
+ if (keySet.has(primaryKey)) {
106
+ return false;
107
+ }
108
+ keySet.add(primaryKey);
109
+ this.keyCount++;
110
+ return true;
111
+ }
112
+ /**
113
+ * 删除索引条目
114
+ * @param value 索引值
115
+ * @param primaryKey 主键
116
+ * @returns 是否删除成功
117
+ */
118
+ delete(value, primaryKey) {
119
+ if (value === null || value === undefined) {
120
+ if (this.config.sparse) {
121
+ return true;
122
+ }
123
+ }
124
+ const valueKey = this.valueToKey(value);
125
+ const keySet = this.index.get(valueKey);
126
+ if (!keySet) {
127
+ return false;
128
+ }
129
+ const deleted = keySet.delete(primaryKey);
130
+ if (deleted) {
131
+ this.keyCount--;
132
+ }
133
+ if (keySet.size === 0) {
134
+ this.index.delete(valueKey);
135
+ }
136
+ return deleted;
137
+ }
138
+ /**
139
+ * 更新索引条目
140
+ * @param oldValue 旧索引值
141
+ * @param newValue 新索引值
142
+ * @param primaryKey 主键
143
+ * @param throwOnDuplicate 如果是唯一索引且新值已存在是否抛出异常
144
+ * @returns 是否更新成功
145
+ */
146
+ update(oldValue, newValue, primaryKey, throwOnDuplicate = false) {
147
+ const oldKey = this.valueToKey(oldValue);
148
+ const newKey = this.valueToKey(newValue);
149
+ if (oldKey === newKey) {
150
+ return true;
151
+ }
152
+ if (this.config.unique) {
153
+ const existing = this.index.get(newKey);
154
+ if (existing && existing.size > 0) {
155
+ if (throwOnDuplicate) {
156
+ throw new errors_1.DuplicateKeyError(this.config.name, newValue);
157
+ }
158
+ return false;
159
+ }
160
+ }
161
+ this.delete(oldValue, primaryKey);
162
+ this.insert(newValue, primaryKey, throwOnDuplicate);
163
+ return true;
164
+ }
165
+ /**
166
+ * 等值查询
167
+ * @param value 索引值
168
+ * @returns 匹配的主键集合
169
+ */
170
+ find(value) {
171
+ const valueKey = this.valueToKey(value);
172
+ const keySet = this.index.get(valueKey);
173
+ return keySet ? new Set(keySet) : new Set();
174
+ }
175
+ /**
176
+ * 检查索引值是否存在
177
+ * @param value 索引值
178
+ */
179
+ has(value) {
180
+ const valueKey = this.valueToKey(value);
181
+ const keySet = this.index.get(valueKey);
182
+ return keySet !== undefined && keySet.size > 0;
183
+ }
184
+ /**
185
+ * 检查索引值和主键组合是否存在
186
+ * @param value 索引值
187
+ * @param primaryKey 主键
188
+ */
189
+ hasEntry(value, primaryKey) {
190
+ const valueKey = this.valueToKey(value);
191
+ const keySet = this.index.get(valueKey);
192
+ return keySet !== undefined && keySet.has(primaryKey);
193
+ }
194
+ /**
195
+ * 条件查询
196
+ * @param condition 查询条件
197
+ * @returns 匹配的主键集合
198
+ */
199
+ query(condition) {
200
+ if (condition.$eq !== undefined) {
201
+ return this.find(condition.$eq);
202
+ }
203
+ const result = new Set();
204
+ if (condition.$in !== undefined) {
205
+ for (const value of condition.$in) {
206
+ const keys = this.find(value);
207
+ for (const key of keys) {
208
+ result.add(key);
209
+ }
210
+ }
211
+ }
212
+ if (condition.$ne !== undefined) {
213
+ const excludeKeys = this.find(condition.$ne);
214
+ for (const [_, keySet] of this.index) {
215
+ for (const key of keySet) {
216
+ if (!excludeKeys.has(key)) {
217
+ result.add(key);
218
+ }
219
+ }
220
+ }
221
+ }
222
+ if (condition.$nin !== undefined) {
223
+ const excludeKeys = new Set();
224
+ for (const value of condition.$nin) {
225
+ const keys = this.find(value);
226
+ for (const key of keys) {
227
+ excludeKeys.add(key);
228
+ }
229
+ }
230
+ for (const [_, keySet] of this.index) {
231
+ for (const key of keySet) {
232
+ if (!excludeKeys.has(key)) {
233
+ result.add(key);
234
+ }
235
+ }
236
+ }
237
+ }
238
+ return result;
239
+ }
240
+ /**
241
+ * 范围查询
242
+ * @param start 起始值
243
+ * @param end 结束值
244
+ * @param includeStart 是否包含起始值
245
+ * @param includeEnd 是否包含结束值
246
+ * @returns 匹配的主键集合
247
+ */
248
+ range(start, end, includeStart = true, includeEnd = true) {
249
+ const result = new Set();
250
+ const sortedEntries = this.getSortedEntries();
251
+ for (const { value, keys } of sortedEntries) {
252
+ if (start !== undefined) {
253
+ const cmp = this.compareValues(value, start);
254
+ if (cmp < 0 || (cmp === 0 && !includeStart)) {
255
+ continue;
256
+ }
257
+ }
258
+ if (end !== undefined) {
259
+ const cmp = this.compareValues(value, end);
260
+ if (cmp > 0 || (cmp === 0 && !includeEnd)) {
261
+ break;
262
+ }
263
+ }
264
+ for (const key of keys) {
265
+ result.add(key);
266
+ }
267
+ }
268
+ return result;
269
+ }
270
+ /**
271
+ * 获取所有索引值
272
+ */
273
+ values() {
274
+ const result = [];
275
+ for (const key of this.index.keys()) {
276
+ result.push(this.keyToValue(key));
277
+ }
278
+ return result;
279
+ }
280
+ /**
281
+ * 获取所有主键
282
+ */
283
+ keys() {
284
+ const result = [];
285
+ for (const keySet of this.index.values()) {
286
+ for (const key of keySet) {
287
+ result.push(key);
288
+ }
289
+ }
290
+ return result;
291
+ }
292
+ /**
293
+ * 获取所有条目
294
+ */
295
+ entries() {
296
+ const result = [];
297
+ for (const [key, keySet] of this.index) {
298
+ result.push({
299
+ value: this.keyToValue(key),
300
+ keys: new Set(keySet),
301
+ });
302
+ }
303
+ return result;
304
+ }
305
+ /**
306
+ * 清空索引
307
+ */
308
+ clear() {
309
+ this.index.clear();
310
+ this.keyCount = 0;
311
+ }
312
+ /**
313
+ * 获取索引统计信息
314
+ */
315
+ getStats() {
316
+ const valueCount = this.index.size;
317
+ const memoryUsage = this.estimateMemoryUsage();
318
+ return {
319
+ name: this.config.name,
320
+ type: this.Type,
321
+ fieldName: this.config.fieldName,
322
+ keyCount: this.keyCount,
323
+ entryCount: valueCount,
324
+ unique: this.config.unique,
325
+ memoryUsage,
326
+ };
327
+ }
328
+ /**
329
+ * 批量插入
330
+ * @param entries 条目数组
331
+ * @param throwOnDuplicate 如果是唯一索引且值已存在是否抛出异常
332
+ */
333
+ insertBatch(entries, throwOnDuplicate = false) {
334
+ let success = 0;
335
+ let failed = 0;
336
+ const errors = [];
337
+ for (const { value, primaryKey } of entries) {
338
+ try {
339
+ if (this.insert(value, primaryKey, throwOnDuplicate)) {
340
+ success++;
341
+ } else {
342
+ failed++;
343
+ errors.push({ primaryKey, error: "Duplicate or existing entry" });
344
+ }
345
+ } catch (error) {
346
+ failed++;
347
+ errors.push({
348
+ primaryKey,
349
+ error: error instanceof Error ? error.message : "Unknown error",
350
+ });
351
+ }
352
+ }
353
+ return { success, failed, errors };
354
+ }
355
+ /**
356
+ * 批量删除
357
+ * @param entries 条目数组
358
+ */
359
+ deleteBatch(entries) {
360
+ let success = 0;
361
+ let failed = 0;
362
+ for (const { value, primaryKey } of entries) {
363
+ if (this.delete(value, primaryKey)) {
364
+ success++;
365
+ } else {
366
+ failed++;
367
+ }
368
+ }
369
+ return { success, failed };
370
+ }
371
+ /**
372
+ * 将索引值转换为存储键
373
+ */
374
+ valueToKey(value) {
375
+ if (value === null) {
376
+ return "\x00null";
377
+ }
378
+ if (value === undefined) {
379
+ return "\x00undefined";
380
+ }
381
+ if (typeof value === "number") {
382
+ return `\x01num:${value}`;
383
+ }
384
+ if (typeof value === "boolean") {
385
+ return `\x02bool:${value}`;
386
+ }
387
+ return `\x03str:${value}`;
388
+ }
389
+ /**
390
+ * 将存储键转换为索引值
391
+ */
392
+ keyToValue(key) {
393
+ if (key === "\x00null") {
394
+ return null;
395
+ }
396
+ if (key === "\x00undefined") {
397
+ return null;
398
+ }
399
+ if (key.startsWith("\x01num:")) {
400
+ return parseFloat(key.slice(6));
401
+ }
402
+ if (key.startsWith("\x02bool:")) {
403
+ return key.slice(7) === "true";
404
+ }
405
+ if (key.startsWith("\x03str:")) {
406
+ return key.slice(6);
407
+ }
408
+ return key;
409
+ }
410
+ /**
411
+ * 比较两个索引值
412
+ */
413
+ compareValues(a, b) {
414
+ if (a === null && b === null) return 0;
415
+ if (a === null) return -1;
416
+ if (b === null) return 1;
417
+ if (a === undefined && b === undefined) return 0;
418
+ if (a === undefined) return -1;
419
+ if (b === undefined) return 1;
420
+ const typeA = typeof a;
421
+ const typeB = typeof b;
422
+ if (typeA !== typeB) {
423
+ return typeA.localeCompare(typeB);
424
+ }
425
+ if (typeA === "number") {
426
+ return a - b;
427
+ }
428
+ if (typeA === "boolean") {
429
+ return (a ? 1 : 0) - (b ? 1 : 0);
430
+ }
431
+ const strA = String(a);
432
+ const strB = String(b);
433
+ if (strA < strB) return -1;
434
+ if (strA > strB) return 1;
435
+ return 0;
436
+ }
437
+ /**
438
+ * 获取排序后的条目
439
+ */
440
+ getSortedEntries() {
441
+ const entries = this.entries();
442
+ entries.sort((a, b) => this.compareValues(a.value, b.value));
443
+ return entries;
444
+ }
445
+ /**
446
+ * 估算内存使用
447
+ */
448
+ estimateMemoryUsage() {
449
+ const avgValueSize = 32;
450
+ const avgKeySize = 16;
451
+ const setOverhead = 64;
452
+ const mapOverhead = 64;
453
+ return this.index.size * (avgValueSize + mapOverhead) + this.keyCount * (avgKeySize + setOverhead);
454
+ }
455
+ /**
456
+ * 验证索引一致性
457
+ */
458
+ validate() {
459
+ const errors = [];
460
+ let countedKeys = 0;
461
+ for (const [valueKey, keySet] of this.index) {
462
+ if (keySet.size === 0) {
463
+ errors.push(`Empty key set for value: ${valueKey}`);
464
+ }
465
+ if (this.config.unique && keySet.size > 1) {
466
+ errors.push(`Unique index has multiple keys for value: ${valueKey}`);
467
+ }
468
+ countedKeys += keySet.size;
469
+ }
470
+ if (countedKeys !== this.keyCount) {
471
+ errors.push(`Key count mismatch: expected ${this.keyCount}, found ${countedKeys}`);
472
+ }
473
+ return {
474
+ valid: errors.length === 0,
475
+ errors,
476
+ };
477
+ }
478
+ }
479
+ exports.SecondaryIndex = SecondaryIndex;
480
+ //# sourceMappingURL=SecondaryIndex.js.map