Skip to content
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"
}
20 changes: 17 additions & 3 deletions core/common/src/ConcurrentQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
/** @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";

const loggerCategory = "core-common.QueryBinder";

Comment thread
anmolshres98 marked this conversation as resolved.
Outdated
/**
* Specifies the format of the rows returned by the `query` and `restartQuery` methods of
* [IModelConnection]($frontend), [IModelDb]($backend), and [ECDb]($backend).
Expand Down Expand Up @@ -478,15 +480,27 @@ 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(loggerCategory, `QueryBinder.bindIdSet: skipped ${skipped} entries that are not valid Id64Strings`);

Object.defineProperty(this._args, name, {
enumerable: true, value: {
type: QueryParamType.IdSet,
value: CompressedId64Set.sortAndCompress(OrderedId64Iterable.uniqueIterator(val)),
value: CompressedId64Set.sortAndCompress(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