@itwin/presentation-backend 5.14.0-dev.16 → 5.14.0-dev.18
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/CHANGELOG.md +6 -1
- package/lib/cjs/presentation-backend/ElementPropertiesHelper.d.ts +11 -14
- package/lib/cjs/presentation-backend/ElementPropertiesHelper.d.ts.map +1 -1
- package/lib/cjs/presentation-backend/ElementPropertiesHelper.js +71 -43
- package/lib/cjs/presentation-backend/ElementPropertiesHelper.js.map +1 -1
- package/lib/esm/presentation-backend/ElementPropertiesHelper.d.ts +11 -14
- package/lib/esm/presentation-backend/ElementPropertiesHelper.d.ts.map +1 -1
- package/lib/esm/presentation-backend/ElementPropertiesHelper.js +72 -43
- package/lib/esm/presentation-backend/ElementPropertiesHelper.js.map +1 -1
- package/package.json +14 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# Change Log - @itwin/presentation-backend
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Tue, 22 Sep 2026 22:39:31 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 5.13.5
|
|
6
|
+
Tue, 22 Sep 2026 22:38:08 GMT
|
|
7
|
+
|
|
8
|
+
_Version update only_
|
|
4
9
|
|
|
5
10
|
## 5.13.4
|
|
6
11
|
Fri, 18 Sep 2026 15:11:19 GMT
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Observable } from "rxjs";
|
|
5
5
|
import { IModelDb } from "@itwin/core-backend";
|
|
6
|
-
import { Id64String } from "@itwin/core-bentley";
|
|
6
|
+
import { Id64Array, Id64String } from "@itwin/core-bentley";
|
|
7
7
|
import { ContentDescriptorRequestOptions, ContentRequestOptions, Descriptor, Item, KeySet, RulesetVariable } from "@itwin/presentation-common";
|
|
8
8
|
/** @internal */
|
|
9
9
|
export declare function getContentItemsObservableFromElementIds(imodel: IModelDb, contentDescriptorGetter: (partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, "rulesetOrId" | "keys">) => Promise<Descriptor | undefined>, contentSetGetter: (partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, "rulesetOrId" | "keys" | "descriptor">) => Promise<Item[]>, elementIds: Id64String[], classParallelism: number, batchesParallelism: number, batchSize: number): {
|
|
@@ -21,23 +21,20 @@ export declare function getContentItemsObservableFromClassNames(imodel: IModelDb
|
|
|
21
21
|
}>;
|
|
22
22
|
count: Observable<number>;
|
|
23
23
|
};
|
|
24
|
+
interface ElementIdBatch {
|
|
25
|
+
ids: Id64Array;
|
|
26
|
+
ranges: Array<{
|
|
27
|
+
from: Id64String;
|
|
28
|
+
to: Id64String;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
24
31
|
/**
|
|
25
32
|
* Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily
|
|
26
|
-
* be sequential, a batch is defined a list of from-to pairs.
|
|
27
|
-
* @internal
|
|
28
|
-
*/
|
|
29
|
-
export declare function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<Array<{
|
|
30
|
-
from: Id64String;
|
|
31
|
-
to: Id64String;
|
|
32
|
-
}>>;
|
|
33
|
-
/**
|
|
34
|
-
* Query all ECInstanceIds from given class and stream from-to pairs that batch the items into batches of `batchSize` size.
|
|
33
|
+
* be sequential, a batch is defined a list of from-to pairs. Ranges combine consecutive local IDs within the same briefcase.
|
|
35
34
|
* @internal
|
|
36
35
|
*/
|
|
37
|
-
export declare function
|
|
38
|
-
from: Id64String;
|
|
39
|
-
to: Id64String;
|
|
40
|
-
}>>;
|
|
36
|
+
export declare function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<ElementIdBatch>;
|
|
41
37
|
/** @internal */
|
|
42
38
|
export declare function getElementsCount(db: IModelDb, classNames: string[]): Promise<any>;
|
|
39
|
+
export {};
|
|
43
40
|
//# sourceMappingURL=ElementPropertiesHelper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElementPropertiesHelper.d.ts","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAoD,UAAU,EAAsC,MAAM,MAAM,CAAC;AACxH,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,
|
|
1
|
+
{"version":3,"file":"ElementPropertiesHelper.d.ts","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAoD,UAAU,EAAsC,MAAM,MAAM,CAAC;AACxH,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAQ,SAAS,EAAE,UAAU,EAAuB,MAAM,qBAAqB,CAAC;AAEvF,OAAO,EACL,+BAA+B,EAC/B,qBAAqB,EACrB,UAAU,EAEV,IAAI,EACJ,MAAM,EAKN,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAQpC,gBAAgB;AAChB,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,QAAQ,EAChB,uBAAuB,EAAE,CACvB,YAAY,EAAE,IAAI,CAAC,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC,KAC3G,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,EACpC,gBAAgB,EAAE,CAChB,YAAY,EAAE,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,KAC5H,OAAO,CAAC,IAAI,EAAE,CAAC,EACpB,UAAU,EAAE,UAAU,EAAE,EACxB,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,GAChB;IAAE,WAAW,EAAE,UAAU,CAAC;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,IAAI,EAAE,CAAA;KAAE,CAAC,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;CAAE,CAkBnG;AAED,gBAAgB;AAChB,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,QAAQ,EAChB,uBAAuB,EAAE,CACvB,YAAY,EAAE,IAAI,CAAC,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC,KAC3G,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,EACpC,gBAAgB,EAAE,CAChB,YAAY,EAAE,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,KAC5H,OAAO,CAAC,IAAI,EAAE,CAAC,EACpB,cAAc,EAAE,MAAM,EAAE,EACxB,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,GAChB;IAAE,WAAW,EAAE,UAAU,CAAC;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,IAAI,EAAE,CAAA;KAAE,CAAC,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;CAAE,CAkBnG;AAsLD,UAAU,cAAc;IACtB,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CACrD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAuBtG;AAUD,gBAAgB;AAChB,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,gBA0BxE"}
|
|
@@ -10,10 +10,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.getContentItemsObservableFromElementIds = getContentItemsObservableFromElementIds;
|
|
11
11
|
exports.getContentItemsObservableFromClassNames = getContentItemsObservableFromClassNames;
|
|
12
12
|
exports.createIdBatches = createIdBatches;
|
|
13
|
-
exports.getBatchedClassElementIds = getBatchedClassElementIds;
|
|
14
13
|
exports.getElementsCount = getElementsCount;
|
|
15
14
|
const rxjs_1 = require("rxjs");
|
|
16
15
|
const core_bentley_1 = require("@itwin/core-bentley");
|
|
16
|
+
const core_common_1 = require("@itwin/core-common");
|
|
17
17
|
const presentation_common_1 = require("@itwin/presentation-common");
|
|
18
18
|
const presentation_shared_1 = require("@itwin/presentation-shared");
|
|
19
19
|
function getECSqlName(fullClassName) {
|
|
@@ -23,18 +23,18 @@ function getECSqlName(fullClassName) {
|
|
|
23
23
|
/** @internal */
|
|
24
24
|
function getContentItemsObservableFromElementIds(imodel, contentDescriptorGetter, contentSetGetter, elementIds, classParallelism, batchesParallelism, batchSize) {
|
|
25
25
|
return {
|
|
26
|
-
itemBatches: getElementClassesFromIds(imodel, elementIds).pipe((0, rxjs_1.mergeMap)(({ classFullName, ids }) => getBatchedClassContentItems(classFullName, contentDescriptorGetter, contentSetGetter, () => createIdBatches(core_bentley_1.OrderedId64Iterable.sortArray(ids), batchSize), batchesParallelism), classParallelism)),
|
|
26
|
+
itemBatches: getElementClassesFromIds(imodel, elementIds).pipe((0, rxjs_1.mergeMap)(({ classFullName, ids }) => getBatchedClassContentItems(imodel, classFullName, contentDescriptorGetter, contentSetGetter, () => createIdBatches(core_bentley_1.OrderedId64Iterable.sortArray(ids), batchSize), batchesParallelism), classParallelism)),
|
|
27
27
|
count: (0, rxjs_1.of)(elementIds.length),
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
/** @internal */
|
|
31
31
|
function getContentItemsObservableFromClassNames(imodel, contentDescriptorGetter, contentSetGetter, elementClasses, classParallelism, batchesParallelism, batchSize) {
|
|
32
32
|
return {
|
|
33
|
-
itemBatches: getClassesWithInstances(imodel, elementClasses).pipe((0, rxjs_1.mergeMap)((classFullName) => getBatchedClassContentItems(classFullName, contentDescriptorGetter, contentSetGetter, () => getBatchedClassElementIds(imodel, classFullName, batchSize), batchesParallelism), classParallelism)),
|
|
33
|
+
itemBatches: getClassesWithInstances(imodel, elementClasses).pipe((0, rxjs_1.mergeMap)((classFullName) => getBatchedClassContentItems(imodel, classFullName, contentDescriptorGetter, contentSetGetter, () => getBatchedClassElementIds(imodel, classFullName, batchSize), batchesParallelism), classParallelism)),
|
|
34
34
|
count: (0, rxjs_1.from)(getElementsCount(imodel, elementClasses)),
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
-
function getBatchedClassContentItems(classFullName, contentDescriptorGetter, contentSetGetter, batcher, batchesParallelism) {
|
|
37
|
+
function getBatchedClassContentItems(imodel, classFullName, contentDescriptorGetter, contentSetGetter, batcher, batchesParallelism) {
|
|
38
38
|
return (0, rxjs_1.defer)(async () => {
|
|
39
39
|
const ruleset = createClassContentRuleset(classFullName);
|
|
40
40
|
const keys = new presentation_common_1.KeySet();
|
|
@@ -42,41 +42,70 @@ function getBatchedClassContentItems(classFullName, contentDescriptorGetter, con
|
|
|
42
42
|
if (!descriptor) {
|
|
43
43
|
throw new presentation_common_1.PresentationError(presentation_common_1.PresentationStatus.Error, `Failed to get descriptor for class ${classFullName}`);
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
(0, rxjs_1.mergeMap)(({ descriptor, keys, ruleset, batch }) => (0, rxjs_1.defer)(async () => {
|
|
51
|
-
const filteringDescriptor = new presentation_common_1.Descriptor(descriptor);
|
|
52
|
-
filteringDescriptor.instanceFilter = {
|
|
45
|
+
const aspectFields = getPrunableAspectFields(descriptor, classFullName);
|
|
46
|
+
return { descriptor, keys, ruleset, aspectFields };
|
|
47
|
+
}).pipe((0, rxjs_1.mergeMap)((x) => batcher().pipe((0, rxjs_1.map)((batch) => ({ ...x, batch })))), (0, rxjs_1.mergeMap)(({ descriptor, keys, ruleset, batch, aspectFields }) => (0, rxjs_1.defer)(async () => {
|
|
48
|
+
const batchDescriptor = new presentation_common_1.Descriptor(descriptor);
|
|
49
|
+
batchDescriptor.instanceFilter = {
|
|
53
50
|
selectClassName: classFullName,
|
|
54
|
-
expression:
|
|
51
|
+
expression: batch.ranges
|
|
52
|
+
.map(({ from: fromId, to }) => fromId === to ? `this.ECInstanceId = ${fromId}` : `this.ECInstanceId >= ${fromId} AND this.ECInstanceId <= ${to}`)
|
|
53
|
+
.join(" OR "),
|
|
55
54
|
};
|
|
56
|
-
|
|
55
|
+
if (aspectFields.length) {
|
|
56
|
+
await selectBatchAspectFields(imodel, batchDescriptor, aspectFields, batch.ids);
|
|
57
|
+
}
|
|
58
|
+
const items = await contentSetGetter({
|
|
57
59
|
rulesetOrId: ruleset,
|
|
58
60
|
keys,
|
|
59
|
-
descriptor:
|
|
61
|
+
descriptor: batchDescriptor,
|
|
60
62
|
});
|
|
61
|
-
|
|
63
|
+
return { descriptor: batchDescriptor, items };
|
|
64
|
+
}), batchesParallelism));
|
|
62
65
|
}
|
|
63
|
-
function
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
filter += " OR ";
|
|
68
|
-
}
|
|
69
|
-
filter += cond;
|
|
66
|
+
function getPrunableAspectFields(descriptor, classFullName) {
|
|
67
|
+
// Caller selections take precedence; don't replace an include/exclude selector with our own.
|
|
68
|
+
if (descriptor.fieldsSelector || countFields(descriptor.fields) <= 1000) {
|
|
69
|
+
return [];
|
|
70
70
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
else {
|
|
76
|
-
appendCondition(`this.ECInstanceId >= ${item.from} AND this.ECInstanceId <= ${item.to}`);
|
|
71
|
+
const { schemaName, className } = (0, presentation_shared_1.parseFullClassName)(classFullName);
|
|
72
|
+
return descriptor.fields.filter((field) => {
|
|
73
|
+
if (!field.isNestedContentField() || field.pathToPrimaryClass.length !== 1) {
|
|
74
|
+
return false;
|
|
77
75
|
}
|
|
76
|
+
const step = field.pathToPrimaryClass[0];
|
|
77
|
+
return (!step.isForwardRelationship &&
|
|
78
|
+
(step.relationshipInfo.name === "BisCore:ElementOwnsMultiAspects" || step.relationshipInfo.name === "BisCore:ElementOwnsUniqueAspect") &&
|
|
79
|
+
step.sourceClassInfo.id === field.contentClassInfo.id &&
|
|
80
|
+
step.targetClassInfo.name === `${schemaName}:${className}`);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function countFields(fields) {
|
|
84
|
+
return fields.reduce((count, field) => count + 1 + (field.isNestedContentField() ? countFields(field.nestedFields) : 0), 0);
|
|
85
|
+
}
|
|
86
|
+
async function selectBatchAspectFields(imodel, descriptor, aspectFields, batch) {
|
|
87
|
+
const query = `
|
|
88
|
+
WITH aspectClasses(ClassId) AS (
|
|
89
|
+
SELECT DISTINCT a.ECClassId
|
|
90
|
+
FROM bis.ElementMultiAspect a
|
|
91
|
+
JOIN IdSet(:elementIds) e ON e.id = a.Element.Id
|
|
92
|
+
UNION ALL
|
|
93
|
+
SELECT DISTINCT a.ECClassId
|
|
94
|
+
FROM bis.ElementUniqueAspect a
|
|
95
|
+
JOIN IdSet(:elementIds) e ON e.id = a.Element.Id
|
|
96
|
+
)
|
|
97
|
+
SELECT IdToHex(b.TargetECInstanceId) classId
|
|
98
|
+
FROM meta.ClassHasAllBaseClasses b
|
|
99
|
+
JOIN aspectClasses a ON a.ClassId = b.SourceECInstanceId
|
|
100
|
+
`;
|
|
101
|
+
const aspectClasses = new Set();
|
|
102
|
+
for await (const row of imodel.createQueryReader(query, core_common_1.QueryBinder.from({ elementIds: batch }))) {
|
|
103
|
+
aspectClasses.add(row.classId);
|
|
104
|
+
}
|
|
105
|
+
const excludedFields = aspectFields.filter((field) => !aspectClasses.has(field.contentClassInfo.id));
|
|
106
|
+
if (excludedFields.length > 0) {
|
|
107
|
+
descriptor.fieldsSelector = { type: "exclude", fields: excludedFields.map((field) => field.getFieldDescriptor()) };
|
|
78
108
|
}
|
|
79
|
-
return filter;
|
|
80
109
|
}
|
|
81
110
|
function createClassContentRuleset(fullClassName) {
|
|
82
111
|
const { schemaName, className } = (0, presentation_shared_1.parseFullClassName)(fullClassName);
|
|
@@ -112,7 +141,10 @@ function getElementClassesFromIds(imodel, elementIds) {
|
|
|
112
141
|
WHERE e.ECInstanceId IN (${elementIds.slice(idsFrom, idsTo).join(",")})
|
|
113
142
|
GROUP BY e.ECClassId
|
|
114
143
|
`));
|
|
115
|
-
}), (0, rxjs_1.map)((row) => ({
|
|
144
|
+
}), (0, rxjs_1.map)((row) => ({
|
|
145
|
+
className: row.className,
|
|
146
|
+
ids: row.ids.split(","),
|
|
147
|
+
})), (0, rxjs_1.groupBy)(({ className }) => className), (0, rxjs_1.mergeMap)((groups) => groups.pipe((0, rxjs_1.reduce)((acc, g) => {
|
|
116
148
|
g.ids.forEach((id) => acc.ids.push(id));
|
|
117
149
|
return {
|
|
118
150
|
classFullName: g.className,
|
|
@@ -120,7 +152,7 @@ function getElementClassesFromIds(imodel, elementIds) {
|
|
|
120
152
|
};
|
|
121
153
|
}, { classFullName: "", ids: [] }))));
|
|
122
154
|
}
|
|
123
|
-
/** Given a list of full class names, get
|
|
155
|
+
/** Given a list of full class names, get concrete class names with instances. */
|
|
124
156
|
function getClassesWithInstances(imodel, fullClassNames) {
|
|
125
157
|
return (0, rxjs_1.from)(fullClassNames).pipe((0, rxjs_1.mergeMap)((fullClassName) => (0, rxjs_1.from)(imodel.createQueryReader(`
|
|
126
158
|
SELECT ec_classname(e.ECClassId, 's.c') className
|
|
@@ -130,12 +162,12 @@ function getClassesWithInstances(imodel, fullClassNames) {
|
|
|
130
162
|
}
|
|
131
163
|
/**
|
|
132
164
|
* Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily
|
|
133
|
-
* be sequential, a batch is defined a list of from-to pairs.
|
|
165
|
+
* be sequential, a batch is defined a list of from-to pairs. Ranges combine consecutive local IDs within the same briefcase.
|
|
134
166
|
* @internal
|
|
135
167
|
*/
|
|
136
168
|
function createIdBatches(sortedIds, batchSize) {
|
|
137
169
|
return (0, rxjs_1.range)(0, sortedIds.length / batchSize).pipe((0, rxjs_1.map)((batchIndex) => {
|
|
138
|
-
const
|
|
170
|
+
const ranges = new Array();
|
|
139
171
|
const startIndex = batchIndex * batchSize;
|
|
140
172
|
const endIndex = Math.min((batchIndex + 1) * batchSize, sortedIds.length) - 1;
|
|
141
173
|
let fromId = sortedIds[startIndex];
|
|
@@ -145,22 +177,18 @@ function createIdBatches(sortedIds, batchSize) {
|
|
|
145
177
|
};
|
|
146
178
|
for (let i = startIndex + 1; i <= endIndex; ++i) {
|
|
147
179
|
const currLocalId = core_bentley_1.Id64.getLocalId(sortedIds[i]);
|
|
148
|
-
if (currLocalId !== to.localId + 1) {
|
|
149
|
-
|
|
180
|
+
if (core_bentley_1.Id64.getBriefcaseId(sortedIds[i]) !== core_bentley_1.Id64.getBriefcaseId(to.id) || currLocalId !== to.localId + 1) {
|
|
181
|
+
ranges.push({ from: fromId, to: sortedIds[i - 1] });
|
|
150
182
|
fromId = sortedIds[i];
|
|
151
183
|
}
|
|
152
184
|
to = { id: sortedIds[i], localId: currLocalId };
|
|
153
185
|
}
|
|
154
|
-
|
|
155
|
-
return
|
|
186
|
+
ranges.push({ from: fromId, to: sortedIds[endIndex] });
|
|
187
|
+
return { ids: sortedIds.slice(startIndex, endIndex + 1), ranges };
|
|
156
188
|
}));
|
|
157
189
|
}
|
|
158
|
-
/**
|
|
159
|
-
* Query all ECInstanceIds from given class and stream from-to pairs that batch the items into batches of `batchSize` size.
|
|
160
|
-
* @internal
|
|
161
|
-
*/
|
|
162
190
|
function getBatchedClassElementIds(imodel, fullClassName, batchSize) {
|
|
163
|
-
return (0, rxjs_1.from)(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe((0, rxjs_1.map)((row) => row.id), (0, rxjs_1.bufferCount)(batchSize), (0, rxjs_1.map)((
|
|
191
|
+
return (0, rxjs_1.from)(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ONLY ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe((0, rxjs_1.map)((row) => row.id), (0, rxjs_1.bufferCount)(batchSize), (0, rxjs_1.map)((ids) => ({ ids, ranges: [{ from: ids[0], to: ids[ids.length - 1] }] })));
|
|
164
192
|
}
|
|
165
193
|
/** @internal */
|
|
166
194
|
async function getElementsCount(db, classNames) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElementPropertiesHelper.js","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n * See LICENSE.md in the project root for license terms and full copyright notice.\r\n *--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Core\r\n */\r\n\r\nimport { bufferCount, defer, from, groupBy, map, mergeMap, Observable, ObservedValueOf, of, range, reduce } from \"rxjs\";\r\nimport { IModelDb } from \"@itwin/core-backend\";\r\nimport { Id64, Id64Array, Id64String, OrderedId64Iterable } from \"@itwin/core-bentley\";\r\nimport { QueryRowProxy } from \"@itwin/core-common\";\r\nimport {\r\n ContentDescriptorRequestOptions,\r\n ContentRequestOptions,\r\n Descriptor,\r\n Item,\r\n KeySet,\r\n PresentationError,\r\n PresentationStatus,\r\n Ruleset,\r\n RulesetVariable,\r\n} from \"@itwin/presentation-common\";\r\nimport { parseFullClassName } from \"@itwin/presentation-shared\";\r\n\r\nfunction getECSqlName(fullClassName: string) {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return `[${schemaName}].[${className}]`;\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromElementIds(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementIds: Id64String[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getElementClassesFromIds(imodel, elementIds).pipe(\r\n mergeMap(\r\n ({ classFullName, ids }) =>\r\n getBatchedClassContentItems(\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => createIdBatches(OrderedId64Iterable.sortArray(ids), batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: of(elementIds.length),\r\n };\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromClassNames(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementClasses: string[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getClassesWithInstances(imodel, elementClasses).pipe(\r\n mergeMap(\r\n (classFullName) =>\r\n getBatchedClassContentItems(\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => getBatchedClassElementIds(imodel, classFullName, batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: from(getElementsCount(imodel, elementClasses)),\r\n };\r\n}\r\n\r\nfunction getBatchedClassContentItems(\r\n classFullName: string,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n batcher: () => Observable<Array<{ from: Id64String; to: Id64String }>>,\r\n batchesParallelism: number,\r\n): Observable<{ descriptor: Descriptor; items: Item[] }> {\r\n return defer(async () => {\r\n const ruleset = createClassContentRuleset(classFullName);\r\n const keys = new KeySet();\r\n const descriptor = await contentDescriptorGetter({ rulesetOrId: ruleset, keys });\r\n if (!descriptor) {\r\n throw new PresentationError(PresentationStatus.Error, `Failed to get descriptor for class ${classFullName}`);\r\n }\r\n return { descriptor, keys, ruleset };\r\n }).pipe(\r\n // create elements' id batches\r\n mergeMap((x) => batcher().pipe(map((batch) => ({ ...x, batch })))),\r\n // request content for each batch, filter by IDs for performance\r\n mergeMap(\r\n ({ descriptor, keys, ruleset, batch }) =>\r\n defer(async () => {\r\n const filteringDescriptor = new Descriptor(descriptor);\r\n filteringDescriptor.instanceFilter = {\r\n selectClassName: classFullName,\r\n expression: createElementIdsECExpressionFilter(batch),\r\n };\r\n return contentSetGetter({\r\n rulesetOrId: ruleset,\r\n keys,\r\n descriptor: filteringDescriptor,\r\n });\r\n }).pipe(map((items) => ({ descriptor, items }))),\r\n batchesParallelism,\r\n ),\r\n );\r\n}\r\n\r\nfunction createElementIdsECExpressionFilter(batch: Array<{ from: Id64String; to: Id64String }>): string {\r\n let filter = \"\";\r\n function appendCondition(cond: string) {\r\n if (filter.length > 0) {\r\n filter += \" OR \";\r\n }\r\n filter += cond;\r\n }\r\n for (const item of batch) {\r\n if (item.from === item.to) {\r\n appendCondition(`this.ECInstanceId = ${item.from}`);\r\n } else {\r\n appendCondition(`this.ECInstanceId >= ${item.from} AND this.ECInstanceId <= ${item.to}`);\r\n }\r\n }\r\n return filter;\r\n}\r\n\r\nfunction createClassContentRuleset(fullClassName: string): Ruleset {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return {\r\n id: `content/class-descriptor/${fullClassName}`,\r\n rules: [\r\n {\r\n ruleType: \"Content\",\r\n specifications: [\r\n {\r\n specType: \"ContentInstancesOfSpecificClasses\",\r\n classes: {\r\n schemaName,\r\n classNames: [className],\r\n arePolymorphic: false,\r\n },\r\n handlePropertiesPolymorphically: true,\r\n },\r\n ],\r\n },\r\n ],\r\n };\r\n}\r\n\r\n/** Given a list of element ids, group them by class name. */\r\nfunction getElementClassesFromIds(imodel: IModelDb, elementIds: string[]): Observable<{ classFullName: string; ids: Id64Array }> {\r\n const elementIdsBatchSize = 5000;\r\n return range(0, elementIds.length / elementIdsBatchSize).pipe(\r\n mergeMap((batchIndex) => {\r\n const idsFrom = batchIndex * elementIdsBatchSize;\r\n const idsTo = Math.min(idsFrom + elementIdsBatchSize, elementIds.length);\r\n return from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId) className, GROUP_CONCAT(IdToHex(e.ECInstanceId)) ids\r\n FROM bis.Element e\r\n WHERE e.ECInstanceId IN (${elementIds.slice(idsFrom, idsTo).join(\",\")})\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n );\r\n }),\r\n map((row: QueryRowProxy): { className: string; ids: Id64Array } => ({ className: row.className, ids: row.ids.split(\",\") })),\r\n groupBy(({ className }) => className),\r\n mergeMap((groups) =>\r\n groups.pipe(\r\n reduce<ObservedValueOf<typeof groups>, { classFullName: string; ids: Id64Array }>(\r\n (acc, g) => {\r\n g.ids.forEach((id) => acc.ids.push(id));\r\n return {\r\n classFullName: g.className,\r\n ids: acc.ids,\r\n };\r\n },\r\n { classFullName: \"\", ids: [] },\r\n ),\r\n ),\r\n ),\r\n );\r\n}\r\n\r\n/** Given a list of full class names, get a stream of actual class names that have instances. */\r\nfunction getClassesWithInstances(imodel: IModelDb, fullClassNames: string[]): Observable<string> {\r\n return from(fullClassNames).pipe(\r\n mergeMap((fullClassName) =>\r\n from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId, 's.c') className\r\n FROM ${getECSqlName(fullClassName)} e\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n ),\r\n ),\r\n map((row: QueryRowProxy): string => row.className),\r\n );\r\n}\r\n\r\n/**\r\n * Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily\r\n * be sequential, a batch is defined a list of from-to pairs.\r\n * @internal\r\n */\r\nexport function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<Array<{ from: Id64String; to: Id64String }>> {\r\n return range(0, sortedIds.length / batchSize).pipe(\r\n map((batchIndex) => {\r\n const sequences = new Array<{ from: Id64String; to: Id64String }>();\r\n const startIndex = batchIndex * batchSize;\r\n const endIndex = Math.min((batchIndex + 1) * batchSize, sortedIds.length) - 1;\r\n let fromId = sortedIds[startIndex];\r\n let to = {\r\n id: sortedIds[startIndex],\r\n localId: Id64.getLocalId(sortedIds[startIndex]),\r\n };\r\n for (let i = startIndex + 1; i <= endIndex; ++i) {\r\n const currLocalId = Id64.getLocalId(sortedIds[i]);\r\n if (currLocalId !== to.localId + 1) {\r\n sequences.push({ from: fromId, to: sortedIds[i - 1] });\r\n fromId = sortedIds[i];\r\n }\r\n to = { id: sortedIds[i], localId: currLocalId };\r\n }\r\n sequences.push({ from: fromId, to: sortedIds[endIndex] });\r\n return sequences;\r\n }),\r\n );\r\n}\r\n\r\n/**\r\n * Query all ECInstanceIds from given class and stream from-to pairs that batch the items into batches of `batchSize` size.\r\n * @internal\r\n */\r\nexport function getBatchedClassElementIds(imodel: IModelDb, fullClassName: string, batchSize: number): Observable<Array<{ from: Id64String; to: Id64String }>> {\r\n return from(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe(\r\n map((row): Id64String => row.id),\r\n bufferCount(batchSize),\r\n map((batch) => [{ from: batch[0], to: batch[batch.length - 1] }]),\r\n );\r\n}\r\n\r\n/** @internal */\r\nexport async function getElementsCount(db: IModelDb, classNames: string[]) {\r\n const whereClause = (() => {\r\n if (classNames === undefined || classNames.length === 0) {\r\n return undefined;\r\n }\r\n // check if list contains only valid class names\r\n const classNameRegExp = new RegExp(/^[\\w]+[.:][\\w]+$/);\r\n const invalidName = classNames.find((name) => !name.match(classNameRegExp));\r\n if (invalidName) {\r\n throw new PresentationError(\r\n PresentationStatus.InvalidArgument,\r\n `Encountered invalid class name - ${invalidName}.\r\n Valid class name formats: \"<schema name or alias>.<class name>\", \"<schema name or alias>:<class name>\"`,\r\n );\r\n }\r\n return `e.ECClassId IS (${classNames.map(getECSqlName).join(\",\")})`;\r\n })();\r\n const query = `\r\n SELECT COUNT(e.ECInstanceId) AS elementCount\r\n FROM bis.Element e\r\n ${whereClause ? `WHERE ${whereClause}` : \"\"}\r\n `;\r\n for await (const row of db.createQueryReader(query)) {\r\n return row.elementCount;\r\n }\r\n return 0;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"ElementPropertiesHelper.js","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n * See LICENSE.md in the project root for license terms and full copyright notice.\r\n *--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Core\r\n */\r\n\r\nimport { bufferCount, defer, from, groupBy, map, mergeMap, Observable, ObservedValueOf, of, range, reduce } from \"rxjs\";\r\nimport { IModelDb } from \"@itwin/core-backend\";\r\nimport { Id64, Id64Array, Id64String, OrderedId64Iterable } from \"@itwin/core-bentley\";\r\nimport { QueryBinder, QueryRowProxy } from \"@itwin/core-common\";\r\nimport {\r\n ContentDescriptorRequestOptions,\r\n ContentRequestOptions,\r\n Descriptor,\r\n Field,\r\n Item,\r\n KeySet,\r\n NestedContentField,\r\n PresentationError,\r\n PresentationStatus,\r\n Ruleset,\r\n RulesetVariable,\r\n} from \"@itwin/presentation-common\";\r\nimport { parseFullClassName } from \"@itwin/presentation-shared\";\r\n\r\nfunction getECSqlName(fullClassName: string) {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return `[${schemaName}].[${className}]`;\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromElementIds(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementIds: Id64String[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getElementClassesFromIds(imodel, elementIds).pipe(\r\n mergeMap(\r\n ({ classFullName, ids }) =>\r\n getBatchedClassContentItems(\r\n imodel,\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => createIdBatches(OrderedId64Iterable.sortArray(ids), batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: of(elementIds.length),\r\n };\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromClassNames(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementClasses: string[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getClassesWithInstances(imodel, elementClasses).pipe(\r\n mergeMap(\r\n (classFullName) =>\r\n getBatchedClassContentItems(\r\n imodel,\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => getBatchedClassElementIds(imodel, classFullName, batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: from(getElementsCount(imodel, elementClasses)),\r\n };\r\n}\r\n\r\nfunction getBatchedClassContentItems(\r\n imodel: IModelDb,\r\n classFullName: string,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n batcher: () => Observable<ElementIdBatch>,\r\n batchesParallelism: number,\r\n): Observable<{ descriptor: Descriptor; items: Item[] }> {\r\n return defer(async () => {\r\n const ruleset = createClassContentRuleset(classFullName);\r\n const keys = new KeySet();\r\n const descriptor = await contentDescriptorGetter({ rulesetOrId: ruleset, keys });\r\n if (!descriptor) {\r\n throw new PresentationError(PresentationStatus.Error, `Failed to get descriptor for class ${classFullName}`);\r\n }\r\n const aspectFields = getPrunableAspectFields(descriptor, classFullName);\r\n return { descriptor, keys, ruleset, aspectFields };\r\n }).pipe(\r\n mergeMap((x) => batcher().pipe(map((batch) => ({ ...x, batch })))),\r\n mergeMap(\r\n ({ descriptor, keys, ruleset, batch, aspectFields }) =>\r\n defer(async () => {\r\n const batchDescriptor = new Descriptor(descriptor);\r\n batchDescriptor.instanceFilter = {\r\n selectClassName: classFullName,\r\n expression: batch.ranges\r\n .map(({ from: fromId, to }) =>\r\n fromId === to ? `this.ECInstanceId = ${fromId}` : `this.ECInstanceId >= ${fromId} AND this.ECInstanceId <= ${to}`,\r\n )\r\n .join(\" OR \"),\r\n };\r\n if (aspectFields.length) {\r\n await selectBatchAspectFields(imodel, batchDescriptor, aspectFields, batch.ids);\r\n }\r\n const items = await contentSetGetter({\r\n rulesetOrId: ruleset,\r\n keys,\r\n descriptor: batchDescriptor,\r\n });\r\n return { descriptor: batchDescriptor, items };\r\n }),\r\n batchesParallelism,\r\n ),\r\n );\r\n}\r\n\r\nfunction getPrunableAspectFields(descriptor: Descriptor, classFullName: string): NestedContentField[] {\r\n // Caller selections take precedence; don't replace an include/exclude selector with our own.\r\n if (descriptor.fieldsSelector || countFields(descriptor.fields) <= 1000) {\r\n return [];\r\n }\r\n const { schemaName, className } = parseFullClassName(classFullName);\r\n return descriptor.fields.filter((field): field is NestedContentField => {\r\n if (!field.isNestedContentField() || field.pathToPrimaryClass.length !== 1) {\r\n return false;\r\n }\r\n const step = field.pathToPrimaryClass[0];\r\n return (\r\n !step.isForwardRelationship &&\r\n (step.relationshipInfo.name === \"BisCore:ElementOwnsMultiAspects\" || step.relationshipInfo.name === \"BisCore:ElementOwnsUniqueAspect\") &&\r\n step.sourceClassInfo.id === field.contentClassInfo.id &&\r\n step.targetClassInfo.name === `${schemaName}:${className}`\r\n );\r\n });\r\n}\r\n\r\nfunction countFields(fields: Field[]): number {\r\n return fields.reduce((count, field) => count + 1 + (field.isNestedContentField() ? countFields(field.nestedFields) : 0), 0);\r\n}\r\n\r\nasync function selectBatchAspectFields(imodel: IModelDb, descriptor: Descriptor, aspectFields: NestedContentField[], batch: Id64Array): Promise<void> {\r\n const query = `\r\n WITH aspectClasses(ClassId) AS (\r\n SELECT DISTINCT a.ECClassId\r\n FROM bis.ElementMultiAspect a\r\n JOIN IdSet(:elementIds) e ON e.id = a.Element.Id\r\n UNION ALL\r\n SELECT DISTINCT a.ECClassId\r\n FROM bis.ElementUniqueAspect a\r\n JOIN IdSet(:elementIds) e ON e.id = a.Element.Id\r\n )\r\n SELECT IdToHex(b.TargetECInstanceId) classId\r\n FROM meta.ClassHasAllBaseClasses b\r\n JOIN aspectClasses a ON a.ClassId = b.SourceECInstanceId\r\n `;\r\n const aspectClasses = new Set<Id64String>();\r\n for await (const row of imodel.createQueryReader(query, QueryBinder.from({ elementIds: batch }))) {\r\n aspectClasses.add(row.classId);\r\n }\r\n const excludedFields = aspectFields.filter((field) => !aspectClasses.has(field.contentClassInfo.id));\r\n if (excludedFields.length > 0) {\r\n descriptor.fieldsSelector = { type: \"exclude\", fields: excludedFields.map((field) => field.getFieldDescriptor()) };\r\n }\r\n}\r\n\r\nfunction createClassContentRuleset(fullClassName: string): Ruleset {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return {\r\n id: `content/class-descriptor/${fullClassName}`,\r\n rules: [\r\n {\r\n ruleType: \"Content\",\r\n specifications: [\r\n {\r\n specType: \"ContentInstancesOfSpecificClasses\",\r\n classes: {\r\n schemaName,\r\n classNames: [className],\r\n arePolymorphic: false,\r\n },\r\n handlePropertiesPolymorphically: true,\r\n },\r\n ],\r\n },\r\n ],\r\n };\r\n}\r\n\r\n/** Given a list of element ids, group them by class name. */\r\nfunction getElementClassesFromIds(imodel: IModelDb, elementIds: string[]): Observable<{ classFullName: string; ids: Id64Array }> {\r\n const elementIdsBatchSize = 5000;\r\n return range(0, elementIds.length / elementIdsBatchSize).pipe(\r\n mergeMap((batchIndex) => {\r\n const idsFrom = batchIndex * elementIdsBatchSize;\r\n const idsTo = Math.min(idsFrom + elementIdsBatchSize, elementIds.length);\r\n return from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId) className, GROUP_CONCAT(IdToHex(e.ECInstanceId)) ids\r\n FROM bis.Element e\r\n WHERE e.ECInstanceId IN (${elementIds.slice(idsFrom, idsTo).join(\",\")})\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n );\r\n }),\r\n map((row: QueryRowProxy): { className: string; ids: Id64Array } => ({\r\n className: row.className,\r\n ids: row.ids.split(\",\"),\r\n })),\r\n groupBy(({ className }) => className),\r\n mergeMap((groups) =>\r\n groups.pipe(\r\n reduce<ObservedValueOf<typeof groups>, { classFullName: string; ids: Id64Array }>(\r\n (acc, g) => {\r\n g.ids.forEach((id) => acc.ids.push(id));\r\n return {\r\n classFullName: g.className,\r\n ids: acc.ids,\r\n };\r\n },\r\n { classFullName: \"\", ids: [] },\r\n ),\r\n ),\r\n ),\r\n );\r\n}\r\n\r\n/** Given a list of full class names, get concrete class names with instances. */\r\nfunction getClassesWithInstances(imodel: IModelDb, fullClassNames: string[]): Observable<string> {\r\n return from(fullClassNames).pipe(\r\n mergeMap((fullClassName) =>\r\n from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId, 's.c') className\r\n FROM ${getECSqlName(fullClassName)} e\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n ),\r\n ),\r\n map((row: QueryRowProxy): string => row.className),\r\n );\r\n}\r\n\r\ninterface ElementIdBatch {\r\n ids: Id64Array;\r\n ranges: Array<{ from: Id64String; to: Id64String }>;\r\n}\r\n\r\n/**\r\n * Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily\r\n * be sequential, a batch is defined a list of from-to pairs. Ranges combine consecutive local IDs within the same briefcase.\r\n * @internal\r\n */\r\nexport function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<ElementIdBatch> {\r\n return range(0, sortedIds.length / batchSize).pipe(\r\n map((batchIndex) => {\r\n const ranges = new Array<{ from: Id64String; to: Id64String }>();\r\n const startIndex = batchIndex * batchSize;\r\n const endIndex = Math.min((batchIndex + 1) * batchSize, sortedIds.length) - 1;\r\n let fromId = sortedIds[startIndex];\r\n let to = {\r\n id: sortedIds[startIndex],\r\n localId: Id64.getLocalId(sortedIds[startIndex]),\r\n };\r\n for (let i = startIndex + 1; i <= endIndex; ++i) {\r\n const currLocalId = Id64.getLocalId(sortedIds[i]);\r\n if (Id64.getBriefcaseId(sortedIds[i]) !== Id64.getBriefcaseId(to.id) || currLocalId !== to.localId + 1) {\r\n ranges.push({ from: fromId, to: sortedIds[i - 1] });\r\n fromId = sortedIds[i];\r\n }\r\n to = { id: sortedIds[i], localId: currLocalId };\r\n }\r\n ranges.push({ from: fromId, to: sortedIds[endIndex] });\r\n return { ids: sortedIds.slice(startIndex, endIndex + 1), ranges };\r\n }),\r\n );\r\n}\r\n\r\nfunction getBatchedClassElementIds(imodel: IModelDb, fullClassName: string, batchSize: number): Observable<ElementIdBatch> {\r\n return from(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ONLY ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe(\r\n map((row): Id64String => row.id),\r\n bufferCount(batchSize),\r\n map((ids) => ({ ids, ranges: [{ from: ids[0], to: ids[ids.length - 1] }] })),\r\n );\r\n}\r\n\r\n/** @internal */\r\nexport async function getElementsCount(db: IModelDb, classNames: string[]) {\r\n const whereClause = (() => {\r\n if (classNames === undefined || classNames.length === 0) {\r\n return undefined;\r\n }\r\n // check if list contains only valid class names\r\n const classNameRegExp = new RegExp(/^[\\w]+[.:][\\w]+$/);\r\n const invalidName = classNames.find((name) => !name.match(classNameRegExp));\r\n if (invalidName) {\r\n throw new PresentationError(\r\n PresentationStatus.InvalidArgument,\r\n `Encountered invalid class name - ${invalidName}.\r\n Valid class name formats: \"<schema name or alias>.<class name>\", \"<schema name or alias>:<class name>\"`,\r\n );\r\n }\r\n return `e.ECClassId IS (${classNames.map(getECSqlName).join(\",\")})`;\r\n })();\r\n const query = `\r\n SELECT COUNT(e.ECInstanceId) AS elementCount\r\n FROM bis.Element e\r\n ${whereClause ? `WHERE ${whereClause}` : \"\"}\r\n `;\r\n for await (const row of db.createQueryReader(query)) {\r\n return row.elementCount;\r\n }\r\n return 0;\r\n}\r\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Observable } from "rxjs";
|
|
5
5
|
import { IModelDb } from "@itwin/core-backend";
|
|
6
|
-
import { Id64String } from "@itwin/core-bentley";
|
|
6
|
+
import { Id64Array, Id64String } from "@itwin/core-bentley";
|
|
7
7
|
import { ContentDescriptorRequestOptions, ContentRequestOptions, Descriptor, Item, KeySet, RulesetVariable } from "@itwin/presentation-common";
|
|
8
8
|
/** @internal */
|
|
9
9
|
export declare function getContentItemsObservableFromElementIds(imodel: IModelDb, contentDescriptorGetter: (partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, "rulesetOrId" | "keys">) => Promise<Descriptor | undefined>, contentSetGetter: (partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, "rulesetOrId" | "keys" | "descriptor">) => Promise<Item[]>, elementIds: Id64String[], classParallelism: number, batchesParallelism: number, batchSize: number): {
|
|
@@ -21,23 +21,20 @@ export declare function getContentItemsObservableFromClassNames(imodel: IModelDb
|
|
|
21
21
|
}>;
|
|
22
22
|
count: Observable<number>;
|
|
23
23
|
};
|
|
24
|
+
interface ElementIdBatch {
|
|
25
|
+
ids: Id64Array;
|
|
26
|
+
ranges: Array<{
|
|
27
|
+
from: Id64String;
|
|
28
|
+
to: Id64String;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
24
31
|
/**
|
|
25
32
|
* Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily
|
|
26
|
-
* be sequential, a batch is defined a list of from-to pairs.
|
|
27
|
-
* @internal
|
|
28
|
-
*/
|
|
29
|
-
export declare function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<Array<{
|
|
30
|
-
from: Id64String;
|
|
31
|
-
to: Id64String;
|
|
32
|
-
}>>;
|
|
33
|
-
/**
|
|
34
|
-
* Query all ECInstanceIds from given class and stream from-to pairs that batch the items into batches of `batchSize` size.
|
|
33
|
+
* be sequential, a batch is defined a list of from-to pairs. Ranges combine consecutive local IDs within the same briefcase.
|
|
35
34
|
* @internal
|
|
36
35
|
*/
|
|
37
|
-
export declare function
|
|
38
|
-
from: Id64String;
|
|
39
|
-
to: Id64String;
|
|
40
|
-
}>>;
|
|
36
|
+
export declare function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<ElementIdBatch>;
|
|
41
37
|
/** @internal */
|
|
42
38
|
export declare function getElementsCount(db: IModelDb, classNames: string[]): Promise<any>;
|
|
39
|
+
export {};
|
|
43
40
|
//# sourceMappingURL=ElementPropertiesHelper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElementPropertiesHelper.d.ts","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAoD,UAAU,EAAsC,MAAM,MAAM,CAAC;AACxH,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,
|
|
1
|
+
{"version":3,"file":"ElementPropertiesHelper.d.ts","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAoD,UAAU,EAAsC,MAAM,MAAM,CAAC;AACxH,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAQ,SAAS,EAAE,UAAU,EAAuB,MAAM,qBAAqB,CAAC;AAEvF,OAAO,EACL,+BAA+B,EAC/B,qBAAqB,EACrB,UAAU,EAEV,IAAI,EACJ,MAAM,EAKN,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAQpC,gBAAgB;AAChB,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,QAAQ,EAChB,uBAAuB,EAAE,CACvB,YAAY,EAAE,IAAI,CAAC,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC,KAC3G,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,EACpC,gBAAgB,EAAE,CAChB,YAAY,EAAE,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,KAC5H,OAAO,CAAC,IAAI,EAAE,CAAC,EACpB,UAAU,EAAE,UAAU,EAAE,EACxB,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,GAChB;IAAE,WAAW,EAAE,UAAU,CAAC;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,IAAI,EAAE,CAAA;KAAE,CAAC,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;CAAE,CAkBnG;AAED,gBAAgB;AAChB,wBAAgB,uCAAuC,CACrD,MAAM,EAAE,QAAQ,EAChB,uBAAuB,EAAE,CACvB,YAAY,EAAE,IAAI,CAAC,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC,KAC3G,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,EACpC,gBAAgB,EAAE,CAChB,YAAY,EAAE,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,YAAY,CAAC,KAC5H,OAAO,CAAC,IAAI,EAAE,CAAC,EACpB,cAAc,EAAE,MAAM,EAAE,EACxB,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,MAAM,GAChB;IAAE,WAAW,EAAE,UAAU,CAAC;QAAE,UAAU,EAAE,UAAU,CAAC;QAAC,KAAK,EAAE,IAAI,EAAE,CAAA;KAAE,CAAC,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;CAAE,CAkBnG;AAsLD,UAAU,cAAc;IACtB,GAAG,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,EAAE,EAAE,UAAU,CAAA;KAAE,CAAC,CAAC;CACrD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,CAuBtG;AAUD,gBAAgB;AAChB,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,gBA0BxE"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { bufferCount, defer, from, groupBy, map, mergeMap, of, range, reduce } from "rxjs";
|
|
9
9
|
import { Id64, OrderedId64Iterable } from "@itwin/core-bentley";
|
|
10
|
+
import { QueryBinder } from "@itwin/core-common";
|
|
10
11
|
import { Descriptor, KeySet, PresentationError, PresentationStatus, } from "@itwin/presentation-common";
|
|
11
12
|
import { parseFullClassName } from "@itwin/presentation-shared";
|
|
12
13
|
function getECSqlName(fullClassName) {
|
|
@@ -16,18 +17,18 @@ function getECSqlName(fullClassName) {
|
|
|
16
17
|
/** @internal */
|
|
17
18
|
export function getContentItemsObservableFromElementIds(imodel, contentDescriptorGetter, contentSetGetter, elementIds, classParallelism, batchesParallelism, batchSize) {
|
|
18
19
|
return {
|
|
19
|
-
itemBatches: getElementClassesFromIds(imodel, elementIds).pipe(mergeMap(({ classFullName, ids }) => getBatchedClassContentItems(classFullName, contentDescriptorGetter, contentSetGetter, () => createIdBatches(OrderedId64Iterable.sortArray(ids), batchSize), batchesParallelism), classParallelism)),
|
|
20
|
+
itemBatches: getElementClassesFromIds(imodel, elementIds).pipe(mergeMap(({ classFullName, ids }) => getBatchedClassContentItems(imodel, classFullName, contentDescriptorGetter, contentSetGetter, () => createIdBatches(OrderedId64Iterable.sortArray(ids), batchSize), batchesParallelism), classParallelism)),
|
|
20
21
|
count: of(elementIds.length),
|
|
21
22
|
};
|
|
22
23
|
}
|
|
23
24
|
/** @internal */
|
|
24
25
|
export function getContentItemsObservableFromClassNames(imodel, contentDescriptorGetter, contentSetGetter, elementClasses, classParallelism, batchesParallelism, batchSize) {
|
|
25
26
|
return {
|
|
26
|
-
itemBatches: getClassesWithInstances(imodel, elementClasses).pipe(mergeMap((classFullName) => getBatchedClassContentItems(classFullName, contentDescriptorGetter, contentSetGetter, () => getBatchedClassElementIds(imodel, classFullName, batchSize), batchesParallelism), classParallelism)),
|
|
27
|
+
itemBatches: getClassesWithInstances(imodel, elementClasses).pipe(mergeMap((classFullName) => getBatchedClassContentItems(imodel, classFullName, contentDescriptorGetter, contentSetGetter, () => getBatchedClassElementIds(imodel, classFullName, batchSize), batchesParallelism), classParallelism)),
|
|
27
28
|
count: from(getElementsCount(imodel, elementClasses)),
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
|
-
function getBatchedClassContentItems(classFullName, contentDescriptorGetter, contentSetGetter, batcher, batchesParallelism) {
|
|
31
|
+
function getBatchedClassContentItems(imodel, classFullName, contentDescriptorGetter, contentSetGetter, batcher, batchesParallelism) {
|
|
31
32
|
return defer(async () => {
|
|
32
33
|
const ruleset = createClassContentRuleset(classFullName);
|
|
33
34
|
const keys = new KeySet();
|
|
@@ -35,41 +36,70 @@ function getBatchedClassContentItems(classFullName, contentDescriptorGetter, con
|
|
|
35
36
|
if (!descriptor) {
|
|
36
37
|
throw new PresentationError(PresentationStatus.Error, `Failed to get descriptor for class ${classFullName}`);
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
mergeMap(({ descriptor, keys, ruleset, batch }) => defer(async () => {
|
|
44
|
-
const filteringDescriptor = new Descriptor(descriptor);
|
|
45
|
-
filteringDescriptor.instanceFilter = {
|
|
39
|
+
const aspectFields = getPrunableAspectFields(descriptor, classFullName);
|
|
40
|
+
return { descriptor, keys, ruleset, aspectFields };
|
|
41
|
+
}).pipe(mergeMap((x) => batcher().pipe(map((batch) => ({ ...x, batch })))), mergeMap(({ descriptor, keys, ruleset, batch, aspectFields }) => defer(async () => {
|
|
42
|
+
const batchDescriptor = new Descriptor(descriptor);
|
|
43
|
+
batchDescriptor.instanceFilter = {
|
|
46
44
|
selectClassName: classFullName,
|
|
47
|
-
expression:
|
|
45
|
+
expression: batch.ranges
|
|
46
|
+
.map(({ from: fromId, to }) => fromId === to ? `this.ECInstanceId = ${fromId}` : `this.ECInstanceId >= ${fromId} AND this.ECInstanceId <= ${to}`)
|
|
47
|
+
.join(" OR "),
|
|
48
48
|
};
|
|
49
|
-
|
|
49
|
+
if (aspectFields.length) {
|
|
50
|
+
await selectBatchAspectFields(imodel, batchDescriptor, aspectFields, batch.ids);
|
|
51
|
+
}
|
|
52
|
+
const items = await contentSetGetter({
|
|
50
53
|
rulesetOrId: ruleset,
|
|
51
54
|
keys,
|
|
52
|
-
descriptor:
|
|
55
|
+
descriptor: batchDescriptor,
|
|
53
56
|
});
|
|
54
|
-
|
|
57
|
+
return { descriptor: batchDescriptor, items };
|
|
58
|
+
}), batchesParallelism));
|
|
55
59
|
}
|
|
56
|
-
function
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
filter += " OR ";
|
|
61
|
-
}
|
|
62
|
-
filter += cond;
|
|
60
|
+
function getPrunableAspectFields(descriptor, classFullName) {
|
|
61
|
+
// Caller selections take precedence; don't replace an include/exclude selector with our own.
|
|
62
|
+
if (descriptor.fieldsSelector || countFields(descriptor.fields) <= 1000) {
|
|
63
|
+
return [];
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
else {
|
|
69
|
-
appendCondition(`this.ECInstanceId >= ${item.from} AND this.ECInstanceId <= ${item.to}`);
|
|
65
|
+
const { schemaName, className } = parseFullClassName(classFullName);
|
|
66
|
+
return descriptor.fields.filter((field) => {
|
|
67
|
+
if (!field.isNestedContentField() || field.pathToPrimaryClass.length !== 1) {
|
|
68
|
+
return false;
|
|
70
69
|
}
|
|
70
|
+
const step = field.pathToPrimaryClass[0];
|
|
71
|
+
return (!step.isForwardRelationship &&
|
|
72
|
+
(step.relationshipInfo.name === "BisCore:ElementOwnsMultiAspects" || step.relationshipInfo.name === "BisCore:ElementOwnsUniqueAspect") &&
|
|
73
|
+
step.sourceClassInfo.id === field.contentClassInfo.id &&
|
|
74
|
+
step.targetClassInfo.name === `${schemaName}:${className}`);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function countFields(fields) {
|
|
78
|
+
return fields.reduce((count, field) => count + 1 + (field.isNestedContentField() ? countFields(field.nestedFields) : 0), 0);
|
|
79
|
+
}
|
|
80
|
+
async function selectBatchAspectFields(imodel, descriptor, aspectFields, batch) {
|
|
81
|
+
const query = `
|
|
82
|
+
WITH aspectClasses(ClassId) AS (
|
|
83
|
+
SELECT DISTINCT a.ECClassId
|
|
84
|
+
FROM bis.ElementMultiAspect a
|
|
85
|
+
JOIN IdSet(:elementIds) e ON e.id = a.Element.Id
|
|
86
|
+
UNION ALL
|
|
87
|
+
SELECT DISTINCT a.ECClassId
|
|
88
|
+
FROM bis.ElementUniqueAspect a
|
|
89
|
+
JOIN IdSet(:elementIds) e ON e.id = a.Element.Id
|
|
90
|
+
)
|
|
91
|
+
SELECT IdToHex(b.TargetECInstanceId) classId
|
|
92
|
+
FROM meta.ClassHasAllBaseClasses b
|
|
93
|
+
JOIN aspectClasses a ON a.ClassId = b.SourceECInstanceId
|
|
94
|
+
`;
|
|
95
|
+
const aspectClasses = new Set();
|
|
96
|
+
for await (const row of imodel.createQueryReader(query, QueryBinder.from({ elementIds: batch }))) {
|
|
97
|
+
aspectClasses.add(row.classId);
|
|
98
|
+
}
|
|
99
|
+
const excludedFields = aspectFields.filter((field) => !aspectClasses.has(field.contentClassInfo.id));
|
|
100
|
+
if (excludedFields.length > 0) {
|
|
101
|
+
descriptor.fieldsSelector = { type: "exclude", fields: excludedFields.map((field) => field.getFieldDescriptor()) };
|
|
71
102
|
}
|
|
72
|
-
return filter;
|
|
73
103
|
}
|
|
74
104
|
function createClassContentRuleset(fullClassName) {
|
|
75
105
|
const { schemaName, className } = parseFullClassName(fullClassName);
|
|
@@ -105,7 +135,10 @@ function getElementClassesFromIds(imodel, elementIds) {
|
|
|
105
135
|
WHERE e.ECInstanceId IN (${elementIds.slice(idsFrom, idsTo).join(",")})
|
|
106
136
|
GROUP BY e.ECClassId
|
|
107
137
|
`));
|
|
108
|
-
}), map((row) => ({
|
|
138
|
+
}), map((row) => ({
|
|
139
|
+
className: row.className,
|
|
140
|
+
ids: row.ids.split(","),
|
|
141
|
+
})), groupBy(({ className }) => className), mergeMap((groups) => groups.pipe(reduce((acc, g) => {
|
|
109
142
|
g.ids.forEach((id) => acc.ids.push(id));
|
|
110
143
|
return {
|
|
111
144
|
classFullName: g.className,
|
|
@@ -113,7 +146,7 @@ function getElementClassesFromIds(imodel, elementIds) {
|
|
|
113
146
|
};
|
|
114
147
|
}, { classFullName: "", ids: [] }))));
|
|
115
148
|
}
|
|
116
|
-
/** Given a list of full class names, get
|
|
149
|
+
/** Given a list of full class names, get concrete class names with instances. */
|
|
117
150
|
function getClassesWithInstances(imodel, fullClassNames) {
|
|
118
151
|
return from(fullClassNames).pipe(mergeMap((fullClassName) => from(imodel.createQueryReader(`
|
|
119
152
|
SELECT ec_classname(e.ECClassId, 's.c') className
|
|
@@ -123,12 +156,12 @@ function getClassesWithInstances(imodel, fullClassNames) {
|
|
|
123
156
|
}
|
|
124
157
|
/**
|
|
125
158
|
* Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily
|
|
126
|
-
* be sequential, a batch is defined a list of from-to pairs.
|
|
159
|
+
* be sequential, a batch is defined a list of from-to pairs. Ranges combine consecutive local IDs within the same briefcase.
|
|
127
160
|
* @internal
|
|
128
161
|
*/
|
|
129
162
|
export function createIdBatches(sortedIds, batchSize) {
|
|
130
163
|
return range(0, sortedIds.length / batchSize).pipe(map((batchIndex) => {
|
|
131
|
-
const
|
|
164
|
+
const ranges = new Array();
|
|
132
165
|
const startIndex = batchIndex * batchSize;
|
|
133
166
|
const endIndex = Math.min((batchIndex + 1) * batchSize, sortedIds.length) - 1;
|
|
134
167
|
let fromId = sortedIds[startIndex];
|
|
@@ -138,22 +171,18 @@ export function createIdBatches(sortedIds, batchSize) {
|
|
|
138
171
|
};
|
|
139
172
|
for (let i = startIndex + 1; i <= endIndex; ++i) {
|
|
140
173
|
const currLocalId = Id64.getLocalId(sortedIds[i]);
|
|
141
|
-
if (currLocalId !== to.localId + 1) {
|
|
142
|
-
|
|
174
|
+
if (Id64.getBriefcaseId(sortedIds[i]) !== Id64.getBriefcaseId(to.id) || currLocalId !== to.localId + 1) {
|
|
175
|
+
ranges.push({ from: fromId, to: sortedIds[i - 1] });
|
|
143
176
|
fromId = sortedIds[i];
|
|
144
177
|
}
|
|
145
178
|
to = { id: sortedIds[i], localId: currLocalId };
|
|
146
179
|
}
|
|
147
|
-
|
|
148
|
-
return
|
|
180
|
+
ranges.push({ from: fromId, to: sortedIds[endIndex] });
|
|
181
|
+
return { ids: sortedIds.slice(startIndex, endIndex + 1), ranges };
|
|
149
182
|
}));
|
|
150
183
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
* @internal
|
|
154
|
-
*/
|
|
155
|
-
export function getBatchedClassElementIds(imodel, fullClassName, batchSize) {
|
|
156
|
-
return from(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe(map((row) => row.id), bufferCount(batchSize), map((batch) => [{ from: batch[0], to: batch[batch.length - 1] }]));
|
|
184
|
+
function getBatchedClassElementIds(imodel, fullClassName, batchSize) {
|
|
185
|
+
return from(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ONLY ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe(map((row) => row.id), bufferCount(batchSize), map((ids) => ({ ids, ranges: [{ from: ids[0], to: ids[ids.length - 1] }] })));
|
|
157
186
|
}
|
|
158
187
|
/** @internal */
|
|
159
188
|
export async function getElementsCount(db, classNames) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ElementPropertiesHelper.js","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n * See LICENSE.md in the project root for license terms and full copyright notice.\r\n *--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Core\r\n */\r\n\r\nimport { bufferCount, defer, from, groupBy, map, mergeMap, Observable, ObservedValueOf, of, range, reduce } from \"rxjs\";\r\nimport { IModelDb } from \"@itwin/core-backend\";\r\nimport { Id64, Id64Array, Id64String, OrderedId64Iterable } from \"@itwin/core-bentley\";\r\nimport { QueryRowProxy } from \"@itwin/core-common\";\r\nimport {\r\n ContentDescriptorRequestOptions,\r\n ContentRequestOptions,\r\n Descriptor,\r\n Item,\r\n KeySet,\r\n PresentationError,\r\n PresentationStatus,\r\n Ruleset,\r\n RulesetVariable,\r\n} from \"@itwin/presentation-common\";\r\nimport { parseFullClassName } from \"@itwin/presentation-shared\";\r\n\r\nfunction getECSqlName(fullClassName: string) {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return `[${schemaName}].[${className}]`;\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromElementIds(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementIds: Id64String[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getElementClassesFromIds(imodel, elementIds).pipe(\r\n mergeMap(\r\n ({ classFullName, ids }) =>\r\n getBatchedClassContentItems(\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => createIdBatches(OrderedId64Iterable.sortArray(ids), batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: of(elementIds.length),\r\n };\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromClassNames(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementClasses: string[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getClassesWithInstances(imodel, elementClasses).pipe(\r\n mergeMap(\r\n (classFullName) =>\r\n getBatchedClassContentItems(\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => getBatchedClassElementIds(imodel, classFullName, batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: from(getElementsCount(imodel, elementClasses)),\r\n };\r\n}\r\n\r\nfunction getBatchedClassContentItems(\r\n classFullName: string,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n batcher: () => Observable<Array<{ from: Id64String; to: Id64String }>>,\r\n batchesParallelism: number,\r\n): Observable<{ descriptor: Descriptor; items: Item[] }> {\r\n return defer(async () => {\r\n const ruleset = createClassContentRuleset(classFullName);\r\n const keys = new KeySet();\r\n const descriptor = await contentDescriptorGetter({ rulesetOrId: ruleset, keys });\r\n if (!descriptor) {\r\n throw new PresentationError(PresentationStatus.Error, `Failed to get descriptor for class ${classFullName}`);\r\n }\r\n return { descriptor, keys, ruleset };\r\n }).pipe(\r\n // create elements' id batches\r\n mergeMap((x) => batcher().pipe(map((batch) => ({ ...x, batch })))),\r\n // request content for each batch, filter by IDs for performance\r\n mergeMap(\r\n ({ descriptor, keys, ruleset, batch }) =>\r\n defer(async () => {\r\n const filteringDescriptor = new Descriptor(descriptor);\r\n filteringDescriptor.instanceFilter = {\r\n selectClassName: classFullName,\r\n expression: createElementIdsECExpressionFilter(batch),\r\n };\r\n return contentSetGetter({\r\n rulesetOrId: ruleset,\r\n keys,\r\n descriptor: filteringDescriptor,\r\n });\r\n }).pipe(map((items) => ({ descriptor, items }))),\r\n batchesParallelism,\r\n ),\r\n );\r\n}\r\n\r\nfunction createElementIdsECExpressionFilter(batch: Array<{ from: Id64String; to: Id64String }>): string {\r\n let filter = \"\";\r\n function appendCondition(cond: string) {\r\n if (filter.length > 0) {\r\n filter += \" OR \";\r\n }\r\n filter += cond;\r\n }\r\n for (const item of batch) {\r\n if (item.from === item.to) {\r\n appendCondition(`this.ECInstanceId = ${item.from}`);\r\n } else {\r\n appendCondition(`this.ECInstanceId >= ${item.from} AND this.ECInstanceId <= ${item.to}`);\r\n }\r\n }\r\n return filter;\r\n}\r\n\r\nfunction createClassContentRuleset(fullClassName: string): Ruleset {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return {\r\n id: `content/class-descriptor/${fullClassName}`,\r\n rules: [\r\n {\r\n ruleType: \"Content\",\r\n specifications: [\r\n {\r\n specType: \"ContentInstancesOfSpecificClasses\",\r\n classes: {\r\n schemaName,\r\n classNames: [className],\r\n arePolymorphic: false,\r\n },\r\n handlePropertiesPolymorphically: true,\r\n },\r\n ],\r\n },\r\n ],\r\n };\r\n}\r\n\r\n/** Given a list of element ids, group them by class name. */\r\nfunction getElementClassesFromIds(imodel: IModelDb, elementIds: string[]): Observable<{ classFullName: string; ids: Id64Array }> {\r\n const elementIdsBatchSize = 5000;\r\n return range(0, elementIds.length / elementIdsBatchSize).pipe(\r\n mergeMap((batchIndex) => {\r\n const idsFrom = batchIndex * elementIdsBatchSize;\r\n const idsTo = Math.min(idsFrom + elementIdsBatchSize, elementIds.length);\r\n return from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId) className, GROUP_CONCAT(IdToHex(e.ECInstanceId)) ids\r\n FROM bis.Element e\r\n WHERE e.ECInstanceId IN (${elementIds.slice(idsFrom, idsTo).join(\",\")})\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n );\r\n }),\r\n map((row: QueryRowProxy): { className: string; ids: Id64Array } => ({ className: row.className, ids: row.ids.split(\",\") })),\r\n groupBy(({ className }) => className),\r\n mergeMap((groups) =>\r\n groups.pipe(\r\n reduce<ObservedValueOf<typeof groups>, { classFullName: string; ids: Id64Array }>(\r\n (acc, g) => {\r\n g.ids.forEach((id) => acc.ids.push(id));\r\n return {\r\n classFullName: g.className,\r\n ids: acc.ids,\r\n };\r\n },\r\n { classFullName: \"\", ids: [] },\r\n ),\r\n ),\r\n ),\r\n );\r\n}\r\n\r\n/** Given a list of full class names, get a stream of actual class names that have instances. */\r\nfunction getClassesWithInstances(imodel: IModelDb, fullClassNames: string[]): Observable<string> {\r\n return from(fullClassNames).pipe(\r\n mergeMap((fullClassName) =>\r\n from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId, 's.c') className\r\n FROM ${getECSqlName(fullClassName)} e\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n ),\r\n ),\r\n map((row: QueryRowProxy): string => row.className),\r\n );\r\n}\r\n\r\n/**\r\n * Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily\r\n * be sequential, a batch is defined a list of from-to pairs.\r\n * @internal\r\n */\r\nexport function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<Array<{ from: Id64String; to: Id64String }>> {\r\n return range(0, sortedIds.length / batchSize).pipe(\r\n map((batchIndex) => {\r\n const sequences = new Array<{ from: Id64String; to: Id64String }>();\r\n const startIndex = batchIndex * batchSize;\r\n const endIndex = Math.min((batchIndex + 1) * batchSize, sortedIds.length) - 1;\r\n let fromId = sortedIds[startIndex];\r\n let to = {\r\n id: sortedIds[startIndex],\r\n localId: Id64.getLocalId(sortedIds[startIndex]),\r\n };\r\n for (let i = startIndex + 1; i <= endIndex; ++i) {\r\n const currLocalId = Id64.getLocalId(sortedIds[i]);\r\n if (currLocalId !== to.localId + 1) {\r\n sequences.push({ from: fromId, to: sortedIds[i - 1] });\r\n fromId = sortedIds[i];\r\n }\r\n to = { id: sortedIds[i], localId: currLocalId };\r\n }\r\n sequences.push({ from: fromId, to: sortedIds[endIndex] });\r\n return sequences;\r\n }),\r\n );\r\n}\r\n\r\n/**\r\n * Query all ECInstanceIds from given class and stream from-to pairs that batch the items into batches of `batchSize` size.\r\n * @internal\r\n */\r\nexport function getBatchedClassElementIds(imodel: IModelDb, fullClassName: string, batchSize: number): Observable<Array<{ from: Id64String; to: Id64String }>> {\r\n return from(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe(\r\n map((row): Id64String => row.id),\r\n bufferCount(batchSize),\r\n map((batch) => [{ from: batch[0], to: batch[batch.length - 1] }]),\r\n );\r\n}\r\n\r\n/** @internal */\r\nexport async function getElementsCount(db: IModelDb, classNames: string[]) {\r\n const whereClause = (() => {\r\n if (classNames === undefined || classNames.length === 0) {\r\n return undefined;\r\n }\r\n // check if list contains only valid class names\r\n const classNameRegExp = new RegExp(/^[\\w]+[.:][\\w]+$/);\r\n const invalidName = classNames.find((name) => !name.match(classNameRegExp));\r\n if (invalidName) {\r\n throw new PresentationError(\r\n PresentationStatus.InvalidArgument,\r\n `Encountered invalid class name - ${invalidName}.\r\n Valid class name formats: \"<schema name or alias>.<class name>\", \"<schema name or alias>:<class name>\"`,\r\n );\r\n }\r\n return `e.ECClassId IS (${classNames.map(getECSqlName).join(\",\")})`;\r\n })();\r\n const query = `\r\n SELECT COUNT(e.ECInstanceId) AS elementCount\r\n FROM bis.Element e\r\n ${whereClause ? `WHERE ${whereClause}` : \"\"}\r\n `;\r\n for await (const row of db.createQueryReader(query)) {\r\n return row.elementCount;\r\n }\r\n return 0;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"ElementPropertiesHelper.js","sourceRoot":"","sources":["../../../src/presentation-backend/ElementPropertiesHelper.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n * See LICENSE.md in the project root for license terms and full copyright notice.\r\n *--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Core\r\n */\r\n\r\nimport { bufferCount, defer, from, groupBy, map, mergeMap, Observable, ObservedValueOf, of, range, reduce } from \"rxjs\";\r\nimport { IModelDb } from \"@itwin/core-backend\";\r\nimport { Id64, Id64Array, Id64String, OrderedId64Iterable } from \"@itwin/core-bentley\";\r\nimport { QueryBinder, QueryRowProxy } from \"@itwin/core-common\";\r\nimport {\r\n ContentDescriptorRequestOptions,\r\n ContentRequestOptions,\r\n Descriptor,\r\n Field,\r\n Item,\r\n KeySet,\r\n NestedContentField,\r\n PresentationError,\r\n PresentationStatus,\r\n Ruleset,\r\n RulesetVariable,\r\n} from \"@itwin/presentation-common\";\r\nimport { parseFullClassName } from \"@itwin/presentation-shared\";\r\n\r\nfunction getECSqlName(fullClassName: string) {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return `[${schemaName}].[${className}]`;\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromElementIds(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementIds: Id64String[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getElementClassesFromIds(imodel, elementIds).pipe(\r\n mergeMap(\r\n ({ classFullName, ids }) =>\r\n getBatchedClassContentItems(\r\n imodel,\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => createIdBatches(OrderedId64Iterable.sortArray(ids), batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: of(elementIds.length),\r\n };\r\n}\r\n\r\n/** @internal */\r\nexport function getContentItemsObservableFromClassNames(\r\n imodel: IModelDb,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n elementClasses: string[],\r\n classParallelism: number,\r\n batchesParallelism: number,\r\n batchSize: number,\r\n): { itemBatches: Observable<{ descriptor: Descriptor; items: Item[] }>; count: Observable<number> } {\r\n return {\r\n itemBatches: getClassesWithInstances(imodel, elementClasses).pipe(\r\n mergeMap(\r\n (classFullName) =>\r\n getBatchedClassContentItems(\r\n imodel,\r\n classFullName,\r\n contentDescriptorGetter,\r\n contentSetGetter,\r\n () => getBatchedClassElementIds(imodel, classFullName, batchSize),\r\n batchesParallelism,\r\n ),\r\n classParallelism,\r\n ),\r\n ),\r\n count: from(getElementsCount(imodel, elementClasses)),\r\n };\r\n}\r\n\r\nfunction getBatchedClassContentItems(\r\n imodel: IModelDb,\r\n classFullName: string,\r\n contentDescriptorGetter: (\r\n partialProps: Pick<ContentDescriptorRequestOptions<IModelDb, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\">,\r\n ) => Promise<Descriptor | undefined>,\r\n contentSetGetter: (\r\n partialProps: Pick<ContentRequestOptions<IModelDb, Descriptor, KeySet, RulesetVariable>, \"rulesetOrId\" | \"keys\" | \"descriptor\">,\r\n ) => Promise<Item[]>,\r\n batcher: () => Observable<ElementIdBatch>,\r\n batchesParallelism: number,\r\n): Observable<{ descriptor: Descriptor; items: Item[] }> {\r\n return defer(async () => {\r\n const ruleset = createClassContentRuleset(classFullName);\r\n const keys = new KeySet();\r\n const descriptor = await contentDescriptorGetter({ rulesetOrId: ruleset, keys });\r\n if (!descriptor) {\r\n throw new PresentationError(PresentationStatus.Error, `Failed to get descriptor for class ${classFullName}`);\r\n }\r\n const aspectFields = getPrunableAspectFields(descriptor, classFullName);\r\n return { descriptor, keys, ruleset, aspectFields };\r\n }).pipe(\r\n mergeMap((x) => batcher().pipe(map((batch) => ({ ...x, batch })))),\r\n mergeMap(\r\n ({ descriptor, keys, ruleset, batch, aspectFields }) =>\r\n defer(async () => {\r\n const batchDescriptor = new Descriptor(descriptor);\r\n batchDescriptor.instanceFilter = {\r\n selectClassName: classFullName,\r\n expression: batch.ranges\r\n .map(({ from: fromId, to }) =>\r\n fromId === to ? `this.ECInstanceId = ${fromId}` : `this.ECInstanceId >= ${fromId} AND this.ECInstanceId <= ${to}`,\r\n )\r\n .join(\" OR \"),\r\n };\r\n if (aspectFields.length) {\r\n await selectBatchAspectFields(imodel, batchDescriptor, aspectFields, batch.ids);\r\n }\r\n const items = await contentSetGetter({\r\n rulesetOrId: ruleset,\r\n keys,\r\n descriptor: batchDescriptor,\r\n });\r\n return { descriptor: batchDescriptor, items };\r\n }),\r\n batchesParallelism,\r\n ),\r\n );\r\n}\r\n\r\nfunction getPrunableAspectFields(descriptor: Descriptor, classFullName: string): NestedContentField[] {\r\n // Caller selections take precedence; don't replace an include/exclude selector with our own.\r\n if (descriptor.fieldsSelector || countFields(descriptor.fields) <= 1000) {\r\n return [];\r\n }\r\n const { schemaName, className } = parseFullClassName(classFullName);\r\n return descriptor.fields.filter((field): field is NestedContentField => {\r\n if (!field.isNestedContentField() || field.pathToPrimaryClass.length !== 1) {\r\n return false;\r\n }\r\n const step = field.pathToPrimaryClass[0];\r\n return (\r\n !step.isForwardRelationship &&\r\n (step.relationshipInfo.name === \"BisCore:ElementOwnsMultiAspects\" || step.relationshipInfo.name === \"BisCore:ElementOwnsUniqueAspect\") &&\r\n step.sourceClassInfo.id === field.contentClassInfo.id &&\r\n step.targetClassInfo.name === `${schemaName}:${className}`\r\n );\r\n });\r\n}\r\n\r\nfunction countFields(fields: Field[]): number {\r\n return fields.reduce((count, field) => count + 1 + (field.isNestedContentField() ? countFields(field.nestedFields) : 0), 0);\r\n}\r\n\r\nasync function selectBatchAspectFields(imodel: IModelDb, descriptor: Descriptor, aspectFields: NestedContentField[], batch: Id64Array): Promise<void> {\r\n const query = `\r\n WITH aspectClasses(ClassId) AS (\r\n SELECT DISTINCT a.ECClassId\r\n FROM bis.ElementMultiAspect a\r\n JOIN IdSet(:elementIds) e ON e.id = a.Element.Id\r\n UNION ALL\r\n SELECT DISTINCT a.ECClassId\r\n FROM bis.ElementUniqueAspect a\r\n JOIN IdSet(:elementIds) e ON e.id = a.Element.Id\r\n )\r\n SELECT IdToHex(b.TargetECInstanceId) classId\r\n FROM meta.ClassHasAllBaseClasses b\r\n JOIN aspectClasses a ON a.ClassId = b.SourceECInstanceId\r\n `;\r\n const aspectClasses = new Set<Id64String>();\r\n for await (const row of imodel.createQueryReader(query, QueryBinder.from({ elementIds: batch }))) {\r\n aspectClasses.add(row.classId);\r\n }\r\n const excludedFields = aspectFields.filter((field) => !aspectClasses.has(field.contentClassInfo.id));\r\n if (excludedFields.length > 0) {\r\n descriptor.fieldsSelector = { type: \"exclude\", fields: excludedFields.map((field) => field.getFieldDescriptor()) };\r\n }\r\n}\r\n\r\nfunction createClassContentRuleset(fullClassName: string): Ruleset {\r\n const { schemaName, className } = parseFullClassName(fullClassName);\r\n return {\r\n id: `content/class-descriptor/${fullClassName}`,\r\n rules: [\r\n {\r\n ruleType: \"Content\",\r\n specifications: [\r\n {\r\n specType: \"ContentInstancesOfSpecificClasses\",\r\n classes: {\r\n schemaName,\r\n classNames: [className],\r\n arePolymorphic: false,\r\n },\r\n handlePropertiesPolymorphically: true,\r\n },\r\n ],\r\n },\r\n ],\r\n };\r\n}\r\n\r\n/** Given a list of element ids, group them by class name. */\r\nfunction getElementClassesFromIds(imodel: IModelDb, elementIds: string[]): Observable<{ classFullName: string; ids: Id64Array }> {\r\n const elementIdsBatchSize = 5000;\r\n return range(0, elementIds.length / elementIdsBatchSize).pipe(\r\n mergeMap((batchIndex) => {\r\n const idsFrom = batchIndex * elementIdsBatchSize;\r\n const idsTo = Math.min(idsFrom + elementIdsBatchSize, elementIds.length);\r\n return from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId) className, GROUP_CONCAT(IdToHex(e.ECInstanceId)) ids\r\n FROM bis.Element e\r\n WHERE e.ECInstanceId IN (${elementIds.slice(idsFrom, idsTo).join(\",\")})\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n );\r\n }),\r\n map((row: QueryRowProxy): { className: string; ids: Id64Array } => ({\r\n className: row.className,\r\n ids: row.ids.split(\",\"),\r\n })),\r\n groupBy(({ className }) => className),\r\n mergeMap((groups) =>\r\n groups.pipe(\r\n reduce<ObservedValueOf<typeof groups>, { classFullName: string; ids: Id64Array }>(\r\n (acc, g) => {\r\n g.ids.forEach((id) => acc.ids.push(id));\r\n return {\r\n classFullName: g.className,\r\n ids: acc.ids,\r\n };\r\n },\r\n { classFullName: \"\", ids: [] },\r\n ),\r\n ),\r\n ),\r\n );\r\n}\r\n\r\n/** Given a list of full class names, get concrete class names with instances. */\r\nfunction getClassesWithInstances(imodel: IModelDb, fullClassNames: string[]): Observable<string> {\r\n return from(fullClassNames).pipe(\r\n mergeMap((fullClassName) =>\r\n from(\r\n imodel.createQueryReader(\r\n `\r\n SELECT ec_classname(e.ECClassId, 's.c') className\r\n FROM ${getECSqlName(fullClassName)} e\r\n GROUP BY e.ECClassId\r\n `,\r\n ),\r\n ),\r\n ),\r\n map((row: QueryRowProxy): string => row.className),\r\n );\r\n}\r\n\r\ninterface ElementIdBatch {\r\n ids: Id64Array;\r\n ranges: Array<{ from: Id64String; to: Id64String }>;\r\n}\r\n\r\n/**\r\n * Given a sorted list of ECInstanceIds and a batch size, create a stream of batches. Because the IDs won't necessarily\r\n * be sequential, a batch is defined a list of from-to pairs. Ranges combine consecutive local IDs within the same briefcase.\r\n * @internal\r\n */\r\nexport function createIdBatches(sortedIds: Id64String[], batchSize: number): Observable<ElementIdBatch> {\r\n return range(0, sortedIds.length / batchSize).pipe(\r\n map((batchIndex) => {\r\n const ranges = new Array<{ from: Id64String; to: Id64String }>();\r\n const startIndex = batchIndex * batchSize;\r\n const endIndex = Math.min((batchIndex + 1) * batchSize, sortedIds.length) - 1;\r\n let fromId = sortedIds[startIndex];\r\n let to = {\r\n id: sortedIds[startIndex],\r\n localId: Id64.getLocalId(sortedIds[startIndex]),\r\n };\r\n for (let i = startIndex + 1; i <= endIndex; ++i) {\r\n const currLocalId = Id64.getLocalId(sortedIds[i]);\r\n if (Id64.getBriefcaseId(sortedIds[i]) !== Id64.getBriefcaseId(to.id) || currLocalId !== to.localId + 1) {\r\n ranges.push({ from: fromId, to: sortedIds[i - 1] });\r\n fromId = sortedIds[i];\r\n }\r\n to = { id: sortedIds[i], localId: currLocalId };\r\n }\r\n ranges.push({ from: fromId, to: sortedIds[endIndex] });\r\n return { ids: sortedIds.slice(startIndex, endIndex + 1), ranges };\r\n }),\r\n );\r\n}\r\n\r\nfunction getBatchedClassElementIds(imodel: IModelDb, fullClassName: string, batchSize: number): Observable<ElementIdBatch> {\r\n return from(imodel.createQueryReader(`SELECT IdToHex(ECInstanceId) id FROM ONLY ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`)).pipe(\r\n map((row): Id64String => row.id),\r\n bufferCount(batchSize),\r\n map((ids) => ({ ids, ranges: [{ from: ids[0], to: ids[ids.length - 1] }] })),\r\n );\r\n}\r\n\r\n/** @internal */\r\nexport async function getElementsCount(db: IModelDb, classNames: string[]) {\r\n const whereClause = (() => {\r\n if (classNames === undefined || classNames.length === 0) {\r\n return undefined;\r\n }\r\n // check if list contains only valid class names\r\n const classNameRegExp = new RegExp(/^[\\w]+[.:][\\w]+$/);\r\n const invalidName = classNames.find((name) => !name.match(classNameRegExp));\r\n if (invalidName) {\r\n throw new PresentationError(\r\n PresentationStatus.InvalidArgument,\r\n `Encountered invalid class name - ${invalidName}.\r\n Valid class name formats: \"<schema name or alias>.<class name>\", \"<schema name or alias>:<class name>\"`,\r\n );\r\n }\r\n return `e.ECClassId IS (${classNames.map(getECSqlName).join(\",\")})`;\r\n })();\r\n const query = `\r\n SELECT COUNT(e.ECInstanceId) AS elementCount\r\n FROM bis.Element e\r\n ${whereClause ? `WHERE ${whereClause}` : \"\"}\r\n `;\r\n for await (const row of db.createQueryReader(query)) {\r\n return row.elementCount;\r\n }\r\n return 0;\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itwin/presentation-backend",
|
|
3
|
-
"version": "5.14.0-dev.
|
|
3
|
+
"version": "5.14.0-dev.18",
|
|
4
4
|
"description": "Backend of iTwin.js Presentation library",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"./package.json": "./package.json"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@itwin/core-
|
|
40
|
-
"@itwin/core-
|
|
41
|
-
"@itwin/
|
|
42
|
-
"@itwin/core-
|
|
43
|
-
"@itwin/
|
|
44
|
-
"@itwin/presentation-common": "5.14.0-dev.
|
|
39
|
+
"@itwin/core-backend": "5.14.0-dev.18",
|
|
40
|
+
"@itwin/core-bentley": "5.14.0-dev.18",
|
|
41
|
+
"@itwin/ecschema-metadata": "5.14.0-dev.18",
|
|
42
|
+
"@itwin/core-quantity": "5.14.0-dev.18",
|
|
43
|
+
"@itwin/core-common": "5.14.0-dev.18",
|
|
44
|
+
"@itwin/presentation-common": "5.14.0-dev.18"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@itwin/eslint-plugin": "^6.0.0",
|
|
@@ -75,14 +75,14 @@
|
|
|
75
75
|
"sinon": "^17.0.2",
|
|
76
76
|
"sinon-chai": "^3.7.0",
|
|
77
77
|
"typescript": "~5.6.2",
|
|
78
|
-
"@itwin/build-tools": "5.14.0-dev.
|
|
79
|
-
"@itwin/
|
|
80
|
-
"@itwin/core-common": "5.14.0-dev.
|
|
81
|
-
"@itwin/core-bentley": "5.14.0-dev.16",
|
|
82
|
-
"@itwin/ecschema-metadata": "5.14.0-dev.16",
|
|
83
|
-
"@itwin/presentation-common": "5.14.0-dev.16",
|
|
78
|
+
"@itwin/build-tools": "5.14.0-dev.18",
|
|
79
|
+
"@itwin/ecschema-metadata": "5.14.0-dev.18",
|
|
80
|
+
"@itwin/core-common": "5.14.0-dev.18",
|
|
84
81
|
"internal-tools": "3.0.0-dev.69",
|
|
85
|
-
"@itwin/core-
|
|
82
|
+
"@itwin/core-bentley": "5.14.0-dev.18",
|
|
83
|
+
"@itwin/core-quantity": "5.14.0-dev.18",
|
|
84
|
+
"@itwin/presentation-common": "5.14.0-dev.18",
|
|
85
|
+
"@itwin/core-backend": "5.14.0-dev.18"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
88
|
"@itwin/presentation-shared": "^1.2.2",
|