n3 2.13.5 → 2.13.6
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/browser/n3.esm.min.js +8 -8
- package/browser/n3.min.js +7 -7
- package/lib/N3Store.js +80 -116
- package/package.json +7 -2
- package/src/N3Store.js +77 -124
package/lib/N3Store.js
CHANGED
|
@@ -32,94 +32,6 @@ function hasInIndex(index0, key0, key1, key2) {
|
|
|
32
32
|
return !!index2 && key2 in index2;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// The number of index leaves that the last `merge` call added
|
|
36
|
-
let mergedLeaves = 0;
|
|
37
|
-
function merge(target, source, depth = 4) {
|
|
38
|
-
let size = target[SIZE] || 0;
|
|
39
|
-
for (const key in source) {
|
|
40
|
-
if (!(key in target)) {
|
|
41
|
-
size++;
|
|
42
|
-
if (depth === 0) mergedLeaves++;
|
|
43
|
-
target[key] = depth === 0 ? null : merge(Object.create(null), source[key], depth - 1);
|
|
44
|
-
}
|
|
45
|
-
// Merge into the existing object in place,
|
|
46
|
-
// as graph objects are frozen and cannot be reassigned
|
|
47
|
-
else if (depth !== 0) merge(target[key], source[key], depth - 1);
|
|
48
|
-
}
|
|
49
|
-
// Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
|
|
50
|
-
if (depth <= 2) target[SIZE] = size;
|
|
51
|
-
return target;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Determines the intersection of the `_graphs` index s1 and s2.
|
|
56
|
-
* s1 and s2 *must* belong to Stores that share an `_entityIndex`.
|
|
57
|
-
*
|
|
58
|
-
* False is returned when there is no intersection; this should
|
|
59
|
-
* *not* be set as the value for an index.
|
|
60
|
-
*/
|
|
61
|
-
function intersect(s1, s2, depth = 4) {
|
|
62
|
-
let target = false,
|
|
63
|
-
size = 0;
|
|
64
|
-
if (depth <= 2 && s2[SIZE] < s1[SIZE]) [s1, s2] = [s2, s1];
|
|
65
|
-
for (const key in s1) {
|
|
66
|
-
if (key in s2) {
|
|
67
|
-
const intersection = depth === 0 ? null : intersect(s1[key], s2[key], depth - 1);
|
|
68
|
-
if (intersection !== false) {
|
|
69
|
-
target = target || Object.create(null);
|
|
70
|
-
target[key] = intersection;
|
|
71
|
-
size++;
|
|
72
|
-
}
|
|
73
|
-
// Depth 3 is the 'subjects', 'predicates' and 'objects' keys.
|
|
74
|
-
// If the 'subjects' index is empty, so will the 'predicates' and 'objects' index.
|
|
75
|
-
else if (depth === 3) {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
|
|
82
|
-
if (depth <= 2 && target) target[SIZE] = size;
|
|
83
|
-
return target;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Determines the difference of the `_graphs` index s1 and s2.
|
|
88
|
-
* s1 and s2 *must* belong to Stores that share an `_entityIndex`.
|
|
89
|
-
*
|
|
90
|
-
* False is returned when there is no difference; this should
|
|
91
|
-
* *not* be set as the value for an index.
|
|
92
|
-
*/
|
|
93
|
-
function difference(s1, s2, depth = 4) {
|
|
94
|
-
let target = false,
|
|
95
|
-
size = 0;
|
|
96
|
-
for (const key in s1) {
|
|
97
|
-
// When the key is not in the index, then none of the triples defined by s1[key] are
|
|
98
|
-
// in s2 and so we want to copy them over to the resultant store.
|
|
99
|
-
if (!(key in s2)) {
|
|
100
|
-
target = target || Object.create(null);
|
|
101
|
-
target[key] = depth === 0 ? null : merge({}, s1[key], depth - 1);
|
|
102
|
-
size++;
|
|
103
|
-
} else if (depth !== 0) {
|
|
104
|
-
const diff = difference(s1[key], s2[key], depth - 1);
|
|
105
|
-
if (diff !== false) {
|
|
106
|
-
target = target || Object.create(null);
|
|
107
|
-
target[key] = diff;
|
|
108
|
-
size++;
|
|
109
|
-
}
|
|
110
|
-
// Depth 3 is the 'subjects', 'predicates' and 'objects' keys.
|
|
111
|
-
// If the 'subjects' index is empty, so will the 'predicates' and 'objects' index.
|
|
112
|
-
else if (depth === 3) {
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
|
|
119
|
-
if (depth <= 2 && target) target[SIZE] = size;
|
|
120
|
-
return target;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
35
|
// Returns the key of a term in the entity index.
|
|
124
36
|
// Keys mark the term type by their first character, so the IRI of a named node
|
|
125
37
|
// that starts with such a marker (as relative IRIs can) is wrapped in < and >.
|
|
@@ -234,6 +146,7 @@ class N3Store {
|
|
|
234
146
|
this._size = 0;
|
|
235
147
|
// `_graphs` contains subject, predicate, and object indexes per graph
|
|
236
148
|
this._graphs = Object.create(null);
|
|
149
|
+
this._graphCount = 0;
|
|
237
150
|
// `_observers` contains weak references to views notified before every mutation
|
|
238
151
|
this._observers = null;
|
|
239
152
|
|
|
@@ -528,6 +441,7 @@ class N3Store {
|
|
|
528
441
|
// Freezing a graph helps subsequent `add` performance,
|
|
529
442
|
// and properties will never be modified anyway
|
|
530
443
|
Object.freeze(graphItem);
|
|
444
|
+
this._graphCount++;
|
|
531
445
|
}
|
|
532
446
|
|
|
533
447
|
// Notify observers before inserting a new quad so snapshots retain their prior contents
|
|
@@ -542,6 +456,64 @@ class N3Store {
|
|
|
542
456
|
return true;
|
|
543
457
|
}
|
|
544
458
|
|
|
459
|
+
// ### `_addFromIndex` adds the quads in the given graph indexes of a store
|
|
460
|
+
// that shares this store's entity index, so no terms need to be converted.
|
|
461
|
+
// With `otherGraphs`, it only adds the quads that are not in those indexes.
|
|
462
|
+
// Index keys are strings, so the ids are converted back to the numbers that
|
|
463
|
+
// `addQuad` uses: forwarded views compare the ids they are notified with to
|
|
464
|
+
// their own numeric ids.
|
|
465
|
+
_addFromIndex(graphs, otherGraphs = null) {
|
|
466
|
+
for (const graphKey in graphs) {
|
|
467
|
+
const subjects = graphs[graphKey].subjects,
|
|
468
|
+
other = otherGraphs && otherGraphs[graphKey];
|
|
469
|
+
const otherSubjects = other ? other.subjects : null;
|
|
470
|
+
for (const subjectKey in subjects) {
|
|
471
|
+
const subject = Number(subjectKey),
|
|
472
|
+
predicates = subjects[subjectKey];
|
|
473
|
+
const otherPredicates = otherSubjects && otherSubjects[subjectKey];
|
|
474
|
+
for (const predicateKey in predicates) {
|
|
475
|
+
const predicate = Number(predicateKey),
|
|
476
|
+
objects = predicates[predicateKey];
|
|
477
|
+
const otherObjects = otherPredicates && otherPredicates[predicateKey];
|
|
478
|
+
for (const objectKey in objects) {
|
|
479
|
+
if (!otherObjects || !(objectKey in otherObjects)) this._addQuad(subject, predicate, Number(objectKey), Number(graphKey));
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// ### `_addIntersectionFromIndex` adds the quads that are in both of the
|
|
487
|
+
// given graph indexes, walking the graphs of the first and, below them,
|
|
488
|
+
// whichever index has fewer keys
|
|
489
|
+
_addIntersectionFromIndex(graphs, otherGraphs) {
|
|
490
|
+
for (const graphKey in graphs) {
|
|
491
|
+
const other = otherGraphs[graphKey];
|
|
492
|
+
if (other) {
|
|
493
|
+
let subjects = graphs[graphKey].subjects,
|
|
494
|
+
otherSubjects = other.subjects;
|
|
495
|
+
if (otherSubjects[SIZE] < subjects[SIZE]) [subjects, otherSubjects] = [otherSubjects, subjects];
|
|
496
|
+
for (const subjectKey in subjects) {
|
|
497
|
+
let predicates = subjects[subjectKey],
|
|
498
|
+
otherPredicates = otherSubjects[subjectKey];
|
|
499
|
+
if (otherPredicates) {
|
|
500
|
+
if (otherPredicates[SIZE] < predicates[SIZE]) [predicates, otherPredicates] = [otherPredicates, predicates];
|
|
501
|
+
for (const predicateKey in predicates) {
|
|
502
|
+
let objects = predicates[predicateKey],
|
|
503
|
+
otherObjects = otherPredicates[predicateKey];
|
|
504
|
+
if (otherObjects) {
|
|
505
|
+
if (otherObjects[SIZE] < objects[SIZE]) [objects, otherObjects] = [otherObjects, objects];
|
|
506
|
+
for (const objectKey in objects) {
|
|
507
|
+
if (objectKey in otherObjects) this._addQuad(Number(subjectKey), Number(predicateKey), Number(objectKey), Number(graphKey));
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
545
517
|
// ### `addQuads` adds multiple quads to the store
|
|
546
518
|
addQuads(quads) {
|
|
547
519
|
for (let i = 0; i < quads.length; i++) this.addQuad(quads[i]);
|
|
@@ -614,7 +586,10 @@ class N3Store {
|
|
|
614
586
|
if (this._size !== null) this._size--;
|
|
615
587
|
|
|
616
588
|
// Remove the graph if it is empty
|
|
617
|
-
if (graphItem.subjects[SIZE] === 0)
|
|
589
|
+
if (graphItem.subjects[SIZE] === 0) {
|
|
590
|
+
delete graphs[graph];
|
|
591
|
+
this._graphCount--;
|
|
592
|
+
}
|
|
618
593
|
return true;
|
|
619
594
|
}
|
|
620
595
|
|
|
@@ -1025,15 +1000,8 @@ class N3Store {
|
|
|
1025
1000
|
addAll(quads) {
|
|
1026
1001
|
if (quads instanceof DatasetCoreAndReadableStream) quads = quads.filtered;
|
|
1027
1002
|
if (Array.isArray(quads)) this.addQuads(quads);
|
|
1028
|
-
//
|
|
1029
|
-
else if (
|
|
1030
|
-
if (quads.size !== 0) {
|
|
1031
|
-
// Each new quad adds one leaf to each of the three indexes
|
|
1032
|
-
mergedLeaves = 0;
|
|
1033
|
-
this._graphs = merge(this._graphs, quads._graphs);
|
|
1034
|
-
if (this._size !== null) this._size += mergedLeaves / 3;
|
|
1035
|
-
}
|
|
1036
|
-
} else {
|
|
1003
|
+
// A store with the same entity index can be copied by identifier
|
|
1004
|
+
else if (quads instanceof N3Store && quads._entityIndex === this._entityIndex) this._addFromIndex(quads._graphs);else {
|
|
1037
1005
|
for (const quad of quads) this.add(quad);
|
|
1038
1006
|
}
|
|
1039
1007
|
return this;
|
|
@@ -1105,11 +1073,7 @@ class N3Store {
|
|
|
1105
1073
|
const store = new N3Store({
|
|
1106
1074
|
entityIndex: this._entityIndex
|
|
1107
1075
|
});
|
|
1108
|
-
|
|
1109
|
-
if (graphs) {
|
|
1110
|
-
store._graphs = graphs;
|
|
1111
|
-
store._size = null;
|
|
1112
|
-
}
|
|
1076
|
+
store._addFromIndex(this._graphs, other._graphs);
|
|
1113
1077
|
return store;
|
|
1114
1078
|
}
|
|
1115
1079
|
return this.filter(quad => !other.has(quad));
|
|
@@ -1147,17 +1111,15 @@ class N3Store {
|
|
|
1147
1111
|
const store = new N3Store({
|
|
1148
1112
|
entityIndex: this._entityIndex
|
|
1149
1113
|
});
|
|
1150
|
-
store.
|
|
1151
|
-
store._size = this.size;
|
|
1114
|
+
store._addFromIndex(this._graphs);
|
|
1152
1115
|
return store;
|
|
1153
1116
|
} else if (other instanceof N3Store && this._entityIndex === other._entityIndex) {
|
|
1154
1117
|
const store = new N3Store({
|
|
1155
1118
|
entityIndex: this._entityIndex
|
|
1156
1119
|
});
|
|
1157
|
-
|
|
1158
|
-
if (
|
|
1159
|
-
store._graphs
|
|
1160
|
-
store._size = null;
|
|
1120
|
+
// Starting a loop over no graphs costs more than checking for an empty store
|
|
1121
|
+
if (this._size !== 0 && other._size !== 0) {
|
|
1122
|
+
if (other._graphCount < this._graphCount) store._addIntersectionFromIndex(other._graphs, this._graphs);else store._addIntersectionFromIndex(this._graphs, other._graphs);
|
|
1161
1123
|
}
|
|
1162
1124
|
return store;
|
|
1163
1125
|
}
|
|
@@ -1250,8 +1212,7 @@ class N3Store {
|
|
|
1250
1212
|
const store = new N3Store({
|
|
1251
1213
|
entityIndex: this._entityIndex
|
|
1252
1214
|
});
|
|
1253
|
-
store.
|
|
1254
|
-
store._size = this.size;
|
|
1215
|
+
store._addFromIndex(this._graphs);
|
|
1255
1216
|
store.addAll(quads);
|
|
1256
1217
|
return store;
|
|
1257
1218
|
}
|
|
@@ -1516,11 +1477,14 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
|
|
|
1516
1477
|
predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
|
|
1517
1478
|
objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
|
|
1518
1479
|
}
|
|
1519
|
-
if (subjects)
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1480
|
+
if (subjects) {
|
|
1481
|
+
newStore._graphs[graphKey] = {
|
|
1482
|
+
subjects,
|
|
1483
|
+
predicates,
|
|
1484
|
+
objects
|
|
1485
|
+
};
|
|
1486
|
+
newStore._graphCount++;
|
|
1487
|
+
}
|
|
1524
1488
|
}
|
|
1525
1489
|
}
|
|
1526
1490
|
newStore._size = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n3",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.6",
|
|
4
4
|
"description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
|
|
5
5
|
"author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
|
|
6
6
|
"keywords": [
|
|
@@ -131,7 +131,12 @@
|
|
|
131
131
|
}
|
|
132
132
|
],
|
|
133
133
|
"@semantic-release/npm",
|
|
134
|
-
|
|
134
|
+
[
|
|
135
|
+
"@semantic-release/github",
|
|
136
|
+
{
|
|
137
|
+
"successCommentCondition": "<% return !branch.prerelease; %>"
|
|
138
|
+
}
|
|
139
|
+
]
|
|
135
140
|
]
|
|
136
141
|
},
|
|
137
142
|
"publishConfig": {
|
package/src/N3Store.js
CHANGED
|
@@ -23,105 +23,6 @@ function hasInIndex(index0, key0, key1, key2) {
|
|
|
23
23
|
return !!index2 && key2 in index2;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// The number of index leaves that the last `merge` call added
|
|
27
|
-
let mergedLeaves = 0;
|
|
28
|
-
|
|
29
|
-
function merge(target, source, depth = 4) {
|
|
30
|
-
let size = target[SIZE] || 0;
|
|
31
|
-
for (const key in source) {
|
|
32
|
-
if (!(key in target)) {
|
|
33
|
-
size++;
|
|
34
|
-
if (depth === 0) mergedLeaves++;
|
|
35
|
-
target[key] = depth === 0 ? null : merge(Object.create(null), source[key], depth - 1);
|
|
36
|
-
}
|
|
37
|
-
// Merge into the existing object in place,
|
|
38
|
-
// as graph objects are frozen and cannot be reassigned
|
|
39
|
-
else if (depth !== 0)
|
|
40
|
-
merge(target[key], source[key], depth - 1);
|
|
41
|
-
}
|
|
42
|
-
// Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
|
|
43
|
-
if (depth <= 2)
|
|
44
|
-
target[SIZE] = size;
|
|
45
|
-
|
|
46
|
-
return target;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Determines the intersection of the `_graphs` index s1 and s2.
|
|
51
|
-
* s1 and s2 *must* belong to Stores that share an `_entityIndex`.
|
|
52
|
-
*
|
|
53
|
-
* False is returned when there is no intersection; this should
|
|
54
|
-
* *not* be set as the value for an index.
|
|
55
|
-
*/
|
|
56
|
-
function intersect(s1, s2, depth = 4) {
|
|
57
|
-
let target = false, size = 0;
|
|
58
|
-
|
|
59
|
-
if (depth <= 2 && s2[SIZE] < s1[SIZE])
|
|
60
|
-
[s1, s2] = [s2, s1];
|
|
61
|
-
|
|
62
|
-
for (const key in s1) {
|
|
63
|
-
if (key in s2) {
|
|
64
|
-
const intersection = depth === 0 ? null : intersect(s1[key], s2[key], depth - 1);
|
|
65
|
-
if (intersection !== false) {
|
|
66
|
-
target = target || Object.create(null);
|
|
67
|
-
target[key] = intersection;
|
|
68
|
-
size++;
|
|
69
|
-
}
|
|
70
|
-
// Depth 3 is the 'subjects', 'predicates' and 'objects' keys.
|
|
71
|
-
// If the 'subjects' index is empty, so will the 'predicates' and 'objects' index.
|
|
72
|
-
else if (depth === 3) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
|
|
79
|
-
if (depth <= 2 && target)
|
|
80
|
-
target[SIZE] = size;
|
|
81
|
-
|
|
82
|
-
return target;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Determines the difference of the `_graphs` index s1 and s2.
|
|
87
|
-
* s1 and s2 *must* belong to Stores that share an `_entityIndex`.
|
|
88
|
-
*
|
|
89
|
-
* False is returned when there is no difference; this should
|
|
90
|
-
* *not* be set as the value for an index.
|
|
91
|
-
*/
|
|
92
|
-
function difference(s1, s2, depth = 4) {
|
|
93
|
-
let target = false, size = 0;
|
|
94
|
-
|
|
95
|
-
for (const key in s1) {
|
|
96
|
-
// When the key is not in the index, then none of the triples defined by s1[key] are
|
|
97
|
-
// in s2 and so we want to copy them over to the resultant store.
|
|
98
|
-
if (!(key in s2)) {
|
|
99
|
-
target = target || Object.create(null);
|
|
100
|
-
target[key] = depth === 0 ? null : merge({}, s1[key], depth - 1);
|
|
101
|
-
size++;
|
|
102
|
-
}
|
|
103
|
-
else if (depth !== 0) {
|
|
104
|
-
const diff = difference(s1[key], s2[key], depth - 1);
|
|
105
|
-
if (diff !== false) {
|
|
106
|
-
target = target || Object.create(null);
|
|
107
|
-
target[key] = diff;
|
|
108
|
-
size++;
|
|
109
|
-
}
|
|
110
|
-
// Depth 3 is the 'subjects', 'predicates' and 'objects' keys.
|
|
111
|
-
// If the 'subjects' index is empty, so will the 'predicates' and 'objects' index.
|
|
112
|
-
else if (depth === 3) {
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Depth 2 is the level of the `subjects`, `predicates`, and `objects` indexes.
|
|
119
|
-
if (depth <= 2 && target)
|
|
120
|
-
target[SIZE] = size;
|
|
121
|
-
|
|
122
|
-
return target;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
26
|
// Returns the key of a term in the entity index.
|
|
126
27
|
// Keys mark the term type by their first character, so the IRI of a named node
|
|
127
28
|
// that starts with such a marker (as relative IRIs can) is wrapped in < and >.
|
|
@@ -259,6 +160,7 @@ export default class N3Store {
|
|
|
259
160
|
this._size = 0;
|
|
260
161
|
// `_graphs` contains subject, predicate, and object indexes per graph
|
|
261
162
|
this._graphs = Object.create(null);
|
|
163
|
+
this._graphCount = 0;
|
|
262
164
|
// `_observers` contains weak references to views notified before every mutation
|
|
263
165
|
this._observers = null;
|
|
264
166
|
|
|
@@ -555,6 +457,7 @@ export default class N3Store {
|
|
|
555
457
|
// Freezing a graph helps subsequent `add` performance,
|
|
556
458
|
// and properties will never be modified anyway
|
|
557
459
|
Object.freeze(graphItem);
|
|
460
|
+
this._graphCount++;
|
|
558
461
|
}
|
|
559
462
|
|
|
560
463
|
// Notify observers before inserting a new quad so snapshots retain their prior contents
|
|
@@ -573,6 +476,63 @@ export default class N3Store {
|
|
|
573
476
|
return true;
|
|
574
477
|
}
|
|
575
478
|
|
|
479
|
+
// ### `_addFromIndex` adds the quads in the given graph indexes of a store
|
|
480
|
+
// that shares this store's entity index, so no terms need to be converted.
|
|
481
|
+
// With `otherGraphs`, it only adds the quads that are not in those indexes.
|
|
482
|
+
// Index keys are strings, so the ids are converted back to the numbers that
|
|
483
|
+
// `addQuad` uses: forwarded views compare the ids they are notified with to
|
|
484
|
+
// their own numeric ids.
|
|
485
|
+
_addFromIndex(graphs, otherGraphs = null) {
|
|
486
|
+
for (const graphKey in graphs) {
|
|
487
|
+
const subjects = graphs[graphKey].subjects, other = otherGraphs && otherGraphs[graphKey];
|
|
488
|
+
const otherSubjects = other ? other.subjects : null;
|
|
489
|
+
for (const subjectKey in subjects) {
|
|
490
|
+
const subject = Number(subjectKey), predicates = subjects[subjectKey];
|
|
491
|
+
const otherPredicates = otherSubjects && otherSubjects[subjectKey];
|
|
492
|
+
for (const predicateKey in predicates) {
|
|
493
|
+
const predicate = Number(predicateKey), objects = predicates[predicateKey];
|
|
494
|
+
const otherObjects = otherPredicates && otherPredicates[predicateKey];
|
|
495
|
+
for (const objectKey in objects) {
|
|
496
|
+
if (!otherObjects || !(objectKey in otherObjects))
|
|
497
|
+
this._addQuad(subject, predicate, Number(objectKey), Number(graphKey));
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ### `_addIntersectionFromIndex` adds the quads that are in both of the
|
|
505
|
+
// given graph indexes, walking the graphs of the first and, below them,
|
|
506
|
+
// whichever index has fewer keys
|
|
507
|
+
_addIntersectionFromIndex(graphs, otherGraphs) {
|
|
508
|
+
for (const graphKey in graphs) {
|
|
509
|
+
const other = otherGraphs[graphKey];
|
|
510
|
+
if (other) {
|
|
511
|
+
let subjects = graphs[graphKey].subjects, otherSubjects = other.subjects;
|
|
512
|
+
if (otherSubjects[SIZE] < subjects[SIZE])
|
|
513
|
+
[subjects, otherSubjects] = [otherSubjects, subjects];
|
|
514
|
+
for (const subjectKey in subjects) {
|
|
515
|
+
let predicates = subjects[subjectKey], otherPredicates = otherSubjects[subjectKey];
|
|
516
|
+
if (otherPredicates) {
|
|
517
|
+
if (otherPredicates[SIZE] < predicates[SIZE])
|
|
518
|
+
[predicates, otherPredicates] = [otherPredicates, predicates];
|
|
519
|
+
for (const predicateKey in predicates) {
|
|
520
|
+
let objects = predicates[predicateKey], otherObjects = otherPredicates[predicateKey];
|
|
521
|
+
if (otherObjects) {
|
|
522
|
+
if (otherObjects[SIZE] < objects[SIZE])
|
|
523
|
+
[objects, otherObjects] = [otherObjects, objects];
|
|
524
|
+
for (const objectKey in objects) {
|
|
525
|
+
if (objectKey in otherObjects)
|
|
526
|
+
this._addQuad(Number(subjectKey), Number(predicateKey), Number(objectKey), Number(graphKey));
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
576
536
|
// ### `addQuads` adds multiple quads to the store
|
|
577
537
|
addQuads(quads) {
|
|
578
538
|
for (let i = 0; i < quads.length; i++)
|
|
@@ -643,8 +603,10 @@ export default class N3Store {
|
|
|
643
603
|
if (this._size !== null) this._size--;
|
|
644
604
|
|
|
645
605
|
// Remove the graph if it is empty
|
|
646
|
-
if (graphItem.subjects[SIZE] === 0)
|
|
606
|
+
if (graphItem.subjects[SIZE] === 0) {
|
|
647
607
|
delete graphs[graph];
|
|
608
|
+
this._graphCount--;
|
|
609
|
+
}
|
|
648
610
|
return true;
|
|
649
611
|
}
|
|
650
612
|
|
|
@@ -1104,15 +1066,9 @@ export default class N3Store {
|
|
|
1104
1066
|
|
|
1105
1067
|
if (Array.isArray(quads))
|
|
1106
1068
|
this.addQuads(quads);
|
|
1107
|
-
//
|
|
1108
|
-
else if (
|
|
1109
|
-
|
|
1110
|
-
// Each new quad adds one leaf to each of the three indexes
|
|
1111
|
-
mergedLeaves = 0;
|
|
1112
|
-
this._graphs = merge(this._graphs, quads._graphs);
|
|
1113
|
-
if (this._size !== null) this._size += mergedLeaves / 3;
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1069
|
+
// A store with the same entity index can be copied by identifier
|
|
1070
|
+
else if (quads instanceof N3Store && quads._entityIndex === this._entityIndex)
|
|
1071
|
+
this._addFromIndex(quads._graphs);
|
|
1116
1072
|
else {
|
|
1117
1073
|
for (const quad of quads)
|
|
1118
1074
|
this.add(quad);
|
|
@@ -1189,11 +1145,7 @@ export default class N3Store {
|
|
|
1189
1145
|
|
|
1190
1146
|
if ((other instanceof N3Store) && other._entityIndex === this._entityIndex) {
|
|
1191
1147
|
const store = new N3Store({ entityIndex: this._entityIndex });
|
|
1192
|
-
|
|
1193
|
-
if (graphs) {
|
|
1194
|
-
store._graphs = graphs;
|
|
1195
|
-
store._size = null;
|
|
1196
|
-
}
|
|
1148
|
+
store._addFromIndex(this._graphs, other._graphs);
|
|
1197
1149
|
return store;
|
|
1198
1150
|
}
|
|
1199
1151
|
|
|
@@ -1234,16 +1186,17 @@ export default class N3Store {
|
|
|
1234
1186
|
|
|
1235
1187
|
if (other === this) {
|
|
1236
1188
|
const store = new N3Store({ entityIndex: this._entityIndex });
|
|
1237
|
-
store.
|
|
1238
|
-
store._size = this.size;
|
|
1189
|
+
store._addFromIndex(this._graphs);
|
|
1239
1190
|
return store;
|
|
1240
1191
|
}
|
|
1241
1192
|
else if ((other instanceof N3Store) && this._entityIndex === other._entityIndex) {
|
|
1242
1193
|
const store = new N3Store({ entityIndex: this._entityIndex });
|
|
1243
|
-
|
|
1244
|
-
if (
|
|
1245
|
-
|
|
1246
|
-
|
|
1194
|
+
// Starting a loop over no graphs costs more than checking for an empty store
|
|
1195
|
+
if (this._size !== 0 && other._size !== 0) {
|
|
1196
|
+
if (other._graphCount < this._graphCount)
|
|
1197
|
+
store._addIntersectionFromIndex(other._graphs, this._graphs);
|
|
1198
|
+
else
|
|
1199
|
+
store._addIntersectionFromIndex(this._graphs, other._graphs);
|
|
1247
1200
|
}
|
|
1248
1201
|
return store;
|
|
1249
1202
|
}
|
|
@@ -1331,9 +1284,7 @@ export default class N3Store {
|
|
|
1331
1284
|
*/
|
|
1332
1285
|
union(quads) {
|
|
1333
1286
|
const store = new N3Store({ entityIndex: this._entityIndex });
|
|
1334
|
-
store.
|
|
1335
|
-
store._size = this.size;
|
|
1336
|
-
|
|
1287
|
+
store._addFromIndex(this._graphs);
|
|
1337
1288
|
store.addAll(quads);
|
|
1338
1289
|
return store;
|
|
1339
1290
|
}
|
|
@@ -1598,8 +1549,10 @@ class DatasetCoreAndReadableStream extends Readable {
|
|
|
1598
1549
|
objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
|
|
1599
1550
|
}
|
|
1600
1551
|
|
|
1601
|
-
if (subjects)
|
|
1552
|
+
if (subjects) {
|
|
1602
1553
|
newStore._graphs[graphKey] = { subjects, predicates, objects };
|
|
1554
|
+
newStore._graphCount++;
|
|
1555
|
+
}
|
|
1603
1556
|
}
|
|
1604
1557
|
}
|
|
1605
1558
|
newStore._size = null;
|