From d6329a7f3b898234180b39b3e5e2aa2c235d9f3b Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Mon, 7 Oct 2024 19:33:37 +0530 Subject: [PATCH 01/12] Tests added for IdSet Virtual Table --- core/backend/src/test/ecdb/ECSqlQuery.test.ts | 19 ++++++ .../backend/src/test/ecdb/ECSqlReader.test.ts | 20 +++++++ .../src/test/ecdb/ECSqlStatement.test.ts | 59 +++++++++++++++++++ 3 files changed, 98 insertions(+) diff --git a/core/backend/src/test/ecdb/ECSqlQuery.test.ts b/core/backend/src/test/ecdb/ECSqlQuery.test.ts index 8b78162dbc2d..c5d26d4bad19 100644 --- a/core/backend/src/test/ecdb/ECSqlQuery.test.ts +++ b/core/backend/src/test/ecdb/ECSqlQuery.test.ts @@ -451,6 +451,25 @@ describe("ECSql Query", () => { assert.isTrue(reader.stats.backendCpuTime > 0); assert.isTrue(reader.stats.backendMemUsed > 100); }); + it("concurrent query use idset in IdSet virtual table", async () => { + const ids: string[] = []; + for await (const row of imodel1.createQueryReader("SELECT ECInstanceId FROM BisCore.Element LIMIT 23")) { + ids.push(row[0]); + } + const reader = imodel1.createQueryReader("SELECT * FROM BisCore.element, ECVLib.IdSet(?) WHERE id = ECInstanceId", QueryBinder.from([ids])); + let props = await reader.getMetaData(); + assert.equal(props.length, 12); // 11 for BisCore.element and 1 for IdSet + let rows = 0; + while (await reader.step()) { + rows++; + } + assert.equal(rows, 23); + props = await reader.getMetaData(); + assert.equal(props.length, 12); // 11 for BisCore.element and 1 for IdSet + assert.equal(reader.stats.backendRowsReturned, 23); + assert.isTrue(reader.stats.backendCpuTime > 0); + assert.isTrue(reader.stats.backendMemUsed > 100); + }); it("concurrent query get meta data", async () => { const reader = imodel1.createQueryReader("SELECT * FROM BisCore.element"); let props = await reader.getMetaData(); diff --git a/core/backend/src/test/ecdb/ECSqlReader.test.ts b/core/backend/src/test/ecdb/ECSqlReader.test.ts index 6e0f85ec6634..c8454ef90571 100644 --- a/core/backend/src/test/ecdb/ECSqlReader.test.ts +++ b/core/backend/src/test/ecdb/ECSqlReader.test.ts @@ -27,6 +27,26 @@ describe("ECSqlReader", (() => { describe("bind Id64 enumerable", async () => { const outDir = KnownTestLocations.outputDir; + it("ecsql reader simple", async () => { + await using(ECDbTestHelper.createECDb(outDir, "test.ecdb", + ` + + + + `), async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + ecdb.saveChanges(); + const params = new QueryBinder(); + params.bindIdSet(1, ["0x32"]); + const optionBuilder = new QueryOptionsBuilder(); + optionBuilder.setRowFormat(QueryRowFormat.UseJsPropertyNames); + reader = ecdb.createQueryReader("SELECT ECInstanceId, Name FROM meta.ECClassDef, ECVLib.IdSet(?) WHERE id = ECInstanceId", params, optionBuilder.getOptions()); + const rows = await reader.toArray(); + assert.equal(rows[0].id, "0x32"); + assert.equal(rows.length, 1); + }); + }); + it("ecsql reader simple", async () => { await using(ECDbTestHelper.createECDb(outDir, "test.ecdb", ` diff --git a/core/backend/src/test/ecdb/ECSqlStatement.test.ts b/core/backend/src/test/ecdb/ECSqlStatement.test.ts index 77f03065b8ad..e394fc4a7c4d 100644 --- a/core/backend/src/test/ecdb/ECSqlStatement.test.ts +++ b/core/backend/src/test/ecdb/ECSqlStatement.test.ts @@ -1841,6 +1841,65 @@ describe("ECSqlStatement", () => { }); }); + it.only("should bind IdSets to IdSet Virtual Table", async () => { + await using(ECDbTestHelper.createECDb(outDir, "bindids.ecdb"), async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const idNumbers: number[] = [4444, 4545, 1234, 6758, 1312]; + ecdb.withPreparedStatement("INSERT INTO ecdbf.ExternalFileInfo(ECInstanceId,Name) VALUES(?,?)", (stmt: ECSqlStatement) => { + idNumbers.forEach((idNum: number) => { + const expectedId = Id64.fromLocalAndBriefcaseIds(idNum, 0); + stmt.bindId(1, expectedId); + stmt.bindString(2, `${idNum}.txt`); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(r.id); + assert.equal(r.id!, expectedId); + ecdb.saveChanges(); + + ecdb.withStatement(`SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=${expectedId}`, (confstmt: ECSqlStatement) => { + assert.equal(confstmt.step(), DbResult.BE_SQLITE_ROW); + const row = confstmt.getRow(); + assert.equal(row.id, expectedId); + assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); + assert.equal(row.name, `${Id64.getLocalId(expectedId).toString()}.txt`); + }); + stmt.reset(); + stmt.clearBindings(); + }); + }); + + ecdb.withPreparedStatement("SELECT ECInstanceId, ECClassId, Name from ecdbf.ExternalFileInfo, ECVLib.IdSet(?) WHERE id = ECInstanceId", (stmt: ECSqlStatement) => { + let idSet: Id64String[] = []; + stmt.bindIdSet(1, idSet); + let result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_DONE); + stmt.reset(); + stmt.clearBindings(); + + idSet = [Id64.fromLocalAndBriefcaseIds(idNumbers[2], 0)]; + stmt.bindIdSet(1, idSet); + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_ROW); + let row = stmt.getRow(); + assert.equal(row.name, `${idNumbers[2]}.txt`); + stmt.reset(); + stmt.clearBindings(); + + idSet.push(idNumbers[0].toString()); + stmt.bindIdSet(1, idSet); + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_ROW); + row = stmt.getRow(); + assert.equal(row.name, `${idNumbers[2]}.txt`); + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_ROW); + row = stmt.getRow(); + assert.equal(row.name, `${idNumbers[0]}.txt`); + }); + }); + }); + /* This test doesn't do anything specific with the binder life time but just runs a few scenarios with and without statement cache to test that stuff works fine */ it("check ECSqlBinder life time", async () => { From fdea7a8c76a9e680f79d8d49b31312d3ab61e281 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Tue, 8 Oct 2024 19:18:55 +0530 Subject: [PATCH 02/12] only removed --- core/backend/src/test/ecdb/ECSqlStatement.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/backend/src/test/ecdb/ECSqlStatement.test.ts b/core/backend/src/test/ecdb/ECSqlStatement.test.ts index e394fc4a7c4d..e033a6cb3c26 100644 --- a/core/backend/src/test/ecdb/ECSqlStatement.test.ts +++ b/core/backend/src/test/ecdb/ECSqlStatement.test.ts @@ -1841,7 +1841,7 @@ describe("ECSqlStatement", () => { }); }); - it.only("should bind IdSets to IdSet Virtual Table", async () => { + it("should bind IdSets to IdSet Virtual Table", async () => { await using(ECDbTestHelper.createECDb(outDir, "bindids.ecdb"), async (ecdb: ECDb) => { assert.isTrue(ecdb.isOpen); From ffcf8518863d7c25f04b180d43b32ff54fb79866 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:30:10 +0530 Subject: [PATCH 03/12] More tests added --- core/backend/src/test/ecdb/ECSqlQuery.test.ts | 46 +++++++++++++- .../src/test/ecdb/ECSqlStatement.test.ts | 61 ++++++++++++++++++- 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/core/backend/src/test/ecdb/ECSqlQuery.test.ts b/core/backend/src/test/ecdb/ECSqlQuery.test.ts index d9b3cb514705..5816563120fb 100644 --- a/core/backend/src/test/ecdb/ECSqlQuery.test.ts +++ b/core/backend/src/test/ecdb/ECSqlQuery.test.ts @@ -678,7 +678,7 @@ describe("ECSql Query", () => { assert.isTrue(reader.stats.backendCpuTime > 0); assert.isTrue(reader.stats.backendMemUsed > 100); }); - it("concurrent query use idset in IdSet virtual table", async () => { + it("concurrent query bind idset in IdSet virtual table", async () => { const ids: string[] = []; for await (const row of imodel1.createQueryReader("SELECT ECInstanceId FROM BisCore.Element LIMIT 23")) { ids.push(row[0]); @@ -697,6 +697,50 @@ describe("ECSql Query", () => { assert.isTrue(reader.stats.backendCpuTime > 0); assert.isTrue(reader.stats.backendMemUsed > 100); }); + it("concurrent query bind single id in IdSet virtual table", async () => { + let ids: string = ""; + for await (const row of imodel1.createQueryReader("SELECT ECInstanceId FROM BisCore.Element LIMIT 23")) { + ids = row[0]; // getting only the first id + break; + } + const reader = imodel1.createQueryReader("SELECT * FROM BisCore.element, ECVLib.IdSet(?) WHERE id = ECInstanceId", QueryBinder.from([ids])); + let props = await reader.getMetaData(); + assert.equal(props.length, 12); // 11 for BisCore.element and 1 for IdSet + let rows = 0; // backend will fail to bind so no rows will be returned + while (await reader.step()) { + rows++; + } + assert.equal(rows, 0); + props = await reader.getMetaData(); + assert.equal(props.length, 12); // 11 for BisCore.element and 1 for IdSet + assert.equal(reader.stats.backendRowsReturned, 0); + assert.isTrue(reader.stats.backendCpuTime > 0); + }); + it("concurrent query bind idset with invalid values in IdSet virtual table", async () => { + const ids: string[] = ["0x1","ABC","YZ"]; + + const reader = imodel1.createQueryReader("SELECT * FROM BisCore.element, ECVLib.IdSet(?) WHERE id = ECInstanceId", QueryBinder.from([ids])); + let props = await reader.getMetaData(); + assert.equal(props.length, 12); // 11 for BisCore.element and 1 for IdSet + let rows = 0; // backend will bind successfully but some of the values are not valid for IdSet VT so those values will be ignored + while (await reader.step()) { + rows++; + } + assert.equal(rows, 1); + props = await reader.getMetaData(); + assert.equal(props.length, 12); // 11 for BisCore.element and 1 for IdSet + assert.equal(reader.stats.backendRowsReturned, 1); + assert.isTrue(reader.stats.backendCpuTime > 0); + }); + it.only("concurrent query bind idset with invalid values in IdSet virtual table", async () => { + const ids: string[] = ["ABC", "0x1","YZ"]; // as first value is not an Id so QueryBinder.from will throw error of "unsupported type" + + try{ + const reader = imodel1.createQueryReader("SELECT * FROM BisCore.element, ECVLib.IdSet(?) WHERE id = ECInstanceId", QueryBinder.from([ids])); + }catch(err: any){ + assert.equal(err.message, "unsupported type"); + } + }); it("concurrent query get meta data", async () => { const reader = imodel1.createQueryReader("SELECT * FROM BisCore.element"); let props = await reader.getMetaData(); diff --git a/core/backend/src/test/ecdb/ECSqlStatement.test.ts b/core/backend/src/test/ecdb/ECSqlStatement.test.ts index 92451e82d3a5..542efab4fc93 100644 --- a/core/backend/src/test/ecdb/ECSqlStatement.test.ts +++ b/core/backend/src/test/ecdb/ECSqlStatement.test.ts @@ -2,7 +2,7 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; +import { assert, expect } from "chai"; import { DbResult, Guid, GuidString, Id64, Id64String, using } from "@itwin/core-bentley"; import { NavigationValue, QueryBinder, QueryOptions, QueryOptionsBuilder, QueryRowFormat } from "@itwin/core-common"; import { Point2d, Point3d, Range3d, XAndY, XYAndZ } from "@itwin/core-geometry"; @@ -12,6 +12,7 @@ import { KnownTestLocations } from "../KnownTestLocations"; import { SequentialLogMatcher } from "../SequentialLogMatcher"; import { ECDbTestHelper } from "./ECDbTestHelper"; import { ConcurrentQuery } from "../../ConcurrentQuery"; +import { Exception } from "@opentelemetry/api"; /* eslint-disable @typescript-eslint/naming-convention */ const selectSingleRow = new QueryOptionsBuilder().setLimit({ count: 1, offset: -1 }).setRowFormat(QueryRowFormat.UseJsPropertyNames).getOptions(); @@ -1900,6 +1901,64 @@ describe("ECSqlStatement", () => { }); }); + it("should bind IdSets to IdSet Virtual Table", async () => { + await using(ECDbTestHelper.createECDb(outDir, "bindids.ecdb"), async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const idNumbers: number[] = [4444, 4545, 1234, 6758, 1312]; + ecdb.withPreparedStatement("INSERT INTO ecdbf.ExternalFileInfo(ECInstanceId,Name) VALUES(?,?)", (stmt: ECSqlStatement) => { + idNumbers.forEach((idNum: number) => { + const expectedId = Id64.fromLocalAndBriefcaseIds(idNum, 0); + stmt.bindId(1, expectedId); + stmt.bindString(2, `${idNum}.txt`); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(r.id); + assert.equal(r.id!, expectedId); + ecdb.saveChanges(); + + ecdb.withStatement(`SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=${expectedId}`, (confstmt: ECSqlStatement) => { + assert.equal(confstmt.step(), DbResult.BE_SQLITE_ROW); + const row = confstmt.getRow(); + assert.equal(row.id, expectedId); + assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); + assert.equal(row.name, `${Id64.getLocalId(expectedId).toString()}.txt`); + }); + stmt.reset(); + stmt.clearBindings(); + }); + }); + + ecdb.withPreparedStatement("SELECT ECInstanceId, ECClassId, Name from ecdbf.ExternalFileInfo, ECVLib.IdSet(?) WHERE id = ECInstanceId", (stmt: ECSqlStatement) => { + let idSet: Id64String[] = []; + stmt.bindIdSet(1, idSet); + let result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_DONE); + stmt.reset(); + stmt.clearBindings(); + + idSet = ["0X1","ABC"]; + try{ + stmt.bindIdSet(1, idSet); + }catch(err: any){ + assert.equal(err.message, "Error binding id set"); + } + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_DONE); + stmt.reset(); + stmt.clearBindings(); + + try{ + stmt.bindId(1, idNumbers[0].toString()); + }catch(err: any){ + assert.equal(err.message, "Error binding Id"); + } + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_DONE); + }); + }); + }); + /* This test doesn't do anything specific with the binder life time but just runs a few scenarios with and without statement cache to test that stuff works fine */ it("check ECSqlBinder life time", async () => { From 67419dc55fd00fdc1424b0e1f4a9ccbaf0dbaa3f Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Mon, 14 Oct 2024 18:42:11 +0530 Subject: [PATCH 04/12] changeset and lint errors solved --- .../Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json | 10 ++++++++++ core/backend/src/test/ecdb/ECSqlQuery.test.ts | 2 +- core/backend/src/test/ecdb/ECSqlStatement.test.ts | 3 +-- 3 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json diff --git a/common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json b/common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json new file mode 100644 index 000000000000..c7a188dd4db7 --- /dev/null +++ b/common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-backend", + "comment": "Added test cases for IdSet Virtual table", + "type": "none" + } + ], + "packageName": "@itwin/core-backend" +} \ No newline at end of file diff --git a/core/backend/src/test/ecdb/ECSqlQuery.test.ts b/core/backend/src/test/ecdb/ECSqlQuery.test.ts index 5816563120fb..8393c4fb933c 100644 --- a/core/backend/src/test/ecdb/ECSqlQuery.test.ts +++ b/core/backend/src/test/ecdb/ECSqlQuery.test.ts @@ -736,7 +736,7 @@ describe("ECSql Query", () => { const ids: string[] = ["ABC", "0x1","YZ"]; // as first value is not an Id so QueryBinder.from will throw error of "unsupported type" try{ - const reader = imodel1.createQueryReader("SELECT * FROM BisCore.element, ECVLib.IdSet(?) WHERE id = ECInstanceId", QueryBinder.from([ids])); + imodel1.createQueryReader("SELECT * FROM BisCore.element, ECVLib.IdSet(?) WHERE id = ECInstanceId", QueryBinder.from([ids])); }catch(err: any){ assert.equal(err.message, "unsupported type"); } diff --git a/core/backend/src/test/ecdb/ECSqlStatement.test.ts b/core/backend/src/test/ecdb/ECSqlStatement.test.ts index 542efab4fc93..53c8fa055174 100644 --- a/core/backend/src/test/ecdb/ECSqlStatement.test.ts +++ b/core/backend/src/test/ecdb/ECSqlStatement.test.ts @@ -2,7 +2,7 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; +import { assert } from "chai"; import { DbResult, Guid, GuidString, Id64, Id64String, using } from "@itwin/core-bentley"; import { NavigationValue, QueryBinder, QueryOptions, QueryOptionsBuilder, QueryRowFormat } from "@itwin/core-common"; import { Point2d, Point3d, Range3d, XAndY, XYAndZ } from "@itwin/core-geometry"; @@ -12,7 +12,6 @@ import { KnownTestLocations } from "../KnownTestLocations"; import { SequentialLogMatcher } from "../SequentialLogMatcher"; import { ECDbTestHelper } from "./ECDbTestHelper"; import { ConcurrentQuery } from "../../ConcurrentQuery"; -import { Exception } from "@opentelemetry/api"; /* eslint-disable @typescript-eslint/naming-convention */ const selectSingleRow = new QueryOptionsBuilder().setLimit({ count: 1, offset: -1 }).setRowFormat(QueryRowFormat.UseJsPropertyNames).getOptions(); From abe508f4738a8803bf5d89498843a0b454e900cd Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:16:58 +0530 Subject: [PATCH 05/12] ".only" removed --- core/backend/src/test/ecdb/ECSqlQuery.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/backend/src/test/ecdb/ECSqlQuery.test.ts b/core/backend/src/test/ecdb/ECSqlQuery.test.ts index 8393c4fb933c..cee8e7a97583 100644 --- a/core/backend/src/test/ecdb/ECSqlQuery.test.ts +++ b/core/backend/src/test/ecdb/ECSqlQuery.test.ts @@ -732,7 +732,7 @@ describe("ECSql Query", () => { assert.equal(reader.stats.backendRowsReturned, 1); assert.isTrue(reader.stats.backendCpuTime > 0); }); - it.only("concurrent query bind idset with invalid values in IdSet virtual table", async () => { + it("concurrent query bind idset with invalid values in IdSet virtual table", async () => { const ids: string[] = ["ABC", "0x1","YZ"]; // as first value is not an Id so QueryBinder.from will throw error of "unsupported type" try{ From 3024b0f1aa85685000c29c76bc686488f6bde2b1 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Thu, 16 Jan 2025 13:54:15 +0530 Subject: [PATCH 06/12] More tests added --- ...ddingTestsForIdSetVT_2024-10-14-13-05.json | 2 +- .../backend/src/test/ecdb/ECSqlReader.test.ts | 19 ++++ .../test/ecsql/queries/IdSetVTTests.ecsql.md | 95 +++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md diff --git a/common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json b/common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json index c7a188dd4db7..99b35bb89b62 100644 --- a/common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json +++ b/common/changes/@itwin/core-backend/Soham-AddingTestsForIdSetVT_2024-10-14-13-05.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@itwin/core-backend", - "comment": "Added test cases for IdSet Virtual table", + "comment": "", "type": "none" } ], diff --git a/core/backend/src/test/ecdb/ECSqlReader.test.ts b/core/backend/src/test/ecdb/ECSqlReader.test.ts index c2174fa008d6..5eaf1c635a41 100644 --- a/core/backend/src/test/ecdb/ECSqlReader.test.ts +++ b/core/backend/src/test/ecdb/ECSqlReader.test.ts @@ -67,6 +67,25 @@ describe("ECSqlReader", (() => { }); }); + it("bindIdSet not working with integer Ids", async () => { + await using(ECDbTestHelper.createECDb(outDir, "test.ecdb", + ` + + + + `), async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + ecdb.saveChanges(); + const params = new QueryBinder(); + params.bindIdSet(1, ["50"]); + const optionBuilder = new QueryOptionsBuilder(); + optionBuilder.setRowFormat(QueryRowFormat.UseJsPropertyNames); + reader = ecdb.createQueryReader("SELECT ECInstanceId, Name FROM meta.ECClassDef WHERE InVirtualSet(?, ECInstanceId)", params, optionBuilder.getOptions()); + const rows = await reader.toArray(); + assert.equal(rows.length, 0); + }); + }); + it("ecsql reader simple using query reader", async () => { await using(ECDbTestHelper.createECDb(outDir, "test.ecdb", ` diff --git a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md new file mode 100644 index 000000000000..15d610191712 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md @@ -0,0 +1,95 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Testing with hard coded json string with hex ids + +- dataset: AllProperties.bim + +```sql +SELECT i FROM aps.TestElement,ECVLib.IdSet('["0x15", "0x18", "0x19"]') where id = ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +| i | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing with hard coded json string with decimal ids + +- dataset: AllProperties.bim + +```sql +SELECT i FROM aps.TestElement,ECVLib.IdSet('[21, 24, "25"]') where id = ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +| i | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing by binding with hex ids + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] + +```sql +SELECT i FROM aps.TestElement,ECVLib.IdSet(?) where id = ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +| i | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing by binding with decimal ids for ECSql Statement + +- dataset: AllProperties.bim +- bindIdSet 1, [21, 24, 25] +- mode: Statement + +```sql +SELECT i FROM aps.TestElement,ECVLib.IdSet(?) where id = ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +| i | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing by binding with decimal ids for ConcurrentQuery + +`The purpose of this test is to show that bindIdSet when working with ConcurrentQuery only takes into account hex ids and not decimal ids` + +- dataset: AllProperties.bim +- bindIdSet 1, [21, 24, 25] +- mode: ConcurrentQuery + +```sql +SELECT i FROM aps.TestElement,ECVLib.IdSet(?) where id = ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +| i | +| --- | From 988ad1bbe0e05b4240d128004eee94bd0793fe72 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:58:44 +0530 Subject: [PATCH 07/12] Documentation added --- docs/learning/ECSqlReference/IdSet.md | 47 +++++++++++++++++++++++++++ docs/learning/ECSqlReference/index.md | 1 + 2 files changed, 48 insertions(+) create mode 100644 docs/learning/ECSqlReference/IdSet.md diff --git a/docs/learning/ECSqlReference/IdSet.md b/docs/learning/ECSqlReference/IdSet.md new file mode 100644 index 000000000000..0ea76dd8705a --- /dev/null +++ b/docs/learning/ECSqlReference/IdSet.md @@ -0,0 +1,47 @@ +# IdSet Virtual Table + +`IdSet` is an ECSQl built in virtual table which takes in a valid JSON array string of hex or decimal ids and stores the ids as a virtual table. It can be used as an alternative to `InVirtualSet`. + +## Syntax + +```sql +SELECT i FROM aps.TestElement, ECVLib.IdSet('["0x15", "0x18", "0x19"]') where id = ECInstanceId +``` + +OR + +```sql +SELECT i FROM aps.TestElement, ECVLib.IdSet(?) where id = ECInstanceId +``` + +## Arguments accepted + +- `IdSet` accepts a valid string JSON array with valid string hex ids like `["0x15", "0x18", "0x19"]` +- `IdSet` also accepts a valid string JSON array with valid decimal ids like `[21, 24, 25]` +- `IdSet` also accepts a valid string JSON array with valid decimal ids being passed on as string like `["21", "24", "25"]` + +## BindIdSet support + +As `IdSet` is an alternative to `InVirtualSet()`, `bindIdSet` also works with `IfdSet` virtual table + +```sql +SELECT i FROM aps.TestElement,ECVLib.IdSet(?) where id = ECInstanceId +``` + +- bindIdSet 1, [0x15, 0x18, 0x19] + +## Migrating from `InVirtualSet` + +The following ECSql query using `InVirtualSet` + +```sql +SELECT i FROM aps.TestElement where InVirtualSet(?, ECInstanceId) +``` + +can be translated using `IdSet` as follows + +```sql +SELECT i FROM aps.TestElement,ECVLib.IdSet(?) where id = ECInstanceId +``` + +[ECSql Syntax](./index.md) diff --git a/docs/learning/ECSqlReference/index.md b/docs/learning/ECSqlReference/index.md index 37ffa0488a9d..aa0a8740f9e0 100644 --- a/docs/learning/ECSqlReference/index.md +++ b/docs/learning/ECSqlReference/index.md @@ -46,3 +46,4 @@ - [ECSQL Keywords](./ECSqlKeywords.md) - [Escaping keywords](./ECSqlKeywords.md#escaping-keywords) - [Views](./Views.md) +- [IdSet Virtual Table](./IdSet.md) From 0f0e28dfbea4c1168a6f9edd809fc041b06a8cd7 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Fri, 17 Jan 2025 18:01:53 +0530 Subject: [PATCH 08/12] More tests added --- .../test/ecsql/queries/IdSetVTTests.ecsql.md | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md index 15d610191712..5696b8c94f6a 100644 --- a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md +++ b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md @@ -93,3 +93,177 @@ SELECT i FROM aps.TestElement,ECVLib.IdSet(?) where id = ECInstanceId | i | | --- | + +# Testing IdSet following cte subquery + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] + +```sql +SELECT + b +FROM + ( + WITH + cte (a, b) AS ( + SELECT ECInstanceId, i FROM aps.TestElement ) SELECT * FROM cte + ), + ECVLib.IdSet (?) +WHERE + id = a +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | b | true | 0 | b | b | undefined | int | Int | + +| b | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing cte subquery following IdSet + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] + +```sql +SELECT + b +FROM +ECVLib.IdSet (?), + ( + WITH + cte (a, b) AS ( + SELECT ECInstanceId, i FROM aps.TestElement ) SELECT * FROM cte + ) +WHERE + id = a +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | b | true | 0 | b | b | undefined | int | Int | + +| b | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing nested CTE subquery following IdSet + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] + +```sql +SELECT + b +FROM +ECVLib.IdSet (?), +( select * from ( + WITH + cte (a, b) AS ( + SELECT ECInstanceId, i FROM aps.TestElement ) SELECT * FROM cte + )) +WHERE + id = a +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | b | true | 0 | b | b | undefined | int | Int | + +| b | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing IdSet following nested CTE subquery + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] + +```sql +SELECT + b +FROM +( select * from ( + WITH + cte (a, b) AS ( + SELECT ECInstanceId, i FROM aps.TestElement ) SELECT * FROM cte + )), +ECVLib.IdSet (?) +WHERE + id = a +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | b | true | 0 | b | b | undefined | int | Int | + +| b | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing IdSet following nested CTE without sub columns subquery + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] + +```sql +SELECT + i +FROM +( select * from ( + WITH + cte AS ( + SELECT ECInstanceId, i FROM aps.TestElement ) SELECT * FROM cte + )), +ECVLib.IdSet (?) +WHERE + id = ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | + +| i | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing CTE without sub columns subquery following IdSet + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] + +```sql +SELECT + i +FROM +ECVLib.IdSet (?), +( + WITH + cte AS ( + SELECT ECInstanceId, i FROM aps.TestElement ) SELECT * FROM cte + ) +WHERE + id = ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | + +| i | +| --- | +| 101 | +| 104 | +| 105 | From 97d88f295c2fc960616537ed4a9a6df275afa2d9 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Fri, 17 Jan 2025 18:34:03 +0530 Subject: [PATCH 09/12] More tests added and documentation updated --- .../test/ecsql/queries/IdSetVTTests.ecsql.md | 40 +++++++++++++++++++ docs/learning/ECSqlReference/IdSet.md | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md index 5696b8c94f6a..fc92e2e98ec8 100644 --- a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md +++ b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md @@ -1,5 +1,45 @@ Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. +# Testing returned values of IdSet virtual table + +- dataset: AllProperties.bim + +```sql +SELECT id from ECVLib.IdSet(?) +``` + +- bindIdSet 1, [0x15, 0x18, 0x19] + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| | id | false | 0 | id | id | Id | long | Id | id | + +| id | +| ---- | +| 0x15 | +| 0x18 | +| 0x19 | + +# Testing returned values of IdSet virtual table with alias + +- dataset: AllProperties.bim + +```sql +SELECT id a from ECVLib.IdSet(?) +``` + +- bindIdSet 1, [0x15, 0x18, 0x19] + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| | a | true | 0 | a | a | Id | long | Id | id | + +| a | +| ---- | +| 0x15 | +| 0x18 | +| 0x19 | + # Testing with hard coded json string with hex ids - dataset: AllProperties.bim diff --git a/docs/learning/ECSqlReference/IdSet.md b/docs/learning/ECSqlReference/IdSet.md index 0ea76dd8705a..df5488e5c80c 100644 --- a/docs/learning/ECSqlReference/IdSet.md +++ b/docs/learning/ECSqlReference/IdSet.md @@ -1,6 +1,6 @@ # IdSet Virtual Table -`IdSet` is an ECSQl built in virtual table which takes in a valid JSON array string of hex or decimal ids and stores the ids as a virtual table. It can be used as an alternative to `InVirtualSet`. +`IdSet` is an ECSQl built in virtual table which takes in a valid JSON array string of hex or decimal ids and stores the ids as a virtual table. It can be used as an alternative to `InVirtualSet`. The column retuned by `IdSet` virtual table will always be named `id` by default but can be aliased as per choice. ## Syntax From 898dd59f8affebc90875372f15b1884d2bb7bf6a Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Sat, 18 Jan 2025 01:55:32 +0530 Subject: [PATCH 10/12] More tests added --- .../test/ecsql/queries/IdSetVTTests.ecsql.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md index fc92e2e98ec8..a1cc5e79c812 100644 --- a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md +++ b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md @@ -76,6 +76,52 @@ SELECT i FROM aps.TestElement,ECVLib.IdSet('[21, 24, "25"]') where id = ECInstan | 104 | | 105 | +# Testing JOINS with IdSet + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] +- only: true + +```sql +SELECT e.i FROM aps.TestElement e INNER JOIN ECVLib.IdSet(?) v ON e.ECInstanceId = v.id +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +| i | +| --- | +| 101 | +| 104 | +| 105 | + +# Testing JOINS with IdSet and also select VirtualProp + +- dataset: AllProperties.bim +- bindIdSet 1, [0x15, 0x18, 0x19] +- only: true + +```sql +SELECT + e.i, + v.id +FROM + aps.TestElement e + INNER JOIN ECVLib.IdSet (?) v ON v.id = e.ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | id | false | 1 | id | id | Id | long | Id | id | + +| i | id | +| --- | ---- | +| 101 | 0x15 | +| 104 | 0x18 | +| 105 | 0x19 | + # Testing by binding with hex ids - dataset: AllProperties.bim From b49d57c3975479374dddee8bc15e2477f1870ae7 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Sat, 18 Jan 2025 01:57:31 +0530 Subject: [PATCH 11/12] only removed --- core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md index a1cc5e79c812..94e5342c1a71 100644 --- a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md +++ b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md @@ -80,7 +80,6 @@ SELECT i FROM aps.TestElement,ECVLib.IdSet('[21, 24, "25"]') where id = ECInstan - dataset: AllProperties.bim - bindIdSet 1, [0x15, 0x18, 0x19] -- only: true ```sql SELECT e.i FROM aps.TestElement e INNER JOIN ECVLib.IdSet(?) v ON e.ECInstanceId = v.id @@ -100,7 +99,6 @@ SELECT e.i FROM aps.TestElement e INNER JOIN ECVLib.IdSet(?) v ON e.ECInstanceId - dataset: AllProperties.bim - bindIdSet 1, [0x15, 0x18, 0x19] -- only: true ```sql SELECT From c0527242f57185f0ce86c0284b0cac6c75253482 Mon Sep 17 00:00:00 2001 From: soham-bentley <177123878+soham-bentley@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:11:04 +0530 Subject: [PATCH 12/12] More JOIN tests added --- .../test/ecsql/queries/IdSetVTTests.ecsql.md | 89 ++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md index 94e5342c1a71..35013dcc3227 100644 --- a/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md +++ b/core/backend/src/test/ecsql/queries/IdSetVTTests.ecsql.md @@ -76,7 +76,7 @@ SELECT i FROM aps.TestElement,ECVLib.IdSet('[21, 24, "25"]') where id = ECInstan | 104 | | 105 | -# Testing JOINS with IdSet +# Testing INNER JOINS with IdSet - dataset: AllProperties.bim - bindIdSet 1, [0x15, 0x18, 0x19] @@ -95,7 +95,7 @@ SELECT e.i FROM aps.TestElement e INNER JOIN ECVLib.IdSet(?) v ON e.ECInstanceId | 104 | | 105 | -# Testing JOINS with IdSet and also select VirtualProp +# Testing INNER JOINS with IdSet and also select VirtualProp - dataset: AllProperties.bim - bindIdSet 1, [0x15, 0x18, 0x19] @@ -120,6 +120,91 @@ FROM | 104 | 0x18 | | 105 | 0x19 | +# Testing LEFT OUTER JOIN on virtual table + +- dataset: AllProperties.bim + +```sql +SELECT + e.ECInstanceId, + e.i, + v.id +FROM + ECVLib.IdSet ('["0x15", "0x18", "0x19"]') v + LEFT OUTER JOIN aps.TestElement e ON e.ECInstanceId = v.id +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:IPrimitive | i | false | 1 | i | i | undefined | int | Int | i | +| | id | false | 2 | id_1 | id | Id | long | Id | id | + +| ECInstanceId | i | id | +| ------------ | --- | ---- | +| 0x15 | 101 | 0x15 | +| 0x18 | 104 | 0x18 | +| 0x19 | 105 | 0x19 | + +# Testing LEFT OUTER JOIN on test table + +- dataset: AllProperties.bim + +```sql +SELECT + e.ECInstanceId, + e.i, + v.id +FROM + aps.TestElement e + LEFT OUTER JOIN ECVLib.IdSet ('["0x15", "0x18", "0x19"]') v ON e.ECInstanceId = v.id +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:IPrimitive | i | false | 1 | i | i | undefined | int | Int | i | +| | id | false | 2 | id_1 | id | Id | long | Id | id | + +| ECInstanceId | i | id | +| ------------ | --- | --------- | +| 0x14 | 100 | undefined | +| 0x15 | 101 | 0x15 | +| 0x16 | 102 | undefined | +| 0x17 | 103 | undefined | +| 0x18 | 104 | 0x18 | +| 0x19 | 105 | 0x19 | +| 0x1a | 106 | undefined | +| 0x1b | 107 | undefined | +| 0x1c | 108 | undefined | +| 0x1d | 109 | undefined | + +# Testing JOIN + +- dataset: AllProperties.bim + +```sql +SELECT + e.ECInstanceId, + e.i, + v.id +FROM + aps.TestElement e + JOIN ECVLib.IdSet ('["0x15", "0x18", "0x19"]') v ON e.ECInstanceId = v.id +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:IPrimitive | i | false | 1 | i | i | undefined | int | Int | i | +| | id | false | 2 | id_1 | id | Id | long | Id | id | + +| ECInstanceId | i | id | +| ------------ | --- | ---- | +| 0x15 | 101 | 0x15 | +| 0x18 | 104 | 0x18 | +| 0x19 | 105 | 0x19 | + # Testing by binding with hex ids - dataset: AllProperties.bim