@instantdb/core 0.22.86-experimental.separate-attrs.20122276424.1 → 0.22.86-experimental.split-store.20183617880.1
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/__tests__/src/Reactor.test.js +18 -11
- package/__tests__/src/{datalog.test.js → datalog.test.ts} +17 -5
- package/__tests__/src/{instaml.test.js → instaml.test.ts} +183 -119
- package/__tests__/src/instaql.bench.ts +34 -0
- package/__tests__/src/{instaql.test.js → instaql.test.ts} +342 -455
- package/__tests__/src/instaqlInference.test.js +13 -9
- package/__tests__/src/{store.test.js → store.test.ts} +188 -210
- package/dist/commonjs/Reactor.d.ts +23 -6
- package/dist/commonjs/Reactor.d.ts.map +1 -1
- package/dist/commonjs/Reactor.js +110 -45
- package/dist/commonjs/Reactor.js.map +1 -1
- package/dist/commonjs/SyncTable.d.ts +4 -1
- package/dist/commonjs/SyncTable.d.ts.map +1 -1
- package/dist/commonjs/SyncTable.js +35 -37
- package/dist/commonjs/SyncTable.js.map +1 -1
- package/dist/commonjs/instaml.d.ts +17 -4
- package/dist/commonjs/instaml.d.ts.map +1 -1
- package/dist/commonjs/instaml.js +105 -76
- package/dist/commonjs/instaml.js.map +1 -1
- package/dist/commonjs/instaql.d.ts +4 -3
- package/dist/commonjs/instaql.d.ts.map +1 -1
- package/dist/commonjs/instaql.js +65 -63
- package/dist/commonjs/instaql.js.map +1 -1
- package/dist/commonjs/reactorTypes.d.ts +29 -0
- package/dist/commonjs/reactorTypes.d.ts.map +1 -0
- package/dist/commonjs/reactorTypes.js +3 -0
- package/dist/commonjs/reactorTypes.js.map +1 -0
- package/dist/commonjs/store.d.ts +67 -25
- package/dist/commonjs/store.d.ts.map +1 -1
- package/dist/commonjs/store.js +170 -70
- package/dist/commonjs/store.js.map +1 -1
- package/dist/esm/Reactor.d.ts +23 -6
- package/dist/esm/Reactor.d.ts.map +1 -1
- package/dist/esm/Reactor.js +111 -46
- package/dist/esm/Reactor.js.map +1 -1
- package/dist/esm/SyncTable.d.ts +4 -1
- package/dist/esm/SyncTable.d.ts.map +1 -1
- package/dist/esm/SyncTable.js +35 -37
- package/dist/esm/SyncTable.js.map +1 -1
- package/dist/esm/instaml.d.ts +17 -4
- package/dist/esm/instaml.d.ts.map +1 -1
- package/dist/esm/instaml.js +102 -71
- package/dist/esm/instaml.js.map +1 -1
- package/dist/esm/instaql.d.ts +4 -3
- package/dist/esm/instaql.d.ts.map +1 -1
- package/dist/esm/instaql.js +65 -63
- package/dist/esm/instaql.js.map +1 -1
- package/dist/esm/reactorTypes.d.ts +29 -0
- package/dist/esm/reactorTypes.d.ts.map +1 -0
- package/dist/esm/reactorTypes.js +2 -0
- package/dist/esm/reactorTypes.js.map +1 -0
- package/dist/esm/store.d.ts +67 -25
- package/dist/esm/store.d.ts.map +1 -1
- package/dist/esm/store.js +167 -70
- package/dist/esm/store.js.map +1 -1
- package/dist/standalone/index.js +1580 -1392
- package/dist/standalone/index.umd.cjs +3 -3
- package/package.json +2 -2
- package/src/Reactor.js +154 -77
- package/src/SyncTable.ts +85 -45
- package/src/{instaml.js → instaml.ts} +196 -95
- package/src/instaql.ts +88 -62
- package/src/reactorTypes.ts +32 -0
- package/src/store.ts +248 -90
- package/__tests__/src/instaql.bench.js +0 -29
package/src/store.ts
CHANGED
|
@@ -7,34 +7,169 @@ import { LinkIndex } from './utils/linkIndex.ts';
|
|
|
7
7
|
type Triple = [string, string, any, number];
|
|
8
8
|
type Attrs = Record<string, InstantDBAttr>;
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface AttrIndexes {
|
|
11
11
|
blobAttrs: Map<string, Map<string, InstantDBAttr>>;
|
|
12
12
|
primaryKeys: Map<string, InstantDBAttr>;
|
|
13
13
|
forwardIdents: Map<string, Map<string, InstantDBAttr>>;
|
|
14
14
|
revIdents: Map<string, Map<string, InstantDBAttr>>;
|
|
15
|
-
}
|
|
15
|
+
}
|
|
16
16
|
|
|
17
17
|
export type Store = {
|
|
18
18
|
eav: Map<string, Map<string, Map<any, Triple>>>;
|
|
19
19
|
aev: Map<string, Map<string, Map<any, Triple>>>;
|
|
20
20
|
vae: Map<any, Map<string, Map<string, Triple>>>;
|
|
21
|
-
useDateObjects: boolean | null;
|
|
22
|
-
|
|
23
|
-
attrIndexes: AttrIndexes;
|
|
24
|
-
cardinalityInference: boolean | null;
|
|
25
|
-
linkIndex: LinkIndex | null;
|
|
26
|
-
__type: 'store';
|
|
21
|
+
useDateObjects: boolean | null | undefined;
|
|
22
|
+
cardinalityInference: boolean | null | undefined;
|
|
27
23
|
};
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
type StoreJsonVersion0 = {
|
|
30
26
|
__type: 'store';
|
|
31
27
|
attrs: Attrs;
|
|
32
28
|
triples: Triple[];
|
|
33
|
-
cardinalityInference: boolean | null;
|
|
29
|
+
cardinalityInference: boolean | null | undefined;
|
|
30
|
+
linkIndex: LinkIndex | null;
|
|
31
|
+
useDateObjects: boolean | null | undefined;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type StoreJsonVersion1 = {
|
|
35
|
+
triples: Triple[];
|
|
36
|
+
cardinalityInference: boolean | null | undefined;
|
|
37
|
+
useDateObjects: boolean | null | undefined;
|
|
38
|
+
version: 1;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export type StoreJson = StoreJsonVersion0 | StoreJsonVersion1;
|
|
42
|
+
|
|
43
|
+
export type AttrsStoreJson = {
|
|
44
|
+
attrs: Attrs;
|
|
34
45
|
linkIndex: LinkIndex | null;
|
|
35
|
-
useDateObjects: boolean | null;
|
|
36
46
|
};
|
|
37
47
|
|
|
48
|
+
export interface AttrsStore {
|
|
49
|
+
attrs: Attrs;
|
|
50
|
+
linkIndex: LinkIndex | null;
|
|
51
|
+
resetAttrIndexes(): void;
|
|
52
|
+
addAttr(attr: InstantDBAttr): void;
|
|
53
|
+
deleteAttr(attrId: string): void;
|
|
54
|
+
updateAttr(partialAttr: Partial<InstantDBAttr> & { id: string }): void;
|
|
55
|
+
getAttr(id: string): InstantDBAttr | undefined;
|
|
56
|
+
blobAttrs: Map<string, Map<string, InstantDBAttr>>;
|
|
57
|
+
primaryKeys: Map<string, InstantDBAttr>;
|
|
58
|
+
forwardIdents: Map<string, Map<string, InstantDBAttr>>;
|
|
59
|
+
revIdents: Map<string, Map<string, InstantDBAttr>>;
|
|
60
|
+
toJSON(): AttrsStoreJson;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class AttrsStoreClass implements AttrsStore {
|
|
64
|
+
public attrs: Attrs;
|
|
65
|
+
public linkIndex: LinkIndex | null;
|
|
66
|
+
private _blobAttrs: Map<string, Map<string, InstantDBAttr>> | null = null;
|
|
67
|
+
private _primaryKeys: Map<string, InstantDBAttr> | null = null;
|
|
68
|
+
private _forwardIdents: Map<string, Map<string, InstantDBAttr>> | null = null;
|
|
69
|
+
private _revIdents: Map<string, Map<string, InstantDBAttr>> | null = null;
|
|
70
|
+
constructor(attrs: Attrs, linkIndex: LinkIndex | null) {
|
|
71
|
+
this.attrs = attrs;
|
|
72
|
+
this.linkIndex = linkIndex;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public resetAttrIndexes() {
|
|
76
|
+
this._blobAttrs = null;
|
|
77
|
+
this._primaryKeys = null;
|
|
78
|
+
this._forwardIdents = null;
|
|
79
|
+
this._revIdents = null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
public addAttr(attr: InstantDBAttr) {
|
|
83
|
+
this.attrs[attr.id] = attr;
|
|
84
|
+
this.resetAttrIndexes();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public deleteAttr(attrId: string) {
|
|
88
|
+
delete this.attrs[attrId];
|
|
89
|
+
this.resetAttrIndexes();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public updateAttr(partialAttr: Partial<InstantDBAttr> & { id: string }) {
|
|
93
|
+
const attr = this.attrs[partialAttr.id];
|
|
94
|
+
if (!attr) return;
|
|
95
|
+
this.attrs[partialAttr.id] = { ...attr, ...partialAttr };
|
|
96
|
+
this.resetAttrIndexes();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public getAttr(id: string): InstantDBAttr | undefined {
|
|
100
|
+
return this.attrs[id];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// XXX: Might be better to create all of the indexes at once as soon as someone
|
|
104
|
+
// requests one index
|
|
105
|
+
get blobAttrs(): Map<string, Map<string, InstantDBAttr>> {
|
|
106
|
+
if (this._blobAttrs) {
|
|
107
|
+
return this._blobAttrs;
|
|
108
|
+
}
|
|
109
|
+
console.log('blobAttrs');
|
|
110
|
+
this._blobAttrs = new Map();
|
|
111
|
+
for (const attr of Object.values(this.attrs)) {
|
|
112
|
+
if (isBlob(attr)) {
|
|
113
|
+
const [_, fwdEtype, fwdLabel] = attr['forward-identity'];
|
|
114
|
+
setInMap(this.blobAttrs, [fwdEtype, fwdLabel], attr);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return this._blobAttrs;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
get primaryKeys(): Map<string, InstantDBAttr> {
|
|
121
|
+
if (this._primaryKeys) {
|
|
122
|
+
return this._primaryKeys;
|
|
123
|
+
}
|
|
124
|
+
console.log('primayKeys');
|
|
125
|
+
this._primaryKeys = new Map();
|
|
126
|
+
|
|
127
|
+
for (const attr of Object.values(this.attrs)) {
|
|
128
|
+
if (attr['primary?']) {
|
|
129
|
+
const [_, fwdEtype] = attr['forward-identity'];
|
|
130
|
+
setInMap(this._primaryKeys, [fwdEtype], attr);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return this._primaryKeys;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
get forwardIdents(): Map<string, Map<string, InstantDBAttr>> {
|
|
137
|
+
if (this._forwardIdents) {
|
|
138
|
+
return this._forwardIdents;
|
|
139
|
+
}
|
|
140
|
+
console.log('fwdIdents');
|
|
141
|
+
this._forwardIdents = new Map();
|
|
142
|
+
|
|
143
|
+
for (const attr of Object.values(this.attrs)) {
|
|
144
|
+
const fwdIdent = attr['forward-identity'];
|
|
145
|
+
const [_, fwdEtype, fwdLabel] = fwdIdent;
|
|
146
|
+
setInMap(this._forwardIdents, [fwdEtype, fwdLabel], attr);
|
|
147
|
+
}
|
|
148
|
+
return this._forwardIdents;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
get revIdents(): Map<string, Map<string, InstantDBAttr>> {
|
|
152
|
+
if (this._revIdents) {
|
|
153
|
+
return this._revIdents;
|
|
154
|
+
}
|
|
155
|
+
console.log('revIdents');
|
|
156
|
+
this._revIdents = new Map();
|
|
157
|
+
|
|
158
|
+
for (const attr of Object.values(this.attrs)) {
|
|
159
|
+
const revIdent = attr['reverse-identity'];
|
|
160
|
+
if (revIdent) {
|
|
161
|
+
const [_, revEtype, revLabel] = revIdent;
|
|
162
|
+
setInMap(this._revIdents, [revEtype, revLabel], attr);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return this._revIdents;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public toJSON(): AttrsStoreJson {
|
|
169
|
+
return { attrs: this.attrs, linkIndex: this.linkIndex };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
38
173
|
function hasEA(attr: InstantDBAttr) {
|
|
39
174
|
return attr['cardinality'] === 'one';
|
|
40
175
|
}
|
|
@@ -86,18 +221,18 @@ function isDateAttr(attr: InstantDBAttr) {
|
|
|
86
221
|
}
|
|
87
222
|
|
|
88
223
|
function createTripleIndexes(
|
|
89
|
-
|
|
224
|
+
attrsStore: AttrsStore,
|
|
90
225
|
triples: Triple[],
|
|
91
|
-
useDateObjects: boolean | null,
|
|
226
|
+
useDateObjects: boolean | null | undefined,
|
|
92
227
|
): Pick<Store, 'eav' | 'aev' | 'vae'> {
|
|
93
228
|
const eav = new Map();
|
|
94
229
|
const aev = new Map();
|
|
95
230
|
const vae = new Map();
|
|
96
231
|
for (const triple of triples) {
|
|
97
|
-
let [eid, aid, v
|
|
98
|
-
const attr = getAttr(
|
|
232
|
+
let [eid, aid, v] = triple;
|
|
233
|
+
const attr = attrsStore.getAttr(aid);
|
|
99
234
|
if (!attr) {
|
|
100
|
-
console.warn('no such attr',
|
|
235
|
+
console.warn('no such attr', aid, eid);
|
|
101
236
|
continue;
|
|
102
237
|
}
|
|
103
238
|
|
|
@@ -142,27 +277,36 @@ function createAttrIndexes(attrs: Record<string, InstantDBAttr>): AttrIndexes {
|
|
|
142
277
|
return { blobAttrs, primaryKeys, forwardIdents, revIdents };
|
|
143
278
|
}
|
|
144
279
|
|
|
145
|
-
export function toJSON(store: Store):
|
|
280
|
+
export function toJSON(store: Store): StoreJsonVersion1 {
|
|
146
281
|
return {
|
|
147
|
-
__type: store.__type,
|
|
148
|
-
attrs: store.attrs,
|
|
149
282
|
triples: allMapValues(store.eav, 3),
|
|
150
283
|
cardinalityInference: store.cardinalityInference,
|
|
151
|
-
linkIndex: store.linkIndex,
|
|
152
284
|
useDateObjects: store.useDateObjects,
|
|
285
|
+
version: 1,
|
|
153
286
|
};
|
|
154
287
|
}
|
|
155
288
|
|
|
156
|
-
export function fromJSON(storeJSON: StoreJson): Store {
|
|
289
|
+
export function fromJSON(attrsStore: AttrsStore, storeJSON: StoreJson): Store {
|
|
157
290
|
return createStore(
|
|
158
|
-
|
|
291
|
+
attrsStore,
|
|
159
292
|
storeJSON.triples,
|
|
160
293
|
storeJSON.cardinalityInference,
|
|
161
|
-
storeJSON.linkIndex,
|
|
162
294
|
storeJSON.useDateObjects,
|
|
163
295
|
);
|
|
164
296
|
}
|
|
165
297
|
|
|
298
|
+
export function attrsStoreFromJSON(
|
|
299
|
+
attrsStoreJSON: AttrsStoreJson | null,
|
|
300
|
+
storeJSON: StoreJson | null,
|
|
301
|
+
): AttrsStore | undefined {
|
|
302
|
+
if (attrsStoreJSON) {
|
|
303
|
+
return new AttrsStoreClass(attrsStoreJSON.attrs, attrsStoreJSON.linkIndex);
|
|
304
|
+
}
|
|
305
|
+
if (storeJSON && '__type' in storeJSON) {
|
|
306
|
+
return new AttrsStoreClass(storeJSON.attrs, storeJSON.linkIndex);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
166
310
|
export function hasTriple(store: Store, [e, a, v]: [string, string, any]) {
|
|
167
311
|
return getInMap(store.eav, [e, a, v]) !== undefined;
|
|
168
312
|
}
|
|
@@ -171,29 +315,19 @@ export function hasEntity(store: Store, e: string) {
|
|
|
171
315
|
return getInMap(store.eav, [e]) !== undefined;
|
|
172
316
|
}
|
|
173
317
|
|
|
174
|
-
function resetAttrIndexes(store: Store) {
|
|
175
|
-
store.attrIndexes = createAttrIndexes(store.attrs);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
318
|
export function createStore(
|
|
179
|
-
|
|
319
|
+
attrsStore: AttrsStore,
|
|
180
320
|
triples: Triple[],
|
|
181
|
-
enableCardinalityInference
|
|
182
|
-
|
|
183
|
-
useDateObjects: boolean | null,
|
|
321
|
+
enableCardinalityInference?: boolean | null,
|
|
322
|
+
useDateObjects?: boolean | null,
|
|
184
323
|
): Store {
|
|
185
324
|
const store = createTripleIndexes(
|
|
186
|
-
|
|
325
|
+
attrsStore,
|
|
187
326
|
triples,
|
|
188
327
|
useDateObjects,
|
|
189
328
|
) as unknown as Store;
|
|
190
|
-
store.useDateObjects = useDateObjects;
|
|
191
|
-
store.attrs = attrs;
|
|
192
|
-
store.attrIndexes = createAttrIndexes(attrs);
|
|
193
329
|
store.cardinalityInference = enableCardinalityInference;
|
|
194
|
-
store.
|
|
195
|
-
store.__type = 'store';
|
|
196
|
-
|
|
330
|
+
store.useDateObjects = useDateObjects;
|
|
197
331
|
return store;
|
|
198
332
|
}
|
|
199
333
|
|
|
@@ -254,13 +388,17 @@ function resolveLookupRefs(store: Store, triple: Triple): Triple | null {
|
|
|
254
388
|
}
|
|
255
389
|
}
|
|
256
390
|
|
|
257
|
-
export function retractTriple(
|
|
391
|
+
export function retractTriple(
|
|
392
|
+
store: Store,
|
|
393
|
+
attrsStore: AttrsStore,
|
|
394
|
+
rawTriple: Triple,
|
|
395
|
+
): void {
|
|
258
396
|
const triple = resolveLookupRefs(store, rawTriple);
|
|
259
397
|
if (!triple) {
|
|
260
398
|
return;
|
|
261
399
|
}
|
|
262
400
|
const [eid, aid, v] = triple;
|
|
263
|
-
const attr = getAttr(
|
|
401
|
+
const attr = attrsStore.getAttr(aid);
|
|
264
402
|
if (!attr) {
|
|
265
403
|
return;
|
|
266
404
|
}
|
|
@@ -310,13 +448,17 @@ function getCreatedAt(
|
|
|
310
448
|
return createdAt || Date.now() * 10 + _seed++;
|
|
311
449
|
}
|
|
312
450
|
|
|
313
|
-
export function addTriple(
|
|
451
|
+
export function addTriple(
|
|
452
|
+
store: Store,
|
|
453
|
+
attrsStore: AttrsStore,
|
|
454
|
+
rawTriple: Triple,
|
|
455
|
+
) {
|
|
314
456
|
const triple = resolveLookupRefs(store, rawTriple);
|
|
315
457
|
if (!triple) {
|
|
316
458
|
return;
|
|
317
459
|
}
|
|
318
460
|
let [eid, aid, v] = triple;
|
|
319
|
-
const attr = getAttr(
|
|
461
|
+
const attr = attrsStore.getAttr(aid);
|
|
320
462
|
if (!attr) {
|
|
321
463
|
// (XXX): Due to the way we're handling attrs, it's
|
|
322
464
|
// possible to enter a state where we receive a triple without an attr.
|
|
@@ -349,14 +491,14 @@ export function addTriple(store: Store, rawTriple: Triple) {
|
|
|
349
491
|
}
|
|
350
492
|
}
|
|
351
493
|
|
|
352
|
-
function mergeTriple(store: Store, rawTriple: Triple) {
|
|
494
|
+
function mergeTriple(store: Store, attrsStore: AttrsStore, rawTriple: Triple) {
|
|
353
495
|
const triple = resolveLookupRefs(store, rawTriple);
|
|
354
496
|
if (!triple) {
|
|
355
497
|
return;
|
|
356
498
|
}
|
|
357
499
|
|
|
358
500
|
const [eid, aid, update] = triple;
|
|
359
|
-
const attr = getAttr(
|
|
501
|
+
const attr = attrsStore.getAttr(aid);
|
|
360
502
|
|
|
361
503
|
if (!attr) return;
|
|
362
504
|
|
|
@@ -382,7 +524,7 @@ function mergeTriple(store: Store, rawTriple: Triple) {
|
|
|
382
524
|
setInMap(store.eav, [eid, aid], new Map([[updatedValue, enhancedTriple]]));
|
|
383
525
|
}
|
|
384
526
|
|
|
385
|
-
function deleteEntity(store: Store, args: any[]) {
|
|
527
|
+
function deleteEntity(store: Store, attrsStore: AttrsStore, args: any[]) {
|
|
386
528
|
const [lookup, etype] = args;
|
|
387
529
|
const triple = resolveLookupRefs(store, [lookup] as unknown as Triple);
|
|
388
530
|
|
|
@@ -395,13 +537,13 @@ function deleteEntity(store: Store, args: any[]) {
|
|
|
395
537
|
const eMap = store.eav.get(id);
|
|
396
538
|
if (eMap) {
|
|
397
539
|
for (const a of eMap.keys()) {
|
|
398
|
-
const attr =
|
|
540
|
+
const attr = attrsStore.getAttr(a);
|
|
399
541
|
|
|
400
542
|
// delete cascade refs
|
|
401
543
|
if (attr && attr['on-delete-reverse'] === 'cascade') {
|
|
402
544
|
allMapValues(eMap.get(a), 1).forEach(
|
|
403
545
|
([e, a, v]: [string, string, any]) =>
|
|
404
|
-
deleteEntity(store, [v, attr['reverse-identity']?.[1]]),
|
|
546
|
+
deleteEntity(store, attrsStore, [v, attr['reverse-identity']?.[1]]),
|
|
405
547
|
);
|
|
406
548
|
}
|
|
407
549
|
|
|
@@ -430,7 +572,7 @@ function deleteEntity(store: Store, args: any[]) {
|
|
|
430
572
|
if (vaeTriples) {
|
|
431
573
|
vaeTriples.forEach((triple: Triple) => {
|
|
432
574
|
const [e, a, v] = triple;
|
|
433
|
-
const attr =
|
|
575
|
+
const attr = attrsStore.getAttr(a);
|
|
434
576
|
if (!etype || !attr || attr['reverse-identity']?.[1] === etype) {
|
|
435
577
|
deleteInMap(store.eav, [e, a, v]);
|
|
436
578
|
deleteInMap(store.aev, [a, e, v]);
|
|
@@ -441,7 +583,7 @@ function deleteEntity(store: Store, args: any[]) {
|
|
|
441
583
|
attr['on-delete'] === 'cascade' &&
|
|
442
584
|
attr['reverse-identity']?.[1] === etype
|
|
443
585
|
) {
|
|
444
|
-
deleteEntity(store, [e, attr['forward-identity']?.[1]]);
|
|
586
|
+
deleteEntity(store, attrsStore, [e, attr['forward-identity']?.[1]]);
|
|
445
587
|
}
|
|
446
588
|
});
|
|
447
589
|
}
|
|
@@ -458,9 +600,9 @@ function deleteEntity(store: Store, args: any[]) {
|
|
|
458
600
|
// * We could batch this reset at the end
|
|
459
601
|
// * We could add an ave index for all triples, so removing the
|
|
460
602
|
// right triples is easy and fast.
|
|
461
|
-
function resetIndexMap(store: Store, newTriples: Triple[]) {
|
|
603
|
+
function resetIndexMap(store: Store, attrsStore, newTriples: Triple[]) {
|
|
462
604
|
const newIndexMap = createTripleIndexes(
|
|
463
|
-
|
|
605
|
+
attrsStore,
|
|
464
606
|
newTriples,
|
|
465
607
|
store.useDateObjects,
|
|
466
608
|
);
|
|
@@ -469,57 +611,55 @@ function resetIndexMap(store: Store, newTriples: Triple[]) {
|
|
|
469
611
|
});
|
|
470
612
|
}
|
|
471
613
|
|
|
472
|
-
function addAttr(
|
|
473
|
-
|
|
474
|
-
resetAttrIndexes(store);
|
|
614
|
+
function addAttr(attrsStore: AttrsStore, [attr]: [InstantDBAttr]) {
|
|
615
|
+
attrsStore.addAttr(attr);
|
|
475
616
|
}
|
|
476
617
|
|
|
477
618
|
function getAllTriples(store: Store): Triple[] {
|
|
478
619
|
return allMapValues(store.eav, 3);
|
|
479
620
|
}
|
|
480
621
|
|
|
481
|
-
function deleteAttr(store: Store, [id]: [string]) {
|
|
482
|
-
if (!
|
|
622
|
+
function deleteAttr(store: Store, attrsStore: AttrsStore, [id]: [string]) {
|
|
623
|
+
if (!attrsStore.getAttr(id)) return;
|
|
483
624
|
const newTriples = getAllTriples(store).filter(([_, aid]) => aid !== id);
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
resetIndexMap(store, newTriples);
|
|
625
|
+
attrsStore.deleteAttr(id);
|
|
626
|
+
resetIndexMap(store, attrsStore, newTriples);
|
|
487
627
|
}
|
|
488
628
|
|
|
489
629
|
function updateAttr(
|
|
490
630
|
store: Store,
|
|
631
|
+
attrsStore: AttrsStore,
|
|
491
632
|
[partialAttr]: [Partial<InstantDBAttr> & { id: string }],
|
|
492
633
|
) {
|
|
493
|
-
const attr =
|
|
634
|
+
const attr = attrsStore.getAttr(partialAttr.id);
|
|
494
635
|
if (!attr) return;
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
resetIndexMap(store, getAllTriples(store));
|
|
636
|
+
attrsStore.updateAttr(partialAttr);
|
|
637
|
+
resetIndexMap(store, attrsStore, getAllTriples(store));
|
|
498
638
|
}
|
|
499
639
|
|
|
500
|
-
function applyTxStep(store: Store, txStep) {
|
|
640
|
+
function applyTxStep(store: Store, attrsStore: AttrsStore, txStep) {
|
|
501
641
|
const [action, ...args] = txStep;
|
|
502
642
|
switch (action) {
|
|
503
643
|
case 'add-triple':
|
|
504
|
-
addTriple(store, args);
|
|
644
|
+
addTriple(store, attrsStore, args);
|
|
505
645
|
break;
|
|
506
646
|
case 'deep-merge-triple':
|
|
507
|
-
mergeTriple(store, args);
|
|
647
|
+
mergeTriple(store, attrsStore, args);
|
|
508
648
|
break;
|
|
509
649
|
case 'retract-triple':
|
|
510
|
-
retractTriple(store, args);
|
|
650
|
+
retractTriple(store, attrsStore, args);
|
|
511
651
|
break;
|
|
512
652
|
case 'delete-entity':
|
|
513
|
-
deleteEntity(store, args);
|
|
653
|
+
deleteEntity(store, attrsStore, args);
|
|
514
654
|
break;
|
|
515
655
|
case 'add-attr':
|
|
516
|
-
addAttr(
|
|
656
|
+
addAttr(attrsStore, args);
|
|
517
657
|
break;
|
|
518
658
|
case 'delete-attr':
|
|
519
|
-
deleteAttr(store, args);
|
|
659
|
+
deleteAttr(store, attrsStore, args);
|
|
520
660
|
break;
|
|
521
661
|
case 'update-attr':
|
|
522
|
-
updateAttr(store, args);
|
|
662
|
+
updateAttr(store, attrsStore, args);
|
|
523
663
|
break;
|
|
524
664
|
case 'restore-attr':
|
|
525
665
|
break;
|
|
@@ -700,35 +840,36 @@ export function getAsObject(
|
|
|
700
840
|
}
|
|
701
841
|
|
|
702
842
|
export function getAttrByFwdIdentName(
|
|
703
|
-
|
|
843
|
+
attrsStore: AttrsStore,
|
|
704
844
|
inputEtype: string,
|
|
705
845
|
inputLabel: string,
|
|
706
846
|
) {
|
|
707
|
-
return
|
|
847
|
+
return attrsStore.forwardIdents.get(inputEtype)?.get(inputLabel);
|
|
708
848
|
}
|
|
709
849
|
|
|
710
850
|
export function getAttrByReverseIdentName(
|
|
711
|
-
|
|
851
|
+
attrsStore: AttrsStore,
|
|
712
852
|
inputEtype: string,
|
|
713
853
|
inputLabel: string,
|
|
714
854
|
) {
|
|
715
|
-
return
|
|
855
|
+
return attrsStore.revIdents.get(inputEtype)?.get(inputLabel);
|
|
716
856
|
}
|
|
717
857
|
|
|
718
|
-
export function getBlobAttrs(
|
|
719
|
-
return
|
|
858
|
+
export function getBlobAttrs(attrsStore: AttrsStore, etype: string) {
|
|
859
|
+
return attrsStore.blobAttrs.get(etype);
|
|
720
860
|
}
|
|
721
861
|
|
|
722
|
-
export function getPrimaryKeyAttr(
|
|
723
|
-
const fromPrimary =
|
|
862
|
+
export function getPrimaryKeyAttr(attrsStore: AttrsStore, etype: string) {
|
|
863
|
+
const fromPrimary = attrsStore.primaryKeys.get(etype);
|
|
724
864
|
if (fromPrimary) {
|
|
725
865
|
return fromPrimary;
|
|
726
866
|
}
|
|
727
|
-
return
|
|
867
|
+
return attrsStore.forwardIdents.get(etype)?.get('id');
|
|
728
868
|
}
|
|
729
869
|
|
|
730
870
|
function findTriple(
|
|
731
871
|
store: Store,
|
|
872
|
+
attrsStore: AttrsStore,
|
|
732
873
|
rawTriple: [string, string, any] | Triple,
|
|
733
874
|
): Triple | undefined {
|
|
734
875
|
const triple = resolveLookupRefs(store, rawTriple as Triple);
|
|
@@ -737,7 +878,7 @@ function findTriple(
|
|
|
737
878
|
}
|
|
738
879
|
|
|
739
880
|
const [eid, aid, v] = triple;
|
|
740
|
-
const attr = getAttr(
|
|
881
|
+
const attr = attrsStore.getAttr(aid);
|
|
741
882
|
if (!attr) {
|
|
742
883
|
// (XXX): Due to the way we're handling attrs, it's
|
|
743
884
|
// possible to enter a state where we receive a triple without an attr.
|
|
@@ -749,7 +890,11 @@ function findTriple(
|
|
|
749
890
|
return getInMap(store.eav, [eid, aid]);
|
|
750
891
|
}
|
|
751
892
|
|
|
752
|
-
export function transact(
|
|
893
|
+
export function transact(
|
|
894
|
+
store: Store,
|
|
895
|
+
attrsStore: AttrsStore,
|
|
896
|
+
txSteps,
|
|
897
|
+
): { store: Store; attrsStore: AttrsStore } {
|
|
753
898
|
const txStepsFiltered = txSteps.filter(
|
|
754
899
|
([action, eid, attrId, value, opts]) => {
|
|
755
900
|
if (action !== 'add-triple' && action !== 'deep-merge-triple') {
|
|
@@ -763,10 +908,13 @@ export function transact(store: Store, txSteps) {
|
|
|
763
908
|
|
|
764
909
|
let exists = false;
|
|
765
910
|
|
|
766
|
-
const attr = getAttr(
|
|
911
|
+
const attr = attrsStore.getAttr(attrId);
|
|
767
912
|
if (attr) {
|
|
768
|
-
const idAttr = getPrimaryKeyAttr(
|
|
769
|
-
|
|
913
|
+
const idAttr = getPrimaryKeyAttr(
|
|
914
|
+
attrsStore,
|
|
915
|
+
attr['forward-identity'][1],
|
|
916
|
+
);
|
|
917
|
+
exists = !!findTriple(store, attrsStore, [
|
|
770
918
|
eid as string,
|
|
771
919
|
idAttr?.id as string,
|
|
772
920
|
eid,
|
|
@@ -785,9 +933,19 @@ export function transact(store: Store, txSteps) {
|
|
|
785
933
|
},
|
|
786
934
|
);
|
|
787
935
|
|
|
788
|
-
return create(
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
936
|
+
return create(
|
|
937
|
+
{ store, attrsStore },
|
|
938
|
+
(draft) => {
|
|
939
|
+
txStepsFiltered.forEach((txStep) => {
|
|
940
|
+
applyTxStep(draft.store, draft.attrsStore, txStep);
|
|
941
|
+
});
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
mark: (target) => {
|
|
945
|
+
if (target instanceof AttrsStoreClass) {
|
|
946
|
+
return 'immutable';
|
|
947
|
+
}
|
|
948
|
+
},
|
|
949
|
+
},
|
|
950
|
+
);
|
|
793
951
|
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { bench } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import zenecaAttrs from './data/zeneca/attrs.json';
|
|
4
|
-
import zenecaTriples from './data/zeneca/triples.json';
|
|
5
|
-
import { createStore } from '../../src/store';
|
|
6
|
-
import query from '../../src/instaql';
|
|
7
|
-
|
|
8
|
-
const zenecaIdToAttr = zenecaAttrs.reduce((res, x) => {
|
|
9
|
-
res[x.id] = x;
|
|
10
|
-
return res;
|
|
11
|
-
}, {});
|
|
12
|
-
|
|
13
|
-
const store = createStore(zenecaIdToAttr, zenecaTriples);
|
|
14
|
-
|
|
15
|
-
bench('big query', () => {
|
|
16
|
-
query(
|
|
17
|
-
{ store },
|
|
18
|
-
{
|
|
19
|
-
users: {
|
|
20
|
-
bookshelves: {
|
|
21
|
-
books: {},
|
|
22
|
-
users: {
|
|
23
|
-
bookshelves: {},
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
);
|
|
29
|
-
});
|