Skip to content
Open
1 change: 1 addition & 0 deletions common/api/core-common.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,7 @@ export enum CommonLoggerCategory {
Annotations = "core-common.Annotations",
ElementProps = "core-common.ElementProps",
Geometry = "core-common.Geometry",
QueryBinder = "core-common.QueryBinder",
RpcInterfaceBackend = "core-backend.RpcInterface",
RpcInterfaceFrontend = "core-frontend.RpcInterface"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@itwin/core-common",
"comment": "Fixed QueryBinder.bindIdSet throwing on entries that are not valid Id64Strings; such entries are now skipped with a warning, matching ECSqlStatement.bindIdSet.",
"type": "none"
}
],
"packageName": "@itwin/core-common"
}
2 changes: 2 additions & 0 deletions core/common/src/CommonLoggerCategory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export enum CommonLoggerCategory {
ElementProps = "core-common.ElementProps",
/** The logger category used by common classes relating to Geometry. */
Geometry = "core-common.Geometry",
/** The logger category used by [QueryBinder]($common). */
QueryBinder = "core-common.QueryBinder",
Comment thread
anmolshres98 marked this conversation as resolved.
Outdated
/** The logger category used by the portions of the RpcInterface framework that run on the backend. */
RpcInterfaceBackend = "core-backend.RpcInterface",
/** The logger category used by the portions of the RpcInterface framework that run on the frontend. */
Expand Down
20 changes: 17 additions & 3 deletions core/common/src/ConcurrentQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
/** @packageDocumentation
* @module iModels
*/
import { BentleyError, CompressedId64Set, DbResult, Id64, Id64String, OrderedId64Iterable } from "@itwin/core-bentley";
import { BentleyError, CompressedId64Set, DbResult, Id64, Id64String, Logger, OrderedId64Iterable } from "@itwin/core-bentley";
import { LowAndHighXYZ, Point2d, Point3d, Range3d } from "@itwin/core-geometry";
import { Base64 } from "js-base64";
import { CommonLoggerCategory } from "./CommonLoggerCategory";

/**
* Specifies the format of the rows returned by the `query` and `restartQuery` methods of
Expand Down Expand Up @@ -478,15 +479,28 @@ export class QueryBinder {
* @param indexOrName Specify parameter index or its name used in ECSQL statement.
* @param val @type OrderedId64Iterable value to bind to ECSQL statement.
* @returns @type QueryBinder to allow fluent interface.
* @note Entries that are not valid [Id64String]($bentley)s are skipped with a logged warning.
*/
public bindIdSet(indexOrName: string | number, val: OrderedId64Iterable) {
this.verify(indexOrName);
const name = String(indexOrName);
OrderedId64Iterable.uniqueIterator(val);
const ids: Id64String[] = [];
let skipped = 0;
for (const id of val) {
if (typeof id === "string" && Id64.isValidId64(id))
ids.push(id);
else
skipped++;
}
Comment thread
anmolshres98 marked this conversation as resolved.
Comment thread
anmolshres98 marked this conversation as resolved.

if (skipped > 0)
Logger.logWarning(CommonLoggerCategory.QueryBinder, `QueryBinder.bindIdSet: skipped ${skipped} entries that are not valid Id64Strings`);

Comment thread
anmolshres98 marked this conversation as resolved.
Outdated
OrderedId64Iterable.sortArray(ids);
Object.defineProperty(this._args, name, {
enumerable: true, value: {
type: QueryParamType.IdSet,
value: CompressedId64Set.sortAndCompress(OrderedId64Iterable.uniqueIterator(val)),
value: CompressedId64Set.compressArray(ids),
},
Comment thread
anmolshres98 marked this conversation as resolved.
});
return this;
Expand Down
22 changes: 22 additions & 0 deletions core/common/src/test/ConcurrentQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,28 @@ describe("QueryBinder", () => {
);
});

it("bindIdSet skips entries that are not valid Id64Strings", () => {
const queryBinder = new QueryBinder();
queryBinder.bindIdSet("idSetValue", ["0x22bd8", undefined, null, "0", "50", "0x22bd9"] as unknown as Id64String[]);
assert.deepEqual(queryBinder.serialize(), {
idSetValue: {
type: QueryParamType.IdSet,
value: "+22BD8+1",
},
});
});

it("bindIdSet sorts and deduplicates ids", () => {
const queryBinder = new QueryBinder();
queryBinder.bindIdSet("idSetValue", ["0x22bd9", "0x22bd8", "0x22bd8"]);
assert.deepEqual(queryBinder.serialize(), {
idSetValue: {
type: QueryParamType.IdSet,
value: "+22BD8+1",
},
});
});

it("allows bulk binding", () => {
assert.deepEqual(QueryBinder.from(undefined), new QueryBinder());

Expand Down
Loading