@itwin/presentation-hierarchies 0.3.0 → 0.4.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 +38 -0
- package/README.md +4 -4
- package/lib/cjs/hierarchies/HierarchyDefinition.js +2 -2
- package/lib/cjs/hierarchies/HierarchyDefinition.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNode.d.ts +3 -3
- package/lib/cjs/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts +11 -1
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.js +33 -19
- package/lib/cjs/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/cjs/hierarchies/LimitingECSqlQueryExecutor.d.ts.map +1 -1
- package/lib/cjs/hierarchies/LimitingECSqlQueryExecutor.js +33 -13
- package/lib/cjs/hierarchies/LimitingECSqlQueryExecutor.js.map +1 -1
- package/lib/cjs/hierarchies/Logging.js +2 -3
- package/lib/cjs/hierarchies/Logging.js.map +1 -1
- package/lib/cjs/hierarchies/NodeSelectQueryFactory.d.ts +14 -2
- package/lib/cjs/hierarchies/NodeSelectQueryFactory.d.ts.map +1 -1
- package/lib/cjs/hierarchies/NodeSelectQueryFactory.js +7 -7
- package/lib/cjs/hierarchies/NodeSelectQueryFactory.js.map +1 -1
- package/lib/cjs/hierarchies/internal/ChildNodeObservablesCache.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/ChildNodeObservablesCache.js +3 -3
- package/lib/cjs/hierarchies/internal/ChildNodeObservablesCache.js.map +1 -1
- package/lib/cjs/hierarchies/internal/Common.d.ts +25 -5
- package/lib/cjs/hierarchies/internal/Common.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/Common.js +41 -21
- package/lib/cjs/hierarchies/internal/Common.js.map +1 -1
- package/lib/cjs/hierarchies/internal/EachValueFrom.js +1 -2
- package/lib/cjs/hierarchies/internal/EachValueFrom.js.map +1 -1
- package/lib/cjs/hierarchies/internal/FilteringHierarchyDefinition.d.ts +5 -4
- package/lib/cjs/hierarchies/internal/FilteringHierarchyDefinition.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/FilteringHierarchyDefinition.js +29 -24
- package/lib/cjs/hierarchies/internal/FilteringHierarchyDefinition.js.map +1 -1
- package/lib/cjs/hierarchies/internal/LoggingUtils.d.ts +1 -3
- package/lib/cjs/hierarchies/internal/LoggingUtils.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/LoggingUtils.js +2 -21
- package/lib/cjs/hierarchies/internal/LoggingUtils.js.map +1 -1
- package/lib/cjs/hierarchies/internal/TreeNodesReader.js +2 -3
- package/lib/cjs/hierarchies/internal/TreeNodesReader.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/DetermineChildren.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/DetermineChildren.js +3 -3
- package/lib/cjs/hierarchies/internal/operators/DetermineChildren.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/Grouping.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/Grouping.js +13 -12
- package/lib/cjs/hierarchies/internal/operators/Grouping.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/HideIfNoChildren.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/HideIfNoChildren.js +3 -3
- package/lib/cjs/hierarchies/internal/operators/HideIfNoChildren.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/HideNodesInHierarchy.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/HideNodesInHierarchy.js +3 -3
- package/lib/cjs/hierarchies/internal/operators/HideNodesInHierarchy.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/Partition.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/Partition.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/ReduceToMergeMap.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/ReduceToMergeMap.js +2 -3
- package/lib/cjs/hierarchies/internal/operators/ReduceToMergeMap.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/ReleaseMainThread.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/ReleaseMainThread.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/ReleaseMainThread.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/ShareReplayWithErrors.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/ShareReplayWithErrors.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/Sorting.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/Sorting.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/TapOnce.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/TapOnce.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/grouping/AutoExpand.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/grouping/AutoExpand.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/grouping/BaseClassGrouping.js +3 -4
- package/lib/cjs/hierarchies/internal/operators/grouping/BaseClassGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/grouping/ClassGrouping.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/grouping/ClassGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/grouping/GroupHiding.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/grouping/GroupHiding.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/grouping/LabelGrouping.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/grouping/LabelGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/grouping/PropertiesGrouping.js +7 -8
- package/lib/cjs/hierarchies/internal/operators/grouping/PropertiesGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/internal/operators/grouping/Shared.js +1 -2
- package/lib/cjs/hierarchies/internal/operators/grouping/Shared.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyNode.d.ts +3 -3
- package/lib/esm/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.d.ts +11 -1
- package/lib/esm/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.js +34 -19
- package/lib/esm/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/esm/hierarchies/LimitingECSqlQueryExecutor.d.ts.map +1 -1
- package/lib/esm/hierarchies/LimitingECSqlQueryExecutor.js +35 -14
- package/lib/esm/hierarchies/LimitingECSqlQueryExecutor.js.map +1 -1
- package/lib/esm/hierarchies/NodeSelectQueryFactory.d.ts +14 -2
- package/lib/esm/hierarchies/NodeSelectQueryFactory.d.ts.map +1 -1
- package/lib/esm/hierarchies/NodeSelectQueryFactory.js +5 -5
- package/lib/esm/hierarchies/NodeSelectQueryFactory.js.map +1 -1
- package/lib/esm/hierarchies/internal/ChildNodeObservablesCache.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/ChildNodeObservablesCache.js +3 -3
- package/lib/esm/hierarchies/internal/ChildNodeObservablesCache.js.map +1 -1
- package/lib/esm/hierarchies/internal/Common.d.ts +25 -5
- package/lib/esm/hierarchies/internal/Common.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/Common.js +35 -15
- package/lib/esm/hierarchies/internal/Common.js.map +1 -1
- package/lib/esm/hierarchies/internal/FilteringHierarchyDefinition.d.ts +5 -4
- package/lib/esm/hierarchies/internal/FilteringHierarchyDefinition.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/FilteringHierarchyDefinition.js +27 -22
- package/lib/esm/hierarchies/internal/FilteringHierarchyDefinition.js.map +1 -1
- package/lib/esm/hierarchies/internal/LoggingUtils.d.ts +1 -3
- package/lib/esm/hierarchies/internal/LoggingUtils.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/LoggingUtils.js +0 -17
- package/lib/esm/hierarchies/internal/LoggingUtils.js.map +1 -1
- package/lib/esm/hierarchies/internal/operators/DetermineChildren.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/DetermineChildren.js +2 -2
- package/lib/esm/hierarchies/internal/operators/DetermineChildren.js.map +1 -1
- package/lib/esm/hierarchies/internal/operators/Grouping.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/Grouping.js +11 -10
- package/lib/esm/hierarchies/internal/operators/Grouping.js.map +1 -1
- package/lib/esm/hierarchies/internal/operators/HideIfNoChildren.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/HideIfNoChildren.js +2 -2
- package/lib/esm/hierarchies/internal/operators/HideIfNoChildren.js.map +1 -1
- package/lib/esm/hierarchies/internal/operators/HideNodesInHierarchy.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/HideNodesInHierarchy.js +2 -2
- package/lib/esm/hierarchies/internal/operators/HideNodesInHierarchy.js.map +1 -1
- package/lib/esm/hierarchies/internal/operators/ReduceToMergeMap.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/ReleaseMainThread.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/operators/grouping/PropertiesGrouping.js +2 -2
- package/lib/esm/hierarchies/internal/operators/grouping/PropertiesGrouping.js.map +1 -1
- package/package.json +11 -11
|
@@ -9,10 +9,10 @@ import { HierarchyNodesDefinition } from "./HierarchyDefinition";
|
|
|
9
9
|
import { RowsLimitExceededError } from "./HierarchyErrors";
|
|
10
10
|
import { HierarchyNode, } from "./HierarchyNode";
|
|
11
11
|
import { ChildNodeObservablesCache } from "./internal/ChildNodeObservablesCache";
|
|
12
|
-
import { LOGGING_NAMESPACE as
|
|
12
|
+
import { LOGGING_NAMESPACE as BASE_LOGGING_NAMESPACE, LOGGING_NAMESPACE_INTERNAL as BASE_LOGGING_NAMESPACE_INTERNAL, LOGGING_NAMESPACE_PERFORMANCE as BASE_LOGGING_NAMESPACE_PERFORMANCE, createNodeIdentifierForLogging, hasChildren, } from "./internal/Common";
|
|
13
13
|
import { eachValueFrom } from "./internal/EachValueFrom";
|
|
14
14
|
import { FilteringHierarchyDefinition } from "./internal/FilteringHierarchyDefinition";
|
|
15
|
-
import {
|
|
15
|
+
import { doLog, log } from "./internal/LoggingUtils";
|
|
16
16
|
import { createDetermineChildrenOperator } from "./internal/operators/DetermineChildren";
|
|
17
17
|
import { createGroupingOperator } from "./internal/operators/Grouping";
|
|
18
18
|
import { createHideIfNoChildrenOperator } from "./internal/operators/HideIfNoChildren";
|
|
@@ -24,8 +24,9 @@ import { sortNodesByLabelOperator } from "./internal/operators/Sorting";
|
|
|
24
24
|
import { SubscriptionScheduler } from "./internal/SubscriptionScheduler";
|
|
25
25
|
import { readNodes } from "./internal/TreeNodesReader";
|
|
26
26
|
import { NodeSelectClauseColumnNames } from "./NodeSelectQueryFactory";
|
|
27
|
-
const LOGGING_NAMESPACE = `${
|
|
28
|
-
const
|
|
27
|
+
const LOGGING_NAMESPACE = `${BASE_LOGGING_NAMESPACE}.Provider`;
|
|
28
|
+
const LOGGING_NAMESPACE_INTERNAL = `${BASE_LOGGING_NAMESPACE_INTERNAL}.Provider`;
|
|
29
|
+
const LOGGING_NAMESPACE_PERFORMANCE = `${BASE_LOGGING_NAMESPACE_PERFORMANCE}.Provider`;
|
|
29
30
|
const DEFAULT_QUERY_CONCURRENCY = 10;
|
|
30
31
|
const DEFAULT_QUERY_CACHE_SIZE = 1;
|
|
31
32
|
/**
|
|
@@ -93,12 +94,12 @@ class HierarchyProviderImpl {
|
|
|
93
94
|
}
|
|
94
95
|
createParsedQueryNodesObservable(props) {
|
|
95
96
|
doLog({
|
|
96
|
-
category:
|
|
97
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
97
98
|
message: /* istanbul ignore next */ () => `Requesting hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
98
99
|
});
|
|
99
100
|
// stream hierarchy level definitions
|
|
100
101
|
const definitions = from(defer(async () => this.hierarchyDefinition.defineHierarchyLevel(props))).pipe(mergeAll(), finalize(() => doLog({
|
|
101
|
-
category:
|
|
102
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
102
103
|
message: /* istanbul ignore next */ () => `Received all hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
103
104
|
})));
|
|
104
105
|
// pipe definitions to nodes and put "share replay" on it
|
|
@@ -106,12 +107,9 @@ class HierarchyProviderImpl {
|
|
|
106
107
|
if (HierarchyNodesDefinition.isCustomNode(def)) {
|
|
107
108
|
return of(def.node);
|
|
108
109
|
}
|
|
109
|
-
return this._queryScheduler.scheduleSubscription(of(def.query).pipe(map((query) => filterQueryByInstanceKeys(query, props.filteredInstanceKeys)),
|
|
110
|
-
category: `${LOGGING_NAMESPACE}.Queries`,
|
|
111
|
-
message: /* istanbul ignore next */ (query) => `Query direct nodes for parent ${createNodeIdentifierForLogging(props.parentNode)}: ${createQueryLogMessage(query)}`,
|
|
112
|
-
}), mergeMap((query) => readNodes({ queryExecutor: this.queryExecutor, query, limit: props.hierarchyLevelSizeLimit, parser: this.hierarchyDefinition.parseNode }))));
|
|
110
|
+
return this._queryScheduler.scheduleSubscription(of(def.query).pipe(map((query) => filterQueryByInstanceKeys(query, props.filteredInstanceKeys)), mergeMap((query) => readNodes({ queryExecutor: this.queryExecutor, query, limit: props.hierarchyLevelSizeLimit, parser: this.hierarchyDefinition.parseNode }))));
|
|
113
111
|
}), finalize(() => doLog({
|
|
114
|
-
category:
|
|
112
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
115
113
|
message: /* istanbul ignore next */ () => `Read all child nodes ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
116
114
|
})), shareReplayWithErrors());
|
|
117
115
|
}
|
|
@@ -125,7 +123,7 @@ class HierarchyProviderImpl {
|
|
|
125
123
|
mergeMap(async (node) => applyLabelsFormatting(node, this._imodelAccess, this._valuesFormatter)),
|
|
126
124
|
// we have `ProcessedHierarchyNode` from here
|
|
127
125
|
preProcessNodes(this.hierarchyDefinition), finalize(() => doLog({
|
|
128
|
-
category:
|
|
126
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
129
127
|
message: /* istanbul ignore next */ () => `Finished initializing child nodes for ${createNodeIdentifierForLogging(parentNode)}`,
|
|
130
128
|
})), shareReplayWithErrors());
|
|
131
129
|
}
|
|
@@ -133,14 +131,14 @@ class HierarchyProviderImpl {
|
|
|
133
131
|
return this.createInitializedNodesObservable(queryNodesObservable, props.parentNode).pipe(createHideIfNoChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n }).hasNodes), createHideNodesInHierarchyOperator(
|
|
134
132
|
// note: for child nodes created because of hidden parent, we want to use parent's request props (instance filter, limit)
|
|
135
133
|
(n) => this.getChildNodesObservables({ ...props, parentNode: n }).processedNodes, false), finalize(() => doLog({
|
|
136
|
-
category:
|
|
134
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
137
135
|
message: /* istanbul ignore next */ () => `Finished pre-processing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
138
136
|
})));
|
|
139
137
|
}
|
|
140
138
|
createProcessedNodesObservable(preprocessedNodesObservable, props) {
|
|
141
139
|
return preprocessedNodesObservable.pipe(createGroupingOperator(this._imodelAccess, props.parentNode, this._valuesFormatter, this._localizedStrings, (gn) => this.onGroupingNodeCreated(gn, props)), finalize(() => doLog({
|
|
142
|
-
category:
|
|
143
|
-
message: /* istanbul ignore next */ () => `Finished
|
|
140
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
141
|
+
message: /* istanbul ignore next */ () => `Finished grouping child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
144
142
|
})));
|
|
145
143
|
}
|
|
146
144
|
createFinalizedNodesObservable(processedNodesObservable, props) {
|
|
@@ -152,12 +150,12 @@ class HierarchyProviderImpl {
|
|
|
152
150
|
children: hasChildren(n),
|
|
153
151
|
});
|
|
154
152
|
}), finalize(() => doLog({
|
|
155
|
-
category:
|
|
153
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
156
154
|
message: /* istanbul ignore next */ () => `Finished finalizing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
157
155
|
})));
|
|
158
156
|
}
|
|
159
157
|
createHasNodesObservable(preprocessedNodesObservable, possiblyKnownChildrenObservable) {
|
|
160
|
-
const loggingCategory = `${
|
|
158
|
+
const loggingCategory = `${LOGGING_NAMESPACE_INTERNAL}.HasNodes`;
|
|
161
159
|
return concat((possiblyKnownChildrenObservable ?? EMPTY).pipe(filter((n) => hasChildren(n))), preprocessedNodesObservable).pipe(log({ category: loggingCategory, message: /* istanbul ignore next */ (n) => `Node before mapping to 'true': ${createNodeIdentifierForLogging(n)}` }), take(1), map(() => true), defaultIfEmpty(false), catchError((e) => {
|
|
162
160
|
doLog({ category: loggingCategory, message: /* istanbul ignore next */ () => `Error while determining children: ${e.message}` });
|
|
163
161
|
if (e instanceof RowsLimitExceededError) {
|
|
@@ -167,7 +165,7 @@ class HierarchyProviderImpl {
|
|
|
167
165
|
}), log({ category: loggingCategory, message: /* istanbul ignore next */ (r) => `Result: ${r}` }));
|
|
168
166
|
}
|
|
169
167
|
getCachedObservableEntry(props) {
|
|
170
|
-
const loggingCategory = `${LOGGING_NAMESPACE}.
|
|
168
|
+
const loggingCategory = `${LOGGING_NAMESPACE}.QueryResultsCache`;
|
|
171
169
|
const { parentNode, ...restProps } = props;
|
|
172
170
|
const cached = props.ignoreCache || !this._nodesCache ? undefined : this._nodesCache.get(props);
|
|
173
171
|
if (cached) {
|
|
@@ -306,11 +304,24 @@ class HierarchyProviderImpl {
|
|
|
306
304
|
*/
|
|
307
305
|
getNodeInstanceKeys(props) {
|
|
308
306
|
const loggingCategory = `${LOGGING_NAMESPACE}.GetNodeInstanceKeys`;
|
|
307
|
+
const timer = new StopWatch(undefined, true);
|
|
309
308
|
doLog({
|
|
310
309
|
category: loggingCategory,
|
|
311
310
|
message: /* istanbul ignore next */ () => `Requesting keys for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
312
311
|
});
|
|
313
|
-
|
|
312
|
+
let error;
|
|
313
|
+
let keysCount = 0;
|
|
314
|
+
return eachValueFrom(this.getNodeInstanceKeysObs(props).pipe(tap(() => ++keysCount), catchError((e) => {
|
|
315
|
+
error = e;
|
|
316
|
+
throw e;
|
|
317
|
+
}), finalize(() => {
|
|
318
|
+
doLog({
|
|
319
|
+
category: loggingCategory,
|
|
320
|
+
message: /* istanbul ignore next */ () => error
|
|
321
|
+
? `Error creating node instance keys for ${createNodeIdentifierForLogging(props.parentNode)}: ${error instanceof Error ? error.message : error.toString()}`
|
|
322
|
+
: `Returned ${keysCount} instance keys for ${createNodeIdentifierForLogging(props.parentNode)} in ${timer.currentSeconds.toFixed(2)} s.`,
|
|
323
|
+
});
|
|
324
|
+
})));
|
|
314
325
|
}
|
|
315
326
|
/**
|
|
316
327
|
* A function that should be called when the underlying data source, used by `HierarchyProviderProps.schemaProvider`,
|
|
@@ -319,6 +330,10 @@ class HierarchyProviderImpl {
|
|
|
319
330
|
* Calling the function invalidates internal caches to make sure fresh data is retrieved on new requests.
|
|
320
331
|
*/
|
|
321
332
|
notifyDataSourceChanged() {
|
|
333
|
+
doLog({
|
|
334
|
+
category: `${LOGGING_NAMESPACE}.Events`,
|
|
335
|
+
message: /* istanbul ignore next */ () => `Data source changed: clear query results cache`,
|
|
336
|
+
});
|
|
322
337
|
this._nodesCache?.clear();
|
|
323
338
|
}
|
|
324
339
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HierarchyProvider.js","sourceRoot":"","sources":["../../../src/hierarchies/HierarchyProvider.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 {\n catchError,\n concat,\n defaultIfEmpty,\n defer,\n EMPTY,\n filter,\n finalize,\n from,\n map,\n merge,\n mergeAll,\n mergeMap,\n Observable,\n ObservableInput,\n of,\n take,\n tap,\n} from \"rxjs\";\nimport { assert, StopWatch } from \"@itwin/core-bentley\";\nimport { GenericInstanceFilter } from \"@itwin/core-common\";\nimport {\n ConcatenatedValue,\n createDefaultValueFormatter,\n ECClassHierarchyInspector,\n ECSchemaProvider,\n ECSqlBinding,\n ECSqlQueryDef,\n formatConcatenatedValue,\n InstanceKey,\n IPrimitiveValueFormatter,\n normalizeFullClassName,\n} from \"@itwin/presentation-shared\";\nimport { DefineHierarchyLevelProps, HierarchyDefinition, HierarchyNodesDefinition } from \"./HierarchyDefinition\";\nimport { RowsLimitExceededError } from \"./HierarchyErrors\";\nimport {\n HierarchyNode,\n NonGroupingHierarchyNode,\n ParentHierarchyNode,\n ParsedHierarchyNode,\n ProcessedCustomHierarchyNode,\n ProcessedGroupingHierarchyNode,\n ProcessedHierarchyNode,\n ProcessedInstanceHierarchyNode,\n} from \"./HierarchyNode\";\nimport { HierarchyNodeIdentifiersPath } from \"./HierarchyNodeIdentifier\";\nimport { InstancesNodeKey } from \"./HierarchyNodeKey\";\nimport { CachedNodesObservableEntry, ChildNodeObservablesCache, ParsedQueryNodesObservable } from \"./internal/ChildNodeObservablesCache\";\nimport { LOGGING_NAMESPACE as CommonLoggingNamespace, createNodeIdentifierForLogging, hasChildren } from \"./internal/Common\";\nimport { eachValueFrom } from \"./internal/EachValueFrom\";\nimport { FilteringHierarchyDefinition } from \"./internal/FilteringHierarchyDefinition\";\nimport { createQueryLogMessage, doLog, log } from \"./internal/LoggingUtils\";\nimport { createDetermineChildrenOperator } from \"./internal/operators/DetermineChildren\";\nimport { createGroupingOperator } from \"./internal/operators/Grouping\";\nimport { createHideIfNoChildrenOperator } from \"./internal/operators/HideIfNoChildren\";\nimport { createHideNodesInHierarchyOperator } from \"./internal/operators/HideNodesInHierarchy\";\nimport { partition } from \"./internal/operators/Partition\";\nimport { reduceToMergeMapList } from \"./internal/operators/ReduceToMergeMap\";\nimport { shareReplayWithErrors } from \"./internal/operators/ShareReplayWithErrors\";\nimport { sortNodesByLabelOperator } from \"./internal/operators/Sorting\";\nimport { SubscriptionScheduler } from \"./internal/SubscriptionScheduler\";\nimport { readNodes } from \"./internal/TreeNodesReader\";\nimport { LimitingECSqlQueryExecutor } from \"./LimitingECSqlQueryExecutor\";\nimport { NodeSelectClauseColumnNames } from \"./NodeSelectQueryFactory\";\n\nconst LOGGING_NAMESPACE = `${CommonLoggingNamespace}.HierarchyProvider`;\nconst PERF_LOGGING_NAMESPACE = `${LOGGING_NAMESPACE}.Performance`;\nconst DEFAULT_QUERY_CONCURRENCY = 10;\nconst DEFAULT_QUERY_CACHE_SIZE = 1;\n\n/**\n * Props for the `HierarchyProvider.getNodes` call.\n * @beta\n */\nexport interface GetHierarchyNodesProps {\n /** Parent node to get children for. Pass `undefined` to get root nodes. */\n parentNode: ParentHierarchyNode | undefined;\n\n /** Optional hierarchy level filter. Has no effect if `parentNode` is a `GroupingNode`. */\n instanceFilter?: GenericInstanceFilter;\n\n /**\n * Optional hierarchy level size limit override. This value is passed to `LimitingECSqlQueryExecutor` used\n * by this provider to override query rows limit per hierarchy level. If not provided, defaults to whatever\n * is used by the limiting query executor.\n *\n * Has no effect if `parentNode` is a `GroupingNode`.\n */\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n\n /** When set to true ignores the cache and fetches the nodes again. */\n ignoreCache?: boolean;\n}\n\n/**\n * An interface for a hierarchy provider knows how to create child nodes for a given parent node.\n * @beta\n */\nexport interface HierarchyProvider {\n /** Gets nodes for the specified parent node. */\n getNodes(props: GetHierarchyNodesProps): AsyncIterableIterator<HierarchyNode>;\n\n /** Gets instance keys for the specified parent node. */\n getNodeInstanceKeys(props: Omit<GetHierarchyNodesProps, \"ignoreCache\">): AsyncIterableIterator<InstanceKey>;\n\n /** Notifies the provider that the underlying data source has changed and caches should be invalidated. */\n notifyDataSourceChanged(): void;\n\n /**\n * Overrides the property value formatter used by the hierarchy provider. Setting to `undefined`\n * resets the formatter to the result of `createDefaultValueFormatter` called with default parameters.\n */\n setFormatter(formatter: IPrimitiveValueFormatter | undefined): void;\n}\n\n/**\n * Defines the strings used by hierarchy provider.\n * @beta\n */\ninterface HierarchyProviderLocalizedStrings {\n /**\n * A string for \"Unspecified\". Used for labels of property grouping nodes\n * that group by an empty value.\n */\n unspecified: string;\n\n /**\n * A string for \"Other\". Used for label of a range property grouping node that\n * groups values which don't fit into any other range.\n */\n other: string;\n}\n\n/**\n * Props for `createHierarchyProvider`.\n * @beta\n */\ninterface HierarchyProviderProps {\n /**\n * An object that provides access to iModel's data and metadata.\n *\n * @see `ECSchemaProvider`\n * @see `LimitingECSqlQueryExecutor`\n * @see `ECClassHierarchyInspector`\n */\n imodelAccess: ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;\n\n /**\n * A function that returns a hierarchy definition, describing how the hierarchy that the provider should be create. The\n * function is called once during the provider's construction.\n */\n hierarchyDefinition: HierarchyDefinition;\n\n /** Maximum number of queries that the provider attempts to execute in parallel. Defaults to `10`. */\n queryConcurrency?: number;\n /**\n * The amount of queries whose results are stored in-memory for quick retrieval. Defaults to `1`,\n * which means only results of the last run query are cached.\n */\n queryCacheSize?: number;\n\n /**\n * A values formatter for formatting node labels. Defaults to the\n * result of `createDefaultValueFormatter` called with default parameters.\n */\n formatter?: IPrimitiveValueFormatter;\n\n /** A set of localized strings to use. Defaults to English strings. */\n localizedStrings?: Partial<HierarchyProviderLocalizedStrings>;\n\n /** Props for filtering the hierarchy. */\n filtering?: {\n /** A list of node identifiers from root to target node. */\n paths: HierarchyNodeIdentifiersPath[];\n };\n}\n\n/**\n * Creates an instance of `HierarchyProvider` that creates a hierarchy based on given iModel and\n * a hierarchy definition, which defines each hierarchy level through ECSQL queries.\n *\n * @beta\n */\nexport function createHierarchyProvider(props: HierarchyProviderProps): HierarchyProvider {\n return new HierarchyProviderImpl(props);\n}\n\nclass HierarchyProviderImpl implements HierarchyProvider {\n private _imodelAccess: ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;\n private _valuesFormatter: IPrimitiveValueFormatter;\n private _localizedStrings: HierarchyProviderLocalizedStrings;\n private _queryScheduler: SubscriptionScheduler;\n private _nodesCache?: ChildNodeObservablesCache;\n\n /**\n * Hierarchy level definitions factory used by this provider.\n *\n * @note This does not necessarily match the `hierarchyDefinition` passed through props when constructing\n * the provider. For example, it may be a factory that decorates given `hierarchyDefinition` with filtering\n * features.\n */\n public readonly hierarchyDefinition: HierarchyDefinition;\n\n /**\n * A limiting ECSQL query executor used by this provider.\n * @see HierarchyProviderProps.queryExecutor\n */\n public get queryExecutor(): LimitingECSqlQueryExecutor {\n return this._imodelAccess;\n }\n\n public constructor(props: HierarchyProviderProps) {\n this._imodelAccess = props.imodelAccess;\n this.hierarchyDefinition = props.hierarchyDefinition;\n if (props.filtering) {\n const filteringDefinition = new FilteringHierarchyDefinition({\n classHierarchy: this._imodelAccess,\n source: this.hierarchyDefinition,\n nodeIdentifierPaths: props.filtering.paths,\n });\n this.hierarchyDefinition = filteringDefinition;\n }\n this._valuesFormatter = props?.formatter ?? createDefaultValueFormatter();\n this._localizedStrings = { other: \"Other\", unspecified: \"Not specified\", ...props?.localizedStrings };\n this._queryScheduler = new SubscriptionScheduler(props.queryConcurrency ?? DEFAULT_QUERY_CONCURRENCY);\n\n const queryCacheSize = props.queryCacheSize ?? DEFAULT_QUERY_CACHE_SIZE;\n if (queryCacheSize !== 0) {\n this._nodesCache = new ChildNodeObservablesCache({\n // we divide the size by 2, because each variation also counts as a query that we cache\n size: Math.ceil(queryCacheSize / 2),\n variationsCount: 1,\n });\n }\n }\n\n /**\n * Sets `HierarchyProvider` values formatter that formats nodes' labels. If provided `undefined`, then defaults to the\n * result of `createDefaultValueFormatter` called with default parameters.\n */\n public setFormatter(formatter: IPrimitiveValueFormatter | undefined) {\n this._valuesFormatter = formatter ?? createDefaultValueFormatter();\n }\n\n private onGroupingNodeCreated(groupingNode: ProcessedGroupingHierarchyNode, props: GetHierarchyNodesProps) {\n this._nodesCache?.set({ ...props, parentNode: groupingNode }, { observable: from(groupingNode.children), processingStatus: \"pre-processed\" });\n }\n\n private createParsedQueryNodesObservable(\n props: DefineHierarchyLevelProps & { hierarchyLevelSizeLimit?: number | \"unbounded\"; filteredInstanceKeys?: InstanceKey[] },\n ): ParsedQueryNodesObservable {\n doLog({\n category: PERF_LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Requesting hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,\n });\n // stream hierarchy level definitions\n const definitions = from(defer(async () => this.hierarchyDefinition.defineHierarchyLevel(props))).pipe(\n mergeAll(),\n finalize(() =>\n doLog({\n category: PERF_LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Received all hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n // pipe definitions to nodes and put \"share replay\" on it\n return definitions.pipe(\n mergeMap((def): ObservableInput<ParsedHierarchyNode> => {\n if (HierarchyNodesDefinition.isCustomNode(def)) {\n return of(def.node);\n }\n return this._queryScheduler.scheduleSubscription(\n of(def.query).pipe(\n map((query) => filterQueryByInstanceKeys(query, props.filteredInstanceKeys)),\n log({\n category: `${LOGGING_NAMESPACE}.Queries`,\n message: /* istanbul ignore next */ (query) =>\n `Query direct nodes for parent ${createNodeIdentifierForLogging(props.parentNode)}: ${createQueryLogMessage(query)}`,\n }),\n mergeMap((query) =>\n readNodes({ queryExecutor: this.queryExecutor, query, limit: props.hierarchyLevelSizeLimit, parser: this.hierarchyDefinition.parseNode }),\n ),\n ),\n );\n }),\n finalize(() =>\n doLog({\n category: PERF_LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Read all child nodes ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n shareReplayWithErrors(),\n );\n }\n\n private createInitializedNodesObservable(nodes: Observable<ParsedHierarchyNode>, parentNode: ParentHierarchyNode | undefined) {\n return nodes.pipe(\n // we're going to be mutating the nodes, but don't want to mutate the original one, so just clone it here once\n map((node) => ({ ...node })),\n // set parent node keys on the parsed node\n map((node) => Object.assign(node, { parentKeys: createParentNodeKeysList(parentNode) })),\n // format `ConcatenatedValue` labels into string labels\n mergeMap(async (node) => applyLabelsFormatting(node, this._imodelAccess, this._valuesFormatter)),\n // we have `ProcessedHierarchyNode` from here\n preProcessNodes(this.hierarchyDefinition),\n finalize(() =>\n doLog({\n category: PERF_LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Finished initializing child nodes for ${createNodeIdentifierForLogging(parentNode)}`,\n }),\n ),\n shareReplayWithErrors(),\n );\n }\n\n private createPreProcessedNodesObservable(\n queryNodesObservable: ParsedQueryNodesObservable,\n props: GetHierarchyNodesProps,\n ): Observable<ProcessedHierarchyNode> {\n return this.createInitializedNodesObservable(queryNodesObservable, props.parentNode).pipe(\n createHideIfNoChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n }).hasNodes),\n createHideNodesInHierarchyOperator(\n // note: for child nodes created because of hidden parent, we want to use parent's request props (instance filter, limit)\n (n) => this.getChildNodesObservables({ ...props, parentNode: n }).processedNodes,\n false,\n ),\n finalize(() =>\n doLog({\n category: PERF_LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Finished pre-processing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n }\n\n private createProcessedNodesObservable(\n preprocessedNodesObservable: Observable<ProcessedHierarchyNode>,\n props: GetHierarchyNodesProps,\n ): Observable<ProcessedHierarchyNode> {\n return preprocessedNodesObservable.pipe(\n createGroupingOperator(this._imodelAccess, props.parentNode, this._valuesFormatter, this._localizedStrings, (gn) =>\n this.onGroupingNodeCreated(gn, props),\n ),\n finalize(() =>\n doLog({\n category: PERF_LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Finished processing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n }\n\n private createFinalizedNodesObservable(\n processedNodesObservable: Observable<ProcessedHierarchyNode>,\n props: GetHierarchyNodesProps,\n ): Observable<HierarchyNode> {\n return processedNodesObservable.pipe(\n createDetermineChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n }).hasNodes),\n postProcessNodes(this.hierarchyDefinition),\n sortNodesByLabelOperator,\n map((n): HierarchyNode => {\n if (HierarchyNode.isCustom(n) || HierarchyNode.isInstancesNode(n)) {\n delete n.processingParams;\n }\n return Object.assign(n, {\n children: hasChildren(n),\n });\n }),\n finalize(() =>\n doLog({\n category: PERF_LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Finished finalizing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n }\n\n private createHasNodesObservable(\n preprocessedNodesObservable: Observable<ProcessedHierarchyNode>,\n possiblyKnownChildrenObservable?: ParsedQueryNodesObservable,\n ): Observable<boolean> {\n const loggingCategory = `${LOGGING_NAMESPACE}.HasNodes`;\n return concat((possiblyKnownChildrenObservable ?? EMPTY).pipe(filter((n) => hasChildren(n))), preprocessedNodesObservable).pipe(\n log({ category: loggingCategory, message: /* istanbul ignore next */ (n) => `Node before mapping to 'true': ${createNodeIdentifierForLogging(n)}` }),\n take(1),\n map(() => true),\n defaultIfEmpty(false),\n catchError((e: Error) => {\n doLog({ category: loggingCategory, message: /* istanbul ignore next */ () => `Error while determining children: ${e.message}` });\n if (e instanceof RowsLimitExceededError) {\n return of(true);\n }\n throw e;\n }),\n log({ category: loggingCategory, message: /* istanbul ignore next */ (r) => `Result: ${r}` }),\n );\n }\n\n private getCachedObservableEntry(props: GetHierarchyNodesProps): CachedNodesObservableEntry {\n const loggingCategory = `${LOGGING_NAMESPACE}.GetCachedObservableEntry`;\n const { parentNode, ...restProps } = props;\n const cached = props.ignoreCache || !this._nodesCache ? undefined : this._nodesCache.get(props);\n if (cached) {\n // istanbul ignore next\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Found query nodes observable for ${createNodeIdentifierForLogging(parentNode)}`,\n });\n return cached;\n }\n\n // if we don't find an entry for a grouping node, we load its instances by getting a query and applying\n // a filter based on grouped instance keys\n let filteredInstanceKeys: InstanceKey[] | undefined;\n let parentNonGroupingNode: ParentHierarchyNode<NonGroupingHierarchyNode> | undefined;\n if (parentNode) {\n if (HierarchyNode.isGroupingNode(parentNode)) {\n parentNonGroupingNode = parentNode.nonGroupingAncestor;\n filteredInstanceKeys = parentNode.groupedInstanceKeys;\n } else {\n // not sure why type checker doesn't pick this up\n assert(HierarchyNode.isCustom(parentNode) || HierarchyNode.isInstancesNode(parentNode));\n parentNonGroupingNode = parentNode;\n }\n }\n\n const nonGroupingNodeChildrenRequestProps = {\n ...restProps,\n parentNode: parentNonGroupingNode,\n ...(filteredInstanceKeys ? { filteredInstanceKeys } : undefined),\n };\n const value = { observable: this.createParsedQueryNodesObservable(nonGroupingNodeChildrenRequestProps), processingStatus: \"none\" as const };\n this._nodesCache?.set(nonGroupingNodeChildrenRequestProps, value);\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Saved query nodes observable for ${createNodeIdentifierForLogging(parentNode)}`,\n });\n return value;\n }\n\n private getChildNodesObservables(props: GetHierarchyNodesProps & { hierarchyLevelSizeLimit?: number | \"unbounded\" }) {\n const entry = this.getCachedObservableEntry(props);\n switch (entry.processingStatus) {\n case \"none\": {\n const pre = this.createPreProcessedNodesObservable(entry.observable, props);\n const post = this.createProcessedNodesObservable(pre, props);\n return {\n processedNodes: post,\n hasNodes: this.createHasNodesObservable(pre, entry.observable),\n finalizedNodes: this.createFinalizedNodesObservable(post, props),\n };\n }\n case \"pre-processed\": {\n const post = this.createProcessedNodesObservable(entry.observable, props);\n return {\n processedNodes: post,\n hasNodes: this.createHasNodesObservable(entry.observable),\n finalizedNodes: this.createFinalizedNodesObservable(post, props),\n };\n }\n }\n }\n\n /**\n * Creates and runs a query based on provided props, then processes retrieved nodes and returns them.\n */\n public getNodes(props: GetHierarchyNodesProps): AsyncIterableIterator<HierarchyNode> {\n const loggingCategory = `${LOGGING_NAMESPACE}.GetNodes`;\n const timer = new StopWatch(undefined, true);\n let error: any;\n let nodesCount = 0;\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Requesting child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n });\n return eachValueFrom(\n this.getChildNodesObservables(props).finalizedNodes.pipe(\n tap(() => ++nodesCount),\n catchError((e) => {\n error = e;\n throw e;\n }),\n finalize(() => {\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () =>\n error\n ? `Error creating child nodes for ${createNodeIdentifierForLogging(props.parentNode)}: ${error instanceof Error ? error.message : error.toString()}`\n : `Returned ${nodesCount} child nodes for ${createNodeIdentifierForLogging(props.parentNode)} in ${timer.currentSeconds.toFixed(2)} s.`,\n });\n }),\n ),\n );\n }\n\n private getNodeInstanceKeysObs(props: Omit<GetHierarchyNodesProps, \"ignoreCache\">): Observable<InstanceKey> {\n const { parentNode, instanceFilter, hierarchyLevelSizeLimit = \"unbounded\" } = props;\n\n if (parentNode && HierarchyNode.isGroupingNode(parentNode)) {\n return from(parentNode.groupedInstanceKeys);\n }\n\n assert(!parentNode || HierarchyNode.isCustom(parentNode) || HierarchyNode.isInstancesNode(parentNode));\n\n // split the definitions based on whether they're for custom nodes or for instance nodes\n const [customDefs, instanceDefs] = partition(\n from(this.hierarchyDefinition.defineHierarchyLevel({ parentNode, instanceFilter })).pipe(mergeAll()),\n HierarchyNodesDefinition.isCustomNode,\n );\n\n // query instance keys and a flag whether they should be hidden\n const instanceKeys = instanceDefs.pipe(\n mergeMap((def) =>\n this._queryScheduler.scheduleSubscription(\n of(def.query).pipe(\n mergeMap(async (query) => {\n const ecsql = `\n SELECT\n ${NodeSelectClauseColumnNames.FullClassName},\n ${NodeSelectClauseColumnNames.ECInstanceId},\n ${NodeSelectClauseColumnNames.HideNodeInHierarchy}\n FROM (\n ${query.ecsql}\n )\n `;\n const reader = this.queryExecutor.createQueryReader({ ...query, ecsql }, { rowFormat: \"Indexes\", limit: hierarchyLevelSizeLimit });\n return from(reader).pipe(\n map((row) => ({\n key: {\n className: normalizeFullClassName(row[0]),\n id: row[1],\n },\n hide: !!row[2],\n })),\n );\n }),\n mergeAll(),\n ),\n ),\n ),\n );\n // split the instance keys observable based on whether they should be hidden or not\n const [visibleNodeInstanceKeys, hiddenNodeInstanceKeys] = partition(instanceKeys, ({ hide }) => !hide);\n\n // hidden items' handling:\n // - if a custom node is hidden, we'll want to retrieve instance keys of its children, otherwise we don't care about it,\n // - if an instance key is hidden, we want to create a merged node similar to what we do in `createHideNodesInHierarchyOperator`\n const hiddenParentNodes = merge(\n customDefs.pipe(\n mergeMap((def) => (def.node.processingParams?.hideInHierarchy ? this.createInitializedNodesObservable(of(def.node), parentNode) : EMPTY)),\n ),\n hiddenNodeInstanceKeys.pipe(\n // first merge all keys by class\n reduceToMergeMapList(\n ({ key }) => key.className,\n ({ key }) => key.id,\n ),\n // then, for each class, create a temp node\n mergeMap(\n (mergedMap): Array<ParentHierarchyNode & { key: InstancesNodeKey }> =>\n [...mergedMap.entries()].map(([className, ids]) => ({\n key: {\n type: \"instances\",\n instanceKeys: ids.map((id) => ({ className, id })),\n },\n parentKeys: [],\n label: \"\",\n })),\n ),\n ),\n );\n\n // merge visible instance keys from this level & the ones we get recursively requesting from deeper levels\n return merge(\n visibleNodeInstanceKeys.pipe(map(({ key }) => key)),\n hiddenParentNodes.pipe(mergeMap((hiddenNode) => this.getNodeInstanceKeysObs({ parentNode: hiddenNode }))),\n );\n }\n\n /**\n * Creates an iterator for all child hierarchy level instance keys, taking into account any hidden hierarchy levels\n * that there may be under the given parent node.\n */\n public getNodeInstanceKeys(props: Omit<GetHierarchyNodesProps, \"ignoreCache\">): AsyncIterableIterator<InstanceKey> {\n const loggingCategory = `${LOGGING_NAMESPACE}.GetNodeInstanceKeys`;\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Requesting keys for ${createNodeIdentifierForLogging(props.parentNode)}`,\n });\n return eachValueFrom(this.getNodeInstanceKeysObs(props));\n }\n\n /**\n * A function that should be called when the underlying data source, used by `HierarchyProviderProps.schemaProvider`,\n * `HierarchyProviderProps.queryExecutor` or `HierarchyProviderProps.hierarchyDefinition`, changes.\n *\n * Calling the function invalidates internal caches to make sure fresh data is retrieved on new requests.\n */\n public notifyDataSourceChanged() {\n this._nodesCache?.clear();\n }\n}\n\nfunction preProcessNodes(hierarchyFactory: HierarchyDefinition) {\n return hierarchyFactory.preProcessNode\n ? processNodes(hierarchyFactory.preProcessNode.bind(hierarchyFactory))\n : (o: Observable<ProcessedCustomHierarchyNode | ProcessedInstanceHierarchyNode>) => o;\n}\n\nfunction postProcessNodes(hierarchyFactory: HierarchyDefinition) {\n return hierarchyFactory.postProcessNode\n ? processNodes(hierarchyFactory.postProcessNode.bind(hierarchyFactory))\n : (o: Observable<ProcessedHierarchyNode>) => o;\n}\n\nfunction processNodes<TNode>(processor: (node: TNode) => Promise<TNode | undefined>) {\n return (nodes: Observable<TNode>) =>\n nodes.pipe(\n mergeMap(processor),\n filter((n): n is TNode => !!n),\n );\n}\n\nasync function applyLabelsFormatting<TNode extends { label: string | ConcatenatedValue }>(\n node: TNode,\n schemaProvider: ECSchemaProvider,\n valueFormatter: IPrimitiveValueFormatter,\n): Promise<TNode & { label: string }> {\n return {\n ...node,\n label: await formatConcatenatedValue({\n value: node.label,\n schemaProvider,\n valueFormatter,\n }),\n };\n}\n\nfunction createParentNodeKeysList(parentNode: ParentHierarchyNode | undefined) {\n if (!parentNode) {\n return [];\n }\n return [...parentNode.parentKeys, parentNode.key];\n}\n\nfunction filterQueryByInstanceKeys(query: ECSqlQueryDef, filteredInstanceKeys: InstanceKey[] | undefined): ECSqlQueryDef {\n if (!filteredInstanceKeys || !filteredInstanceKeys.length) {\n return query;\n }\n const MAX_ALLOWED_BINDINGS = 1000;\n // istanbul ignore else\n if (filteredInstanceKeys.length < MAX_ALLOWED_BINDINGS) {\n return {\n ...query,\n ecsql: `\n SELECT *\n FROM (${query.ecsql}) q\n WHERE q.ECInstanceId IN (${filteredInstanceKeys.map(() => \"?\").join(\",\")})\n `,\n bindings: [...(query.bindings ?? []), ...filteredInstanceKeys.map((k): ECSqlBinding => ({ type: \"id\", value: k.id }))],\n };\n }\n // istanbul ignore next\n return {\n ...query,\n ecsql: `\n SELECT *\n FROM (${query.ecsql}) q\n WHERE InVirtualSet(?, q.ECInstanceId)\n `,\n bindings: [...(query.bindings ?? []), { type: \"idset\", value: filteredInstanceKeys.map((k) => k.id) }],\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"HierarchyProvider.js","sourceRoot":"","sources":["../../../src/hierarchies/HierarchyProvider.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 {\n catchError,\n concat,\n defaultIfEmpty,\n defer,\n EMPTY,\n filter,\n finalize,\n from,\n map,\n merge,\n mergeAll,\n mergeMap,\n Observable,\n ObservableInput,\n of,\n take,\n tap,\n} from \"rxjs\";\nimport { assert, StopWatch } from \"@itwin/core-bentley\";\nimport { GenericInstanceFilter } from \"@itwin/core-common\";\nimport {\n ConcatenatedValue,\n createDefaultValueFormatter,\n ECClassHierarchyInspector,\n ECSchemaProvider,\n ECSqlBinding,\n ECSqlQueryDef,\n formatConcatenatedValue,\n InstanceKey,\n IPrimitiveValueFormatter,\n normalizeFullClassName,\n} from \"@itwin/presentation-shared\";\nimport { DefineHierarchyLevelProps, HierarchyDefinition, HierarchyNodesDefinition } from \"./HierarchyDefinition\";\nimport { RowsLimitExceededError } from \"./HierarchyErrors\";\nimport {\n HierarchyNode,\n NonGroupingHierarchyNode,\n ParentHierarchyNode,\n ParsedHierarchyNode,\n ProcessedCustomHierarchyNode,\n ProcessedGroupingHierarchyNode,\n ProcessedHierarchyNode,\n ProcessedInstanceHierarchyNode,\n} from \"./HierarchyNode\";\nimport { HierarchyNodeIdentifiersPath } from \"./HierarchyNodeIdentifier\";\nimport { InstancesNodeKey } from \"./HierarchyNodeKey\";\nimport { CachedNodesObservableEntry, ChildNodeObservablesCache, ParsedQueryNodesObservable } from \"./internal/ChildNodeObservablesCache\";\nimport {\n LOGGING_NAMESPACE as BASE_LOGGING_NAMESPACE,\n LOGGING_NAMESPACE_INTERNAL as BASE_LOGGING_NAMESPACE_INTERNAL,\n LOGGING_NAMESPACE_PERFORMANCE as BASE_LOGGING_NAMESPACE_PERFORMANCE,\n createNodeIdentifierForLogging,\n hasChildren,\n} from \"./internal/Common\";\nimport { eachValueFrom } from \"./internal/EachValueFrom\";\nimport { FilteringHierarchyDefinition } from \"./internal/FilteringHierarchyDefinition\";\nimport { doLog, log } from \"./internal/LoggingUtils\";\nimport { createDetermineChildrenOperator } from \"./internal/operators/DetermineChildren\";\nimport { createGroupingOperator } from \"./internal/operators/Grouping\";\nimport { createHideIfNoChildrenOperator } from \"./internal/operators/HideIfNoChildren\";\nimport { createHideNodesInHierarchyOperator } from \"./internal/operators/HideNodesInHierarchy\";\nimport { partition } from \"./internal/operators/Partition\";\nimport { reduceToMergeMapList } from \"./internal/operators/ReduceToMergeMap\";\nimport { shareReplayWithErrors } from \"./internal/operators/ShareReplayWithErrors\";\nimport { sortNodesByLabelOperator } from \"./internal/operators/Sorting\";\nimport { SubscriptionScheduler } from \"./internal/SubscriptionScheduler\";\nimport { readNodes } from \"./internal/TreeNodesReader\";\nimport { LimitingECSqlQueryExecutor } from \"./LimitingECSqlQueryExecutor\";\nimport { NodeSelectClauseColumnNames } from \"./NodeSelectQueryFactory\";\n\nconst LOGGING_NAMESPACE = `${BASE_LOGGING_NAMESPACE}.Provider`;\nconst LOGGING_NAMESPACE_INTERNAL = `${BASE_LOGGING_NAMESPACE_INTERNAL}.Provider`;\nconst LOGGING_NAMESPACE_PERFORMANCE = `${BASE_LOGGING_NAMESPACE_PERFORMANCE}.Provider`;\n\nconst DEFAULT_QUERY_CONCURRENCY = 10;\nconst DEFAULT_QUERY_CACHE_SIZE = 1;\n\n/**\n * Props for the `HierarchyProvider.getNodes` call.\n * @beta\n */\nexport interface GetHierarchyNodesProps {\n /** Parent node to get children for. Pass `undefined` to get root nodes. */\n parentNode: ParentHierarchyNode | undefined;\n\n /** Optional hierarchy level filter. Has no effect if `parentNode` is a `GroupingNode`. */\n instanceFilter?: GenericInstanceFilter;\n\n /**\n * Optional hierarchy level size limit override. This value is passed to `LimitingECSqlQueryExecutor` used\n * by this provider to override query rows limit per hierarchy level. If not provided, defaults to whatever\n * is used by the limiting query executor.\n *\n * Has no effect if `parentNode` is a `GroupingNode`.\n */\n hierarchyLevelSizeLimit?: number | \"unbounded\";\n\n /** When set to true ignores the cache and fetches the nodes again. */\n ignoreCache?: boolean;\n}\n\n/**\n * An interface for a hierarchy provider knows how to create child nodes for a given parent node.\n * @beta\n */\nexport interface HierarchyProvider {\n /** Gets nodes for the specified parent node. */\n getNodes(props: GetHierarchyNodesProps): AsyncIterableIterator<HierarchyNode>;\n\n /** Gets instance keys for the specified parent node. */\n getNodeInstanceKeys(props: Omit<GetHierarchyNodesProps, \"ignoreCache\">): AsyncIterableIterator<InstanceKey>;\n\n /** Notifies the provider that the underlying data source has changed and caches should be invalidated. */\n notifyDataSourceChanged(): void;\n\n /**\n * Overrides the property value formatter used by the hierarchy provider. Setting to `undefined`\n * resets the formatter to the result of `createDefaultValueFormatter` called with default parameters.\n */\n setFormatter(formatter: IPrimitiveValueFormatter | undefined): void;\n}\n\n/**\n * Defines the strings used by hierarchy provider.\n * @beta\n */\ninterface HierarchyProviderLocalizedStrings {\n /**\n * A string for \"Unspecified\". Used for labels of property grouping nodes\n * that group by an empty value.\n */\n unspecified: string;\n\n /**\n * A string for \"Other\". Used for label of a range property grouping node that\n * groups values which don't fit into any other range.\n */\n other: string;\n}\n\n/**\n * A path of hierarchy node identifiers for filtering the hierarchy with additional options.\n * @beta\n */\nexport type HierarchyFilteringPath = HierarchyNodeIdentifiersPath | { path: HierarchyNodeIdentifiersPath; options?: { autoExpand?: boolean } };\n\n/**\n * Props for `createHierarchyProvider`.\n * @beta\n */\ninterface HierarchyProviderProps {\n /**\n * An object that provides access to iModel's data and metadata.\n *\n * @see `ECSchemaProvider`\n * @see `LimitingECSqlQueryExecutor`\n * @see `ECClassHierarchyInspector`\n */\n imodelAccess: ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;\n\n /**\n * A function that returns a hierarchy definition, describing how the hierarchy that the provider should be create. The\n * function is called once during the provider's construction.\n */\n hierarchyDefinition: HierarchyDefinition;\n\n /** Maximum number of queries that the provider attempts to execute in parallel. Defaults to `10`. */\n queryConcurrency?: number;\n /**\n * The amount of queries whose results are stored in-memory for quick retrieval. Defaults to `1`,\n * which means only results of the last run query are cached.\n */\n queryCacheSize?: number;\n\n /**\n * A values formatter for formatting node labels. Defaults to the\n * result of `createDefaultValueFormatter` called with default parameters.\n */\n formatter?: IPrimitiveValueFormatter;\n\n /** A set of localized strings to use. Defaults to English strings. */\n localizedStrings?: Partial<HierarchyProviderLocalizedStrings>;\n\n /** Props for filtering the hierarchy. */\n filtering?: {\n /** A list of node identifiers from root to target node. */\n paths: HierarchyFilteringPath[];\n };\n}\n\n/**\n * Creates an instance of `HierarchyProvider` that creates a hierarchy based on given iModel and\n * a hierarchy definition, which defines each hierarchy level through ECSQL queries.\n *\n * @beta\n */\nexport function createHierarchyProvider(props: HierarchyProviderProps): HierarchyProvider {\n return new HierarchyProviderImpl(props);\n}\n\nclass HierarchyProviderImpl implements HierarchyProvider {\n private _imodelAccess: ECSchemaProvider & LimitingECSqlQueryExecutor & ECClassHierarchyInspector;\n private _valuesFormatter: IPrimitiveValueFormatter;\n private _localizedStrings: HierarchyProviderLocalizedStrings;\n private _queryScheduler: SubscriptionScheduler;\n private _nodesCache?: ChildNodeObservablesCache;\n\n /**\n * Hierarchy level definitions factory used by this provider.\n *\n * @note This does not necessarily match the `hierarchyDefinition` passed through props when constructing\n * the provider. For example, it may be a factory that decorates given `hierarchyDefinition` with filtering\n * features.\n */\n public readonly hierarchyDefinition: HierarchyDefinition;\n\n /**\n * A limiting ECSQL query executor used by this provider.\n * @see HierarchyProviderProps.queryExecutor\n */\n public get queryExecutor(): LimitingECSqlQueryExecutor {\n return this._imodelAccess;\n }\n\n public constructor(props: HierarchyProviderProps) {\n this._imodelAccess = props.imodelAccess;\n this.hierarchyDefinition = props.hierarchyDefinition;\n if (props.filtering) {\n const filteringDefinition = new FilteringHierarchyDefinition({\n classHierarchy: this._imodelAccess,\n source: this.hierarchyDefinition,\n nodeIdentifierPaths: props.filtering.paths,\n });\n this.hierarchyDefinition = filteringDefinition;\n }\n this._valuesFormatter = props?.formatter ?? createDefaultValueFormatter();\n this._localizedStrings = { other: \"Other\", unspecified: \"Not specified\", ...props?.localizedStrings };\n this._queryScheduler = new SubscriptionScheduler(props.queryConcurrency ?? DEFAULT_QUERY_CONCURRENCY);\n\n const queryCacheSize = props.queryCacheSize ?? DEFAULT_QUERY_CACHE_SIZE;\n if (queryCacheSize !== 0) {\n this._nodesCache = new ChildNodeObservablesCache({\n // we divide the size by 2, because each variation also counts as a query that we cache\n size: Math.ceil(queryCacheSize / 2),\n variationsCount: 1,\n });\n }\n }\n\n /**\n * Sets `HierarchyProvider` values formatter that formats nodes' labels. If provided `undefined`, then defaults to the\n * result of `createDefaultValueFormatter` called with default parameters.\n */\n public setFormatter(formatter: IPrimitiveValueFormatter | undefined) {\n this._valuesFormatter = formatter ?? createDefaultValueFormatter();\n }\n\n private onGroupingNodeCreated(groupingNode: ProcessedGroupingHierarchyNode, props: GetHierarchyNodesProps) {\n this._nodesCache?.set({ ...props, parentNode: groupingNode }, { observable: from(groupingNode.children), processingStatus: \"pre-processed\" });\n }\n\n private createParsedQueryNodesObservable(\n props: DefineHierarchyLevelProps & { hierarchyLevelSizeLimit?: number | \"unbounded\"; filteredInstanceKeys?: InstanceKey[] },\n ): ParsedQueryNodesObservable {\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n message: /* istanbul ignore next */ () => `Requesting hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,\n });\n // stream hierarchy level definitions\n const definitions = from(defer(async () => this.hierarchyDefinition.defineHierarchyLevel(props))).pipe(\n mergeAll(),\n finalize(() =>\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n message: /* istanbul ignore next */ () => `Received all hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n // pipe definitions to nodes and put \"share replay\" on it\n return definitions.pipe(\n mergeMap((def): ObservableInput<ParsedHierarchyNode> => {\n if (HierarchyNodesDefinition.isCustomNode(def)) {\n return of(def.node);\n }\n return this._queryScheduler.scheduleSubscription(\n of(def.query).pipe(\n map((query) => filterQueryByInstanceKeys(query, props.filteredInstanceKeys)),\n mergeMap((query) =>\n readNodes({ queryExecutor: this.queryExecutor, query, limit: props.hierarchyLevelSizeLimit, parser: this.hierarchyDefinition.parseNode }),\n ),\n ),\n );\n }),\n finalize(() =>\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n message: /* istanbul ignore next */ () => `Read all child nodes ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n shareReplayWithErrors(),\n );\n }\n\n private createInitializedNodesObservable(nodes: Observable<ParsedHierarchyNode>, parentNode: ParentHierarchyNode | undefined) {\n return nodes.pipe(\n // we're going to be mutating the nodes, but don't want to mutate the original one, so just clone it here once\n map((node) => ({ ...node })),\n // set parent node keys on the parsed node\n map((node) => Object.assign(node, { parentKeys: createParentNodeKeysList(parentNode) })),\n // format `ConcatenatedValue` labels into string labels\n mergeMap(async (node) => applyLabelsFormatting(node, this._imodelAccess, this._valuesFormatter)),\n // we have `ProcessedHierarchyNode` from here\n preProcessNodes(this.hierarchyDefinition),\n finalize(() =>\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n message: /* istanbul ignore next */ () => `Finished initializing child nodes for ${createNodeIdentifierForLogging(parentNode)}`,\n }),\n ),\n shareReplayWithErrors(),\n );\n }\n\n private createPreProcessedNodesObservable(\n queryNodesObservable: ParsedQueryNodesObservable,\n props: GetHierarchyNodesProps,\n ): Observable<ProcessedHierarchyNode> {\n return this.createInitializedNodesObservable(queryNodesObservable, props.parentNode).pipe(\n createHideIfNoChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n }).hasNodes),\n createHideNodesInHierarchyOperator(\n // note: for child nodes created because of hidden parent, we want to use parent's request props (instance filter, limit)\n (n) => this.getChildNodesObservables({ ...props, parentNode: n }).processedNodes,\n false,\n ),\n finalize(() =>\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n message: /* istanbul ignore next */ () => `Finished pre-processing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n }\n\n private createProcessedNodesObservable(\n preprocessedNodesObservable: Observable<ProcessedHierarchyNode>,\n props: GetHierarchyNodesProps,\n ): Observable<ProcessedHierarchyNode> {\n return preprocessedNodesObservable.pipe(\n createGroupingOperator(this._imodelAccess, props.parentNode, this._valuesFormatter, this._localizedStrings, (gn) =>\n this.onGroupingNodeCreated(gn, props),\n ),\n finalize(() =>\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n message: /* istanbul ignore next */ () => `Finished grouping child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n }\n\n private createFinalizedNodesObservable(\n processedNodesObservable: Observable<ProcessedHierarchyNode>,\n props: GetHierarchyNodesProps,\n ): Observable<HierarchyNode> {\n return processedNodesObservable.pipe(\n createDetermineChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n }).hasNodes),\n postProcessNodes(this.hierarchyDefinition),\n sortNodesByLabelOperator,\n map((n): HierarchyNode => {\n if (HierarchyNode.isCustom(n) || HierarchyNode.isInstancesNode(n)) {\n delete n.processingParams;\n }\n return Object.assign(n, {\n children: hasChildren(n),\n });\n }),\n finalize(() =>\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n message: /* istanbul ignore next */ () => `Finished finalizing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n }),\n ),\n );\n }\n\n private createHasNodesObservable(\n preprocessedNodesObservable: Observable<ProcessedHierarchyNode>,\n possiblyKnownChildrenObservable?: ParsedQueryNodesObservable,\n ): Observable<boolean> {\n const loggingCategory = `${LOGGING_NAMESPACE_INTERNAL}.HasNodes`;\n return concat((possiblyKnownChildrenObservable ?? EMPTY).pipe(filter((n) => hasChildren(n))), preprocessedNodesObservable).pipe(\n log({ category: loggingCategory, message: /* istanbul ignore next */ (n) => `Node before mapping to 'true': ${createNodeIdentifierForLogging(n)}` }),\n take(1),\n map(() => true),\n defaultIfEmpty(false),\n catchError((e: Error) => {\n doLog({ category: loggingCategory, message: /* istanbul ignore next */ () => `Error while determining children: ${e.message}` });\n if (e instanceof RowsLimitExceededError) {\n return of(true);\n }\n throw e;\n }),\n log({ category: loggingCategory, message: /* istanbul ignore next */ (r) => `Result: ${r}` }),\n );\n }\n\n private getCachedObservableEntry(props: GetHierarchyNodesProps): CachedNodesObservableEntry {\n const loggingCategory = `${LOGGING_NAMESPACE}.QueryResultsCache`;\n const { parentNode, ...restProps } = props;\n const cached = props.ignoreCache || !this._nodesCache ? undefined : this._nodesCache.get(props);\n if (cached) {\n // istanbul ignore next\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Found query nodes observable for ${createNodeIdentifierForLogging(parentNode)}`,\n });\n return cached;\n }\n\n // if we don't find an entry for a grouping node, we load its instances by getting a query and applying\n // a filter based on grouped instance keys\n let filteredInstanceKeys: InstanceKey[] | undefined;\n let parentNonGroupingNode: ParentHierarchyNode<NonGroupingHierarchyNode> | undefined;\n if (parentNode) {\n if (HierarchyNode.isGroupingNode(parentNode)) {\n parentNonGroupingNode = parentNode.nonGroupingAncestor;\n filteredInstanceKeys = parentNode.groupedInstanceKeys;\n } else {\n // not sure why type checker doesn't pick this up\n assert(HierarchyNode.isCustom(parentNode) || HierarchyNode.isInstancesNode(parentNode));\n parentNonGroupingNode = parentNode;\n }\n }\n\n const nonGroupingNodeChildrenRequestProps = {\n ...restProps,\n parentNode: parentNonGroupingNode,\n ...(filteredInstanceKeys ? { filteredInstanceKeys } : undefined),\n };\n const value = { observable: this.createParsedQueryNodesObservable(nonGroupingNodeChildrenRequestProps), processingStatus: \"none\" as const };\n this._nodesCache?.set(nonGroupingNodeChildrenRequestProps, value);\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Saved query nodes observable for ${createNodeIdentifierForLogging(parentNode)}`,\n });\n return value;\n }\n\n private getChildNodesObservables(props: GetHierarchyNodesProps & { hierarchyLevelSizeLimit?: number | \"unbounded\" }) {\n const entry = this.getCachedObservableEntry(props);\n switch (entry.processingStatus) {\n case \"none\": {\n const pre = this.createPreProcessedNodesObservable(entry.observable, props);\n const post = this.createProcessedNodesObservable(pre, props);\n return {\n processedNodes: post,\n hasNodes: this.createHasNodesObservable(pre, entry.observable),\n finalizedNodes: this.createFinalizedNodesObservable(post, props),\n };\n }\n case \"pre-processed\": {\n const post = this.createProcessedNodesObservable(entry.observable, props);\n return {\n processedNodes: post,\n hasNodes: this.createHasNodesObservable(entry.observable),\n finalizedNodes: this.createFinalizedNodesObservable(post, props),\n };\n }\n }\n }\n\n /**\n * Creates and runs a query based on provided props, then processes retrieved nodes and returns them.\n */\n public getNodes(props: GetHierarchyNodesProps): AsyncIterableIterator<HierarchyNode> {\n const loggingCategory = `${LOGGING_NAMESPACE}.GetNodes`;\n const timer = new StopWatch(undefined, true);\n let error: any;\n let nodesCount = 0;\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Requesting child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,\n });\n return eachValueFrom(\n this.getChildNodesObservables(props).finalizedNodes.pipe(\n tap(() => ++nodesCount),\n catchError((e) => {\n error = e;\n throw e;\n }),\n finalize(() => {\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () =>\n error\n ? `Error creating child nodes for ${createNodeIdentifierForLogging(props.parentNode)}: ${error instanceof Error ? error.message : error.toString()}`\n : `Returned ${nodesCount} child nodes for ${createNodeIdentifierForLogging(props.parentNode)} in ${timer.currentSeconds.toFixed(2)} s.`,\n });\n }),\n ),\n );\n }\n\n private getNodeInstanceKeysObs(props: Omit<GetHierarchyNodesProps, \"ignoreCache\">): Observable<InstanceKey> {\n const { parentNode, instanceFilter, hierarchyLevelSizeLimit = \"unbounded\" } = props;\n\n if (parentNode && HierarchyNode.isGroupingNode(parentNode)) {\n return from(parentNode.groupedInstanceKeys);\n }\n\n assert(!parentNode || HierarchyNode.isCustom(parentNode) || HierarchyNode.isInstancesNode(parentNode));\n\n // split the definitions based on whether they're for custom nodes or for instance nodes\n const [customDefs, instanceDefs] = partition(\n from(this.hierarchyDefinition.defineHierarchyLevel({ parentNode, instanceFilter })).pipe(mergeAll()),\n HierarchyNodesDefinition.isCustomNode,\n );\n\n // query instance keys and a flag whether they should be hidden\n const instanceKeys = instanceDefs.pipe(\n mergeMap((def) =>\n this._queryScheduler.scheduleSubscription(\n of(def.query).pipe(\n mergeMap(async (query) => {\n const ecsql = `\n SELECT\n ${NodeSelectClauseColumnNames.FullClassName},\n ${NodeSelectClauseColumnNames.ECInstanceId},\n ${NodeSelectClauseColumnNames.HideNodeInHierarchy}\n FROM (\n ${query.ecsql}\n )\n `;\n const reader = this.queryExecutor.createQueryReader({ ...query, ecsql }, { rowFormat: \"Indexes\", limit: hierarchyLevelSizeLimit });\n return from(reader).pipe(\n map((row) => ({\n key: {\n className: normalizeFullClassName(row[0]),\n id: row[1],\n },\n hide: !!row[2],\n })),\n );\n }),\n mergeAll(),\n ),\n ),\n ),\n );\n // split the instance keys observable based on whether they should be hidden or not\n const [visibleNodeInstanceKeys, hiddenNodeInstanceKeys] = partition(instanceKeys, ({ hide }) => !hide);\n\n // hidden items' handling:\n // - if a custom node is hidden, we'll want to retrieve instance keys of its children, otherwise we don't care about it,\n // - if an instance key is hidden, we want to create a merged node similar to what we do in `createHideNodesInHierarchyOperator`\n const hiddenParentNodes = merge(\n customDefs.pipe(\n mergeMap((def) => (def.node.processingParams?.hideInHierarchy ? this.createInitializedNodesObservable(of(def.node), parentNode) : EMPTY)),\n ),\n hiddenNodeInstanceKeys.pipe(\n // first merge all keys by class\n reduceToMergeMapList(\n ({ key }) => key.className,\n ({ key }) => key.id,\n ),\n // then, for each class, create a temp node\n mergeMap(\n (mergedMap): Array<ParentHierarchyNode & { key: InstancesNodeKey }> =>\n [...mergedMap.entries()].map(([className, ids]) => ({\n key: {\n type: \"instances\",\n instanceKeys: ids.map((id) => ({ className, id })),\n },\n parentKeys: [],\n label: \"\",\n })),\n ),\n ),\n );\n\n // merge visible instance keys from this level & the ones we get recursively requesting from deeper levels\n return merge(\n visibleNodeInstanceKeys.pipe(map(({ key }) => key)),\n hiddenParentNodes.pipe(mergeMap((hiddenNode) => this.getNodeInstanceKeysObs({ parentNode: hiddenNode }))),\n );\n }\n\n /**\n * Creates an iterator for all child hierarchy level instance keys, taking into account any hidden hierarchy levels\n * that there may be under the given parent node.\n */\n public getNodeInstanceKeys(props: Omit<GetHierarchyNodesProps, \"ignoreCache\">): AsyncIterableIterator<InstanceKey> {\n const loggingCategory = `${LOGGING_NAMESPACE}.GetNodeInstanceKeys`;\n const timer = new StopWatch(undefined, true);\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () => `Requesting keys for ${createNodeIdentifierForLogging(props.parentNode)}`,\n });\n let error: any;\n let keysCount = 0;\n return eachValueFrom(\n this.getNodeInstanceKeysObs(props).pipe(\n tap(() => ++keysCount),\n catchError((e) => {\n error = e;\n throw e;\n }),\n finalize(() => {\n doLog({\n category: loggingCategory,\n message: /* istanbul ignore next */ () =>\n error\n ? `Error creating node instance keys for ${createNodeIdentifierForLogging(props.parentNode)}: ${error instanceof Error ? error.message : error.toString()}`\n : `Returned ${keysCount} instance keys for ${createNodeIdentifierForLogging(props.parentNode)} in ${timer.currentSeconds.toFixed(2)} s.`,\n });\n }),\n ),\n );\n }\n\n /**\n * A function that should be called when the underlying data source, used by `HierarchyProviderProps.schemaProvider`,\n * `HierarchyProviderProps.queryExecutor` or `HierarchyProviderProps.hierarchyDefinition`, changes.\n *\n * Calling the function invalidates internal caches to make sure fresh data is retrieved on new requests.\n */\n public notifyDataSourceChanged() {\n doLog({\n category: `${LOGGING_NAMESPACE}.Events`,\n message: /* istanbul ignore next */ () => `Data source changed: clear query results cache`,\n });\n this._nodesCache?.clear();\n }\n}\n\nfunction preProcessNodes(hierarchyFactory: HierarchyDefinition) {\n return hierarchyFactory.preProcessNode\n ? processNodes(hierarchyFactory.preProcessNode.bind(hierarchyFactory))\n : (o: Observable<ProcessedCustomHierarchyNode | ProcessedInstanceHierarchyNode>) => o;\n}\n\nfunction postProcessNodes(hierarchyFactory: HierarchyDefinition) {\n return hierarchyFactory.postProcessNode\n ? processNodes(hierarchyFactory.postProcessNode.bind(hierarchyFactory))\n : (o: Observable<ProcessedHierarchyNode>) => o;\n}\n\nfunction processNodes<TNode>(processor: (node: TNode) => Promise<TNode | undefined>) {\n return (nodes: Observable<TNode>) =>\n nodes.pipe(\n mergeMap(processor),\n filter((n): n is TNode => !!n),\n );\n}\n\nasync function applyLabelsFormatting<TNode extends { label: string | ConcatenatedValue }>(\n node: TNode,\n schemaProvider: ECSchemaProvider,\n valueFormatter: IPrimitiveValueFormatter,\n): Promise<TNode & { label: string }> {\n return {\n ...node,\n label: await formatConcatenatedValue({\n value: node.label,\n schemaProvider,\n valueFormatter,\n }),\n };\n}\n\nfunction createParentNodeKeysList(parentNode: ParentHierarchyNode | undefined) {\n if (!parentNode) {\n return [];\n }\n return [...parentNode.parentKeys, parentNode.key];\n}\n\nfunction filterQueryByInstanceKeys(query: ECSqlQueryDef, filteredInstanceKeys: InstanceKey[] | undefined): ECSqlQueryDef {\n if (!filteredInstanceKeys || !filteredInstanceKeys.length) {\n return query;\n }\n const MAX_ALLOWED_BINDINGS = 1000;\n // istanbul ignore else\n if (filteredInstanceKeys.length < MAX_ALLOWED_BINDINGS) {\n return {\n ...query,\n ecsql: `\n SELECT *\n FROM (${query.ecsql}) q\n WHERE q.ECInstanceId IN (${filteredInstanceKeys.map(() => \"?\").join(\",\")})\n `,\n bindings: [...(query.bindings ?? []), ...filteredInstanceKeys.map((k): ECSqlBinding => ({ type: \"id\", value: k.id }))],\n };\n }\n // istanbul ignore next\n return {\n ...query,\n ecsql: `\n SELECT *\n FROM (${query.ecsql}) q\n WHERE InVirtualSet(?, q.ECInstanceId)\n `,\n bindings: [...(query.bindings ?? []), { type: \"idset\", value: filteredInstanceKeys.map((k) => k.id) }],\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LimitingECSqlQueryExecutor.d.ts","sourceRoot":"","sources":["../../../src/hierarchies/LimitingECSqlQueryExecutor.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,aAAa,EACb,kBAAkB,EAClB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"LimitingECSqlQueryExecutor.d.ts","sourceRoot":"","sources":["../../../src/hierarchies/LimitingECSqlQueryExecutor.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,aAAa,EACb,kBAAkB,EAClB,uBAAuB,EAGxB,MAAM,4BAA4B,CAAC;AAKpC;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,iBAAiB,CACf,KAAK,EAAE,aAAa,EACpB,MAAM,CAAC,EAAE,uBAAuB,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAA;KAAE,GAClE,UAAU,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAC,CAAC;CACxD;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,GAAG,WAAW,GAAG,0BAA0B,CA4CjJ"}
|
|
@@ -2,10 +2,10 @@
|
|
|
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 { StopWatch } from "@itwin/core-bentley";
|
|
6
|
-
import { createMainThreadReleaseOnTimePassedHandler, } from "@itwin/presentation-shared";
|
|
5
|
+
import { Guid, StopWatch } from "@itwin/core-bentley";
|
|
6
|
+
import { createMainThreadReleaseOnTimePassedHandler, trimWhitespace, } from "@itwin/presentation-shared";
|
|
7
7
|
import { RowsLimitExceededError } from "./HierarchyErrors";
|
|
8
|
-
import { LOGGING_NAMESPACE as
|
|
8
|
+
import { LOGGING_NAMESPACE as BASE_LOGGING_NAMESPACE, LOGGING_NAMESPACE_PERFORMANCE as BASE_LOGGING_NAMESPACE_PERFORMANCE } from "./internal/Common";
|
|
9
9
|
import { doLog } from "./internal/LoggingUtils";
|
|
10
10
|
/**
|
|
11
11
|
* Creates an `LimitingECSqlQueryExecutor` that throws `RowsLimitExceededError` if the query exceeds given amount of rows.
|
|
@@ -16,7 +16,7 @@ export function createLimitingECSqlQueryExecutor(baseExecutor, defaultLimit) {
|
|
|
16
16
|
async *createQueryReader(query, config) {
|
|
17
17
|
const { limit: configLimit, ...restConfig } = config ?? {};
|
|
18
18
|
const limit = configLimit ?? defaultLimit;
|
|
19
|
-
const
|
|
19
|
+
const queryLogger = createQueryLogger(query);
|
|
20
20
|
const releaseMainThread = createMainThreadReleaseOnTimePassedHandler();
|
|
21
21
|
// handle "unbounded" case without a buffer
|
|
22
22
|
const reader = baseExecutor.createQueryReader({ ...query, ecsql: addLimit(query.ecsql, limit) }, restConfig);
|
|
@@ -24,12 +24,12 @@ export function createLimitingECSqlQueryExecutor(baseExecutor, defaultLimit) {
|
|
|
24
24
|
try {
|
|
25
25
|
for await (const row of reader) {
|
|
26
26
|
await releaseMainThread();
|
|
27
|
-
|
|
27
|
+
queryLogger.onStep();
|
|
28
28
|
yield row;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
finally {
|
|
32
|
-
|
|
32
|
+
queryLogger.onComplete();
|
|
33
33
|
}
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
@@ -38,7 +38,7 @@ export function createLimitingECSqlQueryExecutor(baseExecutor, defaultLimit) {
|
|
|
38
38
|
try {
|
|
39
39
|
for await (const row of reader) {
|
|
40
40
|
await releaseMainThread();
|
|
41
|
-
|
|
41
|
+
queryLogger.onStep();
|
|
42
42
|
buffer.push(row);
|
|
43
43
|
if (buffer.length > limit) {
|
|
44
44
|
throw new RowsLimitExceededError(limit);
|
|
@@ -46,7 +46,7 @@ export function createLimitingECSqlQueryExecutor(baseExecutor, defaultLimit) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
finally {
|
|
49
|
-
|
|
49
|
+
queryLogger.onComplete();
|
|
50
50
|
}
|
|
51
51
|
for (const row of buffer) {
|
|
52
52
|
await releaseMainThread();
|
|
@@ -65,8 +65,14 @@ function addLimit(ecsql, limit) {
|
|
|
65
65
|
LIMIT ${limit + 1}
|
|
66
66
|
`;
|
|
67
67
|
}
|
|
68
|
-
const LOGGING_NAMESPACE = `${
|
|
69
|
-
|
|
68
|
+
const LOGGING_NAMESPACE = `${BASE_LOGGING_NAMESPACE}.Queries`;
|
|
69
|
+
const LOGGING_NAMESPACE_PERFORMANCE = `${BASE_LOGGING_NAMESPACE_PERFORMANCE}.Queries`;
|
|
70
|
+
function createQueryLogger(query, firstStepWarningThreshold = 3000, allRowsWarningThreshold = 5000) {
|
|
71
|
+
const queryId = Guid.createValue();
|
|
72
|
+
doLog({
|
|
73
|
+
category: LOGGING_NAMESPACE,
|
|
74
|
+
message: /* istanbul ignore next */ () => `Executing query [${queryId}]: ${createQueryLogMessage(query)}`,
|
|
75
|
+
});
|
|
70
76
|
let firstStep = true;
|
|
71
77
|
let rowsCount = 0;
|
|
72
78
|
const timer = new StopWatch(undefined, true);
|
|
@@ -75,9 +81,9 @@ function createQueryPerformanceLogger(firstStepWarningThreshold = 3000, allRowsW
|
|
|
75
81
|
if (firstStep) {
|
|
76
82
|
// istanbul ignore next
|
|
77
83
|
doLog({
|
|
78
|
-
category:
|
|
84
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
79
85
|
severity: timer.current.milliseconds >= firstStepWarningThreshold ? "warning" : "trace",
|
|
80
|
-
message: () => `First step took ${timer.currentSeconds} s.`,
|
|
86
|
+
message: () => `[${queryId}] First step took ${timer.currentSeconds} s.`,
|
|
81
87
|
});
|
|
82
88
|
firstStep = false;
|
|
83
89
|
}
|
|
@@ -86,11 +92,26 @@ function createQueryPerformanceLogger(firstStepWarningThreshold = 3000, allRowsW
|
|
|
86
92
|
onComplete() {
|
|
87
93
|
// istanbul ignore next
|
|
88
94
|
doLog({
|
|
89
|
-
category:
|
|
95
|
+
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
90
96
|
severity: timer.current.milliseconds >= allRowsWarningThreshold ? "warning" : "trace",
|
|
91
|
-
message: () => `Query took ${timer.currentSeconds} s. for ${rowsCount} rows.`,
|
|
97
|
+
message: () => `[${queryId}] Query took ${timer.currentSeconds} s. for ${rowsCount} rows.`,
|
|
92
98
|
});
|
|
93
99
|
},
|
|
94
100
|
};
|
|
95
101
|
}
|
|
102
|
+
// istanbul ignore next
|
|
103
|
+
function createQueryLogMessage(query) {
|
|
104
|
+
const ctes = query.ctes?.map((cte) => ` ${trimWhitespace(cte)}`).join(", \n");
|
|
105
|
+
const bindings = query.bindings?.map((b) => JSON.stringify(b.value)).join(", ");
|
|
106
|
+
let output = "{\n";
|
|
107
|
+
if (ctes) {
|
|
108
|
+
output += ` ctes: [ \n${ctes} \n], \n`;
|
|
109
|
+
}
|
|
110
|
+
output += ` ecsql: ${trimWhitespace(query.ecsql)}, \n`;
|
|
111
|
+
if (bindings) {
|
|
112
|
+
output += ` bindings: [${bindings}], \n`;
|
|
113
|
+
}
|
|
114
|
+
output += "}";
|
|
115
|
+
return output;
|
|
116
|
+
}
|
|
96
117
|
//# sourceMappingURL=LimitingECSqlQueryExecutor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LimitingECSqlQueryExecutor.js","sourceRoot":"","sources":["../../../src/hierarchies/LimitingECSqlQueryExecutor.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"LimitingECSqlQueryExecutor.js","sourceRoot":"","sources":["../../../src/hierarchies/LimitingECSqlQueryExecutor.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, StopWatch } from \"@itwin/core-bentley\";\nimport {\n createMainThreadReleaseOnTimePassedHandler,\n ECSqlQueryDef,\n ECSqlQueryExecutor,\n ECSqlQueryReaderOptions,\n ECSqlQueryRow,\n trimWhitespace,\n} from \"@itwin/presentation-shared\";\nimport { RowsLimitExceededError } from \"./HierarchyErrors\";\nimport { LOGGING_NAMESPACE as BASE_LOGGING_NAMESPACE, LOGGING_NAMESPACE_PERFORMANCE as BASE_LOGGING_NAMESPACE_PERFORMANCE } from \"./internal/Common\";\nimport { doLog } from \"./internal/LoggingUtils\";\n\n/**\n * An interface for something that knows how to create a limiting ECSQL query reader.\n * @beta\n */\nexport interface LimitingECSqlQueryExecutor {\n /**\n * Creates a query reader for given query, but makes sure it doesn't return more than the configured\n * limit of rows.\n * @throws `RowsLimitExceededError` when the query returns more than configured limit of rows.\n */\n createQueryReader(\n query: ECSqlQueryDef,\n config?: ECSqlQueryReaderOptions & { limit?: number | \"unbounded\" },\n ): ReturnType<ECSqlQueryExecutor[\"createQueryReader\"]>;\n}\n\n/**\n * Creates an `LimitingECSqlQueryExecutor` that throws `RowsLimitExceededError` if the query exceeds given amount of rows.\n * @beta\n */\nexport function createLimitingECSqlQueryExecutor(baseExecutor: ECSqlQueryExecutor, defaultLimit: number | \"unbounded\"): LimitingECSqlQueryExecutor {\n return {\n async *createQueryReader(query: ECSqlQueryDef, config?: ECSqlQueryReaderOptions & { limit?: number | \"unbounded\" }) {\n const { limit: configLimit, ...restConfig } = config ?? {};\n const limit = configLimit ?? defaultLimit;\n const queryLogger = createQueryLogger(query);\n const releaseMainThread = createMainThreadReleaseOnTimePassedHandler();\n\n // handle \"unbounded\" case without a buffer\n const reader = baseExecutor.createQueryReader({ ...query, ecsql: addLimit(query.ecsql, limit) }, restConfig);\n if (limit === \"unbounded\") {\n try {\n for await (const row of reader) {\n await releaseMainThread();\n queryLogger.onStep();\n yield row;\n }\n } finally {\n queryLogger.onComplete();\n }\n return;\n }\n\n // avoid streaming until we know the number of rows is okay\n const buffer: ECSqlQueryRow[] = [];\n try {\n for await (const row of reader) {\n await releaseMainThread();\n queryLogger.onStep();\n buffer.push(row);\n if (buffer.length > limit) {\n throw new RowsLimitExceededError(limit);\n }\n }\n } finally {\n queryLogger.onComplete();\n }\n\n for (const row of buffer) {\n await releaseMainThread();\n yield row;\n }\n },\n };\n}\n\nfunction addLimit(ecsql: string, limit: number | \"unbounded\") {\n if (limit === \"unbounded\") {\n return ecsql;\n }\n return `\n SELECT *\n FROM (${ecsql})\n LIMIT ${limit + 1}\n `;\n}\n\nconst LOGGING_NAMESPACE = `${BASE_LOGGING_NAMESPACE}.Queries`;\nconst LOGGING_NAMESPACE_PERFORMANCE = `${BASE_LOGGING_NAMESPACE_PERFORMANCE}.Queries`;\nfunction createQueryLogger(query: ECSqlQueryDef, firstStepWarningThreshold = 3000, allRowsWarningThreshold = 5000) {\n const queryId = Guid.createValue();\n doLog({\n category: LOGGING_NAMESPACE,\n message: /* istanbul ignore next */ () => `Executing query [${queryId}]: ${createQueryLogMessage(query)}`,\n });\n\n let firstStep = true;\n let rowsCount = 0;\n const timer = new StopWatch(undefined, true);\n return {\n onStep() {\n if (firstStep) {\n // istanbul ignore next\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n severity: timer.current.milliseconds >= firstStepWarningThreshold ? \"warning\" : \"trace\",\n message: () => `[${queryId}] First step took ${timer.currentSeconds} s.`,\n });\n firstStep = false;\n }\n ++rowsCount;\n },\n onComplete() {\n // istanbul ignore next\n doLog({\n category: LOGGING_NAMESPACE_PERFORMANCE,\n severity: timer.current.milliseconds >= allRowsWarningThreshold ? \"warning\" : \"trace\",\n message: () => `[${queryId}] Query took ${timer.currentSeconds} s. for ${rowsCount} rows.`,\n });\n },\n };\n}\n\n// istanbul ignore next\nfunction createQueryLogMessage(query: ECSqlQueryDef): string {\n const ctes = query.ctes?.map((cte) => ` ${trimWhitespace(cte)}`).join(\", \\n\");\n const bindings = query.bindings?.map((b) => JSON.stringify(b.value)).join(\", \");\n let output = \"{\\n\";\n if (ctes) {\n output += ` ctes: [ \\n${ctes} \\n], \\n`;\n }\n output += ` ecsql: ${trimWhitespace(query.ecsql)}, \\n`;\n if (bindings) {\n output += ` bindings: [${bindings}], \\n`;\n }\n output += \"}\";\n return output;\n}\n"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Id64String } from "@itwin/core-bentley";
|
|
2
2
|
import { GenericInstanceFilter } from "@itwin/core-common";
|
|
3
3
|
import { ECClassHierarchyInspector, ECSchemaProvider } from "@itwin/presentation-shared";
|
|
4
|
+
import { HierarchyNodeAutoExpandProp } from "./HierarchyNode";
|
|
4
5
|
/**
|
|
5
6
|
* Column names of the SELECT clause created by `NodeSelectClauseFactory`. Order of the names matches the order of columns
|
|
6
7
|
* created by the factory.
|
|
@@ -105,7 +106,7 @@ type ECSqlSelectClauseLabelGroupingParams = boolean | ECSqlValueSelector | ECSql
|
|
|
105
106
|
interface ECSqlSelectClauseGroupingParamsBase {
|
|
106
107
|
hideIfNoSiblings?: boolean | ECSqlValueSelector;
|
|
107
108
|
hideIfOneGroupedNode?: boolean | ECSqlValueSelector;
|
|
108
|
-
autoExpand?:
|
|
109
|
+
autoExpand?: HierarchyNodeAutoExpandProp | ECSqlValueSelector;
|
|
109
110
|
}
|
|
110
111
|
/**
|
|
111
112
|
* A data structure for defining properties grouping.
|
|
@@ -193,7 +194,18 @@ interface ECSqlSelectClauseBaseClassGroupingParams extends ECSqlSelectClauseGrou
|
|
|
193
194
|
export interface NodesQueryClauseFactory {
|
|
194
195
|
/** Create a SELECT clause in a format understood by nodes query parser used by `HierarchyProvider`. */
|
|
195
196
|
createSelectClause(props: NodeSelectClauseProps): Promise<string>;
|
|
196
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* Creates the necessary ECSQL snippets to create an instance filter described by the given `GenericInstanceFilter` argument.
|
|
199
|
+
* - `from` is set to either the `contentClass.fullName` or one of `filter.propertyClassNames`, depending on which is more specific.
|
|
200
|
+
* - `joins` is set to a number of `JOIN` clauses required to join all relationships described by `filter.relatedInstances`.
|
|
201
|
+
* - `where` is set to a `WHERE` clause (without the `WHERE` keyword) that filters instances by classes on
|
|
202
|
+
* `filter.filterClassNames` and by properties as described by `filter.rules`.
|
|
203
|
+
*
|
|
204
|
+
* Special cases:
|
|
205
|
+
* - If `filter` is `undefined`, `joins` and `where` are set to empty strings and `from` is set to `contentClass.fullName`.
|
|
206
|
+
* - If the provided content class doesn't intersect with the property class in provided filter, a special result
|
|
207
|
+
* is returned to make sure the resulting query is valid and doesn't return anything.
|
|
208
|
+
*/
|
|
197
209
|
createFilterClauses(props: {
|
|
198
210
|
contentClass: {
|
|
199
211
|
fullName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeSelectQueryFactory.d.ts","sourceRoot":"","sources":["../../../src/hierarchies/NodeSelectQueryFactory.ts"],"names":[],"mappings":"AAKA,OAAO,EAAU,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACL,qBAAqB,EAOtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAM,yBAAyB,EAAE,gBAAgB,EAAuD,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"NodeSelectQueryFactory.d.ts","sourceRoot":"","sources":["../../../src/hierarchies/NodeSelectQueryFactory.ts"],"names":[],"mappings":"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"}
|
|
@@ -73,14 +73,14 @@ class NodeSelectQueryFactory {
|
|
|
73
73
|
`;
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
|
-
* Creates the necessary ECSQL snippets to create an instance filter described by the `
|
|
77
|
-
* - `from` is set to either the `contentClass.fullName` or `
|
|
78
|
-
* - `joins` is set to a number of `JOIN` clauses required to join all relationships described by `
|
|
76
|
+
* Creates the necessary ECSQL snippets to create an instance filter described by the `filter` argument.
|
|
77
|
+
* - `from` is set to either the `contentClass.fullName` or one of `filter.propertyClassNames`, depending on which is more specific.
|
|
78
|
+
* - `joins` is set to a number of `JOIN` clauses required to join all relationships described by `filter.relatedInstances`.
|
|
79
79
|
* - `where` is set to a `WHERE` clause (without the `WHERE` keyword) that filters instances by classes on
|
|
80
|
-
* `
|
|
80
|
+
* `filter.filterClassNames` and by properties as described by `filter.rules`.
|
|
81
81
|
*
|
|
82
82
|
* Special cases:
|
|
83
|
-
* - If `
|
|
83
|
+
* - If `filter` is `undefined`, `joins` and `where` are set to empty strings and `from` is set to `contentClass.fullName`.
|
|
84
84
|
* - If the provided content class doesn't intersect with the property class in provided filter, a special result
|
|
85
85
|
* is returned to make sure the resulting query is valid and doesn't return anything.
|
|
86
86
|
*/
|