@itwin/unified-selection 1.5.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +1 -0
- package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -1
- package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +9 -1
- package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -1
- package/lib/cjs/unified-selection/HiliteSetProvider.d.ts.map +1 -1
- package/lib/cjs/unified-selection/HiliteSetProvider.js +22 -5
- package/lib/cjs/unified-selection/HiliteSetProvider.js.map +1 -1
- package/lib/cjs/unified-selection/SelectionScope.d.ts +2 -0
- package/lib/cjs/unified-selection/SelectionScope.d.ts.map +1 -1
- package/lib/cjs/unified-selection/SelectionScope.js +39 -18
- package/lib/cjs/unified-selection/SelectionScope.js.map +1 -1
- package/lib/cjs/unified-selection/Utils.d.ts +7 -2
- package/lib/cjs/unified-selection/Utils.d.ts.map +1 -1
- package/lib/cjs/unified-selection/Utils.js +2 -2
- package/lib/cjs/unified-selection/Utils.js.map +1 -1
- package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +1 -0
- package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -1
- package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +9 -1
- package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -1
- package/lib/esm/unified-selection/HiliteSetProvider.d.ts.map +1 -1
- package/lib/esm/unified-selection/HiliteSetProvider.js +23 -6
- package/lib/esm/unified-selection/HiliteSetProvider.js.map +1 -1
- package/lib/esm/unified-selection/SelectionScope.d.ts +2 -0
- package/lib/esm/unified-selection/SelectionScope.d.ts.map +1 -1
- package/lib/esm/unified-selection/SelectionScope.js +40 -19
- package/lib/esm/unified-selection/SelectionScope.js.map +1 -1
- package/lib/esm/unified-selection/Utils.d.ts +7 -2
- package/lib/esm/unified-selection/Utils.d.ts.map +1 -1
- package/lib/esm/unified-selection/Utils.js +3 -3
- package/lib/esm/unified-selection/Utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { Id64 } from "@itwin/core-bentley";
|
|
5
|
+
import { Guid, Id64 } from "@itwin/core-bentley";
|
|
6
6
|
import { formIdBindings, genericExecuteQuery } from "./Utils.js";
|
|
7
7
|
/**
|
|
8
8
|
* Computes selection from given element IDs.
|
|
@@ -10,8 +10,10 @@ import { formIdBindings, genericExecuteQuery } from "./Utils.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export async function* computeSelection(props) {
|
|
12
12
|
const { queryExecutor, elementIds, scope } = props;
|
|
13
|
+
const componentId = props.componentId ?? Guid.createValue();
|
|
14
|
+
const componentName = "computeSelection";
|
|
13
15
|
if (typeof scope === "string") {
|
|
14
|
-
yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope } });
|
|
16
|
+
yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope }, componentId });
|
|
15
17
|
return;
|
|
16
18
|
}
|
|
17
19
|
const nonTransientIds = [];
|
|
@@ -22,20 +24,20 @@ export async function* computeSelection(props) {
|
|
|
22
24
|
}
|
|
23
25
|
switch (scope.id) {
|
|
24
26
|
case "element":
|
|
25
|
-
yield* computeElementSelection(queryExecutor, nonTransientIds, scope.ancestorLevel ?? 0);
|
|
27
|
+
yield* computeElementSelection(queryExecutor, nonTransientIds, scope.ancestorLevel ?? 0, componentId, componentName);
|
|
26
28
|
return;
|
|
27
29
|
case "category":
|
|
28
|
-
yield* computeCategorySelection(queryExecutor, nonTransientIds);
|
|
30
|
+
yield* computeCategorySelection(queryExecutor, nonTransientIds, componentId, componentName);
|
|
29
31
|
return;
|
|
30
32
|
case "model":
|
|
31
|
-
yield* computeModelSelection(queryExecutor, nonTransientIds);
|
|
33
|
+
yield* computeModelSelection(queryExecutor, nonTransientIds, componentId, componentName);
|
|
32
34
|
return;
|
|
33
35
|
case "functional":
|
|
34
|
-
yield* computeFunctionalElementSelection(queryExecutor, nonTransientIds, scope.ancestorLevel ?? 0);
|
|
36
|
+
yield* computeFunctionalElementSelection(queryExecutor, nonTransientIds, scope.ancestorLevel ?? 0, componentId, componentName);
|
|
35
37
|
return;
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
|
-
async function* computeElementSelection(queryExecutor, elementIds, ancestorLevel) {
|
|
40
|
+
async function* computeElementSelection(queryExecutor, elementIds, ancestorLevel, componentId, componentName) {
|
|
39
41
|
const bindings = [];
|
|
40
42
|
const recurseUntilRoot = ancestorLevel < 0;
|
|
41
43
|
const ctes = [
|
|
@@ -57,9 +59,13 @@ async function* computeElementSelection(queryExecutor, elementIds, ancestorLevel
|
|
|
57
59
|
FROM AncestorElements
|
|
58
60
|
WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL
|
|
59
61
|
`;
|
|
60
|
-
yield* executeQuery(
|
|
62
|
+
yield* executeQuery({
|
|
63
|
+
queryExecutor,
|
|
64
|
+
query: { ctes, ecsql, bindings },
|
|
65
|
+
config: { restartToken: `${componentName}/${componentId}/element` },
|
|
66
|
+
});
|
|
61
67
|
}
|
|
62
|
-
async function* computeCategorySelection(queryExecutor, ids) {
|
|
68
|
+
async function* computeCategorySelection(queryExecutor, ids, componentId, componentName) {
|
|
63
69
|
const bindings = [];
|
|
64
70
|
const ecsql = [
|
|
65
71
|
`
|
|
@@ -75,9 +81,13 @@ async function* computeCategorySelection(queryExecutor, ids) {
|
|
|
75
81
|
WHERE ${formIdBindings("ge.ECInstanceId", ids, bindings)}
|
|
76
82
|
`,
|
|
77
83
|
].join(" UNION ALL ");
|
|
78
|
-
yield* executeQuery(
|
|
84
|
+
yield* executeQuery({
|
|
85
|
+
queryExecutor,
|
|
86
|
+
query: { ecsql, bindings },
|
|
87
|
+
config: { restartToken: `${componentName}/${componentId}/category` },
|
|
88
|
+
});
|
|
79
89
|
}
|
|
80
|
-
async function* computeModelSelection(queryExecutor, ids) {
|
|
90
|
+
async function* computeModelSelection(queryExecutor, ids, componentId, componentName) {
|
|
81
91
|
const bindings = [];
|
|
82
92
|
const ecsql = `
|
|
83
93
|
SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName
|
|
@@ -85,9 +95,13 @@ async function* computeModelSelection(queryExecutor, ids) {
|
|
|
85
95
|
JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId
|
|
86
96
|
WHERE ${formIdBindings("e.ECInstanceId", ids, bindings)}
|
|
87
97
|
`;
|
|
88
|
-
yield* executeQuery(
|
|
98
|
+
yield* executeQuery({
|
|
99
|
+
queryExecutor,
|
|
100
|
+
query: { ecsql, bindings },
|
|
101
|
+
config: { restartToken: `${componentName}/${componentId}/model` },
|
|
102
|
+
});
|
|
89
103
|
}
|
|
90
|
-
async function* computeFunctionalElementSelection(queryExecutor, ids, ancestorLevel) {
|
|
104
|
+
async function* computeFunctionalElementSelection(queryExecutor, ids, ancestorLevel, componentId, componentName) {
|
|
91
105
|
const bindings = [];
|
|
92
106
|
const recurseUntilRoot = ancestorLevel < 0;
|
|
93
107
|
// cspell:disable
|
|
@@ -178,16 +192,23 @@ async function* computeFunctionalElementSelection(queryExecutor, ids, ancestorLe
|
|
|
178
192
|
`,
|
|
179
193
|
].join(" UNION ");
|
|
180
194
|
// cspell:enable
|
|
181
|
-
yield* executeQuery(
|
|
195
|
+
yield* executeQuery({
|
|
196
|
+
queryExecutor,
|
|
197
|
+
query: { ctes, ecsql, bindings },
|
|
198
|
+
config: { restartToken: `${componentName}/${componentId}/functional-element` },
|
|
199
|
+
});
|
|
182
200
|
}
|
|
183
201
|
function formAncestorLevelBinding(ancestorLevel, bindings) {
|
|
184
202
|
bindings.push({ type: "int", value: ancestorLevel });
|
|
185
203
|
return "?";
|
|
186
204
|
}
|
|
187
|
-
async function* executeQuery(
|
|
188
|
-
yield* genericExecuteQuery(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
205
|
+
async function* executeQuery(props) {
|
|
206
|
+
yield* genericExecuteQuery({
|
|
207
|
+
...props,
|
|
208
|
+
parseQueryRow: (row) => ({
|
|
209
|
+
className: row.ClassName,
|
|
210
|
+
id: row.ECInstanceId,
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
192
213
|
}
|
|
193
214
|
//# sourceMappingURL=SelectionScope.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionScope.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionScope.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Id64, Id64Arg, Id64Array } from \"@itwin/core-bentley\";\nimport { ECSqlBinding, ECSqlQueryDef, ECSqlQueryExecutor, ECSqlQueryRow } from \"@itwin/presentation-shared\";\nimport { SelectableInstanceKey } from \"./Selectable.js\";\nimport { formIdBindings, genericExecuteQuery } from \"./Utils.js\";\n\n/**\n * Available selection scopes.\n * @public\n */\ntype SelectionScopeIdentifier = \"element\" | \"model\" | \"category\" | \"functional\";\n\n/**\n * Props for computing element selection.\n * @public\n */\nexport interface ElementSelectionScopeProps {\n /** Identifies this as either \"element\" or \"functional\" selection scope */\n id: \"element\" | \"functional\";\n /**\n * Specifies how far \"up\" we should walk to find the target element. When not specified or `0`,\n * the target element matches the request element. When set to `1`, the target element matches the direct parent element.\n * When set to `2`, the target element is parent of the parent element and so on. In all situations when this is `> 0`,\n * we're not walking further than the last existing element, for example when `ancestorLevel = 1` (direct parent\n * element is requested), but the request element doesn't have a parent, the request element is returned as the result.\n * A negative value would result in the top-most element to be returned.\n */\n ancestorLevel?: number;\n}\n\n/**\n * A union of types that can be used to define a selection scope.\n * @public\n * @since 1.4.0\n */\nexport type SelectionScope = ElementSelectionScopeProps | { id: SelectionScopeIdentifier } | SelectionScopeIdentifier;\n\n/**\n * Props for `computeSelection`.\n * @public\n */\nexport interface ComputeSelectionProps {\n /** iModel query executor. */\n queryExecutor: ECSqlQueryExecutor;\n /** IDs of elements to compute selection for. */\n elementIds: Id64Arg;\n /** Selection scope to compute selection with. */\n scope: SelectionScope;\n}\n\n/**\n * Computes selection from given element IDs.\n * @public\n */\nexport async function* computeSelection(props: ComputeSelectionProps): AsyncIterableIterator<SelectableInstanceKey> {\n const { queryExecutor, elementIds, scope } = props;\n\n if (typeof scope === \"string\") {\n yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope } });\n return;\n }\n\n const nonTransientIds: Id64Array = [];\n for (const id of Id64.iterable(elementIds)) {\n if (!Id64.isTransient(id)) {\n nonTransientIds.push(id);\n }\n }\n\n switch (scope.id) {\n case \"element\":\n yield* computeElementSelection(queryExecutor, nonTransientIds, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n case \"category\":\n yield* computeCategorySelection(queryExecutor, nonTransientIds);\n return;\n case \"model\":\n yield* computeModelSelection(queryExecutor, nonTransientIds);\n return;\n case \"functional\":\n yield* computeFunctionalElementSelection(queryExecutor, nonTransientIds, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0);\n return;\n }\n}\n\nasync function* computeElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n elementIds: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const ctes = [\n `\n AncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", elementIds, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id\n FROM AncestorElements a\n JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n ];\n const ecsql = `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM AncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `;\n yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });\n}\n\nasync function* computeCategorySelection(queryExecutor: ECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = [\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n ].join(\" UNION ALL \");\n yield* executeQuery(queryExecutor, { ecsql, bindings });\n}\n\nasync function* computeModelSelection(queryExecutor: ECSqlQueryExecutor, ids: string[]): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = `\n SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName\n FROM BisCore.Model m\n JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId\n WHERE ${formIdBindings(\"e.ECInstanceId\", ids, bindings)}\n `;\n yield* executeQuery(queryExecutor, { ecsql, bindings });\n}\n\nasync function* computeFunctionalElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n ids: string[],\n ancestorLevel: number,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n // cspell:disable\n const ctes = [\n `\n Elements2dOrNearestFunctionalElements(OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d)\n UNION ALL\n SELECT\n e2onfe.OriginalECInstanceId,\n e2onfe.OriginalECClassId,\n COALESCE(dgrfe.TargetECInstanceId, pe.ECInstanceId),\n COALESCE(dgrfe.TargetECClassId, pe.ECClassId),\n pe.Parent.Id\n FROM Elements2dOrNearestFunctionalElements e2onfe\n LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId\n LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId\n WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL)\n )\n `,\n `\n Element2dNearestFunctionalElements(OriginalECInstanceId, ECInstanceId, ECClassId) AS (\n SELECT OriginalECInstanceId, ECInstanceId, ECClassId\n FROM Elements2dOrNearestFunctionalElements\n WHERE ECClassId IS (Functional.FunctionalElement)\n )\n `,\n `\n Elements2dWithoutFunctionalElement(ECInstanceId, ECClassId) AS (\n SELECT e2wfe.OriginalECInstanceId, OriginalECClassId\n FROM Elements2dOrNearestFunctionalElements e2wfe\n LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId\n WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL\n )\n `,\n `\n Elements2d(ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements\n UNION\n SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement\n )\n `,\n `\n Element2dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id\n FROM BisCore.Element e\n JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id\n FROM Element2dAncestorElements e2ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id\n FROM BisCore.GeometricElement3d ge\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id\n FROM Element3dAncestorElements e3ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorRelatedFunctionalElement(ECInstanceId, ClassName) AS (\n SELECT\n COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId),\n ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c')\n FROM Element3dAncestorElements e3ae\n LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId\n WHERE ${recurseUntilRoot ? \"\" : \"e3ae.Depth = 0 OR\"} e3ae.ParentId IS NULL\n )\n `,\n ];\n const ecsql = [\n `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM Element2dAncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `,\n `\n SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement\n `,\n ].join(\" UNION \");\n // cspell:enable\n yield* executeQuery(queryExecutor, { ctes, ecsql, bindings });\n}\n\nfunction formAncestorLevelBinding(ancestorLevel: number, bindings: ECSqlBinding[]) {\n bindings.push({ type: \"int\", value: ancestorLevel });\n return \"?\";\n}\n\nasync function* executeQuery(queryExecutor: ECSqlQueryExecutor, query: ECSqlQueryDef): AsyncIterableIterator<SelectableInstanceKey> {\n yield* genericExecuteQuery(queryExecutor, query, (row: ECSqlQueryRow) => ({\n className: row.ClassName,\n id: row.ECInstanceId,\n }));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SelectionScope.js","sourceRoot":"","sources":["../../../src/unified-selection/SelectionScope.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Guid, Id64, Id64Arg, Id64Array } from \"@itwin/core-bentley\";\nimport { ECSqlBinding, ECSqlQueryDef, ECSqlQueryExecutor, ECSqlQueryReaderOptions, ECSqlQueryRow } from \"@itwin/presentation-shared\";\nimport { SelectableInstanceKey } from \"./Selectable.js\";\nimport { formIdBindings, genericExecuteQuery } from \"./Utils.js\";\n\n/**\n * Available selection scopes.\n * @public\n */\ntype SelectionScopeIdentifier = \"element\" | \"model\" | \"category\" | \"functional\";\n\n/**\n * Props for computing element selection.\n * @public\n */\nexport interface ElementSelectionScopeProps {\n /** Identifies this as either \"element\" or \"functional\" selection scope */\n id: \"element\" | \"functional\";\n /**\n * Specifies how far \"up\" we should walk to find the target element. When not specified or `0`,\n * the target element matches the request element. When set to `1`, the target element matches the direct parent element.\n * When set to `2`, the target element is parent of the parent element and so on. In all situations when this is `> 0`,\n * we're not walking further than the last existing element, for example when `ancestorLevel = 1` (direct parent\n * element is requested), but the request element doesn't have a parent, the request element is returned as the result.\n * A negative value would result in the top-most element to be returned.\n */\n ancestorLevel?: number;\n}\n\n/**\n * A union of types that can be used to define a selection scope.\n * @public\n * @since 1.4.0\n */\nexport type SelectionScope = ElementSelectionScopeProps | { id: SelectionScopeIdentifier } | SelectionScopeIdentifier;\n\n/**\n * Props for `computeSelection`.\n * @public\n */\nexport interface ComputeSelectionProps {\n /** iModel query executor. */\n queryExecutor: ECSqlQueryExecutor;\n /** IDs of elements to compute selection for. */\n elementIds: Id64Arg;\n /** Selection scope to compute selection with. */\n scope: SelectionScope;\n /** Optional unique id of the component that consumes this function. It can be any string, as long as it is not shared across different components. */\n componentId?: string;\n}\n\n/**\n * Computes selection from given element IDs.\n * @public\n */\nexport async function* computeSelection(props: ComputeSelectionProps): AsyncIterableIterator<SelectableInstanceKey> {\n const { queryExecutor, elementIds, scope } = props;\n const componentId = props.componentId ?? Guid.createValue();\n const componentName = \"computeSelection\";\n if (typeof scope === \"string\") {\n yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope }, componentId });\n return;\n }\n\n const nonTransientIds: Id64Array = [];\n for (const id of Id64.iterable(elementIds)) {\n if (!Id64.isTransient(id)) {\n nonTransientIds.push(id);\n }\n }\n\n switch (scope.id) {\n case \"element\":\n yield* computeElementSelection(queryExecutor, nonTransientIds, (scope as ElementSelectionScopeProps).ancestorLevel ?? 0, componentId, componentName);\n return;\n case \"category\":\n yield* computeCategorySelection(queryExecutor, nonTransientIds, componentId, componentName);\n return;\n case \"model\":\n yield* computeModelSelection(queryExecutor, nonTransientIds, componentId, componentName);\n return;\n case \"functional\":\n yield* computeFunctionalElementSelection(\n queryExecutor,\n nonTransientIds,\n (scope as ElementSelectionScopeProps).ancestorLevel ?? 0,\n componentId,\n componentName,\n );\n return;\n }\n}\n\nasync function* computeElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n elementIds: string[],\n ancestorLevel: number,\n componentId: string,\n componentName: string,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n const ctes = [\n `\n AncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", elementIds, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id\n FROM AncestorElements a\n JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n ];\n const ecsql = `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM AncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `;\n yield* executeQuery({\n queryExecutor,\n query: { ctes, ecsql, bindings },\n config: { restartToken: `${componentName}/${componentId}/element` },\n });\n}\n\nasync function* computeCategorySelection(\n queryExecutor: ECSqlQueryExecutor,\n ids: string[],\n componentId: string,\n componentName: string,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = [\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n `\n SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName\n FROM BisCore.Category c\n JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n `,\n ].join(\" UNION ALL \");\n yield* executeQuery({\n queryExecutor,\n query: { ecsql, bindings },\n config: { restartToken: `${componentName}/${componentId}/category` },\n });\n}\n\nasync function* computeModelSelection(\n queryExecutor: ECSqlQueryExecutor,\n ids: string[],\n componentId: string,\n componentName: string,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const ecsql = `\n SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName\n FROM BisCore.Model m\n JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId\n WHERE ${formIdBindings(\"e.ECInstanceId\", ids, bindings)}\n `;\n yield* executeQuery({\n queryExecutor,\n query: { ecsql, bindings },\n config: { restartToken: `${componentName}/${componentId}/model` },\n });\n}\n\nasync function* computeFunctionalElementSelection(\n queryExecutor: ECSqlQueryExecutor,\n ids: string[],\n ancestorLevel: number,\n componentId: string,\n componentName: string,\n): AsyncIterableIterator<SelectableInstanceKey> {\n const bindings: ECSqlBinding[] = [];\n const recurseUntilRoot = ancestorLevel < 0;\n // cspell:disable\n const ctes = [\n `\n Elements2dOrNearestFunctionalElements(OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS (\n SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id\n FROM BisCore.Element\n WHERE ${formIdBindings(\"ECInstanceId\", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d)\n UNION ALL\n SELECT\n e2onfe.OriginalECInstanceId,\n e2onfe.OriginalECClassId,\n COALESCE(dgrfe.TargetECInstanceId, pe.ECInstanceId),\n COALESCE(dgrfe.TargetECClassId, pe.ECClassId),\n pe.Parent.Id\n FROM Elements2dOrNearestFunctionalElements e2onfe\n LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId\n LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId\n WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL)\n )\n `,\n `\n Element2dNearestFunctionalElements(OriginalECInstanceId, ECInstanceId, ECClassId) AS (\n SELECT OriginalECInstanceId, ECInstanceId, ECClassId\n FROM Elements2dOrNearestFunctionalElements\n WHERE ECClassId IS (Functional.FunctionalElement)\n )\n `,\n `\n Elements2dWithoutFunctionalElement(ECInstanceId, ECClassId) AS (\n SELECT e2wfe.OriginalECInstanceId, OriginalECClassId\n FROM Elements2dOrNearestFunctionalElements e2wfe\n LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId\n WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL\n )\n `,\n `\n Elements2d(ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements\n UNION\n SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement\n )\n `,\n `\n Element2dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id\n FROM BisCore.Element e\n JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id\n FROM Element2dAncestorElements e2ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS (\n SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id\n FROM BisCore.GeometricElement3d ge\n WHERE ${formIdBindings(\"ge.ECInstanceId\", ids, bindings)}\n UNION ALL\n SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id\n FROM Element3dAncestorElements e3ae\n JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId\n WHERE ${recurseUntilRoot ? \"\" : \"Depth > 0 AND\"} ParentId IS NOT NULL\n )\n `,\n `\n Element3dAncestorRelatedFunctionalElement(ECInstanceId, ClassName) AS (\n SELECT\n COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId),\n ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c')\n FROM Element3dAncestorElements e3ae\n LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId\n WHERE ${recurseUntilRoot ? \"\" : \"e3ae.Depth = 0 OR\"} e3ae.ParentId IS NULL\n )\n `,\n ];\n const ecsql = [\n `\n SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName\n FROM Element2dAncestorElements\n WHERE ${recurseUntilRoot ? \"\" : \"Depth = 0 OR\"} ParentId IS NULL\n `,\n `\n SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement\n `,\n ].join(\" UNION \");\n // cspell:enable\n yield* executeQuery({\n queryExecutor,\n query: { ctes, ecsql, bindings },\n config: { restartToken: `${componentName}/${componentId}/functional-element` },\n });\n}\n\nfunction formAncestorLevelBinding(ancestorLevel: number, bindings: ECSqlBinding[]) {\n bindings.push({ type: \"int\", value: ancestorLevel });\n return \"?\";\n}\n\nasync function* executeQuery(props: {\n queryExecutor: ECSqlQueryExecutor;\n query: ECSqlQueryDef;\n config?: ECSqlQueryReaderOptions;\n}): AsyncIterableIterator<SelectableInstanceKey> {\n yield* genericExecuteQuery({\n ...props,\n parseQueryRow: (row: ECSqlQueryRow) => ({\n className: row.ClassName,\n id: row.ECInstanceId,\n }),\n });\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./DisposePolyfill.js";
|
|
2
2
|
import { Observable } from "rxjs";
|
|
3
|
-
import { ECSqlBinding, ECSqlQueryDef, ECSqlQueryExecutor, ECSqlQueryRow } from "@itwin/presentation-shared";
|
|
3
|
+
import { ECSqlBinding, ECSqlQueryDef, ECSqlQueryExecutor, ECSqlQueryReaderOptions, ECSqlQueryRow } from "@itwin/presentation-shared";
|
|
4
4
|
/**
|
|
5
5
|
* Forms ECSql bindings from given ID's.
|
|
6
6
|
* @internal
|
|
@@ -10,7 +10,12 @@ export declare function formIdBindings(property: string, ids: string[], bindings
|
|
|
10
10
|
* Executes given ECSql query and extracts data from rows. Additionally handles main thread releasing.
|
|
11
11
|
* @internal
|
|
12
12
|
*/
|
|
13
|
-
export declare function genericExecuteQuery<T>(queryExecutor
|
|
13
|
+
export declare function genericExecuteQuery<T>({ queryExecutor, parseQueryRow, query, config, }: {
|
|
14
|
+
queryExecutor: ECSqlQueryExecutor;
|
|
15
|
+
query: ECSqlQueryDef;
|
|
16
|
+
parseQueryRow: (row: ECSqlQueryRow) => T;
|
|
17
|
+
config?: ECSqlQueryReaderOptions;
|
|
18
|
+
}): AsyncIterableIterator<T>;
|
|
14
19
|
/**
|
|
15
20
|
* Emits a certain amount of values, then releases the main thread for other timers to use.
|
|
16
21
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAKA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAA4C,UAAU,EAAM,MAAM,MAAM,CAAC;AAChF,OAAO,
|
|
1
|
+
{"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAKA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAA4C,UAAU,EAAM,MAAM,MAAM,CAAC;AAChF,OAAO,EAEL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EACvB,aAAa,EACd,MAAM,4BAA4B,CAAC;AAEpC;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAYhG;AAED;;;GAGG;AACH,wBAAuB,mBAAmB,CAAC,CAAC,EAAE,EAC5C,aAAa,EACb,aAAa,EACb,KAAK,EACL,MAAM,GACP,EAAE;IACD,aAAa,EAAE,kBAAkB,CAAC;IAClC,KAAK,EAAE,aAAa,CAAC;IACrB,aAAa,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAO3B;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,SACtD,UAAU,CAAC,CAAC,CAAC,KAAG,UAAU,CAAC,CAAC,CAAC,CAa3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,EAAE,GAAG;IAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,QAMtG"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import "./DisposePolyfill.js";
|
|
6
6
|
import { bufferCount, concatAll, concatMap, delay, of } from "rxjs";
|
|
7
|
-
import { createMainThreadReleaseOnTimePassedHandler } from "@itwin/presentation-shared";
|
|
7
|
+
import { createMainThreadReleaseOnTimePassedHandler, } from "@itwin/presentation-shared";
|
|
8
8
|
/**
|
|
9
9
|
* Forms ECSql bindings from given ID's.
|
|
10
10
|
* @internal
|
|
@@ -24,9 +24,9 @@ export function formIdBindings(property, ids, bindings) {
|
|
|
24
24
|
* Executes given ECSql query and extracts data from rows. Additionally handles main thread releasing.
|
|
25
25
|
* @internal
|
|
26
26
|
*/
|
|
27
|
-
export async function* genericExecuteQuery(queryExecutor, query,
|
|
27
|
+
export async function* genericExecuteQuery({ queryExecutor, parseQueryRow, query, config, }) {
|
|
28
28
|
const releaseMainThread = createMainThreadReleaseOnTimePassedHandler();
|
|
29
|
-
const reader = queryExecutor.createQueryReader(query);
|
|
29
|
+
const reader = queryExecutor.createQueryReader(query, config);
|
|
30
30
|
for await (const row of reader) {
|
|
31
31
|
yield parseQueryRow(row);
|
|
32
32
|
await releaseMainThread();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAc,EAAE,EAAE,MAAM,MAAM,CAAC;AAChF,OAAO,
|
|
1
|
+
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../src/unified-selection/Utils.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAc,EAAE,EAAE,MAAM,MAAM,CAAC;AAChF,OAAO,EACL,0CAA0C,GAM3C,MAAM,4BAA4B,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,GAAa,EAAE,QAAwB;IACtF,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,OAAO,mBAAmB,QAAQ,GAAG,CAAC;IACxC,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9D,OAAO,GAAG,QAAQ,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,mBAAmB,CAAI,EAC5C,aAAa,EACb,aAAa,EACb,KAAK,EACL,MAAM,GAMP;IACC,MAAM,iBAAiB,GAAG,0CAA0C,EAAE,CAAC;IACvE,MAAM,MAAM,GAAG,aAAa,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QAC/B,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;QACzB,MAAM,iBAAiB,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAI,YAAoB;IACnE,OAAO,CAAC,GAAkB,EAAiB,EAAE;QAC3C,OAAO,GAAG,CAAC,IAAI,CACb,WAAW,CAAC,YAAY,CAAC,EACzB,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;YACpB,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;gBAC1C,OAAO,GAAG,CAAC;YACb,CAAC;YACD,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC,EACF,SAAS,EAAE,CACZ,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,UAA2E;IACrG,IAAI,SAAS,IAAI,UAAU,EAAE,CAAC;QAC5B,UAAU,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC;SAAM,IAAI,MAAM,CAAC,OAAO,IAAI,UAAU,EAAE,CAAC;QACxC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport \"./DisposePolyfill.js\";\nimport { bufferCount, concatAll, concatMap, delay, Observable, of } from \"rxjs\";\nimport {\n createMainThreadReleaseOnTimePassedHandler,\n ECSqlBinding,\n ECSqlQueryDef,\n ECSqlQueryExecutor,\n ECSqlQueryReaderOptions,\n ECSqlQueryRow,\n} from \"@itwin/presentation-shared\";\n\n/**\n * Forms ECSql bindings from given ID's.\n * @internal\n */\nexport function formIdBindings(property: string, ids: string[], bindings: ECSqlBinding[]): string {\n if (ids.length > 1000) {\n bindings.push({ type: \"idset\", value: ids });\n return `InVirtualSet(?, ${property})`;\n }\n\n if (ids.length === 0) {\n return `FALSE`;\n }\n\n ids.forEach((id) => bindings.push({ type: \"id\", value: id }));\n return `${property} IN (${ids.map(() => \"?\").join(\",\")})`;\n}\n\n/**\n * Executes given ECSql query and extracts data from rows. Additionally handles main thread releasing.\n * @internal\n */\nexport async function* genericExecuteQuery<T>({\n queryExecutor,\n parseQueryRow,\n query,\n config,\n}: {\n queryExecutor: ECSqlQueryExecutor;\n query: ECSqlQueryDef;\n parseQueryRow: (row: ECSqlQueryRow) => T;\n config?: ECSqlQueryReaderOptions;\n}): AsyncIterableIterator<T> {\n const releaseMainThread = createMainThreadReleaseOnTimePassedHandler();\n const reader = queryExecutor.createQueryReader(query, config);\n for await (const row of reader) {\n yield parseQueryRow(row);\n await releaseMainThread();\n }\n}\n\n/**\n * Emits a certain amount of values, then releases the main thread for other timers to use.\n * @internal\n */\nexport function releaseMainThreadOnItemsCount<T>(elementCount: number) {\n return (obs: Observable<T>): Observable<T> => {\n return obs.pipe(\n bufferCount(elementCount),\n concatMap((buff, i) => {\n const out = of(buff);\n if (i === 0 && buff.length < elementCount) {\n return out;\n }\n return out.pipe(delay(0));\n }),\n concatAll(),\n );\n };\n}\n\n/**\n * A helper that disposes the given object, if it's disposable.\n *\n * The first option is to dispose using the deprecated `dispose` method if it exists on the object.\n * If not, we use the new `Symbol.dispose` method. If that doesn't exist either, the object is\n * considered as non-disposable and nothing is done with it.\n *\n * @internal\n */\nexport function safeDispose(disposable: {} | { [Symbol.dispose]: () => void } | { dispose: () => void }) {\n if (\"dispose\" in disposable) {\n disposable.dispose();\n } else if (Symbol.dispose in disposable) {\n disposable[Symbol.dispose]();\n }\n}\n"]}
|