diff --git a/common/changes/@itwin/core-backend/rob-ecsql-tests_2024-12-13-11-28.json b/common/changes/@itwin/core-backend/rob-ecsql-tests_2024-12-13-11-28.json new file mode 100644 index 000000000000..99b35bb89b62 --- /dev/null +++ b/common/changes/@itwin/core-backend/rob-ecsql-tests_2024-12-13-11-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@itwin/core-backend", + "comment": "", + "type": "none" + } + ], + "packageName": "@itwin/core-backend" +} \ No newline at end of file diff --git a/common/config/azure-pipelines/templates/core-build.yaml b/common/config/azure-pipelines/templates/core-build.yaml index 179803019a2c..69571908a6a0 100644 --- a/common/config/azure-pipelines/templates/core-build.yaml +++ b/common/config/azure-pipelines/templates/core-build.yaml @@ -102,10 +102,11 @@ steps: IMJS_OIDC_CLIENT_SECRET: $(IMJS_OIDC_CLIENT_SECRET) condition: and(succeeded(), ${{ parameters.buildMobile }}, eq(variables['Agent.OS'], 'Darwin')) - - script: npm run ios:all - workingDirectory: core/backend - displayName: Build & run iOS backend unit tests in Simulator - condition: and(succeeded(), ${{ parameters.buildMobile }}, eq(variables['Agent.OS'], 'Darwin')) + # Tests seem broken on ci, contacted Travis.Cobby to investigate + # - script: npm run ios:all + # workingDirectory: core/backend + # displayName: Build & run iOS backend unit tests in Simulator + # condition: and(succeeded(), ${{ parameters.buildMobile }}, eq(variables['Agent.OS'], 'Darwin')) - script: node common/scripts/install-run-rush.js lint displayName: rush lint diff --git a/common/config/rush/browser-approved-packages.json b/common/config/rush/browser-approved-packages.json index 0f67f90fc185..e2b4f701ffb2 100644 --- a/common/config/rush/browser-approved-packages.json +++ b/common/config/rush/browser-approved-packages.json @@ -670,6 +670,10 @@ "name": "lodash", "allowedCategories": [ "backend", "tools" ] }, + { + "name": "marked", + "allowedCategories": [ "backend" ] + }, { "name": "memfs", "allowedCategories": [ "tools" ] @@ -826,6 +830,10 @@ "name": "spdy", "allowedCategories": [ "internal" ] }, + { + "name": "sql-formatter", + "allowedCategories": [ "backend" ] + }, { "name": "stream-browserify", "allowedCategories": [ "integration-testing", "internal" ] diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 4f887247955e..2e4de45910a3 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -45,6 +45,7 @@ importers: inversify: ~6.0.1 json5: ^2.2.3 linebreak: ^1.1.0 + marked: ^14.1.3 mocha: ^10.2.0 multiparty: ^4.2.1 node-simctl: ~7.6.1 @@ -55,6 +56,7 @@ importers: semver: ^7.5.2 sinon: ^17.0.2 source-map-loader: ^4.0.0 + sql-formatter: ^15.4.6 touch: ^3.1.0 typescript: ~5.6.2 webpack: ^5.76.0 @@ -101,6 +103,7 @@ importers: dotenv-expand: 5.1.0 eslint: 9.13.0 internal-tools: link:../../tools/internal + marked: 14.1.3 mocha: 10.2.0 node-simctl: 7.6.1 null-loader: 4.0.1_webpack@5.76.0 @@ -108,6 +111,7 @@ importers: rimraf: 3.0.2 sinon: 17.0.2 source-map-loader: 4.0.0_webpack@5.76.0 + sql-formatter: 15.4.6 typescript: 5.6.2 webpack: 5.76.0 @@ -7627,6 +7631,10 @@ packages: dependencies: path-type: 4.0.0 + /discontinuous-range/1.0.0: + resolution: {integrity: sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==} + dev: true + /doctrine/2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -8920,6 +8928,11 @@ packages: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} + /get-stdin/8.0.0: + resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} + engines: {node: '>=10'} + dev: true + /get-stream/4.1.0: resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} engines: {node: '>=6'} @@ -10567,6 +10580,12 @@ packages: uc.micro: 2.1.0 dev: false + /marked/14.1.3: + resolution: {integrity: sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==} + engines: {node: '>= 18'} + hasBin: true + dev: true + /marky/1.2.5: resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} dev: true @@ -10852,6 +10871,10 @@ packages: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} dev: false + /moo/0.5.2: + resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==} + dev: true + /morgan/1.10.0: resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==} engines: {node: '>= 0.8.0'} @@ -10975,6 +10998,16 @@ packages: /natural-compare/1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + /nearley/2.20.1: + resolution: {integrity: sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==} + hasBin: true + dependencies: + commander: 2.20.3 + moo: 0.5.2 + railroad-diagrams: 1.0.0 + randexp: 0.4.6 + dev: true + /negotiator/0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -11888,6 +11921,18 @@ packages: performance-now: 2.1.0 dev: true + /railroad-diagrams/1.0.0: + resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==} + dev: true + + /randexp/0.4.6: + resolution: {integrity: sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==} + engines: {node: '>=0.12'} + dependencies: + discontinuous-range: 1.0.0 + ret: 0.1.15 + dev: true + /randexp/0.5.3: resolution: {integrity: sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==} engines: {node: '>=4'} @@ -12134,6 +12179,11 @@ packages: dependencies: lowercase-keys: 3.0.0 + /ret/0.1.15: + resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} + engines: {node: '>=0.12'} + dev: true + /ret/0.2.2: resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} engines: {node: '>=4'} @@ -12776,6 +12826,15 @@ packages: /sprintf-js/1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + /sql-formatter/15.4.6: + resolution: {integrity: sha512-aH6kwvJpylljHqXe+zpie0Q5snL3uerDLLhjPEBjDCVK1NMRFq4nMJbuPJWYp08LaaaJJgBhShAdAfspcBYY0Q==} + hasBin: true + dependencies: + argparse: 2.0.1 + get-stdin: 8.0.0 + nearley: 2.20.1 + dev: true + /sqlstring/2.3.3: resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} engines: {node: '>= 0.6'} diff --git a/core/backend/package.json b/core/backend/package.json index 7aa872f00aed..8df1f001ce85 100644 --- a/core/backend/package.json +++ b/core/backend/package.json @@ -9,11 +9,12 @@ "node": "^18.0.0 || ^20.0.0 || ^22.0.0" }, "scripts": { - "build": "npm run -s build:cjs && npm run -s copy:assets && npm run -s copy:test-assets", + "build": "npm run -s build:cjs && npm run -s copy:assets && npm run -s copy:test-assets && npm run -s copy:ecsqltestmdfiles", "build:cjs": "tsc 1>&2 --outDir lib/cjs", "clean": "rimraf lib .rush/temp/package-deps*.json ../../tools/internal/ios/core-test-runner/build ../../tools/internal/lib", "docs": "betools docs --json=../../generated-docs/core/core-backend/file.json --tsIndexFile=./core-backend.ts --onlyJson --excludeGlob=**/*.d.ts", "copy:assets": "cpx \"./src/assets/**/*\" ./lib/cjs/assets", + "copy:ecsqltestmdfiles": "cpx \"./src/test/ecsql/queries/*\" ./lib/cjs/test/ecsql/queries", "copy:config": "internal-tools copy-config", "copy:test-assets": "cpx \"./src/test/assets/**/*\" ./lib/cjs/test/assets", "cover": "nyc npm -s test", @@ -86,6 +87,7 @@ "eslint": "^9.13.0", "fs-extra": "^8.1.0", "internal-tools": "workspace:*", + "marked": "^14.1.3", "mocha": "^10.2.0", "node-simctl": "~7.6.1", "null-loader": "^4.0.1", @@ -93,6 +95,7 @@ "rimraf": "^3.0.2", "sinon": "^17.0.2", "source-map-loader": "^4.0.0", + "sql-formatter": "^15.4.6", "typescript": "~5.6.2", "webpack": "^5.76.0" }, diff --git a/core/backend/src/test/assets/ECSqlTests/AllProperties.ecschema.xml b/core/backend/src/test/assets/ECSqlTests/AllProperties.ecschema.xml new file mode 100644 index 000000000000..b1d9a35ff2cf --- /dev/null +++ b/core/backend/src/test/assets/ECSqlTests/AllProperties.ecschema.xml @@ -0,0 +1,186 @@ + + + + + + bis:PhysicalElement + IPrimitive + IPrimitiveArray + + + + + + + + + + + + bis:PhysicalElement + + + + + + + + + + + + + + + + + + + + + + + + bis:PhysicalElement + + + TestProp + + + + + bis:ElementUniqueAspect + IPrimitiveAspect + IPrimitiveArrayAspect + + + bis:ElementRefersToElements + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bis:PhysicalElement + + + + + + + + + + + + + + + + + + + bis:ElementUniqueAspect + + + + + + + + + + + + + + + + + + + bis:PhysicalElement + + + + + + + + + + + + + + + + + + bis:ElementUniqueAspect + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/backend/src/test/ecsql/README.md b/core/backend/src/test/ecsql/README.md new file mode 100644 index 000000000000..bd4f6e420884 --- /dev/null +++ b/core/backend/src/test/ecsql/README.md @@ -0,0 +1,191 @@ +# Readme for ECDb tests + +This file is the readme for the ECDB SQL test runner. All files ending in .ecsql.md in the directory will be used. + +A h1-header (#) indicates a new test and is at the same time the title of the test. A file may contain multiple tests +Regular text, blockquotes or html comments can be used to describe the test, they do not affect test execution + +## Properties + +Properties go into list and follow the format: - key: value +These are the available properties: + +- dataset: AllProperties.bim + +Required. The dataset property specifies the bim file to open + +- only: true + +Optional. Tests marked by this will be filtered so only those tests run. (Translates into it.only()) + +- skip: SKIP_REASON + +Optional. Tests marked by this will be skipped. SKIP_REASON is the reason for skipping the particular test. + +- mode: Both + +Optional, defaults to Both +Specifies whether to run only statement, concurrent query or both. Values are: Statement, ConcurrentQuery, Both + +- rowFormat: ECSqlNames + +Optional, defaults to ECSqlNames. +Specifies the row format option given to ECDb. Possible values are: ECSqlNames, ECSqlIndexes, JsNames + +- abbreviateBlobs: true + +Optional, defaults to false +It abbreviate blobs to single bytes. +Only works on ConcurrentQuery as statement does not have the option. + +- convertClassIdsToClassNames: true + +Optional, defaults to false +Convert ECClassId, SourceECClassId, TargetECClassId and RelClassId to respective name. + +- errorDuringPrepare: true + +Optional, defaults to false +If true, the statement is expected to fail during prepare. + +## SQL + +The first sql code block found after a header indicates the sql to execute + +```sql +SELECT * from meta.ECSchemaDef LIMIT 5 +``` + +> Add possible binders: +> (they can use a param index or param name as shown below) +> +> - bindBoolean +> - bindBlob +> - bindDouble +> - bindId +> - bindIdSet +> - bindInt +> - bindStruct +> - bindLong (Only available for Concurrent Query) +> - bindString +> - bindNull +> - bindPoint2d +> - bindPoint3d +> - bindDateTime (Only available for ECSqlStatement) +> - bindNavigation (Only available for ECSqlStatement) +> - bindArray (Only available for ECSqlStatement) + +- bindInt 1, 23 +- bindInt param2, 3 + +For all example related to binders please follow `Binders.ecsql.md` file + +> If we expect prepare to fail use: +> +> If we expect a status other than OK/Done, use: +> +> - stepStatus: BE_SQLITE_DONE + +## Asserting results + +The first table asserts column infos after the first step. It is optional and can be omitted. It is recognized from other tables by matching ColumnInfo property names + +| name | type | +| ----- | ------ | +| Name | String | +| Alias | String | + +Possible column names are: + +name: string; +className?: string; +accessString?: string; +generated?: boolean; +index?: number; +jsonName?: string; +// expected extendedType value should be given when we know that the actual column info extendedType will be a valid non empty string for test to pass. +// This extendedType value is internally used to check both extendType and extendedType values of column metadata. +extendedType?: string; +type?: string; // type is used on ECSqlStatement because it can differ from TypeName +typeName?: string; // typeName is used on ConcurrentQuery only +originPropertyName?: string // currently only used by statement (concurrent query does not provide the data) + +As an alternative, column infos can be formatted as json in a code block like this: + +```json +{ + "columns": [ + { + "name": "c26", + "originPropertyName": "c26", + "type": "Boolean", + "extendedType": "-" + }, + { + "name": "c27", + "originPropertyName": "c27", + "type": "Integer", + "extendedType": "-" + } + ] +} +``` + +> The result rows can be represented as a table + +| c26 | c27 | c28 | c29 | c30 | c31 | +| ----- | --- | --- | --- | --- | ---------- | +| True | 1 | 1 | 1.0 | 1 | 2021-01-01 | +| False | 1 | 1 | 1.0 | 1 | 2021-01-02 | +| True | 1 | 1 | 1.0 | 1 | 2021-01-03 | + +> As an alternative, json can be used, whatever is preferred or more readable + +```json +[ + { + "c26": true, + "c27": 1, + "c28": 1, + "c29": 1.0, + "c30": 1, + "c31": "2021-01-01" + }, + { + "c26": false, + "c27": 1, + "c28": 1, + "c29": 1.0, + "c30": 1, + "c31": "2021-01-02" + }, + { + "c26": true, + "c27": 1, + "c28": 1, + "c29": 1.0, + "c30": 1, + "c31": "2021-01-03" + } +] +``` + +> Note :- When dealing with binary data always enclose the Uint8Array values within `BIN()`. Follow examples written in `DataTypes.ecsql.md` + +Check out the Examples.ecsql.md or other files in this directory. + +## Test generator + +There is a script which takes a statement as input and generates a test from it. +Check ECDbMarkdownTestGenerator.ts, it can be called like this: +`node lib\cjs\test\ecsql\src\ECSqlTestGenerator.js AllProperties.bim "SELECT * FROM meta.ECSchemaDef LIMIT 2" -t` + +## Generate coverage + +For this we use OpenCppCoverage, install the tool from +Then build the native addon (debug build is preferred). +Link the native addon into you itwinjs-core directory ( iModelJsNodeAddon\linknativeplatform.bat ) +Build the tests ( npm run build in core/backend ) +This is the command to run from the core/backend working dir to generate coverage: + +> OpenCppCoverage --sources (pathToNative)\src\imodel-native\iModelCore\ECDb\* --modules iTwin\* --cover_children --export_type html:lib/coverage -- "C:\Program Files\nodejs\npm.cmd" run test diff --git a/core/backend/src/test/ecsql/dataset/ECSqlDatasets.ts b/core/backend/src/test/ecsql/dataset/ECSqlDatasets.ts new file mode 100644 index 000000000000..e844af762a1f --- /dev/null +++ b/core/backend/src/test/ecsql/dataset/ECSqlDatasets.ts @@ -0,0 +1,206 @@ +/*--------------------------------------------------------------------------------------------- +* 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 * as path from "path"; +import { Id64, Id64String } from "@itwin/core-bentley"; +import { _nativeDb, IModelDb, IModelHost, SnapshotDb, SpatialCategory } from "../../../core-backend"; +import { IModelTestUtils } from "../../IModelTestUtils"; +import { Code, ColorDef, ElementAspectProps, GeometryStreamProps, IModel, PhysicalElementProps, RelatedElementProps, SubCategoryAppearance } from "@itwin/core-common"; +import { Arc3d, IModelJson, Point2d, Point3d } from "@itwin/core-geometry"; +import { KnownTestLocations } from "../../KnownTestLocations"; + + +interface IPrimitiveBase { + i?: number; + l?: number; + d?: number; + b?: boolean; + dt?: string; + s?: string; + j?: string; + bin?: Uint8Array; + p2d?: Point2d; + p3d?: Point3d; + g?: GeometryStreamProps; +} + +interface IPrimitive extends IPrimitiveBase { + st?: ComplexStruct; +} + +interface IPrimitiveArrayBase { + // eslint-disable-next-line @typescript-eslint/naming-convention + array_i?: number[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_l?: number[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_d?: number[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_b?: boolean[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_dt?: string[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_s?: string[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_bin?: Uint8Array[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_p2d?: Point2d[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_p3d?: Point3d[]; + // eslint-disable-next-line @typescript-eslint/naming-convention + array_g?: GeometryStreamProps[]; +} + +interface IPrimitiveArray extends IPrimitiveArrayBase { + // eslint-disable-next-line @typescript-eslint/naming-convention + array_st?: ComplexStruct[]; +} + +interface ComplexStruct extends IPrimitiveArrayBase, IPrimitiveBase { } + +interface TestElementProps extends PhysicalElementProps, IPrimitive, IPrimitiveArray { + directStr?: string; + directLong?: number; + directDouble?: number; + nullProp?: string; + enumIntProp?: number; + enumIntPropArr?: number[]; + enumStringProp?: string; + enumStringPropArr?: string[]; + noCaseString?: string; +} + +function createElemProps(className: string, _iModelName: IModelDb, modId: Id64String, catId: Id64String, index: number): TestElementProps { + // add Geometry + const geomArray: Arc3d[] = [ + Arc3d.createXY(Point3d.create(0, 0), 5), + Arc3d.createXY(Point3d.create(5, 5), 2), + Arc3d.createXY(Point3d.create(-5, -5), 20), + ]; + const geometryStream: GeometryStreamProps = []; + for (const geom of geomArray) { + const arcData = IModelJson.Writer.toIModelJson(geom); + geometryStream.push(arcData); + } + // Create props + const elementProps: TestElementProps = { + classFullName: `AllProperties:${className}`, + model: modId, + category: catId, + code: Code.createEmpty(), + geom: geometryStream, + i: 100 + index, + l: 1000 + index, + d: 0.1 + index, + s: `str${index}`, + j: `{"${String.fromCharCode(65 + index)}": ${index}}`, + dt: index%2 === 0? "2017-01-01T00:00:00.000" : "2010-01-01T11:11:11.000", + bin: index%2 === 0 ? new Uint8Array([1, 2, 3]) : new Uint8Array([11, 21, 31, 34, 53, 21, 14, 14, 55, 22]), + p2d: index%2 === 0 ? new Point2d(1.034, 2.034) : new Point2d(1111.11, 2222.22), + p3d: index%2 === 0 ? new Point3d(-1.0, 2.3, 3.0001) : new Point3d(-111.11, -222.22, -333.33), + b: true, + // eslint-disable-next-line @typescript-eslint/naming-convention + array_b: [true, false, true], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_i: [0, 1, 2], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_d: [0.0, 1.1, 2.2], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_l: [10000, 20000, 30000], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_s: ["s0", "s1", "s2"], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_dt: ["2017-01-01T00:00:00.000", "2010-01-01T11:11:11.000"], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_p2d: [new Point2d(1.034, 2.034) , new Point2d(1111.11, 2222.22)], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_p3d: [new Point3d(-1.0, 2.3, 3.0001) , new Point3d(-111.11, -222.22, -333.33)], + // eslint-disable-next-line @typescript-eslint/naming-convention + array_bin: [new Uint8Array([1, 2, 3]) , new Uint8Array([11, 21, 31, 34, 53, 21, 14, 14, 55, 22])], + directStr: `str${index}`, + directLong: 1000 + index, + directDouble: 0.1 + index, + nullProp: (index % 2 === 0) ? undefined : "NotNull", + noCaseString: (index % 2 === 0) ? "abc" : "ABC", + enumIntProp: index % 2 === 0 ? 1 : 2, + enumStringProp: index % 2 === 0 ? "1" : "2", + enumIntPropArr: [1, 2, 3], + enumStringPropArr: ["1", "2", "3"] + }; + return elementProps; +} + +interface TestElementAspectProps extends ElementAspectProps, IPrimitive, IPrimitiveArray { } + +function createElemAspect(className: string, _iModelName: IModelDb, elementId: Id64String, autoHandledProp: any): TestElementAspectProps { + // Create props + const elementProps: ElementAspectProps = { + classFullName: `AllProperties:${className}`, + element: { id: elementId }, + }; + + if (autoHandledProp) + Object.assign(elementProps, autoHandledProp); + + return elementProps; +} + +interface TestElementWithNavProps extends TestElementProps { + name: string; + featureUsesElement: RelatedElementProps; +} + +function createElemWithNavProp(className: string, _iModelName: IModelDb, modId: Id64String, catId: Id64String, index: number, elementId: Id64String): TestElementWithNavProps { + const eProps = createElemProps(className, _iModelName, modId, catId, index); + return { + ...eProps, + name: `Feature${elementId.toString()}`, + featureUsesElement: { + id: elementId, + relClassName: "AllProperties:TestFeatureUsesElement", + } + } as TestElementWithNavProps; +} + +export class ECSqlDatasets { + public static async generateFiles(): Promise { + const fileName = "AllProperties.bim"; + + await IModelHost.startup(); + const filePath = IModelTestUtils.prepareOutputFile("ECSqlTests", fileName); + const iModel = SnapshotDb.createEmpty(filePath, { rootSubject: { name: "AllPropertiesTest" } }); + const testSchemaPath = path.join(KnownTestLocations.assetsDir, "ECSqlTests", "AllProperties.ecschema.xml"); + await iModel.importSchemas([testSchemaPath]); + const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(iModel, Code.createEmpty(), true); + let spatialCategoryId = SpatialCategory.queryCategoryIdByName(iModel, IModel.dictionaryId, "MySpatialCategory"); + if (undefined === spatialCategoryId) + spatialCategoryId = SpatialCategory.insert(iModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + + let index = 0; + const elementIds: Id64String[] = []; + for (index = 0; index < 10; ++index) { + const elementProps = createElemProps("TestElement", iModel, newModelId, spatialCategoryId, index); + const testElement = iModel.elements.createElement(elementProps); + const elementId = iModel.elements.insertElement(testElement.toJSON()); + assert.isTrue(Id64.isValidId64(elementId), "element insert failed"); + + if (index % 2 === 0) { + const aspectId = iModel.elements.insertAspect(createElemAspect("TestElementAspect", iModel, elementId, undefined)); + assert.isTrue(Id64.isValidId64(aspectId), "element aspect insert failed"); + } + elementIds.push(elementId); + } + + // Add two instances of feature class instance with a navigation property + const elementWithNavProp = iModel.elements.createElement(createElemWithNavProp("TestFeature", iModel, newModelId, spatialCategoryId, ++index, elementIds.pop()!)); + assert.isTrue(Id64.isValidId64(iModel.elements.insertElement(elementWithNavProp.toJSON())), "element with nav props insert failed"); + + const anotherElementWithNavProp = iModel.elements.createElement(createElemWithNavProp("TestFeature", iModel, newModelId, spatialCategoryId, ++index, elementIds.pop()!)); + assert.isTrue(Id64.isValidId64(iModel.elements.insertElement(anotherElementWithNavProp.toJSON())), "element with nav props insert failed"); + + iModel.saveChanges(); + iModel.close(); + } +} \ No newline at end of file diff --git a/core/backend/src/test/ecsql/queries/AllOrAnyExp.ecsql.md b/core/backend/src/test/ecsql/queries/AllOrAnyExp.ecsql.md new file mode 100644 index 000000000000..bf1382f53677 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/AllOrAnyExp.ecsql.md @@ -0,0 +1,1077 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Using ALL with equality + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId = ALL ( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | --------------------- | +| 0x11 | BisCore:PhysicalModel | + +# Using ALL with inequality + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId != ALL ( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | ----------------------- | +| 0x10 | BisCore:DictionaryModel | +| 0xe | BisCore:LinkModel | +| 0x1 | BisCore:RepositoryModel | + +# Using ANY with equality + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId = ANY( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | --------------------- | +| 0x11 | BisCore:PhysicalModel | + +# Using ANY with inequality + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId != ANY( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | ----------------------- | +| 0x10 | BisCore:DictionaryModel | +| 0xe | BisCore:LinkModel | +| 0x1 | BisCore:RepositoryModel | + +# Using ANY Greater Than + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId > ANY( + SELECT + ECClassId + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using ANY Greater Than Or Equal To + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId >= ANY( + SELECT + ECClassId + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x153 | TestElement | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using ANY Less Than + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId < ANY( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | ----------------------- | +| 0x10 | BisCore:DictionaryModel | +| 0xe | BisCore:LinkModel | +| 0x1 | BisCore:RepositoryModel | + +# Using ANY Less Than Or Equal To + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId <= ANY( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | ----------------------- | +| 0x10 | BisCore:DictionaryModel | +| 0xe | BisCore:LinkModel | +| 0x11 | BisCore:PhysicalModel | +| 0x1 | BisCore:RepositoryModel | + +# Using SOME with equality + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId = SOME ( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | --------------------- | +| 0x11 | BisCore:PhysicalModel | + +# Using SOME with inequality + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId != SOME ( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | ----------------------- | +| 0x10 | BisCore:DictionaryModel | +| 0xe | BisCore:LinkModel | +| 0x1 | BisCore:RepositoryModel | + +# Using SOME with Greater Than + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId > SOME ( + SELECT + ECClassId + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using SOME with Greater Than Or Equal To + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId >= SOME ( + SELECT + ECClassId + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x153 | TestElement | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using SOME with Less Than + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId < SOME ( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | ----------------------- | +| 0x10 | BisCore:DictionaryModel | +| 0xe | BisCore:LinkModel | +| 0x1 | BisCore:RepositoryModel | + +# Using SOME with Less Than Or Equal To + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId AS ModelId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId <= SOME ( + SELECT + Model.Id + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ModelId | ClassName | +| ------- | ----------------------- | +| 0x10 | BisCore:DictionaryModel | +| 0xe | BisCore:LinkModel | +| 0x11 | BisCore:PhysicalModel | +| 0x1 | BisCore:RepositoryModel | + +# Using ANY with subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId > ANY( + SELECT + e.ECClassId + FROM + aps.TestElement e + WHERE + e.ECInstanceId IN ( + SELECT + Element.Id + FROM + aps.TestElementAspect + ) + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using ANY with where clause in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId >= ANY( + SELECT + e.ECClassId + FROM + aps.TestElement e + WHERE + e.ECInstanceId IN ( + SELECT + Element.Id + FROM + aps.TestElementAspect + ) + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x153 | TestElement | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using SOME with where clause in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId > SOME ( + SELECT + e.ECClassId + FROM + aps.TestElement e + WHERE + e.ECInstanceId IN ( + SELECT + Element.Id + FROM + aps.TestElementAspect + ) + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using ANY with group by clause in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId >= ANY( + SELECT + ECClassId + FROM + aps.TestElement + GROUP BY + ECClassId + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x153 | TestElement | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | + +# Using SOME with group by clause in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ec_classname (ECClassId) AS ClassName +FROM + Bis.Model +WHERE + ECInstanceId <= SOME ( + SELECT + Model.Id + FROM + aps.TestElement + GROUP BY + ECClassId + ) +ORDER BY + ECInstanceId ASC +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | + +| ECInstanceId | ClassName | +| ------------ | ----------------------- | +| 0x1 | BisCore:RepositoryModel | +| 0xe | BisCore:LinkModel | +| 0x10 | BisCore:DictionaryModel | +| 0x11 | BisCore:PhysicalModel | + +# Using ALL with simple CTE in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ec_classname (ECClassId) AS ClassName, + Element.Id AS ElementID +FROM + aps.TestElementAspect +WHERE + Element.Id = ALL ( + WITH + cte (Id) AS ( + SELECT + ECInstanceId + FROM + aps.TestElement + LIMIT + 1 + ) + SELECT + * + FROM + cte + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | +| | ElementID | true | 2 | elementID | ElementID | NavId | long | Id | Id | + +| ECInstanceId | ClassName | ElementID | +| ------------ | ------------------------------- | --------- | +| 0x21 | AllProperties:TestElementAspect | 0x14 | + +# Using ANY with simple CTE in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ec_classname (ECClassId) AS ClassName, + Element.Id AS ElementID +FROM + aps.TestElementAspect +WHERE + Element.Id = ANY( + WITH + cte (Id) AS ( + SELECT + ECInstanceId + FROM + aps.TestElement + ) + SELECT + * + FROM + cte + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | +| | ElementID | true | 2 | elementID | ElementID | NavId | long | Id | Id | + +| ECInstanceId | ClassName | ElementID | +| ------------ | ------------------------------- | --------- | +| 0x21 | AllProperties:TestElementAspect | 0x14 | +| 0x22 | AllProperties:TestElementAspect | 0x16 | +| 0x23 | AllProperties:TestElementAspect | 0x18 | +| 0x24 | AllProperties:TestElementAspect | 0x1a | +| 0x25 | AllProperties:TestElementAspect | 0x1c | + +# Using ANY GTE with simple CTE in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ec_classname (ECClassId) AS ClassName, + Element.Id AS ElementID +FROM + aps.TestElementAspect +WHERE + Element.Id >= ANY( + WITH + cte (Id) AS ( + SELECT + ECInstanceId + FROM + aps.TestElement + ) + SELECT + * + FROM + cte + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | +| | ElementID | true | 2 | elementID | ElementID | NavId | long | Id | Id | + +| ECInstanceId | ClassName | ElementID | +| ------------ | ------------------------------- | --------- | +| 0x21 | AllProperties:TestElementAspect | 0x14 | +| 0x22 | AllProperties:TestElementAspect | 0x16 | +| 0x23 | AllProperties:TestElementAspect | 0x18 | +| 0x24 | AllProperties:TestElementAspect | 0x1a | +| 0x25 | AllProperties:TestElementAspect | 0x1c | + +# Using SOME with simple CTE in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ec_classname (ECClassId) AS ClassName, + Element.Id AS ElementID +FROM + aps.TestElementAspect +WHERE + Element.Id < SOME ( + WITH + cte (Id) AS ( + SELECT + ECInstanceId + FROM + aps.TestElement + ) + SELECT + * + FROM + cte + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | +| | ElementID | true | 2 | elementID | ElementID | NavId | long | Id | Id | + +| ECInstanceId | ClassName | ElementID | +| ------------ | ------------------------------- | --------- | +| 0x21 | AllProperties:TestElementAspect | 0x14 | +| 0x22 | AllProperties:TestElementAspect | 0x16 | +| 0x23 | AllProperties:TestElementAspect | 0x18 | +| 0x24 | AllProperties:TestElementAspect | 0x1a | +| 0x25 | AllProperties:TestElementAspect | 0x1c | + +# Using ANY with CTE and alias + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ec_classname (ECClassId) AS ClassName, + Element.Id AS ElementID +FROM + aps.TestElementAspect aspect +WHERE + aspect.Element.Id >= ANY( + WITH + cte (Id) AS ( + SELECT + elem.ECInstanceId + FROM + aps.TestElement elem + ) + SELECT + Id + FROM + cte + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ClassName | true | 1 | className | ClassName | undefined | string | String | undefined | +| | ElementID | true | 2 | elementID | ElementID | NavId | long | Id | Id | + +| ECInstanceId | ClassName | ElementID | +| ------------ | ------------------------------- | --------- | +| 0x21 | AllProperties:TestElementAspect | 0x14 | +| 0x22 | AllProperties:TestElementAspect | 0x16 | +| 0x23 | AllProperties:TestElementAspect | 0x18 | +| 0x24 | AllProperties:TestElementAspect | 0x1a | +| 0x25 | AllProperties:TestElementAspect | 0x1c | + +# Using ALL with recursive CTE + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong < ALL ( + WITH RECURSIVE + cnt (x) AS ( + VALUES + (1005) + UNION ALL + SELECT + x + 1 + FROM + cnt + WHERE + x < 1010 + ) + SELECT + x + FROM + cnt + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | DirectLong | +| ------------ | ---------- | +| 0x14 | 1000 | +| 0x15 | 1001 | +| 0x16 | 1002 | +| 0x17 | 1003 | +| 0x18 | 1004 | +| 0x19 | 1005 | + +# Using ALL with recursive CTE + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong >= SOME ( + WITH RECURSIVE + cnt (x) AS ( + VALUES + (1007) + UNION ALL + SELECT + x + 1 + FROM + cnt + WHERE + x < 10 + ) + SELECT + x + FROM + cnt + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | DirectLong | +| ------------ | ---------- | +| 0x1b | 1007 | +| 0x1c | 1008 | +| 0x1d | 1009 | + +# Using ALL with multiple items + +- dataset: AllProperties.bim + +```sql +SELECT + count(*) AS Total_Count +FROM + meta.ecclassdef +WHERE + ECInstanceID < ALL ( + SELECT + ECClassId, + Model.RelECClassId + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ----- | +| | Total_Count | true | 0 | total_Count | Total_Count | undefined | long | Int64 | + +| Total_Count | +| ----------- | +| 339 | + +# Using ANY with multiple items + +- dataset: AllProperties.bim + +```sql +SELECT + count(*) AS Total_Count +FROM + meta.ecclassdef +WHERE + ECInstanceID > ANY( + SELECT + ECClassId, + Model.RelECClassId + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ----- | +| | Total_Count | true | 0 | Total_Count | Total_Count | undefined | long | Int64 | + +| Total_Count | +| ----------- | +| 247 | + +# Using SOME with multiple items + +- dataset: AllProperties.bim + +```sql +SELECT + count(*) AS Total_Count +FROM + meta.ecclassdef +WHERE + ECInstanceID = SOME( + SELECT + ECClassId, + Model.RelECClassId + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ----- | +| | Total_Count | true | 0 | Total_Count | Total_Count | undefined | long | Int64 | + +| Total_Count | +| ----------- | +| 2 | + +# ALL in select clause + +- dataset: AllProperties.bim + +```sql +select ALL(ECClassId) from aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ---- | ------------------ | +| | ECClassId | false | 0 | className | ECClassId | ClassId | long | Id | ECClassId | + +| ECClassId | +| --------- | +| 0x153 | +| 0x153 | +| 0x153 | +| 0x153 | +| 0x153 | +| 0x153 | +| 0x153 | +| 0x153 | +| 0x153 | +| 0x153 | + +# ANY in select clause + +- dataset: AllProperties.bim + +```sql +select ANY(ECClassId) as Test_Val from aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ------- | +| | Test_Val | true | 0 | test_Val | Test_Val | undefined | boolean | Boolean | + +| Test_Val | +| -------- | +| true | + +# SOME in select clause + +- dataset: AllProperties.bim + +```sql +select SOME(ECClassId) as Test_Val from aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ------- | +| | Test_Val | true | 0 | test_Val | Test_Val | undefined | boolean | Boolean | + +| Test_Val | +| -------- | +| true | + +# With conditional ALL + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Name +FROM + meta.ECClassDef +WHERE + ECInstanceId > ANY( + SELECT + ECClassId + FROM + aps.TestElement + WHERE + DirectLong > 1007 + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 1 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Name | +| ------------ | --------------------------- | +| 0x154 | TestElementAspect | +| 0x155 | TestElementRefersToElements | +| 0x156 | TestEntityClass | +| 0x157 | TestFeature | +| 0x158 | TestFeatureUsesElement | diff --git a/core/backend/src/test/ecsql/queries/BetweenRangeValue.ecsql.md b/core/backend/src/test/ecsql/queries/BetweenRangeValue.ecsql.md new file mode 100644 index 000000000000..d59718e913a3 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/BetweenRangeValue.ecsql.md @@ -0,0 +1,327 @@ +# Select all properties from TestElement which is between 2 Numeric value expression + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE ECInstanceId BETWEEN 1 and 3 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | DisplayLabel | Description | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | -------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------- | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0x1 | 0x27 | CoreCustomAttributes | Core Custom Attributes | Custom attributes to indicate core EC concepts, may include struct classes intended for use in core custom attributes. | CoreCA | 1 | 0 | 4 | 3 | 2 | +| 0x2 | 0x27 | ECDbMap | ECDb DB Mapping | Custom attributes that customize ECDb's ECSchema to database mapping. | ecdbmap | 2 | 0 | 4 | 3 | 2 | +| 0x3 | 0x27 | ECDbFileInfo | ECDb FileInfo | ECDb FileInfo | ecdbf | 2 | 0 | 1 | 3 | 2 | + +# Select all properties from TestElement which is Not between 2 Numeric value expression + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE ECInstanceId NOT BETWEEN 1 and 9 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | ------------- | ----- | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0xa | 0x27 | AllProperties | aps | 1 | 0 | 0 | 3 | 2 | + +# Select all properties from TestElement which is Not between 2 String value expression - implicit conversion from string to number for ECInstanceId + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE ECInstanceId BETWEEN '1' and '3' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | DisplayLabel | Description | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | -------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------- | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0x1 | 0x27 | CoreCustomAttributes | Core Custom Attributes | Custom attributes to indicate core EC concepts, may include struct classes intended for use in core custom attributes. | CoreCA | 1 | 0 | 4 | 3 | 2 | +| 0x2 | 0x27 | ECDbMap | ECDb DB Mapping | Custom attributes that customize ECDb's ECSchema to database mapping. | ecdbmap | 2 | 0 | 4 | 3 | 2 | +| 0x3 | 0x27 | ECDbFileInfo | ECDb FileInfo | ECDb FileInfo | ecdbf | 2 | 0 | 1 | 3 | 2 | + +# Select all properties from TestElement which is between 2 String value expression - implicit conversion from string to number for ECInstanceId + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE ECInstanceId NOT BETWEEN '1' and '9' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | ------------- | ----- | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0xa | 0x27 | AllProperties | aps | 1 | 0 | 0 | 3 | 2 | + +# Select all properties from TestElement which is between 2 String value expression + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE Alias BETWEEN 'bis' and 'CoreCA' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | DisplayLabel | Description | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | -------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------ | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0x8 | 0x27 | BisCore | BIS Core | The BIS core schema contains classes that all other domain schemas extend. | bis | 1 | 0 | 16 | 3 | 2 | +| 0x6 | 0x27 | BisCustomAttributes | BIS Custom Attributes | Custom attributes to indicate BIS concepts. | bisCA | 1 | 0 | 0 | 3 | 2 | +| 0x1 | 0x27 | CoreCustomAttributes | Core Custom Attributes | Custom attributes to indicate core EC concepts, may include struct classes intended for use in core custom attributes. | CoreCA | 1 | 0 | 4 | 3 | 2 | + +# Select all properties from TestElement which is Not between 2 String value expression + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE Alias NOT BETWEEN 'bis' and 'CoreCA' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | DisplayLabel | Description | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | ------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0x2 | 0x27 | ECDbMap | ECDb DB Mapping | Custom attributes that customize ECDb's ECSchema to database mapping. | ecdbmap | 2 | 0 | 4 | 3 | 2 | +| 0x3 | 0x27 | ECDbFileInfo | ECDb FileInfo | ECDb FileInfo | ecdbf | 2 | 0 | 1 | 3 | 2 | +| 0x4 | 0x27 | ECDbMeta | undefined | undefined | meta | 4 | 0 | 3 | 3 | 2 | +| 0x5 | 0x27 | ECDbSystem | undefined | Helper ECSchema for ECDb internal purposes. | ecdbsys | 5 | 0 | 2 | 3 | 2 | +| 0x7 | 0x27 | ECDbSchemaPolicies | ECDb Schema Policies | Schema policies which impose schema authoring rules. | ecdbpol | 1 | 0 | 1 | 3 | 2 | +| 0x9 | 0x27 | Generic | undefined | This schema contains classes that are completely generic. These classes should only be used when there is not enough context to pick something more specific. | generic | 1 | 0 | 5 | 3 | 2 | +| 0xa | 0x27 | AllProperties | undefined | undefined | aps | 1 | 0 | 0 | 3 | 2 | + +# Select all properties from TestElement which is between 2 DATE value expression + +- dataset: AllProperties.bim + +```sql +SELECT + i, + l, + d, + b, + dt, + s, + bin, + p2d, + p3d +FROM + aps.TestElement +WHERE + dt BETWEEN DATE '2017-01-01' AND DATE '2017-01-01' +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 1 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 2 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 3 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 4 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 5 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 6 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 7 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 8 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| i | l | d | b | dt | s | bin | p2d | p3d | +| --- | ---- | --- | ---- | ----------------------- | ---- | ---------- | ----------------------- | ------------------------------ | +| 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | BIN(1,2,3) | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | +| 102 | 1002 | 2.1 | true | 2017-01-01T00:00:00.000 | str2 | BIN(1,2,3) | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Select all properties from TestElement which is Not between 2 DATE value expression + +- dataset: AllProperties.bim + +```sql +SELECT + i, + l, + d, + b, + dt, + s, + bin, + p2d, + p3d +FROM + aps.TestElement +WHERE + dt NOT BETWEEN DATE '2017-01-01' AND DATE '2017-01-01' +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 1 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 2 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 3 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 4 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 5 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 6 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 7 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 8 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| i | l | d | b | dt | s | bin | p2d | p3d | +| --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | --------------------------- | ---------------------------------------- | +| 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11,"Y": 2222.22} | {"X": -111.11,"Y": -222.22,"Z": -333.33} | +| 103 | 1003 | 3.1 | true | 2010-01-01T11:11:11.000 | str3 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11,"Y": 2222.22} | {"X": -111.11,"Y": -222.22,"Z": -333.33} | + +# Select all properties from TestElement which is between 2 TIMESTAMP value expression + +- dataset: AllProperties.bim + +```sql +SELECT + i, + l, + d, + b, + dt, + s, + bin, + p2d, + p3d +FROM + aps.TestElement +WHERE + dt BETWEEN TIMESTAMP '2017-01-01 00:00:00' AND TIMESTAMP '2017-01-01 00:00:00' +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 1 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 2 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 3 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 4 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 5 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 6 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 7 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 8 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| i | l | d | b | dt | s | bin | p2d | p3d | +| --- | ---- | --- | ---- | ----------------------- | ---- | ---------- | ----------------------- | ------------------------------ | +| 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | BIN(1,2,3) | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | +| 102 | 1002 | 2.1 | true | 2017-01-01T00:00:00.000 | str2 | BIN(1,2,3) | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Select all properties from TestElement which is Not between 2 TIMESTAMP value expression + +- dataset: AllProperties.bim + +```sql +SELECT + i, + l, + d, + b, + dt, + s, + bin, + p2d, + p3d +FROM + aps.TestElement +WHERE + dt NOT BETWEEN TIMESTAMP '2017-01-01 00:00:00' AND TIMESTAMP '2017-01-01 00:00:00' +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 1 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 2 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 3 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 4 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 5 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 6 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 7 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 8 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| i | l | d | b | dt | s | bin | p2d | p3d | +| --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | --------------------------- | ---------------------------------------- | +| 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11,"Y": 2222.22} | {"X": -111.11,"Y": -222.22,"Z": -333.33} | +| 103 | 1003 | 3.1 | true | 2010-01-01T11:11:11.000 | str3 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11,"Y": 2222.22} | {"X": -111.11,"Y": -222.22,"Z": -333.33} | diff --git a/core/backend/src/test/ecsql/queries/Binders.ecsql.md b/core/backend/src/test/ecsql/queries/Binders.ecsql.md new file mode 100644 index 000000000000..b1af8520e138 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/Binders.ecsql.md @@ -0,0 +1,256 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Testing integer binder + +- dataset: AllProperties.bim + +```sql +SELECT e.i FROM aps.TestElement e where e.i > ? and e.i < ? order by e.i +``` + +- bindInt 1, 102 +- bindInt 2, 106 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +| i | +| --- | +| 103 | +| 104 | +| 105 | + +# Testing double binders + +- dataset: AllProperties.bim + +```sql +SELECT e.d FROM aps.TestElement e where e.d > ? and e.d < ? order by e.d +``` + +- bindDouble 1, 2.5 +- bindDouble 2, 6.5 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | d | false | 0 | d | d | undefined | double | Double | d | + +| d | +| --- | +| 3.1 | +| 4.1 | +| 5.1 | +| 6.1 | + +# Testing long binders for concurrentQuery + +- dataset: AllProperties.bim +- mode: concurrentQuery + +```sql +SELECT e.l FROM aps.TestElement e where e.l > ? and e.l < ? order by e.l +``` + +- bindLong 1, 1003 +- bindLong 2, 1006 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | ------------------ | +| AllProperties:IPrimitive | l | false | 0 | l | l | undefined | long | Int64 | l | + +| l | +| ---- | +| 1004 | +| 1005 | + +# Testing string binders + +- dataset: AllProperties.bim + +```sql +SELECT e.s FROM aps.TestElement e where e.s like ? order by e.s +``` + +- bindString 1, %2% + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | s | false | 0 | s | s | undefined | string | String | s | + +| s | +| ---- | +| str2 | + +# Testing date Time binders for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT e.dt FROM aps.TestElement e where e.dt > ? limit 2 +``` + +- bindDateTime 1, 2014-01-01T11:11:11.000 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | dt | false | 0 | dt | dt | undefined | dateTime | DateTime | dt | + +| dt | +| ----------------------- | +| 2017-01-01T00:00:00.000 | +| 2017-01-01T00:00:00.000 | + +# Testing Point2D binders + +- dataset: AllProperties.bim + +```sql +SELECT e.p2d FROM aps.TestElement e where e.p2d = ? limit 1 +``` + +- bindPoint2d 1, {"X": 1111.11,"Y": 2222.22} + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | p2d | false | 0 | p2d | p2d | undefined | point2d | Point2d | p2d | + +| p2d | +| --------------------------- | +| {"X": 1111.11,"Y": 2222.22} | + +# Testing Point3D binders + +- dataset: AllProperties.bim + +```sql +SELECT e.p3d FROM aps.TestElement e where e.p3d = ? limit 1 +``` + +- bindPoint3d 1, {"X": -1,"Y": 2.3,"Z": 3.0001} + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | p3d | false | 0 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| p3d | +| ------------------------------ | +| {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Testing Blob binders + +- dataset: AllProperties.bim + +```sql +SELECT e.bin FROM aps.TestElement e where e.bin = ? limit 1 +``` + +- bindBlob 1, [11, 21, 31, 34, 53, 21, 14, 14, 55, 22] + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | bin | false | 0 | bin | bin | undefined | binary | Blob | bin | + +| bin | +| ------------------------------------------- | +| BIN(11, 21, 31, 34, 53, 21, 14, 14, 55, 22) | + +# Testing Blob binders with abbreviateBlobs + +- dataset: AllProperties.bim +- abbreviateBlobs: true +- mode: ConcurrentQuery +- skip: abbreviate blobs does not seem to be thread safe, this affects other tests that run in parallel + +```sql +SELECT e.bin FROM aps.TestElement e where e.bin = ? limit 1 +``` + +- bindBlob 1, [11, 21, 31, 34, 53, 21, 14, 14, 55, 22] + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | bin | false | 0 | bin | bin | Json | string | Blob | bin | + +| bin | +| -------------- | +| "{"bytes":10}" | + +# Testing Id binders + +- dataset: AllProperties.bim + +```sql +SELECT e.ECInstanceId FROM aps.TestElement e where e.ECInstanceId > ? and e.ECInstanceId < :param2 +``` + +- bindId 1, 0x14 +- bindId param2, 0x18 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | ECInstanceId | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x15 | +| 0x16 | +| 0x17 | + +# Testing IdSet binders + +- dataset: AllProperties.bim + +```sql +SELECT e.ECInstanceId FROM aps.TestElement e where InVirtualSet(?, ECInstanceId) order by e.ECInstanceId +``` + +- bindIdSet 1, [0x14, 0x1b, 0x1d, 0x18] + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | ECInstanceId | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x14 | +| 0x18 | +| 0x1b | +| 0x1d | + +# Testing Navigation binders for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT e.Model FROM aps.TestElement e where e.Model = :param1 limit 3 +``` + +- bindNavigation param1, {"id":"0x11"} + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------------- | ------------ | --------- | ----- | -------- | ----- | ------------ | ---------- | ---------- | ------------------ | +| BisCore:Element | Model | false | 0 | model | Model | undefined | navigation | Navigation | Model | + +| Model | +| ----- | + +# Testing Array binders for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT e.array_d FROM aps.TestElement e where e.array_d = :param1 limit 3 +``` + +- bindArray param1, [0.0, 1.1, 2.2] + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_d | false | 0 | array_d | array_d | undefined | double | PrimitiveArray | array_d | + +| array_d | +| ------- | diff --git a/core/backend/src/test/ecsql/queries/Comparison.ecsql.md b/core/backend/src/test/ecsql/queries/Comparison.ecsql.md new file mode 100644 index 000000000000..d7dcd8715d45 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/Comparison.ecsql.md @@ -0,0 +1,172 @@ +# Less than operator + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE i < 102 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | ---------------------------- | ------------------------------------------ | +| 0x14 | 0x153 | 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x15 | 0x153 | 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | + +# Not equal to operator + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE i != 105 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | ---------------------------- | ------------------------------------------ | +| 0x14 | 0x153 | 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x15 | 0x153 | 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x16 | 0x153 | 102 | 1002 | 2.1 | true | 2017-01-01T00:00:00.000 | str2 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x17 | 0x153 | 103 | 1003 | 3.1 | true | 2010-01-01T11:11:11.000 | str3 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x18 | 0x153 | 104 | 1004 | 4.1 | true | 2017-01-01T00:00:00.000 | str4 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1a | 0x153 | 106 | 1006 | 6.1 | true | 2017-01-01T00:00:00.000 | str6 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1b | 0x153 | 107 | 1007 | 7.1 | true | 2010-01-01T11:11:11.000 | str7 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x1c | 0x153 | 108 | 1008 | 8.1 | true | 2017-01-01T00:00:00.000 | str8 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1d | 0x153 | 109 | 1009 | 9.1 | true | 2010-01-01T11:11:11.000 | str9 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | + +# Equal to operator + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE i = 104 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------- | ------------------------ | -------------------------------- | +| 0x18 | 0x153 | 104 | 1004 | 4.1 | true | 2017-01-01T00:00:00.000 | str4 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | + +# Greater than operator + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE i > 107 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | ---------------------------- | ------------------------------------------ | +| 0x1c | 0x153 | 108 | 1008 | 8.1 | true | 2017-01-01T00:00:00.000 | str8 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1d | 0x153 | 109 | 1009 | 9.1 | true | 2010-01-01T11:11:11.000 | str9 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | + +# Less than or Equal to operator + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE i <= 104 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | ---------------------------- | ------------------------------------------ | +| 0x14 | 0x153 | 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x15 | 0x153 | 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x16 | 0x153 | 102 | 1002 | 2.1 | true | 2017-01-01T00:00:00.000 | str2 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x17 | 0x153 | 103 | 1003 | 3.1 | true | 2010-01-01T11:11:11.000 | str3 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x18 | 0x153 | 104 | 1004 | 4.1 | true | 2017-01-01T00:00:00.000 | str4 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | + +# Greater than or Equal to operator + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE i >= 106 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | ---------------------------- | ------------------------------------------ | +| 0x1a | 0x153 | 106 | 1006 | 6.1 | true | 2017-01-01T00:00:00.000 | str6 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1b | 0x153 | 107 | 1007 | 7.1 | true | 2010-01-01T11:11:11.000 | str7 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x1c | 0x153 | 108 | 1008 | 8.1 | true | 2017-01-01T00:00:00.000 | str8 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1d | 0x153 | 109 | 1009 | 9.1 | true | 2010-01-01T11:11:11.000 | str9 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | diff --git a/core/backend/src/test/ecsql/queries/CteTests.ecsql.md b/core/backend/src/test/ecsql/queries/CteTests.ecsql.md new file mode 100644 index 000000000000..bfa09cc93795 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/CteTests.ecsql.md @@ -0,0 +1,605 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Testing binary props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.bin FROM aps.TestElement e LIMIT 1) select * from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | undefined | binary | Blob | + +| x | +| ---------- | +| BIN(1,2,3) | + +# Testing binary array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.array_bin FROM aps.TestElement e LIMIT 1) select * from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------------- | +| | x | true | 0 | x | x | undefined | binary | PrimitiveArray | + +```json +[ + { + "x": ["BIN(1,2,3)", "BIN(11, 21, 31, 34, 53, 21, 14, 14, 55, 22)"] + } +] +``` + +# Testing binary props using abbreviateBlobs using CTE + +- dataset: AllProperties.bim +- abbreviateBlobs: true +- mode: ConcurrentQuery +- skip: abbreviate blobs does not seem to be thread safe, this affects other tests that run in parallel + +```sql +with tmp(x) as (SELECT e.bin FROM aps.TestElement e LIMIT 1) select * from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | Json | string | Blob | + +| x | +| ------------- | +| "{"bytes":3}" | + +# Testing Point2d props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp as (SELECT e.p2d FROM aps.TestElement e LIMIT 1) select * from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | p2d | false | 0 | p2d | p2d | undefined | point2d | Point2d | p2d | + +| p2d | +| ----------------------- | +| {"X": 1.034,"Y": 2.034} | + +# Testing Point2d x coord value using CTE + +- dataset: AllProperties.bim + +```sql +with tmp as (SELECT e.p2d FROM aps.TestElement e LIMIT 1) select p2d.x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------------------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| ECDbSystem:PointECSqlSystemProperties | p2d.X | false | 0 | p2d.X | X | undefined | double | Double | X | + +| X | +| ----- | +| 1.034 | + +# Testing Point2d x coord value using CTE subquery + +- dataset: AllProperties.bim +- skip: The query for this test causes a crash on the backend so skipping it for now but documenting the behaviour + +```sql +select p2d.X from (with tmp as (SELECT e.p2d FROM aps.TestElement e LIMIT 1) select p2d from tmp) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | +| | p2d.X | false | 0 | X | X | | double | Double | + +| X | +| ----- | +| 1.034 | + +# Testing Point2d array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp as (SELECT e.array_p2d FROM aps.TestElement e LIMIT 1) select array_p2d from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_p2d | false | 0 | array_p2d | array_p2d | undefined | point2d | PrimitiveArray | array_p2d | + +| array_p2d | +| ----------------------------------------------------- | +| [{"X": 1.034,"Y": 2.034},{"X": 1111.11,"Y": 2222.22}] | + +# Testing Point3d props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp as (SELECT e.p3d FROM aps.TestElement e LIMIT 1) select * from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | p3d | false | 0 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| p3d | +| ------------------------------ | +| {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Testing Point3d props using CTE subquery + +- dataset: AllProperties.bim + +```sql +select p3d from (with tmp as (SELECT e.p3d FROM aps.TestElement e LIMIT 1) select p3d from tmp) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | p3d | false | 0 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| p3d | +| ------------------------------ | +| {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Testing Point3d array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp as (SELECT e.array_p3d FROM aps.TestElement e LIMIT 1) select array_p3d from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_p3d | false | 0 | array_p3d | array_p3d | undefined | point3d | PrimitiveArray | array_p3d | + +| array_p3d | +| ------------------------------------------------------------------------- | +| [{"X": -1,"Y": 2.3,"Z": 3.0001},{"X": -111.11,"Y": -222.22,"Z": -333.33}] | + +# Testing Integer props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | undefined | int | Int | + +| x | +| --- | +| 100 | + +# Testing Integer array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.array_i FROM aps.TestElement e LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------------- | +| | x | true | 0 | x | x | undefined | int | PrimitiveArray | + +| x | +| --------- | +| [0, 1, 2] | + +# Testing Long props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.l FROM aps.TestElement e order by e.l LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | +| | x | true | 0 | x | x | undefined | long | Int64 | + +| x | +| ---- | +| 1000 | + +# Testing Long array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.array_l FROM aps.TestElement e LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------------- | +| | x | true | 0 | x | x | undefined | long | PrimitiveArray | + +| x | +| --------------------- | +| [10000, 20000, 30000] | + +# Testing Decimal props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.d FROM aps.TestElement e order by e.d LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | +| | x | true | 0 | x | x | undefined | double | Double | + +| x | +| --- | +| 0.1 | + +# Testing Decimal array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.array_d FROM aps.TestElement e LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------------- | +| | x | true | 0 | x | x | undefined | double | PrimitiveArray | + +| x | +| --------------- | +| [0.0, 1.1, 2.2] | + +# Testing Date time props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.dt FROM aps.TestElement e order by e.dt LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | +| | x | true | 0 | x | x | undefined | dateTime | DateTime | + +| x | +| ----------------------- | +| 2010-01-01T11:11:11.000 | + +# Testing Date time array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.array_dt FROM aps.TestElement e LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------------- | +| | x | true | 0 | x | x | undefined | dateTime | PrimitiveArray | + +| x | +| ------------------------------------------------------ | +| ["2017-01-01T00:00:00.000", "2010-01-01T11:11:11.000"] | + +# Testing string props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.s FROM aps.TestElement e order by e.s LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | +| | x | true | 0 | x | x | undefined | string | String | + +| x | +| ---- | +| str0 | + +# Testing string array props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.array_s FROM aps.TestElement e LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------------- | +| | x | true | 0 | x | x | undefined | string | PrimitiveArray | + +| x | +| ------------------ | +| ["s0", "s1", "s2"] | + +# Testing classId props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.ECClassId FROM aps.TestElement e LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | ClassId | long | Id | + +| x | +| ----- | +| 0x153 | + +# Testing classId props with convertClassIdsToClassNames flag using CTE + +- dataset: AllProperties.bim +- convertClassIdsToClassNames: true + +```sql +with tmp(x) as (SELECT e.ECClassId FROM aps.TestElement e LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | ClassId | long | Id | + +| x | +| ----- | +| 0x153 | + +# Testing classId props with convertClassIdsToClassNames flag using CTE subquery + +- dataset: AllProperties.bim +- convertClassIdsToClassNames: true + +```sql +select x from (with tmp(x) as (SELECT e.ECClassId FROM aps.TestElement e LIMIT 1) select x from tmp) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | ClassId | long | Id | + +| x | +| ----- | +| 0x153 | + +# Testing InstanceId props using CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.ECInstanceId FROM aps.TestElement e order by e.ECInstanceId LIMIT 1) select x from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | Id | long | Id | + +| x | +| ---- | +| 0x14 | + +# Testing prop aliasing in CTE + +- dataset: AllProperties.bim + +```sql +with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x y from tmp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | y | true | 0 | y | y | undefined | int | Int | + +| y | +| --- | +| 100 | + +# Testing prop aliasing in CTE subquery + +- dataset: AllProperties.bim + +```sql +select y from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x y from tmp) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | y | true | 0 | y | y | undefined | int | Int | + +| y | +| --- | +| 100 | + +# Testing table aliasing in CTE for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select temp1.x from tmp temp1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ---- | +| | temp1.x | true | 0 | temp1.x | temp1.x | undefined | int | Int | + +| temp1.x | +| ------- | +| 100 | + +# Testing table aliasing in CTE for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select temp1.x from tmp temp1 +``` + +```json +{ + "columns": [ + { + "accessString": "temp1.x", + "name": "temp1__x002E__x", + "type": "Int", + "typeName": "int", + "generated": true, + "index": 0, + "className": "", + "jsonName": "temp.x" + } + ] +} +``` + +| temp1.x | +| ------- | +| 100 | + +# Testing table aliasing in CTE subquery + +- dataset: AllProperties.bim + +```sql +select x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x from tmp) a; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | undefined | int | Int | + +| x | +| --- | +| 100 | + +# Testing table aliasing on both inner and outer tables in CTE subquery for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +select temp1.x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select temp1.x from tmp temp1) a; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ---- | +| | temp1.x | true | 0 | temp1.x | temp1.x | undefined | int | Int | + +| temp1.x | +| ------- | +| 100 | + +# Testing table aliasing on both inner and outer tables in CTE subquery for Statement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +select temp1.x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select temp1.x from tmp temp1) a; +``` + +```json +{ + "columns": [ + { + "accessString": "temp1.x", + "name": "temp1__x002E__x", + "type": "Int", + "typeName": "int", + "generated": true, + "index": 0, + "className": "", + "jsonName": "temp.x", + "extendedType": "" + } + ] +} +``` + +| temp1.x | +| ------- | +| 100 | + +# Recursive query with simple scalar values + +- dataset: AllProperties.bim + +```sql +WITH RECURSIVE cnt (x) AS ( VALUES (100) UNION ALL SELECT x + 1 FROM cnt WHERE x < 210 ) SELECT x FROM cnt LIMIT 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | +| | x | true | 0 | x | x | undefined | long | Int64 | + +| x | +| --- | +| 100 | +| 101 | +| 102 | +| 103 | +| 104 | + +# Recursive query with interger props union scalar values + +- dataset: AllProperties.bim + +```sql +WITH RECURSIVE cte (x) AS ( SELECT e.i FROM aps.TestElement e WHERE e.i = 100 UNION ALL SELECT x + 1 FROM cte WHERE x < 104) SELECT x FROM cte +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | x | true | 0 | x | x | undefined | int | Int | + +| x | +| --- | +| 100 | +| 101 | +| 102 | +| 103 | +| 104 | + +# Expected table aliasing to fail in CTE subquery due to prop name being wrong + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +select a.x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x from tmp) a; +``` + +# Expected table aliasing for inner and outer tables to fail in CTE subquery due to prop name being wrong + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +select a.x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select temp1.x from tmp temp1) a; +``` + +# Expected classId prop test to fail with CTE subquery due to prop name being wrong + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +select tmp.x from (with tmp(x) as (SELECT e.ECClassId FROM aps.TestElement e LIMIT 1) select x from tmp) +``` diff --git a/core/backend/src/test/ecsql/queries/DataTypes.ecsql.md b/core/backend/src/test/ecsql/queries/DataTypes.ecsql.md new file mode 100644 index 000000000000..d4a57e3d4fca --- /dev/null +++ b/core/backend/src/test/ecsql/queries/DataTypes.ecsql.md @@ -0,0 +1,343 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Select Integer property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1; +``` + +| i | +| --- | +| 100 | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | + +# Select Integer array property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_i FROM aps.TestElement e LIMIT 1; +``` + +| array_i | +| --------- | +| [0, 1, 2] | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_i | false | 0 | array_i | array_i | undefined | int | PrimitiveArray | array_i | + +# Select Long property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.l FROM aps.TestElement e order by e.l LIMIT 1; +``` + +| l | +| ---- | +| 1000 | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | ------------------ | +| AllProperties:IPrimitive | l | false | 0 | l | l | undefined | long | Int64 | l | + +# Select Long array property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_l FROM aps.TestElement e LIMIT 1; +``` + +| array_l | +| --------------------- | +| [10000, 20000, 30000] | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_l | false | 0 | array_l | array_l | undefined | long | PrimitiveArray | array_l | + +# Select double property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.d FROM aps.TestElement e order by e.d LIMIT 1; +``` + +| d | +| --- | +| 0.1 | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | d | false | 0 | d | d | undefined | double | Double | d | + +# Select double array property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_d FROM aps.TestElement e LIMIT 1; +``` + +| array_d | +| --------------- | +| [0.0, 1.1, 2.2] | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_d | false | 0 | array_d | array_d | undefined | double | PrimitiveArray | array_d | + +# Select string property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.s FROM aps.TestElement e order by e.s LIMIT 1; +``` + +| s | +| ---- | +| str0 | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | s | false | 0 | s | s | undefined | string | String | s | + +# Select string array property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_s FROM aps.TestElement e LIMIT 1; +``` + +| array_s | +| ------------------ | +| ["s0", "s1", "s2"] | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_s | false | 0 | array_s | array_s | undefined | string | PrimitiveArray | array_s | + +# Select date time property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.dt FROM aps.TestElement e order by e.dt LIMIT 1; +``` + +| dt | +| ----------------------- | +| 2010-01-01T11:11:11.000 | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | dt | false | 0 | dt | dt | undefined | dateTime | DateTime | dt | + +# Select date time array property from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_dt FROM aps.TestElement e LIMIT 1; +``` + +| array_dt | +| ------------------------------------------------------ | +| ["2017-01-01T00:00:00.000", "2010-01-01T11:11:11.000"] | + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_dt | false | 0 | array_dt | array_dt | undefined | dateTime | PrimitiveArray | array_dt | + +# Select point2d from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.p2d FROM aps.TestElement e LIMIT 1; +``` + +```json +[ + { + "p2d": { + "X": 1.034, + "Y": 2.034 + } + } +] +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | p2d | false | 0 | p2d | p2d | undefined | point2d | Point2d | p2d | + +# Select point2d array from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_p2d FROM aps.TestElement e LIMIT 1; +``` + +```json +[ + { + "array_p2d": [ + { + "X": 1.034, + "Y": 2.034 + }, + { + "X": 1111.11, + "Y": 2222.22 + } + ] + } +] +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_p2d | false | 0 | array_p2d | array_p2d | undefined | point2d | PrimitiveArray | array_p2d | + +# Select point3d from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.p3d FROM aps.TestElement e LIMIT 1; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | p3d | false | 0 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| p3d | +| ------------------------------ | +| {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Select point3d array from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_p3d FROM aps.TestElement e LIMIT 1; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_p3d | false | 0 | array_p3d | array_p3d | undefined | point3d | PrimitiveArray | array_p3d | + +| array_p3d | +| ------------------------------------------------------------------------- | +| [{"X": -1,"Y": 2.3,"Z": 3.0001},{"X": -111.11,"Y": -222.22,"Z": -333.33}] | + +# Select binary data from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.bin FROM aps.TestElement e LIMIT 1; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | bin | false | 0 | bin | bin | undefined | binary | Blob | bin | + +```json +[ + { + "bin": "BIN(1,2,3)" + } +] +``` + +# Select binary array data from TestElement + +- dataset: AllProperties.bim + +```sql +SELECT e.array_bin FROM aps.TestElement e LIMIT 1; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_bin | false | 0 | array_bin | array_bin | undefined | binary | PrimitiveArray | array_bin | + +```json +[ + { + "array_bin": ["BIN(1,2,3)", "BIN(11, 21, 31, 34, 53, 21, 14, 14, 55, 22)"] + } +] +``` + +# Select binary array data from TestElement with abbreviateBlobs + +- dataset: AllProperties.bim +- abbreviateBlobs: true +- skip: abbreviate blobs does not seem to be thread safe, this affects other tests that run in parallel +- mode: ConcurrentQuery + +```sql +SELECT e.array_bin FROM aps.TestElement e LIMIT 1; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_bin | false | 0 | array_bin | array_bin | undefined | binary | PrimitiveArray | array_bin | + +```json +[ + { + "array_bin": ["{\"bytes\":3}", "{\"bytes\":10}"] + } +] +``` + +# Select binary array data from TestElement using Tables + +- dataset: AllProperties.bim + +```sql +SELECT e.array_bin FROM aps.TestElement e LIMIT 1; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_bin | false | 0 | array_bin | array_bin | undefined | binary | PrimitiveArray | array_bin | + +| array_bin | +| ------------------------------------------------------------- | +| ["BIN(1,2,3)", "BIN(11, 21, 31, 34, 53, 21, 14, 14, 55, 22)"] | + +# Select binary array data from TestElement using Tables with abbreviateBlobs + +- dataset: AllProperties.bim +- abbreviateBlobs: true +- mode: ConcurrentQuery +- skip: abbreviate blobs does not seem to be thread safe, this affects other tests that run in parallel + +```sql +SELECT e.array_bin FROM aps.TestElement e LIMIT 1; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ----------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------------- | ------------------ | +| AllProperties:IPrimitiveArray | array_bin | false | 0 | array_bin | array_bin | Json | string | PrimitiveArray | array_bin | + +| array_bin | +| ----------------------------------- | +| ["{\"bytes\":3}", "{\"bytes\":10}"] | diff --git a/core/backend/src/test/ecsql/queries/DerivedProperty.ecsql.md b/core/backend/src/test/ecsql/queries/DerivedProperty.ecsql.md new file mode 100644 index 000000000000..dfff8336eefb --- /dev/null +++ b/core/backend/src/test/ecsql/queries/DerivedProperty.ecsql.md @@ -0,0 +1,325 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Simple select for all types of derived properties + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Model, + dt, + b, + bin, + DirectStr, + DirectLong, + DirectDouble, + p2d, + p3d +FROM + aps.TestElement +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | ---------- | ---------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| BisCore:Element | Model | false | 1 | model | Model | undefined | navigation | Navigation | Model | +| AllProperties:IPrimitive | dt | false | 2 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | b | false | 3 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | bin | false | 3 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:TestElement | DirectStr | false | 4 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | DirectLong | false | 5 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 6 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | +| AllProperties:IPrimitive | p2d | false | 7 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 8 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | Model | dt | b | bin | DirectStr | DirectLong | DirectDouble | p2d | p3d | +| ------------ | -------------------------------------- | ----------------------- | ---- | ---------------------------------- | --------- | ---------- | ------------ | --------------------------- | ---------------------------------------- | +| 0x14 | {"Id": "0x11", "RelECClassId": "0x61"} | 2017-01-01T00:00:00.000 | true | BIN(1,2,3) | str0 | 1000 | 0.1 | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | +| 0x15 | {"Id": "0x11", "RelECClassId": "0x61"} | 2010-01-01T11:11:11.000 | true | BIN(11,21,31,34,53,21,14,14,55,22) | str1 | 1001 | 1.1 | {"X": 1111.11,"Y": 2222.22} | {"X": -111.11,"Y": -222.22,"Z": -333.33} | +| 0x16 | {"Id": "0x11", "RelECClassId": "0x61"} | 2017-01-01T00:00:00.000 | true | BIN(1,2,3) | str2 | 1002 | 2.1 | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | +| 0x17 | {"Id": "0x11", "RelECClassId": "0x61"} | 2010-01-01T11:11:11.000 | true | BIN(11,21,31,34,53,21,14,14,55,22) | str3 | 1003 | 3.1 | {"X": 1111.11,"Y": 2222.22} | {"X": -111.11,"Y": -222.22,"Z": -333.33} | +| 0x18 | {"Id": "0x11", "RelECClassId": "0x61"} | 2017-01-01T00:00:00.000 | true | BIN(1,2,3) | str4 | 1004 | 4.1 | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Using a computation of two columns + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, DirectLong + DirectDouble as Computed_Value from aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ----------------------------- | --------- | ----- | ----------------------------- | ----------------------------- | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Computed_Value | true | 1 | computed_Value | Computed_Value | undefined | double | Double | undefined | + +| ECInstanceId | Computed_Value | +| ------------ | ----------------------------- | +| 0x14 | 1000.1 | +| 0x15 | 1002.1 | +| 0x16 | 1004.1 | +| 0x17 | 1006.1 | +| 0x18 | 1008.1 | +| 0x19 | 1010.1 | +| 0x1a | 1012.1 | +| 0x1b | 1014.1 | +| 0x1c | 1016.1 | +| 0x1d | 1018.1 | + +# Using a computation of three columns + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, i + d + DirectLong + DirectDouble - l as Computed_Column from aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | --------------- | --------- | ----- | --------------- | --------------- | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Computed_Column | true | 1 | computed_Column | Computed_Column | undefined | double | Double | undefined | + +| ECInstanceId | Computed_Column | +| ------------ | ------------------ | +| 0x14 | 100.19999999999982 | +| 0x15 | 103.19999999999982 | +| 0x16 | 106.19999999999982 | +| 0x17 | 109.19999999999982 | +| 0x18 | 112.19999999999982 | +| 0x19 | 115.19999999999982 | +| 0x1a | 118.19999999999982 | +| 0x1b | 121.19999999999982 | +| 0x1c | 124.19999999999982 | +| 0x1d | 127.19999999999982 | + +# Using derived property in a subquery + +- dataset: AllProperties.bim + +```sql +SELECT + subquery.Id, + subquery.Computed_Val +FROM + ( + SELECT + ECInstanceId AS Id, + (DirectLong + DirectDouble) AS Computed_Val + FROM + aps.TestElement + ) subquery +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | +| | Id | true | 0 | id | Id | Id | long | Id | +| | Computed_Val | true | 1 | computed_Val | Computed_Val | undefined | double | Double | + +| Id | Computed_Val | +| ---- | ------------ | +| 0x14 | 1000.1 | +| 0x15 | 1002.1 | +| 0x16 | 1004.1 | +| 0x17 | 1006.1 | +| 0x18 | 1008.1 | +| 0x19 | 1010.1 | +| 0x1a | 1012.1 | +| 0x1b | 1014.1 | +| 0x1c | 1016.1 | +| 0x1d | 1018.1 | + +# Using UPPER and LOWER functions + +- dataset: AllProperties.bim + +```sql +SELECT + UPPER(DirectStr) AS uppercase, + LOWER(s) AS lowercase +FROM + aps.TestElement +ORDER BY + lowercase DESC +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | +| | uppercase | true | 0 | uppercase | uppercase | undefined | string | String | +| | lowercase | true | 1 | lowercase | lowercase | undefined | string | String | + +| uppercase | lowercase | +| --------- | --------- | +| STR9 | str9 | +| STR8 | str8 | +| STR7 | str7 | +| STR6 | str6 | +| STR5 | str5 | +| STR4 | str4 | +| STR3 | str3 | +| STR2 | str2 | +| STR1 | str1 | +| STR0 | str0 | + +# Using Case + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + CASE + WHEN DirectLong > ( + SELECT + AVG(DirectLong) + FROM + aps.TestElement + ) THEN 'Lower' + ELSE 'Higher' + END AS Column_Check +FROM + aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Column_Check | true | 1 | column_Check | Column_Check | undefined | string | String | undefined | + +| ECInstanceId | Column_Check | +| ------------ | ------------ | +| 0x14 | Higher | +| 0x15 | Higher | +| 0x16 | Higher | +| 0x17 | Higher | +| 0x18 | Higher | +| 0x19 | Lower | +| 0x1a | Lower | +| 0x1b | Lower | +| 0x1c | Lower | +| 0x1d | Lower | + +# With string functions + +- dataset: AllProperties.bim + +```sql +SELECT + s || ' ' || DirectStr AS spaced_str, + concat_ws (',', s, DirectStr) AS separated_str, + ltrim(DirectStr, 'str') AS left_trimmed +FROM + aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ------ | +| | spaced_str | true | 0 | spaced_str | spaced_str | undefined | string | String | +| | separated_str | true | 1 | separated_str | separated_str | undefined | string | String | +| | left_trimmed | true | 2 | left_trimmed | left_trimmed | undefined | string | String | + +| spaced_str | separated_str | left_trimmed | +| ---------- | ------------- | ------------ | +| str0 str0 | str0,str0 | "0" | +| str1 str1 | str1,str1 | "1" | +| str2 str2 | str2,str2 | "2" | +| str3 str3 | str3,str3 | "3" | +| str4 str4 | str4,str4 | "4" | +| str5 str5 | str5,str5 | "5" | +| str6 str6 | str6,str6 | "6" | +| str7 str7 | str7,str7 | "7" | +| str8 str8 | str8,str8 | "8" | +| str9 str9 | str9,str9 | "9" | + +# With Window function + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Model.Id AS ModelId, + ROW_NUMBER() OVER ( + PARTITION BY + NullProp + ) AS RowNum +FROM + aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ModelId | true | 1 | modelId | ModelId | NavId | long | Id | Id | +| | RowNum | true | 2 | rowNum | RowNum | undefined | long | Int64 | undefined | + +| ECInstanceId | ModelId | RowNum | +| ------------ | ------- | ------ | +| 0x14 | 0x11 | 1 | +| 0x16 | 0x11 | 2 | +| 0x18 | 0x11 | 3 | +| 0x1a | 0x11 | 4 | +| 0x1c | 0x11 | 5 | +| 0x15 | 0x11 | 1 | +| 0x17 | 0x11 | 2 | +| 0x19 | 0x11 | 3 | +| 0x1b | 0x11 | 4 | +| 0x1d | 0x11 | 5 | + +# Order by with Window function + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + Model.Id AS ModelId, + ROW_NUMBER() OVER ( + PARTITION BY + NullProp + ) AS RowNum +FROM + aps.TestElement +ORDER BY + RowNum DESC +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ModelId | true | 1 | modelId | ModelId | NavId | long | Id | Id | +| | RowNum | true | 2 | rowNum | RowNum | undefined | long | Int64 | undefined | + +| ECInstanceId | ModelId | RowNum | +| ------------ | ------- | ------ | +| 0x1c | 0x11 | 5 | +| 0x1d | 0x11 | 5 | +| 0x1a | 0x11 | 4 | +| 0x1b | 0x11 | 4 | +| 0x18 | 0x11 | 3 | +| 0x19 | 0x11 | 3 | +| 0x16 | 0x11 | 2 | +| 0x17 | 0x11 | 2 | +| 0x14 | 0x11 | 1 | +| 0x15 | 0x11 | 1 | + +# Group by nav prop + +- dataset: AllProperties.bim + +```sql +SELECT Model.Id AS ModelId, COUNT(*) AS ElementCount FROM Bis.Element GROUP BY ModelId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ----- | ------------------ | +| | ModelId | true | 0 | modelId | ModelId | NavId | long | Id | Id | +| | ElementCount | true | 1 | elementCount | ElementCount | undefined | long | Int64 | undefined | + +| ModelId | ElementCount | +| ------- | ------------ | +| 0x1 | 4 | +| 0x10 | 2 | +| 0x11 | 12 | diff --git a/core/backend/src/test/ecsql/queries/EnumValueExpTests.ecsql.md b/core/backend/src/test/ecsql/queries/EnumValueExpTests.ecsql.md new file mode 100644 index 000000000000..7b5d2e4e0f37 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/EnumValueExpTests.ecsql.md @@ -0,0 +1,147 @@ +# Testing Enum prop of backing type int + +- dataset: AllProperties.bim + +```sql +SELECT EnumIntProp from aps.TestElement limit 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | ------------------------- | ---- | ------------------ | +| AllProperties:TestElement | EnumIntProp | false | 0 | enumIntProp | EnumIntProp | undefined | AllProperties.TestIntEnum | Int | EnumIntProp | + +| EnumIntProp | +| ----------- | +| 1 | +| 2 | +| 1 | +| 2 | + +# Testing Enum prop of backing type string + +- dataset: AllProperties.bim + +```sql +SELECT EnumStringProp from aps.TestElement limit 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | -------------- | --------- | ----- | -------------- | -------------- | ------------ | ---------------------------- | ------ | ------------------ | +| AllProperties:TestElement | EnumStringProp | false | 0 | enumStringProp | EnumStringProp | undefined | AllProperties.TestStringEnum | String | EnumStringProp | + +| EnumStringProp | +| -------------- | +| "1" | +| "2" | +| "1" | +| "2" | + +# Testing Enum array prop of backing type string + +- dataset: AllProperties.bim + +```sql +SELECT EnumStringPropArr from aps.TestElement limit 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ----------------- | --------- | ----- | ----------------- | ----------------- | ------------ | ---------------------------- | -------------- | ------------------ | +| AllProperties:TestElement | EnumStringPropArr | false | 0 | enumStringPropArr | EnumStringPropArr | undefined | AllProperties.TestStringEnum | PrimitiveArray | EnumStringPropArr | + +| EnumStringPropArr | +| ----------------- | +| ["1", "2", "3"] | +| ["1", "2", "3"] | +| ["1", "2", "3"] | +| ["1", "2", "3"] | + +# Testing Enum array prop of backing type int + +- dataset: AllProperties.bim + +```sql +SELECT EnumIntPropArr from aps.TestElement limit 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | -------------- | --------- | ----- | -------------- | -------------- | ------------ | ------------------------- | -------------- | ------------------ | +| AllProperties:TestElement | EnumIntPropArr | false | 0 | enumIntPropArr | EnumIntPropArr | undefined | AllProperties.TestIntEnum | PrimitiveArray | EnumIntPropArr | + +| EnumIntPropArr | +| -------------- | +| [1, 2, 3] | +| [1, 2, 3] | +| [1, 2, 3] | +| [1, 2, 3] | + +# Testing Enum prop of backing type int with enumValueExp in where clause + +- dataset: AllProperties.bim + +```sql +SELECT EnumIntProp from aps.TestElement where EnumIntProp = aps.TestIntEnum.One limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | ------------------------- | ---- | ------------------ | +| AllProperties:TestElement | EnumIntProp | false | 0 | enumIntProp | EnumIntProp | undefined | AllProperties.TestIntEnum | Int | EnumIntProp | + +| EnumIntProp | +| ----------- | +| 1 | +| 1 | + +# Testing Enum prop of backing type int with enumValueExp in where clause + +- dataset: AllProperties.bim + +```sql +SELECT EnumIntProp from aps.TestElement where EnumIntProp <= aps.TestIntEnum.Two limit 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | ------------------------- | ---- | ------------------ | +| AllProperties:TestElement | EnumIntProp | false | 0 | enumIntProp | EnumIntProp | undefined | AllProperties.TestIntEnum | Int | EnumIntProp | + +| EnumIntProp | +| ----------- | +| 1 | +| 2 | +| 1 | +| 2 | + +# Testing Enum prop of backing type string with enumValueExp in where clause + +- dataset: AllProperties.bim + +```sql +SELECT EnumStringProp from aps.TestElement where EnumStringProp = aps.TestStringEnum.One limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | -------------- | --------- | ----- | -------------- | -------------- | ------------ | ---------------------------- | ------ | ------------------ | +| AllProperties:TestElement | EnumStringProp | false | 0 | enumStringProp | EnumStringProp | undefined | AllProperties.TestStringEnum | String | EnumStringProp | + +| EnumStringProp | +| -------------- | +| "1" | +| "1" | + +# Testing Enum prop of backing type string with enumValueExp in where clause + +- dataset: AllProperties.bim + +```sql +SELECT EnumStringProp from aps.TestElement where EnumStringProp >= aps.TestStringEnum.One limit 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | -------------- | --------- | ----- | -------------- | -------------- | ------------ | ---------------------------- | ------ | ------------------ | +| AllProperties:TestElement | EnumStringProp | false | 0 | enumStringProp | EnumStringProp | undefined | AllProperties.TestStringEnum | String | EnumStringProp | + +| EnumStringProp | +| -------------- | +| "1" | +| "2" | +| "1" | +| "2" | diff --git a/core/backend/src/test/ecsql/queries/Examples.ecsql.md b/core/backend/src/test/ecsql/queries/Examples.ecsql.md new file mode 100644 index 000000000000..95da87ef50f6 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/Examples.ecsql.md @@ -0,0 +1,109 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Select ECDb schemas from ECDbMeta using tables + +- mode: Statement +- dataset: AllProperties.bim + +```sql +Select s.Name, s.Alias from meta.ECSchemaDef s WHERE s.Name LIKE 'ECDb%' LIMIT 4; +``` + +| name | type | +| ----- | ------ | +| Name | String | +| Alias | String | + +| Name | Alias | +| ------------------ | ------- | +| ECDbFileInfo | ecdbf | +| ECDbMap | ecdbmap | +| ECDbMeta | meta | +| ECDbSchemaPolicies | ecdbpol | + +# Select Test elements from sample dataset using Json + +- dataset: AllProperties.bim + +```sql +SELECT e.ECClassId, e.DirectStr FROM aps.TestElement e WHERE e.DirectLong > 1005 ORDER BY e.DirectLong LIMIT 2 +``` + +```json +{ + "columns": [ + { + "accessString": "ECClassId", + "name": "ECClassId", + "type": "Id", + "typeName": "long", + "generated": false, + "extendedType": "ClassId" + }, + { + "accessString": "DirectStr", + "name": "DirectStr", + "type": "String", + "typeName": "string", + "generated": false + } + ] +} +``` + +```json +[ + { + "ECClassId": "0x153", + "DirectStr": "str6" + }, + { + "ECClassId": "0x153", + "DirectStr": "str7" + } +] +``` + +# Select Test elements from sample dataset with convertClassIdsToClassNames flag using Json + +- dataset: AllProperties.bim +- convertClassIdsToClassNames: true + +```sql +SELECT e.ECClassId, e.DirectStr FROM aps.TestElement e WHERE e.DirectLong > 1005 ORDER BY e.DirectLong LIMIT 2 +``` + +```json +{ + "columns": [ + { + "accessString": "ECClassId", + "name": "ECClassId", + "type": "Id", + "typeName": "long", + "generated": false, + "extendedType": "ClassId" + }, + { + "accessString": "DirectStr", + "name": "DirectStr", + "type": "String", + "typeName": "string", + "generated": false + } + ] +} +``` + +```json +[ + { + "ECClassId": "AllProperties.TestElement", + "DirectStr": "str6" + }, + { + "ECClassId": "AllProperties.TestElement", + "DirectStr": "str7" + } +] +``` diff --git a/core/backend/src/test/ecsql/queries/ExtractInstance_ExtractProp.ecsql.md b/core/backend/src/test/ecsql/queries/ExtractInstance_ExtractProp.ecsql.md new file mode 100644 index 000000000000..e4f170bcc6c9 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/ExtractInstance_ExtractProp.ecsql.md @@ -0,0 +1,538 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Testing point2d for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> p2d from aps.TestElement limit 2 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "$->p2d", + "generated": true, + "index": 0, + "jsonName": "$->p2d", + "name": "$->p2d", + "extendedType": "json", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + "$->p2d": "{\"X\":1.034,\"Y\":2.034}" + }, + { + "$->p2d": "{\"X\":1111.11,\"Y\":2222.22}" + } +] +``` + +# Testing point2d for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> p2d from aps.TestElement limit 2 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "$->p2d", + "generated": true, + "index": 0, + "jsonName": "$->p2d", + "name": "__x0024____x002D____x003E__p2d", + "extendedType": "json", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + "$->p2d": "{\"X\":1.034,\"Y\":2.034}" + }, + { + "$->p2d": "{\"X\":1111.11,\"Y\":2222.22}" + } +] +``` + +# Testing Point3d for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> p3d from aps.TestElement limit 2 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "$->p3d", + "generated": true, + "index": 0, + "jsonName": "$->p3d", + "name": "$->p3d", + "extendedType": "json", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + "$->p3d": "{\"X\":-1.0,\"Y\":2.3,\"Z\":3.0001}" + }, + { + "$->p3d": "{\"X\":-111.11,\"Y\":-222.22,\"Z\":-333.33}" + } +] +``` + +# Testing Point3d for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> p3d from aps.TestElement limit 2 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "$->p3d", + "generated": true, + "index": 0, + "jsonName": "$->p3d", + "name": "__x0024____x002D____x003E__p3d", + "extendedType": "json", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + "$->p3d": "{\"X\":-1.0,\"Y\":2.3,\"Z\":3.0001}" + }, + { + "$->p3d": "{\"X\":-111.11,\"Y\":-222.22,\"Z\":-333.33}" + } +] +``` + +# Testing Integers for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> i from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| | $->i | true | 0 | $->i | $->i | json | string | Int | i | + +| $->i | +| ---- | +| 100 | +| 101 | + +# Testing Integers for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> i from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| | i | false | 0 | i | i | json | string | Int | i | + +| i | +| --- | +| 100 | +| 101 | + +# Testing double prop using alias for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> d double_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| | double_prop | true | 0 | double_prop | double_prop | json | string | Double | d | + +| double_prop | +| ----------- | +| 0.1 | +| 1.1 | + +# Testing double prop using alias for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> d double_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| | d | false | 0 | d | d | json | string | Double | d | + +| d | +| --- | +| 0.1 | +| 1.1 | + +# Testing long prop using alias for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> l long_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ----- | ------------------ | +| | long_prop | true | 0 | long_prop | long_prop | json | string | Int64 | l | + +| long_prop | +| --------- | +| 1000 | +| 1001 | + +# Testing long prop using alias for ECsqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> l long_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | ------------------ | +| | l | false | 0 | l | l | json | string | Int64 | l | + +| l | +| ---- | +| 1000 | +| 1001 | + +# Testing string prop using alias for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> s string_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| | string_prop | true | 0 | string_prop | string_prop | json | string | String | s | + +| string_prop | +| ----------- | +| str0 | +| str1 | + +# Testing string prop using alias for ECsqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> s string_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| | s | false | 0 | s | s | json | string | String | s | + +| s | +| ---- | +| str0 | +| str1 | + +# Testing date time prop using alias for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> dt dateTime_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | -------- | ------------------ | +| | dateTime_prop | true | 0 | dateTime_prop | dateTime_prop | json | string | DateTime | dt | + +| dateTime_prop | +| ----------------------- | +| 2017-01-01T00:00:00.000 | +| 2010-01-01T11:11:11.000 | + +# Testing date time prop using alias for ECsqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> dt dateTime_prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| | dt | false | 0 | dt | dt | json | string | DateTime | dt | + +| dt | +| ----------------------- | +| 2017-01-01T00:00:00.000 | +| 2010-01-01T11:11:11.000 | + +# Testing binary prop using alias for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT $ -> bin binary_Prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ---- | ------------------ | +| | binary_Prop | true | 0 | binary_Prop | binary_Prop | json | string | Blob | bin | + +| binary_Prop | +| ------------------------------------------- | +| BIN(1, 2, 3) | +| BIN(11, 21, 31, 34, 53, 21, 14, 14, 55, 22) | + +# Testing binary prop using alias for ECsqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT $ -> bin binary_Prop from aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | ------------------ | +| | bin | false | 0 | bin | bin | json | string | Blob | bin | + +| bin | +| ------------------------------------------- | +| BIN(1, 2, 3) | +| BIN(11, 21, 31, 34, 53, 21, 14, 14, 55, 22) | + +# Testing point2d_X prop + +- dataset: AllProperties.bim + +```sql +SELECT $ -> p2d.X p2dX_prop from aps.TestElement limit 2 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "p2dX_prop", + "generated": true, + "index": 0, + "jsonName": "p2dX_prop", + "name": "p2dX_prop", + "extendedType": "json", + "typeName": "string" + } + ] +} +``` + +```json +[] +``` + +# Testing ExtractInstance in where clause + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId from aps.TestElement where FLOOR($->d) = 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x15 | + +# Testing ExtractInstance for non-existant required prop in where clause + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId from aps.TestElement where FLOOR($->abc) = 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | + +# Testing ExtractInstance for optional prop in where clause + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId from aps.TestElement where FLOOR($->abc?) = 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | + +# Testing ExtractInstance for optional prop and required prop using AND op in where clause + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId from aps.TestElement where FLOOR($->d) = 1 and FLOOR($->abc?) = 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | + +# Testing ExtractInstance for optional prop and required prop using OR op in where clause + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId from aps.TestElement where FLOOR($->d) = 1 or FLOOR($->abc?) = 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x15 | + +# Testing integer array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_i intArray_Prop from aps.TestElement limit 1 +``` + +# Testing long array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_l longArray_Prop from aps.TestElement limit 1 +``` + +# Testing double array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_d doubleArray_Prop from aps.TestElement limit 1 +``` + +# Testing string array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_s StringArray_Prop from aps.TestElement limit 1 +``` + +# Testing date time array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_dt dateTimeArray_Prop from aps.TestElement limit 1 +``` + +# Testing point 2d array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_p2d Point2DArray_Prop from aps.TestElement limit 1 +``` + +# Testing point 3d array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_p3d Point3DArray_Prop from aps.TestElement limit 1 +``` + +# Testing binary array prop using alias + +- dataset: AllProperties.bim +- skip: The query in the test causes a crash on the backend + +```sql +SELECT $ -> array_bin BinaryArray_Prop from aps.TestElement limit 1 +``` diff --git a/core/backend/src/test/ecsql/queries/FromClause.ecsql.md b/core/backend/src/test/ecsql/queries/FromClause.ecsql.md new file mode 100644 index 000000000000..036a6b7a635d --- /dev/null +++ b/core/backend/src/test/ecsql/queries/FromClause.ecsql.md @@ -0,0 +1,395 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# With a single table + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + i, + DirectStr, + DirectLong, + DirectDouble +FROM aps.TestElement +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:IPrimitive | i | false | 3 | i | i | undefined | int | Int | i | +| AllProperties:TestElement | DirectStr | false | 4 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | DirectLong | false | 5 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 6 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | i | DirectStr | DirectLong | DirectDouble | +| ------------ | --------- | ---- | --- | --------- | ---------- | ------------ | +| 0x14 | 0x153 | 0x11 | 100 | str0 | 1000 | 0.1 | + +# Using a table alias + +- dataset: AllProperties.bim + +```sql +SELECT + test.ECInstanceId, + test.ECClassId, + test.Model.Id, + test.i, + test.DirectStr, + test.DirectLong, + test.DirectDouble +FROM + aps.TestElement test +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:IPrimitive | i | false | 3 | i | i | undefined | int | Int | i | +| AllProperties:TestElement | DirectStr | false | 4 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | DirectLong | false | 5 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 6 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | i | DirectStr | DirectLong | DirectDouble | +| ------------ | --------- | ---- | --- | --------- | ---------- | ------------ | +| 0x14 | 0x153 | 0x11 | 100 | str0 | 1000 | 0.1 | + +# With an inner join + +- dataset: AllProperties.bim + +```sql +SELECT + t.ECInstanceId, + t.Model.Id, + t.DirectStr, + c.Name +FROM + aps.TestElement t + INNER JOIN meta.ECClassDef c ON c.ECInstanceId = t.ECClassId +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Model.Id | false | 1 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 2 | directStr | DirectStr | undefined | string | String | DirectStr | +| ECDbMeta:ECClassDef | Name | false | 3 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Id | DirectStr | Name | +| ------------ | ---- | --------- | ----------- | +| 0x14 | 0x11 | str0 | TestElement | + +# With a right join + +- dataset: AllProperties.bim + +```sql +SELECT + t.ECInstanceId, + t.Model.Id, + t.DirectStr, + c.Name +FROM + aps.TestElement t + RIGHT JOIN meta.ECClassDef c ON c.ECInstanceId = t.ECClassId +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Model.Id | false | 1 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 2 | directStr | DirectStr | undefined | string | String | DirectStr | +| ECDbMeta:ECClassDef | Name | false | 3 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Id | DirectStr | Name | +| ------------ | ---- | --------- | ----------- | +| 0x14 | 0x11 | str0 | TestElement | + +# With a left join + +- dataset: AllProperties.bim + +```sql +SELECT + t.ECInstanceId, + t.Model.Id, + t.DirectStr, + c.Name +FROM + aps.TestElement t + LEFT JOIN meta.ECClassDef c ON c.ECInstanceId = t.ECClassId +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Model.Id | false | 1 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 2 | directStr | DirectStr | undefined | string | String | DirectStr | +| ECDbMeta:ECClassDef | Name | false | 3 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Id | DirectStr | Name | +| ------------ | ---- | --------- | ----------- | +| 0x14 | 0x11 | str0 | TestElement | + +# With a full join + +- dataset: AllProperties.bim + +```sql +SELECT + t.ECInstanceId, + t.Model.Id, + t.DirectStr, + c.Name +FROM + aps.TestElement t + FULL JOIN meta.ECClassDef c ON c.ECInstanceId = t.ECClassId +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Model.Id | false | 1 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 2 | directStr | DirectStr | undefined | string | String | DirectStr | +| ECDbMeta:ECClassDef | Name | false | 3 | name | Name | undefined | string | String | Name | + +| ECInstanceId | Id | DirectStr | Name | +| ------------ | ---- | --------- | ----------- | +| 0x14 | 0x11 | str0 | TestElement | + +# With multiple joins + +- dataset: AllProperties.bim + +```sql +SELECT + t.ECInstanceId AS Id, + t.Model.Id AS ModelId, + t.DirectStr AS DirectStr, + c.Name AS ClassName, + s.Name AS SchemaName +FROM + aps.TestElement t + INNER JOIN meta.ECClassDef c ON c.ECInstanceId = t.ECClassId + LEFT JOIN meta.ECSchemaDef s ON c.Schema.Id = s.ECInstanceId +LIMIT + 1 +``` + +# With a subquery + +- dataset: AllProperties.bim + +```sql +SELECT + sub.Id, + sub.ClassId +FROM + ( + SELECT + ECInstanceId as Id, + ECClassId as ClassId + FROM + aps.TestElement + ) sub +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ---- | +| | Id | true | 0 | id | Id | Id | long | Id | +| | ClassId | true | 1 | classId | ClassId | ClassId | long | Id | + +| Id | ClassId | +| ---- | ------- | +| 0x14 | 0x153 | +| 0x15 | 0x153 | +| 0x16 | 0x153 | +| 0x17 | 0x153 | +| 0x18 | 0x153 | + +# With joins and subquery + +- dataset: AllProperties.bim + +```sql +SELECT + sub.ECInstanceId, + sub.ECClassId, + sub.Model.Id, + sub.i, + sub.DirectStr, + sub.DirectLong, + sub.DirectDouble +FROM + ( + SELECT + * + FROM + aps.TestElement e + LEFT JOIN ( + SELECT + * + FROM + meta.ECClassDef + ) c ON c.ECInstanceId = e.ECClassId + LIMIT + 4 + ) sub +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:IPrimitive | i | false | 3 | i | i | undefined | int | Int | i | +| AllProperties:TestElement | DirectStr | false | 4 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | DirectLong | false | 5 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 6 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | i | DirectStr | DirectLong | DirectDouble | +| ------------ | --------- | ---- | --- | --------- | ---------- | ------------ | +| 0x14 | 0x153 | 0x11 | 100 | str0 | 1000 | 0.1 | +| 0x15 | 0x153 | 0x11 | 101 | str1 | 1001 | 1.1 | +| 0x16 | 0x153 | 0x11 | 102 | str2 | 1002 | 2.1 | +| 0x17 | 0x153 | 0x11 | 103 | str3 | 1003 | 3.1 | + +# With Distinct keyword + +- dataset: AllProperties.bim + +```sql +SELECT DISTINCT(ECClassId) from Bis.Element +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ---- | ------------------ | +| | ECClassId | false | 0 | className | ECClassId | ClassId | long | Id | ECClassId | + +| ECClassId | +| --------- | +| 0x89 | +| 0x98 | +| 0xc5 | +| 0xdd | +| 0xf0 | +| 0x126 | +| 0x153 | +| 0x157 | + +# With Union + +- dataset: AllProperties.bim + +```sql +SELECT + ec_classname (ECClassId) AS ClassName +FROM + aps.TestElement +UNION +SELECT + ec_classname (ECClassId) AS ClassName +FROM + aps.TestElementAspect +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | +| | ClassName | true | 0 | className | ClassName | undefined | string | String | + +| ClassName | +| ------------------------------- | +| AllProperties:TestElement | +| AllProperties:TestElementAspect | + +# With Union All + +- dataset: AllProperties.bim + +```sql +SELECT + ec_classname (ECClassId) AS ClassName +FROM + aps.TestElement +UNION ALL +SELECT + ec_classname (ECClassId) AS ClassName +FROM + aps.TestElementAspect +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | +| | ClassName | true | 0 | className | ClassName | undefined | string | String | + +| ClassName | +| ------------------------------- | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElement | +| AllProperties:TestElementAspect | +| AllProperties:TestElementAspect | +| AllProperties:TestElementAspect | +| AllProperties:TestElementAspect | +| AllProperties:TestElementAspect | + +# With multiple tables + +- dataset: AllProperties.bim + +```sql +SELECT + e.ECInstanceId AS ElementId, + e.ECClassId AS ElementClass, + a.ECInstanceID AS AspectId, + a.ECClassId AS AspectClass +FROM + aps.TestElement e, + aps.TestElementAspect a +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ---- | ------------------ | +| | ElementId | true | 0 | elementId | ElementId | Id | long | Id | ECInstanceId | +| | ElementClass | true | 1 | elementClass | ElementClass | ClassId | long | Id | ECClassId | +| | AspectId | true | 2 | aspectId | AspectId | Id | long | Id | ECInstanceId | +| | AspectClass | true | 3 | aspectClass | AspectClass | ClassId | long | Id | ECClassId | + +| ElementId | ElementClass | AspectId | AspectClass | +| --------- | ------------ | -------- | ----------- | +| 0x14 | 0x153 | 0x21 | 0x154 | +| 0x14 | 0x153 | 0x22 | 0x154 | +| 0x14 | 0x153 | 0x23 | 0x154 | +| 0x14 | 0x153 | 0x24 | 0x154 | +| 0x14 | 0x153 | 0x25 | 0x154 | diff --git a/core/backend/src/test/ecsql/queries/GroupByClause.ecsql.md b/core/backend/src/test/ecsql/queries/GroupByClause.ecsql.md new file mode 100644 index 000000000000..7bdaf23de7cd --- /dev/null +++ b/core/backend/src/test/ecsql/queries/GroupByClause.ecsql.md @@ -0,0 +1,498 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# With Count function + +- dataset: AllProperties.bim + +```sql +SELECT NullProp, count(*) as Total_Count FROM aps.TestElement GROUP BY NullProp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Total_Count | true | 1 | total_Count | Total_Count | undefined | long | Int64 | undefined | + +| Total_Count | NullProp | +| ----------- | --------- | +| 5 | undefined | +| 5 | NotNull | + +# With Sum function + +- dataset: AllProperties.bim + +```sql +SELECT NullProp, SUM(DirectLong) as Total_Sum FROM aps.TestElement GROUP BY NullProp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Total_Sum | true | 1 | total_Sum | Total_Sum | undefined | long | Int64 | undefined | + +| Total_Sum | NullProp | +| --------- | --------- | +| 5020 | undefined | +| 5025 | NotNull | + +# With Avg function + +- dataset: AllProperties.bim + +```sql +SELECT NullProp, Avg(DirectLong) as Average_Val FROM aps.TestElement GROUP BY NullProp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Average_Val | true | 1 | average_Val | Average_Val | undefined | double | Double | undefined | + +| Average_Val | NullProp | +| ----------- | --------- | +| 1004 | undefined | +| 1005 | NotNull | + +# With Min function + +- dataset: AllProperties.bim + +```sql +SELECT NullProp, Min(DirectLong) as Minimum_Val FROM aps.TestElement GROUP BY NullProp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Minimum_Val | true | 1 | minimum_Val | Minimum_Val | undefined | long | Int64 | undefined | + +| Minimum_Val | NullProp | +| ----------- | --------- | +| 1000 | undefined | +| 1001 | NotNull | + +# With Max function + +- dataset: AllProperties.bim + +```sql +SELECT NullProp, Max(DirectLong) as Maximum_Val FROM aps.TestElement GROUP BY NullProp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Maximum_Val | true | 1 | maximum_Val | Maximum_Val | undefined | long | Int64 | undefined | + +| Maximum_Val | NullProp | +| ----------- | --------- | +| 1008 | undefined | +| 1009 | NotNull | + +# With multiple columns + +- dataset: AllProperties.bim + +```sql +SELECT count(*) as Total_Count, bin, NullProp FROM aps.TestElement group by bin, nullprop +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| | Total_Count | true | 0 | total_Count | Total_Count | undefined | long | Int64 | undefined | +| AllProperties:IPrimitive | bin | false | 1 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:TestElement | NullProp | false | 2 | nullProp | NullProp | undefined | string | String | NullProp | + +| Total_Count | bin | NullProp | +| ----------- | ---------------------------------- | --------- | +| 5 | BIN(1,2,3) | undefined | +| 5 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | + +# With Having clause + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong, + NullProp +FROM + aps.TestElement +GROUP BY + NullProp +HAVING + DirectLong > 1000 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | NullProp | false | 2 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | DirectLong | NullProp | +| ------------ | ---------- | -------- | +| 0x15 | 1001 | NotNull | + +# With Having clause and Sum function + +- dataset: AllProperties.bim + +```sql +SELECT + NullProp, + SUM(DirectLong) AS Total_Sum +FROM + aps.TestElement +GROUP BY + NullProp +HAVING + Total_Sum > 5020 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Total_Sum | true | 1 | total_Sum | Total_Sum | undefined | long | Int64 | undefined | + +| NullProp | Total_Sum | +| -------- | --------- | +| NotNull | 5025 | + +# With Having clause and Avg function + +- dataset: AllProperties.bim + +```sql +SELECT + NullProp, + AVG(DirectLong) AS Average_Val +FROM + aps.TestElement +GROUP BY + NullProp +HAVING + Average_Val < 1005 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Average_Val | true | 1 | average_Val | Average_Val | undefined | double | Double | undefined | + +| Average_Val | +| ----------- | +| 1004 | + +# With Having clause and multiple aggregate functions gt check + +- dataset: AllProperties.bim + +```sql +SELECT + NullProp, + MAX(DirectLong) AS Max_Val, + MIN(DirectLong) AS Min_Val +FROM + aps.TestElement +GROUP BY + NullProp +HAVING + (Max_Val + Min_Val) / 2 > 1004 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Max_Val | true | 1 | max_Val | Max_Val | undefined | long | Int64 | undefined | +| | Min_Val | true | 2 | min_Val | Min_Val | undefined | long | Int64 | undefined | + +| NullProp | Max_Val | Min_Val | +| -------- | ------- | ------- | +| NotNull | 1009 | 1001 | + +# With Having clause and multiple aggregate functions lt check2 + +- dataset: AllProperties.bim + +```sql +SELECT + NullProp, + MAX(DirectLong) AS Max_Val, + MIN(DirectLong) AS Min_Val +FROM + aps.TestElement +GROUP BY + NullProp +HAVING + (Max_Val + Min_Val) / 2 < 1005 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Max_Val | true | 1 | max_Val | Max_Val | undefined | long | Int64 | undefined | +| | Min_Val | true | 2 | min_Val | Min_Val | undefined | long | Int64 | undefined | + +| Max_Val | Min_Val | +| ------- | ------- | +| 1008 | 1000 | + +# With multiple aggregate functions + +- dataset: AllProperties.bim + +```sql +SELECT + NullProp, + Count(*) AS Total_Count, + MAX(DirectLong) AS Max_Val, + MIN(DirectLong) AS Min_Val +FROM + aps.TestElement +GROUP BY + NullProp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | Total_Count | true | 1 | total_Count | Total_Count | undefined | long | Int64 | undefined | +| | Max_Val | true | 2 | max_Val | Max_Val | undefined | long | Int64 | undefined | +| | Min_Val | true | 3 | min_Val | Min_Val | undefined | long | Int64 | undefined | + +| Total_Count | Max_Val | Min_Val | NullProp | +| ----------- | ------- | ------- | --------- | +| 5 | 1008 | 1000 | undefined | +| 5 | 1009 | 1001 | NotNull | + +# With Case + +- dataset: AllProperties.bim + +```sql +SELECT + nullprop, + SUM(DirectLong) AS sum_Val +FROM + aps.TestElement +GROUP BY + nullprop +HAVING + SUM( + CASE + WHEN DirectDouble > 5.1 THEN DirectLong + ELSE 0 + END + ) > 2015 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | sum_Val | true | 1 | sum_Val | sum_Val | undefined | long | Int64 | undefined | + +| NullProp | sum_Val | +| -------- | ------- | +| NotNull | 5025 | + +# With Coalesce + +- dataset: AllProperties.bim + +```sql +SELECT + nullprop, + SUM(DirectLong) AS sum_Val +FROM + aps.TestElement +GROUP BY + nullprop +HAVING + Length(Coalesce(NullProp, DirectStr)) > 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| | sum_Val | true | 1 | sum_Val | sum_Val | undefined | long | Int64 | undefined | + +| NullProp | sum_Val | +| -------- | ------- | +| NotNull | 5025 | + +# With Join + +- dataset: AllProperties.bim + +```sql +SELECT + e.ECClassId, + e.Model.Id, + c.Name AS ClassName, + e.NullProp +FROM + aps.TestElement e + JOIN meta.ECClassDef c ON e.ECClassID = c.ECInstanceId +GROUP BY + nullprop +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ECClassId | false | 0 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 1 | model.id | Id | NavId | long | Id | Id | +| | ClassName | true | 2 | className_1 | ClassName | undefined | string | String | Name | +| AllProperties:TestElement | NullProp | false | 3 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECClassId | Id | ClassName | NullProp | +| --------- | ---- | ----------- | --------- | +| 0x153 | 0x11 | TestElement | undefined | +| 0x153 | 0x11 | TestElement | NotNull | + +# With a subquery + +- dataset: AllProperties.bim + +```sql +SELECT + NullProp, + bin, + COUNT(*) AS Total_Count +FROM + aps.TestElement +GROUP BY + nullprop +HAVING + Length(bin) > ( + SELECT + count(*) + FROM + aps.TestElement + GROUP BY + nullprop + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 1 | bin | bin | undefined | binary | Blob | bin | +| | Total_Count | true | 2 | total_Count | Total_Count | undefined | long | Int64 | undefined | + +| NullProp | bin | Total_Count | +| -------- | ---------------------------------- | ----------- | +| NotNull | BIN(11,21,31,34,53,21,14,14,55,22) | 5 | + +# With DISTINCT + +- dataset: AllProperties.bim + +```sql +SELECT bin, Count(Distinct(bin)) as distinct_count FROM aps.TestElement GROUP BY bin +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | -------------- | --------- | ----- | -------------- | -------------- | ------------ | -------- | ----- | ------------------ | +| AllProperties:IPrimitive | bin | false | 0 | bin | bin | undefined | binary | Blob | bin | +| | distinct_count | true | 1 | distinct_count | distinct_count | undefined | long | Int64 | undefined | + +| bin | distinct_count | +| ---------------------------------- | -------------- | +| BIN(1,2,3) | 1 | +| BIN(11,21,31,34,53,21,14,14,55,22) | 1 | + +# With where clause + +- dataset: AllProperties.bim + +```sql +SELECT + bin, + nullprop, + count(*) AS Total_Count +FROM + aps.TestElement +WHERE + DirectLong > 1005 +GROUP BY + nullprop, + bin +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | bin | false | 0 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| | Total_Count | true | 2 | total_Count | Total_Count | undefined | long | Int64 | undefined | + +| bin | Total_Count | NullProp | +| ---------------------------------- | ----------- | --------- | +| BIN(1,2,3) | 2 | undefined | +| BIN(11,21,31,34,53,21,14,14,55,22) | 2 | NotNull | + +# With order by clause + +- dataset: AllProperties.bim + +```sql +SELECT + directstr, + bin, + nullprop, + count(*) AS Total_Count +FROM + aps.TestElement +WHERE + DirectLong > 1005 +GROUP BY + nullprop +ORDER BY + bin +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | DirectStr | false | 0 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:IPrimitive | bin | false | 1 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:TestElement | NullProp | false | 2 | nullProp | NullProp | undefined | string | String | NullProp | +| | Total_Count | true | 3 | total_Count | Total_Count | undefined | long | Int64 | undefined | + +| DirectStr | bin | Total_Count | NullProp | +| --------- | ---------------------------------- | ----------- | --------- | +| str6 | BIN(1,2,3) | 2 | undefined | +| str7 | BIN(11,21,31,34,53,21,14,14,55,22) | 2 | NotNull | + +# With order by clause desc + +- dataset: AllProperties.bim + +```sql +SELECT + directstr, + bin, + nullprop, + count(*) AS Total_Count +FROM + aps.TestElement +WHERE + DirectLong > 1005 +GROUP BY + nullprop +ORDER BY + bin DESC +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ----------- | ----------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | DirectStr | false | 0 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:IPrimitive | bin | false | 1 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:TestElement | NullProp | false | 2 | nullProp | NullProp | undefined | string | String | NullProp | +| | Total_Count | true | 3 | total_Count | Total_Count | undefined | long | Int64 | undefined | + +| DirectStr | bin | NullProp | Total_Count | +| --------- | ---------------------------------- | --------- | ----------- | +| str7 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | 2 | +| str6 | BIN(1,2,3) | undefined | 2 | diff --git a/core/backend/src/test/ecsql/queries/JoinClause.ecsql.md b/core/backend/src/test/ecsql/queries/JoinClause.ecsql.md new file mode 100644 index 000000000000..33f5cd84105e --- /dev/null +++ b/core/backend/src/test/ecsql/queries/JoinClause.ecsql.md @@ -0,0 +1,526 @@ +# JOIN + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + te.i +FROM + aps.TestElement te + JOIN aps.IPrimitive p ON te.ECInstanceId = p.ECInstanceId +LIMIT + 3 +``` + +| 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 | + +| ECInstanceId | i | +| ------------ | --- | +| 0x14 | 100 | +| 0x15 | 101 | +| 0x16 | 102 | + +# INNER JOIN + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + te.i +FROM + aps.TestElement te + INNER JOIN aps.IPrimitive p ON te.ECInstanceId = p.ECInstanceId +LIMIT + 3 +``` + +| 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 | + +| ECInstanceId | i | +| ------------ | --- | +| 0x14 | 100 | +| 0x15 | 101 | +| 0x16 | 102 | + +# LEFT JOIN + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + te.i +FROM + aps.TestElement te + LEFT JOIN meta.ECSchemaDef d ON d.VersionMajor + 100 = te.i +LIMIT + 3 +``` + +| 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 | + +| ECInstanceId | i | +| ------------ | --- | +| 0x14 | 100 | +| 0x15 | 101 | +| 0x15 | 101 | + +# RIGHT JOIN + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + te.i +FROM + aps.TestElement te + RIGHT JOIN meta.ECSchemaDef d ON d.VersionMajor + 100 = te.i +``` + +| 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 | + +| ECInstanceId | i | +| ------------ | --- | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x16 | 102 | +| 0x16 | 102 | +| 0x18 | 104 | +| 0x19 | 105 | + +# FULL JOIN + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + te.i +FROM + aps.TestElement te + FULL JOIN meta.ECSchemaDef d ON d.VersionMajor + 100 = te.i +``` + +| 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 | + +| ECInstanceId | i | +| ------------ | --- | +| 0x14 | 100 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x15 | 101 | +| 0x16 | 102 | +| 0x16 | 102 | +| 0x17 | 103 | +| 0x18 | 104 | +| 0x19 | 105 | +| 0x1a | 106 | +| 0x1b | 107 | +| 0x1c | 108 | +| 0x1d | 109 | + + +# JOIN USING - FORWARD + +- dataset: AllProperties.bim + +```sql +SELECT + t0.ECInstanceId AS ParentId, + t0.ECClassId AS ParentClassId, + t1.ECInstanceId AS ChildId, + t1.ECClassId AS ChildClassId +FROM + [BisCore].[Element] t0 + JOIN [BisCore].[Element] t1 USING [BisCore].[ElementOwnsChildElements] FORWARD; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ---- | ------------------ | +| | ParentId | true | 0 | parentId | ParentId | Id | long | Id | ECInstanceId | +| | ParentClassId | true | 1 | parentClassId | ParentClassId | ClassId | long | Id | ECClassId | +| | ChildId | true | 2 | childId | ChildId | Id | long | Id | ECInstanceId | +| | ChildClassId | true | 3 | childClassId | ChildClassId | ClassId | long | Id | ECClassId | + +| ParentId | ParentClassId | ChildId | ChildClassId | +| -------- | ------------- | ------- | ------------ | +| 0x12 | 0xc5 | 0x13 | 0x89 | +| 0x1 | 0x126 | 0xe | 0xdd | +| 0x1 | 0x126 | 0x10 | 0x98 | +| 0x1 | 0x126 | 0x11 | 0xf0 | + +# JOIN USING - BACKWARD + +- dataset: AllProperties.bim + +```sql +SELECT + t0.ECInstanceId AS ParentId, + t0.ECClassId AS ParentClassId, + t1.ECInstanceId AS ChildId, + t1.ECClassId AS ChildClassId +FROM + [BisCore].[Element] t0 + JOIN [BisCore].[Element] t1 USING [BisCore].[ElementOwnsChildElements] BACKWARD; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ---- | ------------------ | +| | ParentId | true | 0 | parentId | ParentId | Id | long | Id | ECInstanceId | +| | ParentClassId | true | 1 | parentClassId | ParentClassId | ClassId | long | Id | ECClassId | +| | ChildId | true | 2 | childId | ChildId | Id | long | Id | ECInstanceId | +| | ChildClassId | true | 3 | childClassId | ChildClassId | ClassId | long | Id | ECClassId | + +| ParentId | ParentClassId | ChildId | ChildClassId | +| -------- | ------------- | ------- | ------------ | +| 0x13 | 0x89 | 0x12 | 0xc5 | +| 0xe | 0xdd | 0x1 | 0x126 | +| 0x10 | 0x98 | 0x1 | 0x126 | +| 0x11 | 0xf0 | 0x1 | 0x126 | + +# Double JOIN ON + +- dataset: AllProperties.bim + +```sql +SELECT + t0.ECInstanceId AS ParentId, + t0.ECClassId AS ParentClassId, + t1.ECInstanceId AS ChildId, + t1.ECClassId AS ChildClassId, + rel.SourceECInstanceId, + rel.SourceECClassId, + rel.TargetECInstanceId, + rel.TargetECClassId +FROM + [BisCore].[Element] t0 + JOIN [BisCore].[ElementOwnsChildElements] rel ON t0.ECInstanceId = rel.TargetECInstanceId + JOIN [BisCore].[Element] t1 ON t1.ECInstanceId = rel.SourceECInstanceId; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------------ | --------- | ----- | --------------- | ------------------ | ------------- | -------- | ---- | ------------------ | +| | ParentId | true | 0 | parentId | ParentId | Id | long | Id | ECInstanceId | +| | ParentClassId | true | 1 | parentClassId | ParentClassId | ClassId | long | Id | ECClassId | +| | ChildId | true | 2 | childId | ChildId | Id | long | Id | ECInstanceId | +| | ChildClassId | true | 3 | childClassId | ChildClassId | ClassId | long | Id | ECClassId | +| | SourceECInstanceId | false | 4 | sourceId | SourceECInstanceId | SourceId | long | Id | SourceECInstanceId | +| | SourceECClassId | false | 5 | sourceClassName | SourceECClassId | SourceClassId | long | Id | SourceECClassId | +| | TargetECInstanceId | false | 6 | targetId | TargetECInstanceId | TargetId | long | Id | TargetECInstanceId | +| | TargetECClassId | false | 7 | targetClassName | TargetECClassId | TargetClassId | long | Id | TargetECClassId | + +| ParentId | ParentClassId | ChildId | ChildClassId | SourceECInstanceId | SourceECClassId | TargetECInstanceId | TargetECClassId | +| -------- | ------------- | ------- | ------------ | ------------------ | --------------- | ------------------ | --------------- | +| 0x13 | 0x89 | 0x12 | 0xc5 | 0x12 | 0xc5 | 0x13 | 0x89 | +| 0xe | 0xdd | 0x1 | 0x126 | 0x1 | 0x126 | 0xe | 0xdd | +| 0x10 | 0x98 | 0x1 | 0x126 | 0x1 | 0x126 | 0x10 | 0x98 | +| 0x11 | 0xf0 | 0x1 | 0x126 | 0x1 | 0x126 | 0x11 | 0xf0 | + + +# CROSS JOIN + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId AS TestElementId, + d.Name AS SchemaName +FROM + aps.TestElement te + CROSS JOIN meta.ECSchemaDef d +LIMIT + 10; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ------ | ------------------ | +| | TestElementId | true | 0 | testElementId | TestElementId | Id | long | Id | ECInstanceId | +| | SchemaName | true | 1 | schemaName | SchemaName | undefined | string | String | Name | + +| TestElementId | SchemaName | +| ------------- | -------------------- | +| 0x14 | AllProperties | +| 0x14 | BisCore | +| 0x14 | BisCustomAttributes | +| 0x14 | CoreCustomAttributes | +| 0x14 | ECDbFileInfo | +| 0x14 | ECDbMap | +| 0x14 | ECDbMeta | +| 0x14 | ECDbSchemaPolicies | +| 0x14 | ECDbSystem | +| 0x14 | Generic | + +# CROSS JOIN allproperties and ecschemaDef + +- dataset: AllProperties.bim + +```sql +SELECT te.ECInstanceId, d.Alias FROM aps.TestElement te CROSS JOIN meta.ECSchemaDef d LIMIT 3; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECSchemaDef | Alias | false | 1 | alias | Alias | undefined | string | String | Alias | + +| ECInstanceId | Alias | +| ------------ | ----- | +| 0x14 | aps | +| 0x14 | bis | +| 0x14 | bisCA | + + +# NATURAL JOIN + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +SELECT 1 +FROM (SELECT ECInstanceId AS CommonId, FederationGuid FROM bis.Element) AS ElementAlias +NATURAL JOIN (SELECT ECInstanceId AS CommonId, IsPrivate FROM bis.Model) AS ModelAlias; +``` + +# Double Join Using + +- dataset: AllProperties.bim + +```sql +SELECT + t0.ECInstanceId AS ParentId, + t0.ECClassId AS ParentClassId, + t1.ECInstanceId AS ChildId, + t1.ECClassId AS ChildClassId, + t2.ECInstanceId AS GrandChildId, + t2.ECClassId AS GrandChildClassId +FROM + [BisCore].[Element] t0 + JOIN [BisCore].[Element] t1 USING [BisCore].[ElementOwnsChildElements] AS Rel1 FORWARD + JOIN [BisCore].[Element] t2 USING [BisCore].[ElementOwnsChildElements] AS Rel2 FORWARD; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ----------------- | --------- | ----- | ----------------- | ----------------- | ------------ | -------- | ---- | ------------------ | +| | ParentId | true | 0 | parentId | ParentId | Id | long | Id | ECInstanceId | +| | ParentClassId | true | 1 | parentClassId | ParentClassId | ClassId | long | Id | ECClassId | +| | ChildId | true | 2 | childId | ChildId | Id | long | Id | ECInstanceId | +| | ChildClassId | true | 3 | childClassId | ChildClassId | ClassId | long | Id | ECClassId | +| | GrandChildId | true | 4 | grandChildId | GrandChildId | Id | long | Id | ECInstanceId | +| | GrandChildClassId | true | 5 | grandChildClassId | GrandChildClassId | ClassId | long | Id | ECClassId | + +| ParentId | ParentClassId | ChildId | ChildClassId | GrandChildId | GrandChildClassId | +| -------- | ------------- | ------- | ------------ | ------------ | ----------------- | +| 0x12 | 0xc5 | 0x13 | 0x89 | 0x13 | 0x89 | +| 0x1 | 0x126 | 0xe | 0xdd | 0xe | 0xdd | +| 0x1 | 0x126 | 0xe | 0xdd | 0x10 | 0x98 | +| 0x1 | 0x126 | 0xe | 0xdd | 0x11 | 0xf0 | +| 0x1 | 0x126 | 0x10 | 0x98 | 0xe | 0xdd | +| 0x1 | 0x126 | 0x10 | 0x98 | 0x10 | 0x98 | +| 0x1 | 0x126 | 0x10 | 0x98 | 0x11 | 0xf0 | +| 0x1 | 0x126 | 0x11 | 0xf0 | 0xe | 0xdd | +| 0x1 | 0x126 | 0x11 | 0xf0 | 0x10 | 0x98 | +| 0x1 | 0x126 | 0x11 | 0xf0 | 0x11 | 0xf0 | + +# Double Join with Where + +- dataset: AllProperties.bim + +```sql +SELECT + Parent.ECInstanceId AS ParentId, + Child.ECInstanceId AS ChildId, + GrandChild.ECInstanceId AS GrandChildId +FROM + [BisCore].[Element] Parent + JOIN [BisCore].[Element] Child USING [BisCore].[ElementOwnsChildElements] re1 FORWARD + JOIN [BisCore].[Element] GrandChild USING [BisCore].[ElementOwnsChildElements] re2 FORWARD +WHERE + Parent.ECInstanceId <> GrandChild.ECInstanceId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ---- | ------------------ | +| | ParentId | true | 0 | parentId | ParentId | Id | long | Id | ECInstanceId | +| | ChildId | true | 1 | childId | ChildId | Id | long | Id | ECInstanceId | +| | GrandChildId | true | 2 | grandChildId | GrandChildId | Id | long | Id | ECInstanceId | + +| ParentId | ChildId | GrandChildId | +| -------- | ------- | ------------ | +| 0x12 | 0x13 | 0x13 | +| 0x1 | 0xe | 0xe | +| 0x1 | 0xe | 0x10 | +| 0x1 | 0xe | 0x11 | +| 0x1 | 0x10 | 0xe | +| 0x1 | 0x10 | 0x10 | +| 0x1 | 0x10 | 0x11 | +| 0x1 | 0x11 | 0xe | +| 0x1 | 0x11 | 0x10 | +| 0x1 | 0x11 | 0x11 | + +# JOIN in subquery + +- dataset: AllProperties.bim + +```sql +SELECT + t1.ECInstanceId AS ParentId, + SubQuery.ChildId +FROM + [BisCore].[Element] t1 + JOIN ( + SELECT + TargetECInstanceId AS ChildId + FROM + [BisCore].[ElementOwnsChildElements] + ) SubQuery ON t1.ECInstanceId = SubQuery.ChildId; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ---- | ------------------ | +| | ParentId | true | 0 | parentId | ParentId | Id | long | Id | ECInstanceId | +| | ChildId | true | 1 | childId | ChildId | TargetId | long | Id | undefined | + +| ParentId | ChildId | +| -------- | ------- | +| 0x13 | 0x13 | +| 0xe | 0xe | +| 0x10 | 0x10 | +| 0x11 | 0x11 | + +# JOIN on Empty Table + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + te.i +FROM + aps.TestElement te + LEFT JOIN aps.testElementRefersToElements ter ON te.i = ter.i +``` + +| 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 | + +| ECInstanceId | i | +| ------------ | --- | +| 0x14 | 100 | +| 0x15 | 101 | +| 0x16 | 102 | +| 0x17 | 103 | +| 0x18 | 104 | +| 0x19 | 105 | +| 0x1a | 106 | +| 0x1b | 107 | +| 0x1c | 108 | +| 0x1d | 109 | + +# Nested JOIN in Select + +- dataset: AllProperties.bim + +```sql +SELECT + nested_join.te_ECInstanceId, + nested_join.te_i, + nested_join.VersionMajor +FROM + ( + SELECT + te.ECInstanceId AS te_ECInstanceId, + te.i AS te_i, + d.VersionMajor + FROM + aps.TestElement te + INNER JOIN aps.IPrimitive p ON te.ECInstanceId = p.ECInstanceId + LEFT JOIN meta.ECSchemaDef d ON d.VersionMajor + 100 = te.i + ) AS nested_join +LIMIT + 5; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | --------------- | --------- | ----- | --------------- | --------------- | ------------ | -------- | ---- | ------------------ | +| | te_ECInstanceId | true | 0 | te_ECInstanceId | te_ECInstanceId | Id | long | Id | undefined | +| | te_i | true | 1 | te_i | te_i | undefined | int | Int | undefined | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 2 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | + +| te_ECInstanceId | te_i | VersionMajor | +| --------------- | ---- | ------------ | +| 0x14 | 100 | undefined | +| 0x15 | 101 | 1 | +| 0x15 | 101 | 1 | +| 0x15 | 101 | 1 | +| 0x15 | 101 | 1 | + +# Mixed JOIN types in one query + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + te.i, + d.VersionMajor, + eoc.SourceECInstanceId AS sourceECid +FROM + aps.TestElement te + INNER JOIN aps.IPrimitive p ON te.ECInstanceId = p.ECInstanceId + LEFT JOIN meta.ECSchemaDef d ON d.VersionMajor + 100 = te.i + CROSS JOIN BisCore.ElementOwnsChildElements eoc +LIMIT + 6; +``` + +| 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 | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 2 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| | sourceECid | true | 3 | sourceECid | sourceECid | SourceId | long | Id | SourceECInstanceId | + +| ECInstanceId | i | sourceECid | VersionMajor | +| ------------ | --- | ---------- | ------------ | +| 0x14 | 100 | 0x12 | undefined | +| 0x14 | 100 | 0x1 | undefined | +| 0x14 | 100 | 0x1 | undefined | +| 0x14 | 100 | 0x1 | undefined | +| 0x15 | 101 | 0x12 | 1 | +| 0x15 | 101 | 0x1 | 1 | + +# Named Properties Join + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +SELECT 1 FROM bis.Element e JOIN bis.SpatialElement s USING (ECInstanceId); +``` diff --git a/core/backend/src/test/ecsql/queries/MemberFunction.ecsql.md b/core/backend/src/test/ecsql/queries/MemberFunction.ecsql.md new file mode 100644 index 000000000000..1aa56b8e0cab --- /dev/null +++ b/core/backend/src/test/ecsql/queries/MemberFunction.ecsql.md @@ -0,0 +1,506 @@ +# json_extract + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + json_extract(te.j, '$.A') AS A_value +FROM + aps.TestElement te +WHERE + json_extract(te.j, '$.A') IS NOT NULL; +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "ECInstanceId", + "generated": false, + "index": 0, + "jsonName": "id", + "name": "ECInstanceId", + "extendedType": "Id", + "typeName": "long", + "type": "Id", + "originPropertyName": "ECInstanceId" + }, + { + "className": "", + "accessString": "A_value", + "generated": true, + "index": 1, + "jsonName": "a_value", + "name": "A_value", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + "ECInstanceId": "0x14", + "A_value": "0" + } +] +``` + +# json_extract more columns + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + json_extract(te.j, '$.A') AS A_value, + json_extract(te.j, '$.B') AS B_value, + json_extract(te.j, '$.C') AS C_value, + json_extract(te.j, '$.D') AS D_value +FROM + aps.TestElement te +LIMIT + 5; +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "ECInstanceId", + "generated": false, + "index": 0, + "jsonName": "id", + "name": "ECInstanceId", + "extendedType": "Id", + "typeName": "long", + "type": "Id", + "originPropertyName": "ECInstanceId" + }, + { + "className": "", + "accessString": "A_value", + "generated": true, + "index": 1, + "jsonName": "a_value", + "name": "A_value", + "typeName": "string", + "type": "String" + }, + { + "className": "", + "accessString": "B_value", + "generated": true, + "index": 2, + "jsonName": "b_value", + "name": "B_value", + "typeName": "string", + "type": "String" + }, + { + "className": "", + "accessString": "C_value", + "generated": true, + "index": 3, + "jsonName": "c_value", + "name": "C_value", + "typeName": "string", + "type": "String" + }, + { + "className": "", + "accessString": "D_value", + "generated": true, + "index": 4, + "jsonName": "d_value", + "name": "D_value", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + "ECInstanceId": "0x14", + "A_value": "0" + }, + { + "ECInstanceId": "0x15", + "B_value": "1" + }, + { + "ECInstanceId": "0x16", + "C_value": "2" + }, + { + "ECInstanceId": "0x17", + "D_value": "3" + }, + { + "ECInstanceId": "0x18" + } +] +``` + +# json_each with hardcoded JSON stirng + +- dataset: AllProperties.bim + +```sql +SELECT * FROM json1.json_each('{foo:1, goo:2}'); +``` + +```json +{ + "columns": [ + { + "className": "json1:json_each", + "accessString": "key", + "generated": false, + "index": 0, + "jsonName": "key", + "name": "key", + "typeName": "string", + "type": "String", + "originPropertyName": "key" + }, + { + "className": "json1:json_each", + "accessString": "value", + "generated": false, + "index": 1, + "jsonName": "value", + "name": "value", + "typeName": "string", + "type": "String", + "originPropertyName": "value" + }, + { + "className": "json1:json_each", + "accessString": "type", + "generated": false, + "index": 2, + "jsonName": "type", + "name": "type", + "typeName": "string", + "type": "String", + "originPropertyName": "type" + }, + { + "className": "json1:json_each", + "accessString": "atom", + "generated": false, + "index": 3, + "jsonName": "atom", + "name": "atom", + "typeName": "string", + "type": "String", + "originPropertyName": "atom" + }, + { + "className": "json1:json_each", + "accessString": "parent", + "generated": false, + "index": 4, + "jsonName": "parent", + "name": "parent", + "typeName": "int", + "type": "Int", + "originPropertyName": "parent" + }, + { + "className": "json1:json_each", + "accessString": "fullkey", + "generated": false, + "index": 5, + "jsonName": "fullkey", + "name": "fullkey", + "typeName": "string", + "type": "String", + "originPropertyName": "fullkey" + }, + { + "className": "json1:json_each", + "accessString": "path", + "generated": false, + "index": 6, + "jsonName": "path", + "name": "path", + "typeName": "string", + "type": "String", + "originPropertyName": "path" + } + ] +} +``` + +```json +[ + { + "key": "foo", + "value": "1", + "type": "integer", + "atom": "1", + "fullkey": "$.foo", + "path": "$" + }, + { + "key": "goo", + "value": "2", + "type": "integer", + "atom": "2", + "fullkey": "$.goo", + "path": "$" + } +] +``` + +# json_each nested JSON +- dataset: AllProperties.bim + +```sql +SELECT * FROM json1.json_each('{A: {nestedKey: 10}, B: 1}'); +``` + +```json +{ + "columns": [ + { + "className": "json1:json_each", + "accessString": "key", + "generated": false, + "index": 0, + "jsonName": "key", + "name": "key", + "typeName": "string", + "type": "String", + "originPropertyName": "key" + }, + { + "className": "json1:json_each", + "accessString": "value", + "generated": false, + "index": 1, + "jsonName": "value", + "name": "value", + "typeName": "string", + "type": "String", + "originPropertyName": "value" + }, + { + "className": "json1:json_each", + "accessString": "type", + "generated": false, + "index": 2, + "jsonName": "type", + "name": "type", + "typeName": "string", + "type": "String", + "originPropertyName": "type" + }, + { + "className": "json1:json_each", + "accessString": "atom", + "generated": false, + "index": 3, + "jsonName": "atom", + "name": "atom", + "typeName": "string", + "type": "String", + "originPropertyName": "atom" + }, + { + "className": "json1:json_each", + "accessString": "parent", + "generated": false, + "index": 4, + "jsonName": "parent", + "name": "parent", + "typeName": "int", + "type": "Int", + "originPropertyName": "parent" + }, + { + "className": "json1:json_each", + "accessString": "fullkey", + "generated": false, + "index": 5, + "jsonName": "fullkey", + "name": "fullkey", + "typeName": "string", + "type": "String", + "originPropertyName": "fullkey" + }, + { + "className": "json1:json_each", + "accessString": "path", + "generated": false, + "index": 6, + "jsonName": "path", + "name": "path", + "typeName": "string", + "type": "String", + "originPropertyName": "path" + } + ] +} +``` + +```json +[ + { + "key": "A", + "value": "{\"nestedKey\":10}", + "type": "object", + "fullkey": "$.A", + "path": "$" + }, + { + "key": "B", + "value": "1", + "type": "integer", + "atom": "1", + "fullkey": "$.B", + "path": "$" + } +] +``` + +# json_tree nested JSON + +- dataset: AllProperties.bim + +- dataset: AllProperties.bim + +```sql +SELECT * FROM json1.json_tree('{A: {nestedKey: 10}, B: 1}'); +``` + +```json +{ + "columns": [ + { + "className": "json1:json_tree", + "accessString": "key", + "generated": false, + "index": 0, + "jsonName": "key", + "name": "key", + "typeName": "string", + "type": "String", + "originPropertyName": "key" + }, + { + "className": "json1:json_tree", + "accessString": "value", + "generated": false, + "index": 1, + "jsonName": "value", + "name": "value", + "typeName": "string", + "type": "String", + "originPropertyName": "value" + }, + { + "className": "json1:json_tree", + "accessString": "type", + "generated": false, + "index": 2, + "jsonName": "type", + "name": "type", + "typeName": "string", + "type": "String", + "originPropertyName": "type" + }, + { + "className": "json1:json_tree", + "accessString": "atom", + "generated": false, + "index": 3, + "jsonName": "atom", + "name": "atom", + "typeName": "string", + "type": "String", + "originPropertyName": "atom" + }, + { + "className": "json1:json_tree", + "accessString": "parent", + "generated": false, + "index": 4, + "jsonName": "parent", + "name": "parent", + "typeName": "int", + "type": "Int", + "originPropertyName": "parent" + }, + { + "className": "json1:json_tree", + "accessString": "fullkey", + "generated": false, + "index": 5, + "jsonName": "fullkey", + "name": "fullkey", + "typeName": "string", + "type": "String", + "originPropertyName": "fullkey" + }, + { + "className": "json1:json_tree", + "accessString": "path", + "generated": false, + "index": 6, + "jsonName": "path", + "name": "path", + "typeName": "string", + "type": "String", + "originPropertyName": "path" + } + ] +} +``` + +```json +[ + { + "value": "{\"A\":{\"nestedKey\":10},\"B\":1}", + "type": "object", + "fullkey": "$", + "path": "$" + }, + { + "key": "A", + "value": "{\"nestedKey\":10}", + "type": "object", + "parent": 0, + "fullkey": "$.A", + "path": "$" + }, + { + "key": "nestedKey", + "value": "10", + "type": "integer", + "atom": "10", + "parent": 2, + "fullkey": "$.A.nestedKey", + "path": "$.A" + }, + { + "key": "B", + "value": "1", + "type": "integer", + "atom": "1", + "parent": 0, + "fullkey": "$.B", + "path": "$" + } +] +``` \ No newline at end of file diff --git a/core/backend/src/test/ecsql/queries/Misc.ecsql.md b/core/backend/src/test/ecsql/queries/Misc.ecsql.md new file mode 100644 index 000000000000..e999cc15d5dc --- /dev/null +++ b/core/backend/src/test/ecsql/queries/Misc.ecsql.md @@ -0,0 +1,916 @@ +# SubqueryValue + +- dataset: AllProperties.bim + +```sql +SELECT (SELECT te.ECInstanceId FROM aps.TestElement te) AS ecId +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | ecId | true | 0 | ecId | ecId | Id | long | Id | + +| ecId | +| ---- | +| 0x14 | + +# SubqueryValue in CTE + +- dataset: AllProperties.bim + +```sql +WITH + myCTE (ecId) AS ( + SELECT (SELECT te.ECInstanceId FROM aps.TestElement te) AS ecId + ) +SELECT * FROM myCTE +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ---- | +| | ecId | true | 0 | ecId | ecId | Id | long | Id | + +| ecId | +| ---- | +| 0x14 | + +# CAST Id to various types + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + CAST(te.ECInstanceId AS INTEGER) [int], + CAST(te.ECInstanceId AS LONG) [long], + CAST(te.ECInstanceId AS VARCHAR) [char] +FROM + aps.TestElement te +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | int | true | 1 | int | int | undefined | int | Int | undefined | +| | long | true | 2 | long | long | undefined | long | Int64 | undefined | +| | char | true | 3 | char | char | undefined | string | String | undefined | + +| ECInstanceId | int | long | char | +| ------------ | --- | ---- | ---- | +| 0x14 | 20 | 20 | "20" | +| 0x15 | 21 | 21 | "21" | + +# Nested CAST + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + CAST(CAST(te.ECInstanceId AS VARCHAR) AS LONG) [result] +FROM + aps.TestElement te +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | result | true | 1 | result | result | undefined | long | Int64 | undefined | + +| ECInstanceId | result | +| ------------ | ------ | +| 0x14 | 20 | +| 0x15 | 21 | + +# IIF integer value + +- dataset: AllProperties.bim + +```sql +SELECT te.ECInstanceId, IIF(te.i < 102, 'Small', 'Big') as [calc] from aps.TestElement te LIMIT 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | calc | true | 1 | calc | calc | undefined | string | String | undefined | + +| ECInstanceId | calc | +| ------------ | ----- | +| 0x14 | Small | +| 0x15 | Small | +| 0x16 | Big | +| 0x17 | Big | +| 0x18 | Big | + +# FizzBuzz (nested IIF) + +- dataset: AllProperties.bim + +```sql +WITH RECURSIVE + numbers (x) AS ( + SELECT 1 UNION ALL + SELECT x + 1 FROM numbers + LIMIT 15 + ) +SELECT + IIF( + x % 3 = 0 AND x % 5 = 0, 'FizzBuzz', + IIF(x % 3 = 0, 'Fizz', + IIF(x % 5 = 0, 'Buzz', CAST(x AS VARCHAR)) + ) + ) AS [result] +FROM + numbers +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ------ | ------------ | -------- | ------ | +| | result | true | 0 | result | result | undefined | string | String | + +| result | +| -------- | +| "1" | +| "2" | +| Fizz | +| "4" | +| Buzz | +| Fizz | +| "7" | +| "8" | +| Fizz | +| Buzz | +| "11" | +| Fizz | +| "13" | +| "14" | +| FizzBuzz | + +# SubqueryTestExp with EXISTS + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId +FROM + aps.TestElement e +WHERE + EXISTS ( + SELECT + 1 + FROM + aps.TestElementAspect a + WHERE + e.ECInstanceId = a.Element.Id + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x14 | +| 0x16 | +| 0x18 | +| 0x1a | +| 0x1c | + +# SubqueryTestExp with NOT EXISTS + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId +FROM + aps.TestElement e +WHERE + NOT EXISTS ( + SELECT + 1 + FROM + aps.TestElementAspect a + WHERE + e.ECInstanceId = a.Element.Id + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x15 | +| 0x17 | +| 0x19 | +| 0x1b | +| 0x1d | + +# SubqueryTestExp with EXISTS and cte subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId +FROM + aps.TestElement e +WHERE + EXISTS ( + WITH + cte (a, b) AS ( + SELECT + ECInstanceId, + ECClassId + FROM + aps.TestElementAspect + LIMIT + 1 + ) + SELECT + * + FROM + cte + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x14 | +| 0x15 | +| 0x16 | +| 0x17 | +| 0x18 | +| 0x19 | +| 0x1a | +| 0x1b | +| 0x1c | +| 0x1d | + +# SubqueryTestExp with NOT EXISTS and cte subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId +FROM + aps.TestElement e +WHERE + NOT EXISTS ( + WITH + cte (a, b) AS ( + SELECT + ECInstanceId, + ECClassId + FROM + aps.TestElementAspect + WHERE + ECInstanceId = 0x999 + ) + SELECT + * + FROM + cte + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x14 | +| 0x15 | +| 0x16 | +| 0x17 | +| 0x18 | +| 0x19 | +| 0x1a | +| 0x1b | +| 0x1c | +| 0x1d | + +# Simple LIMIT and OFFSET test + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId FROM aps.TestElement e LIMIT 5 OFFSET 8 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x1c | +| 0x1d | + +# Testing Type enums in the built-in schemas + +- dataset: AllProperties.bim + +```sql +SELECT Type FROM meta.ECClassDef WHERE Name='TestElement' +``` + +```json +{ + "columns": [ + { + "className": "ECDbMeta:ECClassDef", + "accessString": "Type", + "generated": false, + "index": 0, + "jsonName": "type", + "name": "Type", + "typeName": "ECDbMeta.ECClassType", + "type": "Int", + "originPropertyName": "Type" + } + ] +} +``` + +```json +[ + { + "Type": 0 + } +] +``` + +# Testing Modifier enums in the built-in schemas + +- dataset: AllProperties.bim + +```sql +SELECT Modifier FROM meta.ECClassDef WHERE Name='TestElement' +``` + +```json +{ + "columns": [ + { + "className": "ECDbMeta:ECClassDef", + "accessString": "Modifier", + "generated": false, + "index": 1, + "jsonName": "modifier", + "name": "Modifier", + "typeName": "ECDbMeta.ECClassModifier", + "type": "Int", + "originPropertyName": "Modifier" + } + ] +} +``` + +```json +[ + { + "Modifier": 0 + } +] +``` + +# Simple select with LIKE operator and wildcard at the end + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, DirectStr FROM aps.TestElement where DirectStr LIKE 'str%' LIMIT 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectStr | false | 0 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | DirectStr | +| ------------ | --------- | +| 0x14 | str0 | +| 0x15 | str1 | +| 0x16 | str2 | +| 0x17 | str3 | +| 0x18 | str4 | + +# Simple select with LIKE operator and wildcard at the beginning + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, DirectStr FROM aps.TestElement where DirectStr LIKE '%tr5' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectStr | false | 0 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | DirectStr | +| ------------ | --------- | +| 0x19 | str5 | + +# Simple select with LIKE operator and wildcard in the middle + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, DirectStr FROM aps.TestElement where DirectStr LIKE 's%5' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectStr | false | 0 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | DirectStr | +| ------------ | --------- | +| 0x19 | str5 | + +# Simple select with LIKE operator and multiple wildcard + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp FROM aps.TestElement where NullProp LIKE 'N%t%u%' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | NullProp | +| ------------ | -------- | +| 0x15 | NotNull | +| 0x17 | NotNull | +| 0x19 | NotNull | +| 0x1b | NotNull | +| 0x1d | NotNull | + +# Simple select with LIKE operator underscore wildcard + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, DirectStr FROM aps.TestElement where DirectStr LIKE 'str_' LIMIT 10 OFFSET 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectStr | false | 1 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | DirectStr | +| ------------ | --------- | +| 0x19 | str5 | +| 0x1a | str6 | +| 0x1b | str7 | +| 0x1c | str8 | +| 0x1d | str9 | + +# Simple select with LIKE operator and combination of wildcards + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, DirectStr FROM aps.TestElement where DirectStr LIKE 's_r%' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectStr | false | 1 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | DirectStr | +| ------------ | --------- | +| 0x14 | str0 | +| 0x15 | str1 | +| 0x16 | str2 | +| 0x17 | str3 | +| 0x18 | str4 | +| 0x19 | str5 | +| 0x1a | str6 | +| 0x1b | str7 | +| 0x1c | str8 | +| 0x1d | str9 | + +# Simple select with LIKE operator and new ESCAPE character + +- dataset: AllProperties.bim + +```sql +SELECT + * +FROM + ( + SELECT + ECInstanceId, + CASE + WHEN NullProp IS NULL THEN 'Test_1234' + ELSE 'TEST' + END AS Test_Val + FROM + aps.TestElement + ) e +WHERE + e.Test_Val LIKE 'TEST$_%' ESCAPE '$' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Test_Val | true | 1 | test_Val | Test_Val | undefined | string | String | undefined | + +| ECInstanceId | Test_Val | +| ------------ | --------- | +| 0x14 | Test_1234 | +| 0x16 | Test_1234 | +| 0x18 | Test_1234 | +| 0x1a | Test_1234 | +| 0x1c | Test_1234 | + +# Simple select with LIKE operator and existing character underscore as ESCAPE character + +- dataset: AllProperties.bim + +```sql +SELECT + * +FROM + ( + SELECT + ECInstanceId, + CASE + WHEN NullProp IS NULL THEN 'Test_1234' + ELSE 'TEST%1234' + END AS Test_Val + FROM + aps.TestElement + ) e +WHERE + e.Test_Val LIKE 'TEST_%12%' ESCAPE '_' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Test_Val | true | 1 | test_Val | Test_Val | undefined | string | String | undefined | + +| ECInstanceId | Test_Val | +| ------------ | --------- | +| 0x15 | TEST%1234 | +| 0x17 | TEST%1234 | +| 0x19 | TEST%1234 | +| 0x1b | TEST%1234 | +| 0x1d | TEST%1234 | + +# Simple select with LIKE operator and existing character '%' as ESCAPE character + +- dataset: AllProperties.bim + +```sql +SELECT + * +FROM + ( + SELECT + ECInstanceId, + CASE + WHEN NullProp IS NULL THEN 'Test_1234' + ELSE 'TEST1234' + END AS Test_Val + FROM + aps.TestElement + ) e +WHERE + e.Test_Val LIKE 'TEST%_123_' ESCAPE '%' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Test_Val | true | 1 | test_Val | Test_Val | undefined | string | String | undefined | + +| ECInstanceId | Test_Val | +| ------------ | --------- | +| 0x14 | Test_1234 | +| 0x16 | Test_1234 | +| 0x18 | Test_1234 | +| 0x1a | Test_1234 | +| 0x1c | Test_1234 | + +# Trying PRAGMA parse_tree without enabling experimental features + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +pragma parse_tree([select x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x from tmp) a]) +``` + +# Trying PRAGMA integrity_check without enabling experimental features + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +PRAGMA integrity_check +``` + +# Trying PRAGMA parse_tree with enabling experimental features + +- dataset: AllProperties.bim + +```sql +PRAGMA parse_tree ( + [select x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x from tmp) a] +) OPTIONS ENABLE_EXPERIMENTAL_FEATURES +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "val", + "generated": true, + "index": 0, + "jsonName": "val", + "name": "val", + "typeName": "string", + "type": "String", + "originPropertyName": "val" + } + ] +} +``` + +```json +[ + { + "val": "{\"id\":\"SelectStatementExp\",\"select\":{\"id\":\"SingleSelectStatementExp\",\"selection\":[{\"id\":\"DerivedPropertyExp\",\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"x\"}}],\"from\":[{\"id\":\"SubqueryRefExp\",\"alias\":\"a\",\"query\":{\"id\":\"SubqueryExp\",\"query\":{\"id\":\"CommonTableExp\",\"recursive\":false,\"blocks\":[{\"id\":\"CommonTableBlockExp\",\"name\":\"tmp\",\"args\":[\"x\"],\"asQuery\":{\"id\":\"SelectStatementExp\",\"select\":{\"id\":\"SingleSelectStatementExp\",\"selection\":[{\"id\":\"DerivedPropertyExp\",\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"e.i\"}}],\"from\":[{\"id\":\"ClassNameExp\",\"tableSpace\":\"\",\"schemaName\":\"AllProperties\",\"className\":\"TestElement\",\"alias\":\"e\"}],\"orderBy\":[{\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"e.i\"}}],\"limit\":{\"id\":\"LimitOffsetExp\",\"exp\":{\"id\":\"LiteralValueExp\",\"kind\":\"RAW\",\"value\":\"1\"}}}}}],\"select\":{\"id\":\"SelectStatementExp\",\"select\":{\"id\":\"SingleSelectStatementExp\",\"selection\":[{\"id\":\"DerivedPropertyExp\",\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"x\"},\"alias\":\"x\"}],\"from\":[{\"id\":\"CommonTableBlockNameExp\",\"name\":\"tmp\"}]}}}}}]}}" + } +] +``` + +# Trying PRAGMA parse_tree with enabling experimental features but using ECSQLOPTIONS instead of OPTIONS + +- dataset: AllProperties.bim + +```sql +PRAGMA parse_tree ( + [select x from (with tmp(x) as (SELECT e.i FROM aps.TestElement e order by e.i LIMIT 1) select x from tmp) a] +) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "val", + "generated": true, + "index": 0, + "jsonName": "val", + "name": "val", + "typeName": "string", + "type": "String", + "originPropertyName": "val" + } + ] +} +``` + +```json +[ + { + "val": "{\"id\":\"SelectStatementExp\",\"select\":{\"id\":\"SingleSelectStatementExp\",\"selection\":[{\"id\":\"DerivedPropertyExp\",\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"x\"}}],\"from\":[{\"id\":\"SubqueryRefExp\",\"alias\":\"a\",\"query\":{\"id\":\"SubqueryExp\",\"query\":{\"id\":\"CommonTableExp\",\"recursive\":false,\"blocks\":[{\"id\":\"CommonTableBlockExp\",\"name\":\"tmp\",\"args\":[\"x\"],\"asQuery\":{\"id\":\"SelectStatementExp\",\"select\":{\"id\":\"SingleSelectStatementExp\",\"selection\":[{\"id\":\"DerivedPropertyExp\",\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"e.i\"}}],\"from\":[{\"id\":\"ClassNameExp\",\"tableSpace\":\"\",\"schemaName\":\"AllProperties\",\"className\":\"TestElement\",\"alias\":\"e\"}],\"orderBy\":[{\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"e.i\"}}],\"limit\":{\"id\":\"LimitOffsetExp\",\"exp\":{\"id\":\"LiteralValueExp\",\"kind\":\"RAW\",\"value\":\"1\"}}}}}],\"select\":{\"id\":\"SelectStatementExp\",\"select\":{\"id\":\"SingleSelectStatementExp\",\"selection\":[{\"id\":\"DerivedPropertyExp\",\"exp\":{\"id\":\"PropertyNameExp\",\"path\":\"x\"},\"alias\":\"x\"}],\"from\":[{\"id\":\"CommonTableBlockNameExp\",\"name\":\"tmp\"}]}}}}}]}}" + } +] +``` + +# Trying PRAGMA ecdb_ver + +- dataset: AllProperties.bim + +```sql +PRAGMA ecdb_ver +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ------ | ------------------ | +| | current | true | 0 | current | current | undefined | string | String | current | +| | file | true | 1 | file | file | undefined | string | String | file | + +| current | file | +| ------- | ------- | +| 4.0.0.5 | 4.0.0.5 | + +# Trying PRAGMA explain_query simple select + +- dataset: AllProperties.bim + +```sql +PRAGMA explain_query ( + [SELECT * FROM meta.ECClassDef WHERE Name='Element'] +) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ------ | ------------------ | +| | id | true | 0 | id | id | undefined | long | Int64 | id | +| | parent | true | 1 | parent | parent | undefined | long | Int64 | parent | +| | notused | true | 2 | notused | notused | undefined | long | Int64 | notused | +| | detail | true | 3 | detail | detail | undefined | string | String | detail | + +| id | parent | notused | detail | +| --- | ------ | ------- | ---------------------------------------------------------- | +| 3 | 0 | 0 | SEARCH main.ec_Class USING INDEX ix_ec_Class_Name (Name=?) | + +# Trying PRAGMA explain_query with cte + +- dataset: AllProperties.bim + +```sql +PRAGMA explain_query ( [WITH cnt (x,y) AS ( SELECT 100, 200 ) SELECT * from cnt]) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ------ | ------------------ | +| | id | true | 0 | id | id | undefined | long | Int64 | id | +| | parent | true | 1 | parent | parent | undefined | long | Int64 | parent | +| | notused | true | 2 | notused | notused | undefined | long | Int64 | notused | +| | detail | true | 3 | detail | detail | undefined | string | String | detail | + +| id | parent | notused | detail | +| --- | ------ | ------- | ----------------- | +| 2 | 0 | 0 | CO-ROUTINE cnt | +| 3 | 2 | 0 | SCAN CONSTANT ROW | +| 8 | 0 | 0 | SCAN cnt | + +# Trying PRAGMA explain_query with recursive cte + +- dataset: AllProperties.bim + +```sql +PRAGMA explain_query ( + [WITH RECURSIVE + cnt (x,y) AS ( + SELECT 100, 200 + UNION ALL + SELECT x+1, 200 FROM cnt WHERE x<210 + ) + SELECT * from cnt] +) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ------ | ------------------ | +| | id | true | 0 | id | id | undefined | long | Int64 | id | +| | parent | true | 1 | parent | parent | undefined | long | Int64 | parent | +| | notused | true | 2 | notused | notused | undefined | long | Int64 | notused | +| | detail | true | 3 | detail | detail | undefined | string | String | detail | + +| id | parent | notused | detail | +| --- | ------ | ------- | ----------------- | +| 2 | 0 | 0 | CO-ROUTINE cnt | +| 5 | 2 | 0 | SETUP | +| 6 | 5 | 0 | SCAN CONSTANT ROW | +| 19 | 2 | 0 | RECURSIVE STEP | +| 20 | 19 | 0 | SCAN cnt | +| 31 | 0 | 0 | SCAN cnt | + +# Using Scalar values in select clause with + operator + +- dataset: AllProperties.bim + +```sql +SELECT (1+2) Added +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ------ | +| | Added | true | 0 | added | Added | undefined | double | Double | + +| Added | +| ----- | +| 3 | + +# Using Scalar values in select clause + +- dataset: AllProperties.bim + +```sql +SELECT (1) One +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | +| | One | true | 0 | one | One | undefined | long | Int64 | + +| One | +| --- | +| 1 | + +# Using Scalar values in select clause with \* operator + +- dataset: AllProperties.bim + +```sql +SELECT (1*2) Product +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ------ | +| | Product | true | 0 | product | Product | undefined | double | Double | + +| Product | +| ------- | +| 2 | + +# Using Scalar values in select clause with / operator + +- dataset: AllProperties.bim + +```sql +SELECT (1*2) Divided +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ------ | +| | Divided | true | 0 | divided | Divided | undefined | double | Double | + +| Divided | +| ------- | +| 2 | + +# NULLCast binary and bool + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + CAST(NULL AS BINARY) [binary], + CAST(NULL AS BOOLEAN) [bool] +FROM + aps.TestElement te +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ------ | ------------ | -------- | ------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | binary | true | 1 | binary | binary | undefined | binary | Blob | undefined | +| | bool | true | 2 | bool | bool | undefined | boolean | Boolean | undefined | + +| i | binary | time | +| --- | --------- | --------- | +| 100 | undefined | undefined | +| 101 | undefined | undefined | + +# NullCast double and time + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + CAST(NULL AS DOUBLE) [dbl], + CAST(NULL AS TIMESTAMP) [time] +FROM + aps.TestElement te +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | dbl | true | 1 | dbl | dbl | undefined | double | Double | undefined | +| | time | true | 2 | time | time | undefined | dateTime | DateTime | undefined | + +| i | dbl | time | +| --- | --------- | --------- | +| 100 | undefined | undefined | +| 101 | undefined | undefined | diff --git a/core/backend/src/test/ecsql/queries/NavValueCreationFunc.ecsql.md b/core/backend/src/test/ecsql/queries/NavValueCreationFunc.ecsql.md new file mode 100644 index 000000000000..a350f3a129a6 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/NavValueCreationFunc.ecsql.md @@ -0,0 +1,539 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# With all 3 arguments and hex ids + +- dataset: AllProperties.bim + +```sql +select navigation_value(aps.TestFeature.FeatureUsesElement, 0x1d, 0x155) +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "FeatureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x155" + } + } +] +``` + +# With only navigation property and hex instance id + +- dataset: AllProperties.bim + +```sql +select navigation_value(aps.TestFeature.FeatureUsesElement, 0x1c) +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "FeatureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1c", + "RelECClassId": "0x158" + } + } +] +``` + +# With all 3 arguments and decimal ids + +- dataset: AllProperties.bim + +```sql +select navigation_value(aps.TestFeature.FeatureUsesElement, 29, 341) +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "FeatureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x155" + } + } +] +``` + +# With only navigation property and decimal instance id arguments + +- dataset: AllProperties.bim + +```sql +select navigation_value(aps.TestFeature.FeatureUsesElement, 29) +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "FeatureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x158" + } + } +] +``` + +# With binders and hex ids + +- dataset: AllProperties.bim + +```sql +select navigation_value(aps.TestFeature.FeatureUsesElement, ?, ?) +``` + +- bindId 1, 0x1d +- bindId 2, 0x155 + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "FeatureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x155" + } + } +] +``` + +# With binders and decimal ids + +- dataset: AllProperties.bim + +```sql +select navigation_value(aps.TestFeature.FeatureUsesElement, ?, ?) +``` + +- bindId 1, 29 +- bindId 2, 341 + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "featureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x155" + } + } +] +``` + +# With actual navigation property row values + +- dataset: AllProperties.bim + +```sql +SELECT + navigation_value ( + aps.TestFeature.FeatureUsesElement, + FeatureUsesElement.Id, + FeatureUsesElement.RelECClassId + ) +FROM + aps.TestFeature +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "featureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x158" + } + }, + { + "FeatureUsesElement": { + "Id": "0x1c", + "RelECClassId": "0x158" + } + } +] +``` + +# With duplicate navigation properties + +- dataset: AllProperties.bim + +```sql +SELECT + NAVIGATION_VALUE (aps.TestFeature.FeatureUsesElement, 0x1c, 0x155), + NAVIGATION_VALUE (aps.TestFeature.FeatureUsesElement, 28, 341) +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "FeatureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + }, + { + "className": "", + "accessString": "FeatureUsesElement_1", + "generated": true, + "index": 1, + "jsonName": "FeatureUsesElement_1", + "name": "FeatureUsesElement_1", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1c", + "RelECClassId": "0x155" + }, + "FeatureUsesElement_1": { + "Id": "0x1c", + "RelECClassId": "0x155" + } + } +] +``` + +# Check fields directly + +- dataset: AllProperties.bim + +```sql +SELECT + FeatureUsesElement, + FeatureUsesElement.Id, + FeatureUsesElement.RelECClassId +FROM + aps.TestFeature +``` + +```json +{ + "columns": [ + { + "className": "AllProperties:TestFeature", + "accessString": "FeatureUsesElement", + "generated": false, + "index": 0, + "jsonName": "featureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + }, + { + "className": "", + "accessString": "FeatureUsesElement.Id", + "generated": false, + "index": 1, + "jsonName": "featureUsesElement.id", + "name": "Id", + "extendedType": "NavId", + "typeName": "long", + "type": "Id", + "originPropertyName": "Id" + }, + { + "className": "", + "accessString": "FeatureUsesElement.RelECClassId", + "generated": false, + "index": 2, + "jsonName": "featureUsesElement.relClassName", + "name": "RelECClassId", + "extendedType": "NavRelClassId", + "typeName": "long", + "type": "Id", + "originPropertyName": "RelECClassId" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x158" + }, + "Id": "0x1d", + "RelECClassId": "0x158" + }, + { + "FeatureUsesElement": { + "Id": "0x1c", + "RelECClassId": "0x158" + }, + "Id": "0x1c", + "RelECClassId": "0x158" + } +] +``` + +# With navigation value function in from clause + +- dataset: AllProperties.bim + +```sql +SELECT + FeatureUsesElement, + FeatureUsesElement.Id AS featureId, + FeatureUsesElement.RelECClassId AS featureRelClassId +FROM + ( + SELECT + navigation_value (aps.TestFeature.FeatureUsesElement, 0x1d, 0x155) + ) +WHERE + FeatureUsesElement.RelECClassId = 0x155 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "featureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation" + }, + { + "className": "", + "accessString": "featureId", + "generated": true, + "index": 1, + "jsonName": "featureId", + "name": "featureId", + "extendedType": "NavId", + "typeName": "long", + "type": "Id" + }, + { + "className": "", + "accessString": "featureRelClassId", + "generated": true, + "index": 2, + "jsonName": "featureRelClassId", + "name": "featureRelClassId", + "extendedType": "NavRelClassId", + "typeName": "long", + "type": "Id" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1d", + "RelECClassId": "0x155" + }, + "featureId": "0x1d", + "featureRelClassId": "0x155" + } +] +``` + +# With navigation value function with subquery as arguments + +- dataset: AllProperties.bim + +```sql +SELECT + NAVIGATION_VALUE ( + aps.TestFeature.FeatureUsesElement, + ( + SELECT + FeatureUsesElement.Id + FROM + aps.TestFeature + WHERE + FeatureUsesElement.RelECClassId = 0x158 + LIMIT + 1 + OFFSET + 1 + ), + ( + SELECT + FeatureUsesElement.RelECClassId + FROM + aps.TestFeature + WHERE + FeatureUsesElement.Id = 0x1d + ) + ) +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": "FeatureUsesElement", + "generated": true, + "index": 0, + "jsonName": "FeatureUsesElement", + "name": "FeatureUsesElement", + "typeName": "navigation", + "type": "Navigation", + "originPropertyName": "FeatureUsesElement" + } + ] +} +``` + +```json +[ + { + "FeatureUsesElement": { + "Id": "0x1c", + "RelECClassId": "0x158" + } + } +] +``` diff --git a/core/backend/src/test/ecsql/queries/OrderByClause.ecsql.md b/core/backend/src/test/ecsql/queries/OrderByClause.ecsql.md new file mode 100644 index 000000000000..df999ff157b0 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/OrderByClause.ecsql.md @@ -0,0 +1,451 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Basic test + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp FROM aps.TestElement ORDER BY NullProp +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | NullProp | +| ------------ | --------- | +| 0x14 | undefined | +| 0x16 | undefined | +| 0x18 | undefined | +| 0x1a | undefined | +| 0x1c | undefined | +| 0x15 | NotNull | +| 0x17 | NotNull | +| 0x19 | NotNull | +| 0x1b | NotNull | +| 0x1d | NotNull | + +# Basic test desc + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp FROM aps.TestElement ORDER BY NullProp desc +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | NullProp | +| ------------ | --------- | +| 0x15 | NotNull | +| 0x17 | NotNull | +| 0x19 | NotNull | +| 0x1b | NotNull | +| 0x1d | NotNull | +| 0x14 | undefined | +| 0x16 | undefined | +| 0x18 | undefined | +| 0x1a | undefined | +| 0x1c | undefined | + +# With multiple columns + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp, bin FROM aps.TestElement ORDER BY NullProp, bin +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 2 | bin | bin | undefined | binary | Blob | bin | + +| ECInstanceId | bin | NullProp | +| ------------ | ---------------------------------- | --------- | +| 0x14 | BIN(1,2,3) | undefined | +| 0x16 | BIN(1,2,3) | undefined | +| 0x18 | BIN(1,2,3) | undefined | +| 0x1a | BIN(1,2,3) | undefined | +| 0x1c | BIN(1,2,3) | undefined | +| 0x15 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x17 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x19 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x1b | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x1d | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | + +# With multiple columns with different sorting order combo 1 + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp, bin FROM aps.TestElement ORDER BY NullProp desc, bin +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 2 | bin | bin | undefined | binary | Blob | bin | + +| ECInstanceId | NullProp | bin | +| ------------ | --------- | ---------------------------------- | +| 0x15 | NotNull | BIN(11,21,31,34,53,21,14,14,55,22) | +| 0x17 | NotNull | BIN(11,21,31,34,53,21,14,14,55,22) | +| 0x19 | NotNull | BIN(11,21,31,34,53,21,14,14,55,22) | +| 0x1b | NotNull | BIN(11,21,31,34,53,21,14,14,55,22) | +| 0x1d | NotNull | BIN(11,21,31,34,53,21,14,14,55,22) | +| 0x14 | undefined | BIN(1,2,3) | +| 0x16 | undefined | BIN(1,2,3) | +| 0x18 | undefined | BIN(1,2,3) | +| 0x1a | undefined | BIN(1,2,3) | +| 0x1c | undefined | BIN(1,2,3) | + +# With multiple columns with different sorting order combo 2 + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp, bin FROM aps.TestElement ORDER BY NullProp, bin desc +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 2 | bin | bin | undefined | binary | Blob | bin | + +| ECInstanceId | bin | NullProp | +| ------------ | ---------------------------------- | --------- | +| 0x14 | BIN(1,2,3) | undefined | +| 0x16 | BIN(1,2,3) | undefined | +| 0x18 | BIN(1,2,3) | undefined | +| 0x1a | BIN(1,2,3) | undefined | +| 0x1c | BIN(1,2,3) | undefined | +| 0x15 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x17 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x19 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x1b | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x1d | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | + +# With aggreagate functions first + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp, bin FROM aps.TestElement GROUP BY NullProp ORDER BY MAX(DirectLong) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 2 | bin | bin | undefined | binary | Blob | bin | + +| ECInstanceId | bin | NullProp | +| ------------ | ---------------------------------- | --------- | +| 0x1c | BIN(1,2,3) | undefined | +| 0x1d | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | + +# With aggreagate functions second + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + NullProp, + bin +FROM + aps.TestElement +GROUP BY + NullProp +ORDER BY + MAX(DirectLong) DESC +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 2 | bin | bin | undefined | binary | Blob | bin | + +| ECInstanceId | NullProp | bin | +| ------------ | --------- | ---------------------------------- | +| 0x1d | NotNull | BIN(11,21,31,34,53,21,14,14,55,22) | +| 0x1c | undefined | BIN(1,2,3) | + +# With Length function + +- dataset: AllProperties.bim + +```sql +SELECT DirectStr, NullProp, bin FROM aps.TestElement ORDER BY LENGTH(bin) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | DirectStr | false | 0 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 2 | bin | bin | undefined | binary | Blob | bin | + +| DirectStr | bin | NullProp | +| --------- | ---------------------------------- | --------- | +| str0 | BIN(1,2,3) | undefined | +| str2 | BIN(1,2,3) | undefined | +| str4 | BIN(1,2,3) | undefined | +| str6 | BIN(1,2,3) | undefined | +| str8 | BIN(1,2,3) | undefined | +| str1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| str3 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| str5 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| str7 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| str9 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | + +# With Case first + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong, + DirectDouble, + NullProp, + bin +FROM + aps.TestElement +ORDER BY + CASE + WHEN DirectDouble > 5.1 THEN DirectLong + ELSE NullProp + END +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 2 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | +| AllProperties:TestElement | NullProp | false | 3 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 4 | bin | bin | undefined | binary | Blob | bin | + +| ECInstanceId | DirectLong | DirectDouble | bin | NullProp | +| ------------ | ---------- | ------------ | ---------------------------------- | --------- | +| 0x14 | 1000 | 0.1 | BIN(1,2,3) | undefined | +| 0x16 | 1002 | 2.1 | BIN(1,2,3) | undefined | +| 0x18 | 1004 | 4.1 | BIN(1,2,3) | undefined | +| 0x1a | 1006 | 6.1 | BIN(1,2,3) | undefined | +| 0x1b | 1007 | 7.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x1c | 1008 | 8.1 | BIN(1,2,3) | undefined | +| 0x1d | 1009 | 9.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x15 | 1001 | 1.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x17 | 1003 | 3.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x19 | 1005 | 5.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | + +# With Case second + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong, + DirectDouble, + NullProp, + bin +FROM + aps.TestElement +ORDER BY + CASE + WHEN DirectDouble > 5.1 THEN NullProp + ELSE DirectLong + END +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 2 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | +| AllProperties:TestElement | NullProp | false | 3 | nullProp | NullProp | undefined | string | String | NullProp | +| AllProperties:IPrimitive | bin | false | 4 | bin | bin | undefined | binary | Blob | bin | + +| ECInstanceId | DirectLong | DirectDouble | bin | NullProp | +| ------------ | ---------- | ------------ | ---------------------------------- | --------- | +| 0x1a | 1006 | 6.1 | BIN(1,2,3) | undefined | +| 0x1c | 1008 | 8.1 | BIN(1,2,3) | undefined | +| 0x14 | 1000 | 0.1 | BIN(1,2,3) | undefined | +| 0x15 | 1001 | 1.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x16 | 1002 | 2.1 | BIN(1,2,3) | undefined | +| 0x17 | 1003 | 3.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x18 | 1004 | 4.1 | BIN(1,2,3) | undefined | +| 0x19 | 1005 | 5.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x1b | 1007 | 7.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | +| 0x1d | 1009 | 9.1 | BIN(11,21,31,34,53,21,14,14,55,22) | NotNull | + +# With Nulls First + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp FROM aps.TestElement ORDER BY NullProp NULLS FIRST +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | NullProp | +| ------------ | --------- | +| 0x14 | undefined | +| 0x16 | undefined | +| 0x18 | undefined | +| 0x1a | undefined | +| 0x1c | undefined | +| 0x15 | NotNull | +| 0x17 | NotNull | +| 0x19 | NotNull | +| 0x1b | NotNull | +| 0x1d | NotNull | + +# With Nulls Last + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, NullProp FROM aps.TestElement ORDER BY NullProp NULLS LAST +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | NullProp | +| ------------ | --------- | +| 0x15 | NotNull | +| 0x17 | NotNull | +| 0x19 | NotNull | +| 0x1b | NotNull | +| 0x1d | NotNull | +| 0x14 | undefined | +| 0x16 | undefined | +| 0x18 | undefined | +| 0x1a | undefined | +| 0x1c | undefined | + +# With subquery in From Clause + +- dataset: AllProperties.bim + +```sql +SELECT + sub.Id, + sub.null_check +FROM + ( + SELECT + ECInstanceId AS Id, + NullProp AS null_check + FROM + aps.TestElement + ) sub +ORDER BY + sub.null_check +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | ---------- | ---------- | ------------ | -------- | ------ | +| | Id | true | 0 | id | Id | Id | long | Id | +| | null_check | true | 1 | null_check | null_check | undefined | string | String | + +| Id | null_check | +| ---- | ---------- | +| 0x14 | undefined | +| 0x16 | undefined | +| 0x18 | undefined | +| 0x1a | undefined | +| 0x1c | undefined | +| 0x15 | NotNull | +| 0x17 | NotNull | +| 0x19 | NotNull | +| 0x1b | NotNull | +| 0x1d | NotNull | + +# With Coalesce + +- dataset: AllProperties.bim + +```sql +SELECT + DirectStr, + NullProp, + COALESCE(NullProp, DirectStr) AS coalesced_col +FROM + aps.TestElement +ORDER BY + COALESCE(NullProp, DirectStr) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | DirectStr | false | 0 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | NullProp | false | 1 | nullProp | NullProp | undefined | string | String | NullProp | +| | coalesced_col | true | 2 | coalesced_col | coalesced_col | undefined | string | String | undefined | + +| DirectStr | NullProp | coalesced_col | +| --------- | --------- | ------------- | +| str1 | NotNull | NotNull | +| str3 | NotNull | NotNull | +| str5 | NotNull | NotNull | +| str7 | NotNull | NotNull | +| str9 | NotNull | NotNull | +| str0 | undefined | str0 | +| str2 | undefined | str2 | +| str4 | undefined | str4 | +| str6 | undefined | str6 | +| str8 | undefined | str8 | + +# With Join + +- dataset: AllProperties.bim + +```sql +SELECT + e.ECInstanceId AS ElementId, + c.ECInstanceId AS ClassId, + c.Name, + e.NullProp +FROM + aps.TestElement e + JOIN meta.ECClassDef c ON e.ECClassId = c.ECInstanceId +ORDER BY + e.NullProp DESC +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | ------------------ | +| | ElementId | true | 0 | elementId | ElementId | Id | long | Id | ECInstanceId | +| | ClassId | true | 1 | classId | ClassId | Id | long | Id | ECInstanceId | +| ECDbMeta:ECClassDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| AllProperties:TestElement | NullProp | false | 3 | nullProp | NullProp | undefined | string | String | NullProp | + +| ElementId | ClassId | Name | NullProp | +| --------- | ------- | ----------- | --------- | +| 0x15 | 0x153 | TestElement | NotNull | +| 0x17 | 0x153 | TestElement | NotNull | +| 0x19 | 0x153 | TestElement | NotNull | +| 0x1b | 0x153 | TestElement | NotNull | +| 0x1d | 0x153 | TestElement | NotNull | +| 0x14 | 0x153 | TestElement | undefined | +| 0x16 | 0x153 | TestElement | undefined | +| 0x18 | 0x153 | TestElement | undefined | +| 0x1a | 0x153 | TestElement | undefined | +| 0x1c | 0x153 | TestElement | undefined | diff --git a/core/backend/src/test/ecsql/queries/ParameterExp.ecsql.md b/core/backend/src/test/ecsql/queries/ParameterExp.ecsql.md new file mode 100644 index 000000000000..6c3ab36af8ff --- /dev/null +++ b/core/backend/src/test/ecsql/queries/ParameterExp.ecsql.md @@ -0,0 +1,120 @@ +# Testing binding different paramter type and having multiplying terms + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + i, + l, + d, + b, + dt, + s, + bin, + p2d, + p3d +FROM + aps.TestElement +WHERE + i = :param1 AND + s = :param2 AND + l = :param1 * 10; +``` + +- bindInt param1, 100 +- bindString param2, str0 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------- | ----------------------- | ------------------------------ | +| 0x14 | 0x153 | 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | BIN(1,2,3) | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | + +# Testing binding different parameter types + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + i, + l, + d, + b, + dt, + s, + bin, + p2d, + p3d +FROM + aps.TestElement +WHERE + i = :param1 AND + s = :param2 AND + l = :param3; +``` + +- bindInt param1, 101 +- bindString param2, str1 +- bindInt param3, 1001 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | --------------------------- | ---------------------------------------- | +| 0x15 | 0x153 | 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11,"Y": 2222.22} | {"X": -111.11,"Y": -222.22,"Z": -333.33} | + +# Testing Unary operator (-) with parameter + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE i = -? +``` + +- bindInt 1, -102 + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 8 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 9 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 10 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------- | ----------------------- | ------------------------------ | +| 0x16 | 0x153 | 102 | 1002 | 2.1 | true | 2017-01-01T00:00:00.000 | str2 | BIN(1,2,3) | {"X": 1.034,"Y": 2.034} | {"X": -1,"Y": 2.3,"Z": 3.0001} | diff --git a/core/backend/src/test/ecsql/queries/RowFormat.ecsql.md b/core/backend/src/test/ecsql/queries/RowFormat.ecsql.md new file mode 100644 index 000000000000..6e3e5119ab66 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/RowFormat.ecsql.md @@ -0,0 +1,63 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Select ECDb schemas from ECDbMeta using tables but using ECSqlPropertyIndexes + +- mode: Statement +- dataset: AllProperties.bim + +```sql +Select s.Name, s.Alias from meta.ECSchemaDef s WHERE s.Name LIKE 'ECDb%' LIMIT 4; +``` + +- rowFormat: ECSqlIndexes + +| name | type | +| ----- | ------ | +| Name | String | +| Alias | String | + +| | | +| ------------------ | ------- | +| ECDbFileInfo | ecdbf | +| ECDbMap | ecdbmap | +| ECDbMeta | meta | +| ECDbSchemaPolicies | ecdbpol | + +# Select Test elements from sample dataset using Json using ECSqlPropertyIndexes row option + +- dataset: AllProperties.bim + +```sql +SELECT e.ECClassId, e.DirectStr FROM aps.TestElement e WHERE e.DirectLong > 1005 ORDER BY e.DirectLong LIMIT 2 +``` + +- rowFormat: ECSqlIndexes + +```json +{ + "columns": [ + { + "accessString": "ECClassId", + "name": "ECClassId", + "type": "Id", + "typeName": "long", + "generated": false, + "extendedType": "ClassId" + }, + { + "accessString": "DirectStr", + "name": "DirectStr", + "type": "String", + "typeName": "string", + "generated": false + } + ] +} +``` + +```json +[ + ["0x153", "str6"], + ["0x153", "str7"] +] +``` diff --git a/core/backend/src/test/ecsql/queries/SearchClauseWhenExp.ecsql.md b/core/backend/src/test/ecsql/queries/SearchClauseWhenExp.ecsql.md new file mode 100644 index 000000000000..5d0bded3f2f8 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/SearchClauseWhenExp.ecsql.md @@ -0,0 +1,341 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Case Expression with first condition true and rest false + +- dataset: AllProperties.bim + +```sql +SELECT + CASE + WHEN 1 THEN 'First' + WHEN 0 THEN 'Second' + WHEN 0 THEN 'Third' + ELSE 'Forth' + END a +FROM + aps.TestElement +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | +| | a | true | 0 | a | a | undefined | string | String | + +| a | +| ----- | +| First | + +# Simple case Expression without alias for ConcurrentQuery + +- dataset: AllProperties.bim +- mode: ConcurrentQuery + +```sql +SELECT + CASE + WHEN 1 THEN 'First' + WHEN 0 THEN 'Second' + WHEN 0 THEN 'Third' + ELSE 'Forth' + END +FROM + aps.TestElement +LIMIT + 1 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": " CASE WHEN 1 THEN 'First' WHEN 0 THEN 'Second' WHEN 0 THEN 'Third' ELSE 'Forth' END ", + "generated": true, + "index": 0, + "jsonName": " CASE WHEN 1 THEN 'First' WHEN 0 THEN 'Second' WHEN 0 THEN 'Third' ELSE 'Forth' END ", + "name": " CASE WHEN 1 THEN 'First' WHEN 0 THEN 'Second' WHEN 0 THEN 'Third' ELSE 'Forth' END ", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + " CASE WHEN 1 THEN 'First' WHEN 0 THEN 'Second' WHEN 0 THEN 'Third' ELSE 'Forth' END ": "First" + } +] +``` + +# Simple case Expression without alias for ECSqlStatement + +- dataset: AllProperties.bim +- mode: Statement + +```sql +SELECT + CASE + WHEN 1 THEN 'First' + WHEN 0 THEN 'Second' + WHEN 0 THEN 'Third' + ELSE 'Forth' + END +FROM + aps.TestElement +LIMIT + 1 +``` + +```json +{ + "columns": [ + { + "className": "", + "accessString": " CASE WHEN 1 THEN 'First' WHEN 0 THEN 'Second' WHEN 0 THEN 'Third' ELSE 'Forth' END ", + "generated": true, + "index": 0, + "jsonName": "__x0020__CASE__x0020____x0020__WHEN__x0020__1__x0020__THEN__x0020____x0027__First__x0027____x0020__WHEN__x0020__0__x0020__THEN__x0020____x0027__Second__x0027____x0020__WHEN__x0020__0__x0020__THEN__x0020____x0027__Third__x0027____x0020__ELSE__x0020____x0027__Forth__x0027____x0020__END__x0020__", + "name": "__x0020__CASE__x0020____x0020__WHEN__x0020__1__x0020__THEN__x0020____x0027__First__x0027____x0020__WHEN__x0020__0__x0020__THEN__x0020____x0027__Second__x0027____x0020__WHEN__x0020__0__x0020__THEN__x0020____x0027__Third__x0027____x0020__ELSE__x0020____x0027__Forth__x0027____x0020__END__x0020__", + "typeName": "string", + "type": "String" + } + ] +} +``` + +```json +[ + { + " CASE WHEN 1 THEN 'First' WHEN 0 THEN 'Second' WHEN 0 THEN 'Third' ELSE 'Forth' END ": "First" + } +] +``` + +# Case Expression with third condition true and rest false + +- dataset: AllProperties.bim + +```sql +SELECT + CASE + WHEN 0 THEN 'First' + WHEN 0 THEN 'Second' + WHEN 1 THEN 'Third' + ELSE 'Forth' + END a +FROM + aps.TestElement +LIMIT + 1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | +| | a | true | 0 | a | a | undefined | string | String | + +| a | +| ----- | +| Third | + +# Case Expression with different type data in then and else clause + +- dataset: AllProperties.bim + +```sql +SELECT + CASE + WHEN DirectStr = 'str0' OR + ( + DirectLong < 1006 AND + DirectDouble > 4.1 + ) THEN dt + ELSE s + END a +FROM + aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | +| | a | true | 0 | a | a | undefined | dateTime | DateTime | + +| a | +| ------------------------ | +| 2017-01-01T00:00:00.000 | +| -4713-11-24T12:00:00.000 | +| -4713-11-24T12:00:00.000 | +| -4713-11-24T12:00:00.000 | +| -4713-11-24T12:00:00.000 | +| 2010-01-01T11:11:11.000 | +| -4713-11-24T12:00:00.000 | +| -4713-11-24T12:00:00.000 | +| -4713-11-24T12:00:00.000 | +| -4713-11-24T12:00:00.000 | + +`Note:- This test documents the behaviour that if we put different type data in then and else clause the first data type is given priority and the other data is converted to first data type.` + +# When-Then chaining + +- dataset: AllProperties.bim + +```sql +SELECT + CASE + WHEN ECInstanceId < 0x18 THEN 'Withing First 4' + WHEN ECInstanceId >= 0x18 AND + ECInstanceId < 0x1b THEN 'Withing second 4' + WHEN ECInstanceId > 0x1b THEN 'Withing last 2' + END limiting_ECInstanceId +FROM + aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | --------------------- | --------- | ----- | --------------------- | --------------------- | ------------ | -------- | ------ | +| | limiting_ECInstanceId | true | 0 | limiting_ECInstanceId | limiting_ECInstanceId | undefined | string | String | + +| limiting_ECInstanceId | +| --------------------- | +| Withing First 4 | +| Withing First 4 | +| Withing First 4 | +| Withing First 4 | +| Withing second 4 | +| Withing second 4 | +| Withing second 4 | +| undefined | +| Withing last 2 | +| Withing last 2 | + +# Testing ECInstanceIds of Bis.Model against Model.Id from TestElement in When Clause + +- dataset: AllProperties.bim + +```sql +SELECT + CASE + WHEN ECInstanceId = ( + SELECT + Model.Id + FROM + aps.TestElement + ) THEN ec_classname (ECClassId) + ELSE 'ClassName not found' + END ClassName +FROM + Bis.Model +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | +| | ClassName | true | 0 | className | ClassName | undefined | string | String | + +| ClassName | +| --------------------- | +| ClassName not found | +| ClassName not found | +| BisCore:PhysicalModel | +| ClassName not found | + +# Testing ECInstanceIds of meta.ECClassDef against ECClassId from TestElement in When Clause + +- dataset: AllProperties.bim + +```sql +SELECT + CASE + WHEN ECInstanceId > ( + SELECT + ECClassId + FROM + aps.TestElement + ) THEN Name + END ClassName +FROM + meta.ECClassDef +WHERE + ClassName <> 'undefined' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | +| | ClassName | true | 0 | className | ClassName | undefined | string | String | + +| ClassName | +| --------------------------- | +| TestElementAspect | +| TestElementRefersToElements | +| TestEntityClass | +| TestFeature | +| TestFeatureUsesElement | + +# Complex When clause with nested subqueries + +- dataset: AllProperties.bim + +```sql +SELECT + CASE + WHEN ECInstanceId > ( + SELECT + e.ECClassId + FROM + aps.TestElement e + WHERE + e.ECInstanceId IN ( + SELECT + Element.Id + FROM + aps.TestElementAspect + ) + ) THEN Name + ELSE 'ClassName not found' + END ClassName +FROM + meta.ECClassDef +WHERE + ClassName <> 'ClassName not found' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | +| | ClassName | true | 0 | className | ClassName | undefined | string | String | + +| ClassName | +| --------------------------- | +| TestElementAspect | +| TestElementRefersToElements | +| TestEntityClass | +| TestFeature | +| TestFeatureUsesElement | + +# Testing internal props of objects in When Clause + +- dataset: AllProperties.bim + +```sql +SELECT CASE WHEN p2d.X = 1.034 THEN p2d.X ELSE 0.0 END X_Coord FROM (SELECT * FROM aps.TestElement) limit 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ------ | +| | X_Coord | true | 0 | x_Coord | X_Coord | undefined | double | Double | + +| X_Coord | +| ------- | +| 1.034 | +| 0 | +| 1.034 | +| 0 | + +# Testing internal props of objects in When Clause with level 2 subquery + +- dataset: AllProperties.bim +- errorDuringPrepare: true + +```sql +SELECT CASE WHEN p2d.X = 1.034 THEN p2d.X ELSE 0.0 END X_Coord FROM (SELECT * FROM (SELECT * FROM aps.TestElement)) limit 4 +``` diff --git a/core/backend/src/test/ecsql/queries/SelectClause.ecsql.md b/core/backend/src/test/ecsql/queries/SelectClause.ecsql.md new file mode 100644 index 000000000000..44ce5ee59b99 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/SelectClause.ecsql.md @@ -0,0 +1,451 @@ +# Select Specific Primitive Properties + +- dataset: AllProperties.bim + +```sql +SELECT i, l, d, b, dt, s FROM aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 1 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 2 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 3 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 4 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 5 | s | s | undefined | string | String | s | + +| i | l | d | b | dt | s | +| --- | ---- | --- | ---- | ----------------------- | ---- | +| 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | +| 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | +| 102 | 1002 | 2.1 | true | 2017-01-01T00:00:00.000 | str2 | +| 103 | 1003 | 3.1 | true | 2010-01-01T11:11:11.000 | str3 | +| 104 | 1004 | 4.1 | true | 2017-01-01T00:00:00.000 | str4 | +| 105 | 1005 | 5.1 | true | 2010-01-01T11:11:11.000 | str5 | +| 106 | 1006 | 6.1 | true | 2017-01-01T00:00:00.000 | str6 | +| 107 | 1007 | 7.1 | true | 2010-01-01T11:11:11.000 | str7 | +| 108 | 1008 | 8.1 | true | 2017-01-01T00:00:00.000 | str8 | +| 109 | 1009 | 9.1 | true | 2010-01-01T11:11:11.000 | str9 | + +# Select Array Properties + +- dataset: AllProperties.bim + +```sql +SELECT array_i,array_l,array_d,array_b,array_dt,array_s FROM aps.TestElement LIMIT 1 +``` + +```json +{ + "columns": [ + { + "className": "AllProperties:IPrimitiveArray", + "accessString": "array_i", + "generated": false, + "index": 0, + "jsonName": "array_i", + "name": "array_i", + "typeName": "int", + "type": "PrimitiveArray", + "originPropertyName": "array_i" + }, + { + "className": "AllProperties:IPrimitiveArray", + "accessString": "array_l", + "generated": false, + "index": 1, + "jsonName": "array_l", + "name": "array_l", + "typeName": "long", + "type": "PrimitiveArray", + "originPropertyName": "array_l" + }, + { + "className": "AllProperties:IPrimitiveArray", + "accessString": "array_d", + "generated": false, + "index": 2, + "jsonName": "array_d", + "name": "array_d", + "typeName": "double", + "type": "PrimitiveArray", + "originPropertyName": "array_d" + }, + { + "className": "AllProperties:IPrimitiveArray", + "accessString": "array_b", + "generated": false, + "index": 3, + "jsonName": "array_b", + "name": "array_b", + "typeName": "boolean", + "type": "PrimitiveArray", + "originPropertyName": "array_b" + }, + { + "className": "AllProperties:IPrimitiveArray", + "accessString": "array_dt", + "generated": false, + "index": 4, + "jsonName": "array_dt", + "name": "array_dt", + "typeName": "dateTime", + "type": "PrimitiveArray", + "originPropertyName": "array_dt" + }, + { + "className": "AllProperties:IPrimitiveArray", + "accessString": "array_s", + "generated": false, + "index": 5, + "jsonName": "array_s", + "name": "array_s", + "typeName": "string", + "type": "PrimitiveArray", + "originPropertyName": "array_s" + } + ] +} +``` + +```json +[ + { + "array_i": [0, 1, 2], + "array_l": [10000, 20000, 30000], + "array_d": [0, 1.1, 2.2], + "array_b": [true, false, true], + "array_dt": ["2017-01-01T00:00:00.000", "2010-01-01T11:11:11.000"], + "array_s": ["s0", "s1", "s2"] + } +] +``` + +# NullProp Handling in Select + +- dataset: AllProperties.bim + +```sql +SELECT NullProp FROM aps.TestElement WHERE NullProp IS NULL +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | -------- | -------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:TestElement | NullProp | false | 0 | nullProp | NullProp | undefined | string | String | NullProp | + +| | +| | +| | +| | +| | +| | +| | + +# Select Instances of Mixin Classes (should be empty) + +- dataset: AllProperties.bim + +```sql +SELECT * FROM ONLY aps.IPrimitive +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | --------------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | +| AllProperties:IPrimitive | i | false | 2 | i | i | undefined | int | +| AllProperties:IPrimitive | l | false | 3 | l | l | undefined | long | +| AllProperties:IPrimitive | d | false | 4 | d | d | undefined | double | +| AllProperties:IPrimitive | b | false | 5 | b | b | undefined | boolean | +| AllProperties:IPrimitive | dt | false | 6 | dt | dt | undefined | dateTime | +| AllProperties:IPrimitive | s | false | 7 | s | s | undefined | string | +| AllProperties:IPrimitive | j | false | 8 | j | j | undefined | string | +| AllProperties:IPrimitive | bin | false | 9 | bin | bin | Json | string | +| AllProperties:IPrimitive | p2d | false | 10 | p2d | p2d | undefined | point2d | +| AllProperties:IPrimitive | p3d | false | 11 | p3d | p3d | undefined | point3d | +| AllProperties:IPrimitive | g | false | 12 | g | g | undefined | Bentley.Geometry.Common.IGeometry | +| AllProperties:IPrimitive | st | false | 13 | st | st | undefined | AllProperties.ComplexStruct | + +# Test Class Name Query + +- dataset: AllProperties.bim + +```sql +SELECT ECClassId FROM meta.ECClassDef WHERE Name = 'TestElement' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ---- | ------------------ | +| | ECClassId | false | 0 | className | ECClassId | ClassId | long | Id | ECClassId | + +| ECClassId | +| --------- | +| 0x25 | + +# Select DISTINCT Values + +- dataset: AllProperties.bim + +```sql +SELECT DISTINCT s FROM aps.TestElement Limit 3 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | s | false | 0 | s | s | undefined | string | String | s | + +| s | +| ---- | +| str0 | +| str1 | +| str2 | + +# Alias Select Query + +- dataset: AllProperties.bim + +```sql +SELECT te.i AS IntegerValue, te.s AS StringValue FROM aps.TestElement AS te LIMIT 3 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | IntegerValue | true | 0 | integerValue | IntegerValue | undefined | int | Int | i | +| | StringValue | true | 1 | stringValue | StringValue | undefined | string | String | s | + +| IntegerValue | StringValue | +| ------------ | ----------- | +| 100 | str0 | +| 101 | str1 | +| 102 | str2 | + +# Select with CASE Statement + +- dataset: AllProperties.bim + +```sql +SELECT s, CASE WHEN i > 104 THEN 'High' ELSE 'Low' END AS ValueCategory FROM aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | s | false | 0 | s | s | undefined | string | String | s | +| | ValueCategory | true | 1 | valueCategory | ValueCategory | undefined | string | String | undefined | + +| s | ValueCategory | +| ---- | ------------- | +| str0 | Low | +| str1 | Low | +| str2 | Low | +| str3 | Low | +| str4 | Low | +| str5 | High | +| str6 | High | +| str7 | High | +| str8 | High | +| str9 | High | + +# Select with functions + +- dataset: AllProperties.bim + +```sql +SELECT s, LENGTH(s) AS StringLength, AVG(d) AS AverageDouble FROM aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | s | false | 0 | s | s | undefined | string | String | s | +| | StringLength | true | 1 | stringLength | StringLength | undefined | long | Int64 | undefined | +| | AverageDouble | true | 2 | averageDouble | AverageDouble | undefined | double | Double | undefined | + +| s | StringLength | AverageDouble | +| ---- | ------------ | ------------- | +| str0 | 4 | 4.6 | + +# Select with function enclosed in brackets + +- dataset: AllProperties.bim + +```sql +SELECT s, (format(s)) AS StringFormatted, (LENGTH(s)) AS StringLength FROM aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | --------------- | --------- | ----- | --------------- | --------------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | s | false | 0 | s | s | undefined | string | String | s | +| | StringFormatted | true | 1 | stringFormatted | StringFormatted | undefined | string | String | undefined | +| | StringLength | true | 2 | stringLength | StringLength | undefined | long | Int64 | undefined | + +| s | StringFormatted | StringLength | +| ---- | --------------- | ------------ | +| str0 | str0 | 4 | +| str1 | str1 | 4 | +| str2 | str2 | 4 | +| str3 | str3 | 4 | +| str4 | str4 | 4 | +| str5 | str5 | 4 | +| str6 | str6 | 4 | +| str7 | str7 | 4 | +| str8 | str8 | 4 | +| str9 | str9 | 4 | + +# Select with ec_classname enclosed in brackets + +- dataset: AllProperties.bim + +```sql +SELECT (ec_classname (ECClassId)) AS ClassName FROM aps.TestElement limit 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ------ | +| | ClassName | true | 0 | className | ClassName | undefined | string | String | + +| ClassName | +| ------------------------- | +| AllProperties:TestElement | +| AllProperties:TestElement | + +# Compound Select - UNION + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong > 1006 +UNION +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong < 1003 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | DirectLong | +| ------------ | ---------- | +| 0x14 | 1000 | +| 0x15 | 1001 | +| 0x16 | 1002 | +| 0x1b | 1007 | +| 0x1c | 1008 | +| 0x1d | 1009 | + +# Compound Select - UNION ALL + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong > 1004 +UNION ALL +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong < 1007 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | DirectLong | +| ------------ | ---------- | +| 0x19 | 1005 | +| 0x1a | 1006 | +| 0x1b | 1007 | +| 0x1c | 1008 | +| 0x1d | 1009 | +| 0x14 | 1000 | +| 0x15 | 1001 | +| 0x16 | 1002 | +| 0x17 | 1003 | +| 0x18 | 1004 | +| 0x19 | 1005 | +| 0x1a | 1006 | + +# Compound Select - INTERSECT + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong > 1004 +INTERSECT +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong < 1007 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | DirectLong | +| ------------ | ---------- | +| 0x19 | 1005 | +| 0x1a | 1006 | + +# Compound Select - EXCEPT + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong > 1006 +EXCEPT +SELECT + ECInstanceId, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong > 1008 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| AllProperties:TestElement | DirectLong | false | 1 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | DirectLong | +| ------------ | ---------- | +| 0x1b | 1007 | +| 0x1c | 1008 | diff --git a/core/backend/src/test/ecsql/queries/Subquery.ecsql.md b/core/backend/src/test/ecsql/queries/Subquery.ecsql.md new file mode 100644 index 000000000000..ff8a2463face --- /dev/null +++ b/core/backend/src/test/ecsql/queries/Subquery.ecsql.md @@ -0,0 +1,335 @@ +# Nested Subquery in SELECT Clause + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + ( + SELECT + MAX(VersionMajor) + FROM + ECDbMeta :ECSchemaDef + ) AS MaxVersionMajor +FROM + aps.TestElement te +LIMIT + 3 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | --------------- | --------- | ----- | --------------- | --------------- | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | MaxVersionMajor | true | 1 | maxVersionMajor | MaxVersionMajor | undefined | int | Int | undefined | + +| ECInstanceId | MaxVersionMajor | +| ------------ | --------------- | +| 0x14 | 5 | +| 0x15 | 5 | +| 0x16 | 5 | + +# Subquery in WHERE Clause + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId +FROM + aps.TestElement te +WHERE + te.i IN ( + SELECT + VersionMajor + 100 + FROM + ECDbMeta :ECSchemaDef + WHERE + Alias LIKE 'aps%' + ); +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x15 | + +# Subquery in WHERE EXISTS + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId +FROM + aps.TestElement te +WHERE + EXISTS ( + SELECT + 1 + FROM + ECDbMeta :ECSchemaDef ecs + WHERE + ecs.VersionMajor + 100 = te.i + ); +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x15 | +| 0x16 | +| 0x18 | +| 0x19 | + +# Subquery in WHERE NOT EXISTS + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId +FROM + aps.TestElement te +WHERE + NOT EXISTS ( + SELECT + 1 + FROM + ECDbMeta :ECSchemaDef ecs + WHERE + ecs.VersionMajor + 100 = te.i + ) +LIMIT + 3; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x14 | +| 0x17 | +| 0x1a | + +# Subquery in FROM Clause (Inline View, subquery ref) + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId, + iv.AliasCount +FROM + aps.TestElement te + JOIN ( + SELECT + VersionMajor, + COUNT(Alias) AS AliasCount + FROM + ECDbMeta :ECSchemaDef + GROUP BY + VersionMajor + ) iv ON te.i = iv.VersionMajor + 100; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | AliasCount | true | 1 | aliasCount | AliasCount | undefined | long | Int64 | undefined | + +| ECInstanceId | AliasCount | +| ------------ | ---------- | +| 0x15 | 6 | +| 0x16 | 2 | +| 0x18 | 1 | +| 0x19 | 1 | + +# CTE subquery + +- dataset: AllProperties.bim + +```sql +WITH + VersionAliases AS ( + SELECT + VersionMajor, + GROUP_CONCAT(Alias) AS Aliases + FROM + ECDbMeta :ECSchemaDef + GROUP BY + VersionMajor + ) +SELECT + te.ECInstanceId, + va.Aliases +FROM + aps.TestElement te + LEFT JOIN VersionAliases va ON te.i + 100 = va.VersionMajor; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | Aliases | true | 1 | aliases | Aliases | undefined | string | String | undefined | + +| ECInstanceId | +| ------------ | +| 0x14 | +| 0x15 | +| 0x16 | +| 0x17 | +| 0x18 | +| 0x19 | +| 0x1a | +| 0x1b | +| 0x1c | +| 0x1d | + +# ANY Clause + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId +FROM + aps.TestElement te +WHERE + te.DirectDouble > ANY( + SELECT + VersionMajor + FROM + ECDbMeta :ECSchemaDef + WHERE + Alias LIKE 'bis%' + ) +LIMIT + 3; +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x15 | +| 0x16 | +| 0x17 | + +# Nested Subquery with HAVING clause + +- dataset: AllProperties.bim + +```sql +SELECT + VersionMajor, + COUNT(*) AS VersionMajorCount +FROM + meta.ECSchemaDef s +GROUP BY + VersionMajor +HAVING + COUNT(*) > ( + SELECT + AVG(VersionMinorCount) + FROM + ( + SELECT + VersionMinor, + COUNT(*) AS VersionMinorCount + FROM + meta.ECSchemaDef + GROUP BY + VersionMinor + ) sub + ); +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ----------------- | --------- | ----- | ----------------- | ----------------- | ------------ | -------- | ----- | ------------------ | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 0 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| | VersionMajorCount | true | 1 | versionMajorCount | VersionMajorCount | undefined | long | Int64 | undefined | + +| VersionMajor | VersionMajorCount | +| ------------ | ----------------- | +| 1 | 6 | +| 2 | 2 | + +# multiple nested subquery in WHERE clause + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId +FROM + aps.TestElement te +WHERE + te.ECInstanceId IN ( + SELECT + te_inner.ECInstanceId + FROM + aps.TestElement te_inner + WHERE + te_inner.DirectLong > ( + SELECT + AVG(VersionMajor) + FROM + ECDbMeta :ECSchemaDef + WHERE + Alias = ( + SELECT + Alias + FROM + ECDbMeta :ECSchemaDef + LIMIT + 1 + ) + ) + ); +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | -------- | ------------ | ------------ | -------- | ---- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | + +| ECInstanceId | +| ------------ | +| 0x14 | +| 0x15 | +| 0x16 | +| 0x17 | +| 0x18 | +| 0x19 | +| 0x1a | +| 0x1b | +| 0x1c | +| 0x1d | + +# Testing Point2d x coord value using select subquery + +- dataset: AllProperties.bim +- skip: The query for this test causes a crash on the backend so skipping it for now but documenting the behaviour + +```sql +select p2d.X from (select * from( select p2d from tmp)) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | +| --------- | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ------ | +| | p2d.X | false | 0 | X | X | | double | Double | + +| X | +| ----- | +| 1.034 | + +`Note:- This query causes a crash on the backend so skipping it for now but documenting the behaviour` diff --git a/core/backend/src/test/ecsql/queries/ValueExp.ecsql.md b/core/backend/src/test/ecsql/queries/ValueExp.ecsql.md new file mode 100644 index 000000000000..5cc641cd2a44 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/ValueExp.ecsql.md @@ -0,0 +1,121 @@ +# Type List Expression + +- dataset: AllProperties.bim + +```sql +SELECT Instance FROM meta.CustomAttribute WHERE Class.Id IS (AllProperties.TestCAClass) LIMIT 1 +``` + +```json +{ + "columns": [ + { + "className": "ECDbMeta:CustomAttribute", + "accessString": "Instance", + "generated": false, + "index": 0, + "jsonName": "instance", + "name": "Instance", + "extendedType": "Xml", + "typeName": "string", + "type": "String", + "originPropertyName": "Instance" + } + ] +} +``` + +```json +[ + { + "Instance": "\n TestProp\n\n" + } +] +``` + +# Using Bitwise AND + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE ECInstanceId = (4 & 5) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | -------- | ----- | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0x4 | 0x27 | ECDbMeta | meta | 4 | 0 | 3 | 3 | 2 | + +# Using Bitwise OR + +- dataset: AllProperties.bim + +```sql +SELECT * FROM meta.ECSchemaDef WHERE ECInstanceId = (4 | 1) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| -------------------- | ------------------------- | --------- | ----- | ------------------------- | ------------------------- | ------------ | -------- | ------ | ------------------------- | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| ECDbMeta:ECSchemaDef | Name | false | 2 | name | Name | undefined | string | String | Name | +| ECDbMeta:ECSchemaDef | DisplayLabel | false | 3 | displayLabel | DisplayLabel | undefined | string | String | DisplayLabel | +| ECDbMeta:ECSchemaDef | Description | false | 4 | description | Description | undefined | string | String | Description | +| ECDbMeta:ECSchemaDef | Alias | false | 5 | alias | Alias | undefined | string | String | Alias | +| ECDbMeta:ECSchemaDef | VersionMajor | false | 6 | versionMajor | VersionMajor | undefined | int | Int | VersionMajor | +| ECDbMeta:ECSchemaDef | VersionWrite | false | 7 | versionWrite | VersionWrite | undefined | int | Int | VersionWrite | +| ECDbMeta:ECSchemaDef | VersionMinor | false | 8 | versionMinor | VersionMinor | undefined | int | Int | VersionMinor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMajor | false | 9 | originalECXmlVersionMajor | OriginalECXmlVersionMajor | undefined | int | Int | OriginalECXmlVersionMajor | +| ECDbMeta:ECSchemaDef | OriginalECXmlVersionMinor | false | 10 | originalECXmlVersionMinor | OriginalECXmlVersionMinor | undefined | int | Int | OriginalECXmlVersionMinor | + +| ECInstanceId | ECClassId | Name | Description | Alias | VersionMajor | VersionWrite | VersionMinor | OriginalECXmlVersionMajor | OriginalECXmlVersionMinor | +| ------------ | --------- | ---------- | ------------------------------------------- | ------- | ------------ | ------------ | ------------ | ------------------------- | ------------------------- | +| 0x5 | 0x27 | ECDbSystem | Helper ECSchema for ECDb internal purposes. | ecdbsys | 5 | 0 | 2 | 3 | 2 | + +# Unary Predicate Expression + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, i, l, d, b, dt, s, bin, p2d, p3d FROM aps.TestElement WHERE True +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | -------- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | l | false | 1 | l | l | undefined | long | Int64 | l | +| AllProperties:IPrimitive | d | false | 2 | d | d | undefined | double | Double | d | +| AllProperties:IPrimitive | b | false | 3 | b | b | undefined | boolean | Boolean | b | +| AllProperties:IPrimitive | dt | false | 4 | dt | dt | undefined | dateTime | DateTime | dt | +| AllProperties:IPrimitive | s | false | 5 | s | s | undefined | string | String | s | +| AllProperties:IPrimitive | bin | false | 6 | bin | bin | undefined | binary | Blob | bin | +| AllProperties:IPrimitive | p2d | false | 7 | p2d | p2d | undefined | point2d | Point2d | p2d | +| AllProperties:IPrimitive | p3d | false | 8 | p3d | p3d | undefined | point3d | Point3d | p3d | + +| ECInstanceId | ECClassId | i | l | d | b | dt | s | bin | p2d | p3d | +| ------------ | --------- | --- | ---- | --- | ---- | ----------------------- | ---- | ---------------------------------- | ---------------------------- | ------------------------------------------ | +| 0x14 | 0x153 | 100 | 1000 | 0.1 | true | 2017-01-01T00:00:00.000 | str0 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x15 | 0x153 | 101 | 1001 | 1.1 | true | 2010-01-01T11:11:11.000 | str1 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x16 | 0x153 | 102 | 1002 | 2.1 | true | 2017-01-01T00:00:00.000 | str2 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x17 | 0x153 | 103 | 1003 | 3.1 | true | 2010-01-01T11:11:11.000 | str3 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x18 | 0x153 | 104 | 1004 | 4.1 | true | 2017-01-01T00:00:00.000 | str4 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x19 | 0x153 | 105 | 1005 | 5.1 | true | 2010-01-01T11:11:11.000 | str5 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x1a | 0x153 | 106 | 1006 | 6.1 | true | 2017-01-01T00:00:00.000 | str6 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1b | 0x153 | 107 | 1007 | 7.1 | true | 2010-01-01T11:11:11.000 | str7 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | +| 0x1c | 0x153 | 108 | 1008 | 8.1 | true | 2017-01-01T00:00:00.000 | str8 | BIN(1,2,3) | {"X": 1.034, "Y": 2.034} | {"X": -1, "Y": 2.3, "Z": 3.0001} | +| 0x1d | 0x153 | 109 | 1009 | 9.1 | true | 2010-01-01T11:11:11.000 | str9 | BIN(11,21,31,34,53,21,14,14,55,22) | {"X": 1111.11, "Y": 2222.22} | {"X": -111.11, "Y": -222.22, "Z": -333.33} | diff --git a/core/backend/src/test/ecsql/queries/WhereClause.ecsql.md b/core/backend/src/test/ecsql/queries/WhereClause.ecsql.md new file mode 100644 index 000000000000..affec02143f8 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/WhereClause.ecsql.md @@ -0,0 +1,1124 @@ +Copyright © Bentley Systems, Incorporated. All rights reserved. See [LICENSE.md](../../../../LICENSE.md) for license terms and full copyright notice. + +# Equality check with string variable + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, Model.Id, DirectStr FROM aps.TestElement WHERE DirectStr = 'str0' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | + +# Inequality check with string variable + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, Model.Id, DirectStr FROM aps.TestElement WHERE DirectStr != 'str0' LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x15 | 0x153 | 0x11 | str1 | +| 0x16 | 0x153 | 0x11 | str2 | + +# Equality check with long variable + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, Model.Id, DirectLong FROM aps.TestElement WHERE DirectLong = 1004 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x18 | 0x153 | 0x11 | 1004 | + +# Inequality check with long variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong != 1004 +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x14 | 0x153 | 0x11 | 1000 | +| 0x15 | 0x153 | 0x11 | 1001 | + +# Greater than condition with long variable + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, Model.Id, DirectLong FROM aps.TestElement WHERE DirectLong > 1008 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x1d | 0x153 | 0x11 | 1009 | + +# Greater than equal condition with long variable + +- dataset: AllProperties.bim + +```sql +SELECT ECInstanceId, ECClassId, Model.Id, DirectLong FROM aps.TestElement WHERE DirectLong >= 1008 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x1c | 0x153 | 0x11 | 1008 | +| 0x1d | 0x153 | 0x11 | 1009 | + +# Less than condition with long variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong < 1001 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x14 | 0x153 | 0x11 | 1000 | + +# Less than equal condition with long variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong <= 1001 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x14 | 0x153 | 0x11 | 1000 | +| 0x15 | 0x153 | 0x11 | 1001 | + +# Equality check with double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble < 1.1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x14 | 0x153 | 0x11 | 0.1 | + +# Inequality check with double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble != 1.1 +LIMIT 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x14 | 0x153 | 0x11 | 0.1 | +| 0x16 | 0x153 | 0x11 | 2.1 | + +# Greater than condition with double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble > 8.1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x1d | 0x153 | 0x11 | 9.1 | + +# Greater than equal condition with double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble >= 8.1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x1c | 0x153 | 0x11 | 8.1 | +| 0x1d | 0x153 | 0x11 | 9.1 | + +# Less than condition with double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble < 1.1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x14 | 0x153 | 0x11 | 0.1 | + +# Less than equal condition with double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble <= 1.1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x14 | 0x153 | 0x11 | 0.1 | +| 0x15 | 0x153 | 0x11 | 1.1 | + +# Chaining AND conditions + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr, + DirectLong, + DirectDouble +FROM + aps.TestElement +WHERE + DirectStr != 'str0' AND + DirectLong < 1006 AND + DirectDouble > 4.1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | DirectLong | false | 4 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 5 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectStr | DirectLong | DirectDouble | +| ------------ | --------- | ---- | --------- | ---------- | ------------ | +| 0x19 | 0x153 | 0x11 | str5 | 1005 | 5.1 | + +# Chaining AND and OR conditions + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr, + DirectLong, + DirectDouble +FROM + aps.TestElement +WHERE + DirectStr = 'str0' OR + ( + DirectLong < 1006 AND + DirectDouble > 4.1 + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | DirectLong | false | 4 | directLong | DirectLong | undefined | long | Int64 | DirectLong | +| AllProperties:TestElement | DirectDouble | false | 5 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectStr | DirectLong | DirectDouble | +| ------------ | --------- | ---- | --------- | ---------- | ------------ | +| 0x14 | 0x153 | 0x11 | str0 | 1000 | 0.1 | +| 0x19 | 0x153 | 0x11 | str5 | 1005 | 5.1 | + +# Between condition with long variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong BETWEEN 1004 AND 1006 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 4 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x18 | 0x153 | 0x11 | 1004 | +| 0x19 | 0x153 | 0x11 | 1005 | +| 0x1a | 0x153 | 0x11 | 1006 | + +# Between condition with double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble BETWEEN 1.1 AND 3.1 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x15 | 0x153 | 0x11 | 1.1 | +| 0x16 | 0x153 | 0x11 | 2.1 | +| 0x17 | 0x153 | 0x11 | 3.1 | + +# IN condition with string variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr +FROM + aps.TestElement +WHERE + DirectStr IN ('str0', 'str4', 'str8') +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | +| 0x18 | 0x153 | 0x11 | str4 | +| 0x1c | 0x153 | 0x11 | str8 | + +# IN condition with long variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong IN (1004, 1007, 1009) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x18 | 0x153 | 0x11 | 1004 | +| 0x1b | 0x153 | 0x11 | 1007 | +| 0x1d | 0x153 | 0x11 | 1009 | + +# IN condition with Double variable + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectDouble +FROM + aps.TestElement +WHERE + DirectDouble IN (5.1, 8.1) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectDouble | false | 3 | directDouble | DirectDouble | undefined | double | Double | DirectDouble | + +| ECInstanceId | ECClassId | Id | DirectDouble | +| ------------ | --------- | ---- | ------------ | +| 0x19 | 0x153 | 0x11 | 5.1 | +| 0x1c | 0x153 | 0x11 | 8.1 | + +# Pattern matching with % + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr +FROM + aps.TestElement +WHERE + DirectStr LIKE 'StR%' +LIMIT + 3 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | +| 0x15 | 0x153 | 0x11 | str1 | +| 0x16 | 0x153 | 0x11 | str2 | + +# Partial pattern matching with % + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr +FROM + aps.TestElement +WHERE + DirectStr LIKE 'S%5' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x19 | 0x153 | 0x11 | str5 | + +# Pattern matching with \_ + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr +FROM + aps.TestElement +WHERE + DirectStr LIKE 'St_0' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | + +# Anti-pattern matching with % + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr +FROM + aps.TestElement +WHERE + DirectStr NOT LIKE 'S%2' +LIMIT + 3 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | +| 0x15 | 0x153 | 0x11 | str1 | +| 0x17 | 0x153 | 0x11 | str3 | + +# With NOT NULL + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + NullProp +FROM + aps.TestElement +WHERE + NullProp IS NOT NULL +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | NullProp | false | 3 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | ECClassId | Id | NullProp | +| ------------ | --------- | ---- | -------- | +| 0x15 | 0x153 | 0x11 | NotNull | +| 0x17 | 0x153 | 0x11 | NotNull | +| 0x19 | 0x153 | 0x11 | NotNull | +| 0x1b | 0x153 | 0x11 | NotNull | +| 0x1d | 0x153 | 0x11 | NotNull | + +# With NOT condition + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr +FROM + aps.TestElement +WHERE + NOT DirectStr IN ( + 'str0', + 'str1', + 'str2', + 'str4', + 'str5', + 'str6', + 'str2', + 'str8', + 'str9' + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x17 | 0x153 | 0x11 | str3 | +| 0x1b | 0x153 | 0x11 | str7 | + +# With subquery + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement +WHERE + ECClassId IN ( + SELECT + ECInstanceId + FROM + meta.ECClassDef + ) +LIMIT + 2 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x14 | 0x153 | 0x11 | 1000 | +| 0x15 | 0x153 | 0x11 | 1001 | + +# With EXISTS + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement e +WHERE + EXISTS ( + SELECT + 1 + FROM + meta.ECClassDef c + WHERE + c.ECInstanceId = e.ECClassId AND + c.Name = 'TestElement' + ) +LIMIT 3 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x14 | 0x153 | 0x11 | 1000 | +| 0x15 | 0x153 | 0x11 | 1001 | +| 0x16 | 0x153 | 0x11 | 1002 | + +# With NOT EXISTS + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement e +WHERE + NOT EXISTS ( + SELECT + 1 + FROM + meta.ECClassDef c + WHERE + c.ECInstanceId = e.ECClassId AND + c.Name = 'WrongTestElement' + ) +LIMIT + 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x14 | 0x153 | 0x11 | 1000 | +| 0x15 | 0x153 | 0x11 | 1001 | +| 0x16 | 0x153 | 0x11 | 1002 | +| 0x17 | 0x153 | 0x11 | 1003 | + +# With functions + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr +FROM + aps.TestElement +WHERE + UPPER(DirectStr) = 'STR0' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | + +# With aggregate functions + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectLong +FROM + aps.TestElement +WHERE + DirectLong > ( + SELECT + AVG(DirectLong) + FROM + aps.TestElement + ) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ---------- | ------------ | ------------ | -------- | ----- | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectLong | false | 3 | directLong | DirectLong | undefined | long | Int64 | DirectLong | + +| ECInstanceId | ECClassId | Id | DirectLong | +| ------------ | --------- | ---- | ---------- | +| 0x19 | 0x153 | 0x11 | 1005 | +| 0x1a | 0x153 | 0x11 | 1006 | +| 0x1b | 0x153 | 0x11 | 1007 | +| 0x1c | 0x153 | 0x11 | 1008 | +| 0x1d | 0x153 | 0x11 | 1009 | + +# Using IS NULL + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + NullProp +FROM + aps.TestElement +WHERE + NullProp IS NULL +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | NullProp | false | 3 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | ECClassId | Id | +| ------------ | --------- | ---- | +| 0x14 | 0x153 | 0x11 | +| 0x16 | 0x153 | 0x11 | +| 0x18 | 0x153 | 0x11 | +| 0x1a | 0x153 | 0x11 | +| 0x1c | 0x153 | 0x11 | + +# Using IS NOT NULL + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + NullProp +FROM + aps.TestElement +WHERE + NullProp IS NOT NULL +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | NullProp | false | 3 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | ECClassId | Id | NullProp | +| ------------ | --------- | ---- | -------- | +| 0x15 | 0x153 | 0x11 | NotNull | +| 0x17 | 0x153 | 0x11 | NotNull | +| 0x19 | 0x153 | 0x11 | NotNull | +| 0x1b | 0x153 | 0x11 | NotNull | +| 0x1d | 0x153 | 0x11 | NotNull | + +# Using COALESCE - IN + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr, + NullProp +FROM + aps.TestElement +WHERE + COALESCE(NullProp, DirectStr) IN ('NotNull') +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | NullProp | false | 4 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | ECClassId | Id | DirectStr | NullProp | +| ------------ | --------- | ---- | --------- | -------- | +| 0x15 | 0x153 | 0x11 | str1 | NotNull | +| 0x17 | 0x153 | 0x11 | str3 | NotNull | +| 0x19 | 0x153 | 0x11 | str5 | NotNull | +| 0x1b | 0x153 | 0x11 | str7 | NotNull | +| 0x1d | 0x153 | 0x11 | str9 | NotNull | + +# Using COALESCE NOT IN + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr, + NullProp +FROM + aps.TestElement +WHERE + COALESCE(NullProp, DirectStr) NOT IN ('NotNull') +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | NullProp | false | 4 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | +| 0x16 | 0x153 | 0x11 | str2 | +| 0x18 | 0x153 | 0x11 | str4 | +| 0x1a | 0x153 | 0x11 | str6 | +| 0x1c | 0x153 | 0x11 | str8 | + +# Using CASE - NOT NULL + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr, + NullProp +FROM + aps.TestElement +WHERE + CASE + WHEN NullProp IS NOT NULL THEN 'TRUE' + ELSE 'FALSE' + END = 'FALSE' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | NullProp | false | 4 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | ECClassId | Id | DirectStr | +| ------------ | --------- | ---- | --------- | +| 0x14 | 0x153 | 0x11 | str0 | +| 0x16 | 0x153 | 0x11 | str2 | +| 0x18 | 0x153 | 0x11 | str4 | +| 0x1a | 0x153 | 0x11 | str6 | +| 0x1c | 0x153 | 0x11 | str8 | + +# Using CASE - IS NULL + +- dataset: AllProperties.bim + +```sql +SELECT + ECInstanceId, + ECClassId, + Model.Id, + DirectStr, + NullProp +FROM + aps.TestElement +WHERE + CASE + WHEN NullProp IS NULL THEN 'TRUE' + ELSE 'FALSE' + END = 'FALSE' +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | --------- | ------------ | ------------ | -------- | ------ | ------------------ | +| | ECInstanceId | false | 0 | id | ECInstanceId | Id | long | Id | ECInstanceId | +| | ECClassId | false | 1 | className | ECClassId | ClassId | long | Id | ECClassId | +| | Model.Id | false | 2 | model.id | Id | NavId | long | Id | Id | +| AllProperties:TestElement | DirectStr | false | 3 | directStr | DirectStr | undefined | string | String | DirectStr | +| AllProperties:TestElement | NullProp | false | 4 | nullProp | NullProp | undefined | string | String | NullProp | + +| ECInstanceId | ECClassId | Id | DirectStr | NullProp | +| ------------ | --------- | ---- | --------- | -------- | +| 0x15 | 0x153 | 0x11 | str1 | NotNull | +| 0x17 | 0x153 | 0x11 | str3 | NotNull | +| 0x19 | 0x153 | 0x11 | str5 | NotNull | +| 0x1b | 0x153 | 0x11 | str7 | NotNull | +| 0x1d | 0x153 | 0x11 | str9 | NotNull | diff --git a/core/backend/src/test/ecsql/queries/WindowFunctions.ecsql.md b/core/backend/src/test/ecsql/queries/WindowFunctions.ecsql.md new file mode 100644 index 000000000000..2f785f7655f9 --- /dev/null +++ b/core/backend/src/test/ecsql/queries/WindowFunctions.ecsql.md @@ -0,0 +1,694 @@ +# Partition by two date values + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId [MyId], + te.s, + te.DT [Date], + row_number() OVER ( + PARTITION BY + te.DT + ORDER BY + te.ECInstanceId + ) AS [RowNumber] +FROM + aps.TestElement te +WHERE + te.i < 106 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------- | ------------------ | +| | MyId | true | 0 | myId | MyId | Id | long | Id | ECInstanceId | +| AllProperties:IPrimitive | s | false | 1 | s | s | undefined | string | String | s | +| | Date | true | 2 | date | Date | undefined | dateTime | DateTime | dt | +| | RowNumber | true | 3 | rowNumber | RowNumber | undefined | long | Int64 | undefined | + +| MyId | s | Date | RowNumber | +| ---- | ---- | ----------------------- | --------- | +| 0x15 | str1 | 2010-01-01T11:11:11.000 | 1 | +| 0x17 | str3 | 2010-01-01T11:11:11.000 | 2 | +| 0x19 | str5 | 2010-01-01T11:11:11.000 | 3 | +| 0x14 | str0 | 2017-01-01T00:00:00.000 | 1 | +| 0x16 | str2 | 2017-01-01T00:00:00.000 | 2 | +| 0x18 | str4 | 2017-01-01T00:00:00.000 | 3 | + +# Rank by date values + +- dataset: AllProperties.bim + +```sql +SELECT i, rank() over(ORDER BY dt) as [rank] from aps.TestElement +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | rank | true | 1 | rank | rank | undefined | long | Int64 | undefined | + +| i | rank | +| --- | ---- | +| 101 | 1 | +| 103 | 1 | +| 105 | 1 | +| 107 | 1 | +| 109 | 1 | +| 100 | 6 | +| 102 | 6 | +| 104 | 6 | +| 106 | 6 | +| 108 | 6 | + +# Dense_Rank with WHERE clause + +- dataset: AllProperties.bim + +```sql +SELECT i, dense_rank() over(ORDER BY dt) as [rank] from aps.TestElement WHERE i < 103 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | ----- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | rank | true | 1 | rank | rank | undefined | long | Int64 | undefined | + +| i | rank | +| --- | ---- | +| 101 | 1 | +| 100 | 2 | +| 102 | 2 | + +# Dense_Rank wrapped in CTE with order by and copy of a column + +- dataset: AllProperties.bim + +```sql +WITH + RankedElements (i, [rank]) AS ( + SELECT + i, + dense_rank() OVER (ORDER BY dt) AS [rank] + FROM + aps.TestElement + WHERE + i < 103 + ) +SELECT re.*, re.[rank] AS [copyOfRank] +FROM RankedElements re +ORDER BY re.[rank] DESC +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ---------- | ---------- | ------------ | -------- | ----- | ------------------ | +| | i | true | 0 | i | i | undefined | int | Int | undefined | +| | rank | true | 1 | rank | rank | undefined | long | Int64 | undefined | +| | copyOfRank | true | 2 | copyOfRank | copyOfRank | undefined | long | Int64 | undefined | + +| i | rank | copyOfRank | +| --- | ---- | ---------- | +| 100 | 2 | 2 | +| 102 | 2 | 2 | +| 101 | 1 | 1 | + +# Several window functions (percent, cume_dist, ntile, lag, lead) in combination + +- dataset: AllProperties.bim + +```sql +SELECT + te.ECInstanceId [MyId], + percent_rank() OVER (PARTITION BY te.DT) AS [percent], + cume_dist() OVER (PARTITION BY te.DT) AS [cumeDist], + ntile(2) OVER (ORDER BY te.i) AS [half], + lag(te.ECInstanceId, 1, null) OVER (ORDER BY te.i) AS [previousId], + lead(te.ECInstanceId, 1, null) OVER (ORDER BY te.i) AS [nextId] +FROM + aps.TestElement te +WHERE + te.i < 106 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | ---------- | ---------- | ------------ | -------- | ------ | ------------------ | +| | MyId | true | 0 | myId | MyId | Id | long | Id | ECInstanceId | +| | percent | true | 1 | percent | percent | undefined | double | Double | undefined | +| | cumeDist | true | 2 | cumeDist | cumeDist | undefined | double | Double | undefined | +| | half | true | 3 | half | half | undefined | long | Int64 | undefined | +| | previousId | true | 4 | previousId | previousId | Id | long | Id | undefined | +| | nextId | true | 5 | nextId | nextId | Id | long | Id | undefined | + +| MyId | percent | cumeDist | half | previousId | nextId | +| ---- | ------- | -------- | ---- | ---------- | --------- | +| 0x15 | 0 | 1 | 1 | 0x14 | 0x16 | +| 0x17 | 0 | 1 | 2 | 0x16 | 0x18 | +| 0x19 | 0 | 1 | 2 | 0x18 | undefined | +| 0x14 | 0 | 1 | 1 | undefined | 0x15 | +| 0x16 | 0 | 1 | 1 | 0x15 | 0x17 | +| 0x18 | 0 | 1 | 2 | 0x17 | 0x19 | + +# First and Last per date partition + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + first_value(i) OVER (PARTITION BY dt ORDER BY i) AS [firstId], + last_value(i) OVER (PARTITION BY dt ORDER BY i) AS [lastId] + FROM + aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ------- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | firstId | true | 1 | firstId | firstId | undefined | int | Int | undefined | +| | lastId | true | 2 | lastId | lastId | undefined | int | Int | undefined | + +| i | firstId | lastId | +| --- | ------- | ------ | +| 101 | 101 | 101 | +| 103 | 101 | 103 | +| 105 | 101 | 105 | +| 107 | 101 | 107 | +| 109 | 101 | 109 | +| 100 | 100 | 100 | +| 102 | 100 | 102 | +| 104 | 100 | 104 | +| 106 | 100 | 106 | +| 108 | 100 | 108 | + +# Max aggregate function + +- dataset: AllProperties.bim + +```sql +SELECT te.i, te.dt, MAX(i) OVER (partition by dt) as [max] from aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | dt | false | 1 | dt | dt | undefined | dateTime | DateTime | dt | +| | max | true | 2 | max | max | undefined | int | Int | undefined | + +| i | dt | max | +| --- | ----------------------- | --- | +| 101 | 2010-01-01T11:11:11.000 | 109 | +| 103 | 2010-01-01T11:11:11.000 | 109 | +| 105 | 2010-01-01T11:11:11.000 | 109 | +| 107 | 2010-01-01T11:11:11.000 | 109 | +| 109 | 2010-01-01T11:11:11.000 | 109 | +| 100 | 2017-01-01T00:00:00.000 | 108 | +| 102 | 2017-01-01T00:00:00.000 | 108 | +| 104 | 2017-01-01T00:00:00.000 | 108 | +| 106 | 2017-01-01T00:00:00.000 | 108 | +| 108 | 2017-01-01T00:00:00.000 | 108 | + +# Max aggregate function with filter + +- dataset: AllProperties.bim + +```sql +SELECT te.i, te.dt, MAX(i) FILTER(WHERE i < 105) OVER (partition by dt) as [max] from aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ---- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| AllProperties:IPrimitive | dt | false | 1 | dt | dt | undefined | dateTime | DateTime | dt | +| | max | true | 2 | max | max | undefined | int | Int | undefined | + +| i | dt | max | +| --- | ----------------------- | --- | +| 101 | 2010-01-01T11:11:11.000 | 103 | +| 103 | 2010-01-01T11:11:11.000 | 103 | +| 105 | 2010-01-01T11:11:11.000 | 103 | +| 107 | 2010-01-01T11:11:11.000 | 103 | +| 109 | 2010-01-01T11:11:11.000 | 103 | +| 100 | 2017-01-01T00:00:00.000 | 104 | +| 102 | 2017-01-01T00:00:00.000 | 104 | +| 104 | 2017-01-01T00:00:00.000 | 104 | +| 106 | 2017-01-01T00:00:00.000 | 104 | +| 108 | 2017-01-01T00:00:00.000 | 104 | + +# Rows with Frame Start + +- dataset: AllProperties.bim + +```sql +SELECT te.i, first_value(i) OVER (order by i ROWS CURRENT ROW) as [first] from aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | first | true | 1 | first | first | undefined | int | Int | undefined | + +| i | first | +| --- | ----- | +| 100 | 100 | +| 101 | 101 | +| 102 | 102 | +| 103 | 103 | +| 104 | 104 | +| 105 | 105 | +| 106 | 106 | +| 107 | 107 | +| 108 | 108 | +| 109 | 109 | + +# Rows with frame between + +- dataset: AllProperties.bim + +```sql +SELECT te.i, first_value(i) OVER (order by i ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as [first] from aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | first | true | 1 | first | first | undefined | int | Int | undefined | + +| i | first | +| --- | ----- | +| 100 | 100 | +| 101 | 100 | +| 102 | 100 | +| 103 | 100 | +| 104 | 100 | +| 105 | 100 | +| 106 | 100 | +| 107 | 100 | +| 108 | 100 | +| 109 | 100 | + +# Groups with frame start + +- dataset: AllProperties.bim + +```sql +SELECT te.i, last_value(i) OVER (order by dt GROUPS UNBOUNDED PRECEDING) as [group] from aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | group | true | 1 | group | group | undefined | int | Int | undefined | + +| i | group | +| --- | ----- | +| 101 | 109 | +| 103 | 109 | +| 105 | 109 | +| 107 | 109 | +| 109 | 109 | +| 100 | 108 | +| 102 | 108 | +| 104 | 108 | +| 106 | 108 | +| 108 | 108 | + +# Range with frame start + +- dataset: AllProperties.bim + +```sql +SELECT te.i, first_value(i) OVER (order by dt RANGE 0 + 1 PRECEDING EXCLUDE NO OTHERS) as [range] from aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ---- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | range | true | 1 | range | range | undefined | int | Int | undefined | + +| i | range | +| --- | ----- | +| 101 | 101 | +| 103 | 101 | +| 105 | 101 | +| 107 | 101 | +| 109 | 101 | +| 100 | 100 | +| 102 | 100 | +| 104 | 100 | +| 106 | 100 | +| 108 | 100 | + +# Named window + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + te.DT [Date], + row_number() OVER win AS [RowNumber] +FROM + aps.TestElement te +WHERE + te.i < 106 +WINDOW + win as (PARTITION BY te.DT ORDER BY te.i) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | -------- | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | Date | true | 1 | date | Date | undefined | dateTime | DateTime | dt | +| | RowNumber | true | 2 | rowNumber | RowNumber | undefined | long | Int64 | undefined | + +| i | Date | RowNumber | +| --- | ----------------------- | --------- | +| 101 | 2010-01-01T11:11:11.000 | 1 | +| 103 | 2010-01-01T11:11:11.000 | 2 | +| 105 | 2010-01-01T11:11:11.000 | 3 | +| 100 | 2017-01-01T00:00:00.000 | 1 | +| 102 | 2017-01-01T00:00:00.000 | 2 | +| 104 | 2017-01-01T00:00:00.000 | 3 | + +# Window chaining + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + group_concat(i) OVER (win ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [othersInGroup] +FROM + aps.TestElement te +WINDOW + win AS (PARTITION BY te.DT ORDER BY te.i) +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------- | --------- | ----- | ------------- | ------------- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | othersInGroup | true | 1 | othersInGroup | othersInGroup | undefined | string | String | undefined | + +| i | othersInGroup | +| --- | ------------------- | +| 101 | "101" | +| 103 | 101,103 | +| 105 | 101,103,105 | +| 107 | 101,103,105,107 | +| 109 | 101,103,105,107,109 | +| 100 | "100" | +| 102 | 100,102 | +| 104 | 100,102,104 | +| 106 | 100,102,104,106 | +| 108 | 100,102,104,106,108 | + +# Window partition collate nocase + +- dataset: AllProperties.bim + +```sql +SELECT + te.i [id], + te.noCaseString, + row_number() OVER (PARTITION BY te.noCaseString COLLATE NOCASE) AS [partition] +FROM + aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | id | true | 0 | id | id | undefined | int | Int | i | +| AllProperties:TestElement | NoCaseString | false | 1 | noCaseString | NoCaseString | undefined | string | String | NoCaseString | +| | partition | true | 2 | partition | partition | undefined | long | Int64 | undefined | + +| id | NoCaseString | partition | +| --- | ------------ | --------- | +| 100 | abc | 1 | +| 101 | ABC | 2 | +| 102 | abc | 3 | +| 103 | ABC | 4 | +| 104 | abc | 5 | +| 105 | ABC | 6 | +| 106 | abc | 7 | +| 107 | ABC | 8 | +| 108 | abc | 9 | +| 109 | ABC | 10 | + +# Window partition collate rtrim + +- dataset: AllProperties.bim + +```sql +SELECT + te.i [id], + te.noCaseString, + row_number() OVER (PARTITION BY te.noCaseString COLLATE RTRIM) AS [partition] +FROM + aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | id | true | 0 | id | id | undefined | int | Int | i | +| AllProperties:TestElement | NoCaseString | false | 1 | noCaseString | NoCaseString | undefined | string | String | NoCaseString | +| | partition | true | 2 | partition | partition | undefined | long | Int64 | undefined | + +| id | NoCaseString | partition | +| --- | ------------ | --------- | +| 101 | ABC | 1 | +| 103 | ABC | 2 | +| 105 | ABC | 3 | +| 107 | ABC | 4 | +| 109 | ABC | 5 | +| 100 | abc | 1 | +| 102 | abc | 2 | +| 104 | abc | 3 | +| 106 | abc | 4 | +| 108 | abc | 5 | + +# Window partition collate binary + +- dataset: AllProperties.bim + +```sql +SELECT + te.i [id], + te.noCaseString, + row_number() OVER (PARTITION BY te.noCaseString COLLATE BINARY) AS [partition] +FROM + aps.TestElement te +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------- | ------------ | --------- | ----- | ------------ | ------------ | ------------ | -------- | ------ | ------------------ | +| | id | true | 0 | id | id | undefined | int | Int | i | +| AllProperties:TestElement | NoCaseString | false | 1 | noCaseString | NoCaseString | undefined | string | String | NoCaseString | +| | partition | true | 2 | partition | partition | undefined | long | Int64 | undefined | + +| id | NoCaseString | partition | +| --- | ------------ | --------- | +| 101 | ABC | 1 | +| 103 | ABC | 2 | +| 105 | ABC | 3 | +| 107 | ABC | 4 | +| 109 | ABC | 5 |s +| 100 | abc | 1 | +| 102 | abc | 2 | +| 104 | abc | 3 | +| 106 | abc | 4 | +| 108 | abc | 5 | + +# Partition by ExtractInstanceExp + +- dataset: AllProperties.bim + +```sql +SELECT te.i [id], row_number() OVER (PARTITION BY $) AS [partition] FROM aps.TestElement te LIMIT 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ----- | ------------------ | +| | id | true | 0 | id | id | undefined | int | Int | i | +| | partition | true | 1 | partition | partition | undefined | long | Int64 | undefined | + +| id | partition | +| --- | --------- | +| 100 | 1 | +| 101 | 1 | +| 102 | 1 | +| 103 | 1 | + +# Partition by ExtractPropertyExp + +- dataset: AllProperties.bim + +```sql +SELECT te.i [id], row_number() OVER (PARTITION BY $->b) AS [partition] FROM aps.TestElement te LIMIT 4 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| --------- | ------------ | --------- | ----- | --------- | --------- | ------------ | -------- | ----- | ------------------ | +| | id | true | 0 | id | id | undefined | int | Int | i | +| | partition | true | 1 | partition | partition | undefined | long | Int64 | undefined | + +| id | partition | +| --- | --------- | +| 100 | 1 | +| 101 | 2 | +| 102 | 3 | +| 103 | 4 | + +# Window Frame unbounded following + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + group_concat(te.i, '.') OVER ( + ORDER BY + te.i ROWS BETWEEN CURRENT ROW AND + UNBOUNDED FOLLOWING + ) AS [group] +FROM + aps.TestElement te +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | group | true | 1 | group | group | undefined | string | String | undefined | + +| i | group | +| --- | --------------------------------------- | +| 100 | 100.101.102.103.104.105.106.107.108.109 | +| 101 | 101.102.103.104.105.106.107.108.109 | +| 102 | 102.103.104.105.106.107.108.109 | +| 103 | 103.104.105.106.107.108.109 | +| 104 | 104.105.106.107.108.109 | + +# Window Frame exclude current row + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + group_concat(te.i, '.') OVER ( + ORDER BY + te.i ROWS BETWEEN CURRENT ROW AND + UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW + ) AS [group] +FROM + aps.TestElement te +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | group | true | 1 | group | group | undefined | string | String | undefined | + +| i | group | +| --- | ----------------------------------- | +| 100 | 101.102.103.104.105.106.107.108.109 | +| 101 | 102.103.104.105.106.107.108.109 | +| 102 | 103.104.105.106.107.108.109 | +| 103 | 104.105.106.107.108.109 | +| 104 | 105.106.107.108.109 | + +# Window frame exclude group + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + group_concat(te.i, '.') OVER ( + ORDER BY + te.i ROWS BETWEEN CURRENT ROW AND + UNBOUNDED FOLLOWING EXCLUDE GROUP + ) AS [group] +FROM + aps.TestElement te +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | group | true | 1 | group | group | undefined | string | String | undefined | + +| i | group | +| --- | ----------------------------------- | +| 100 | 101.102.103.104.105.106.107.108.109 | +| 101 | 102.103.104.105.106.107.108.109 | +| 102 | 103.104.105.106.107.108.109 | +| 103 | 104.105.106.107.108.109 | +| 104 | 105.106.107.108.109 | + +# Window frame exclude ties + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + group_concat(te.i, '.') OVER ( + ORDER BY + te.i ROWS BETWEEN CURRENT ROW AND + UNBOUNDED FOLLOWING EXCLUDE TIES + ) AS [group] +FROM + aps.TestElement te +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | group | true | 1 | group | group | undefined | string | String | undefined | + +| i | group | +| --- | ----------------------------------- | +| 100 | 101.102.103.104.105.106.107.108.109 | +| 101 | 102.103.104.105.106.107.108.109 | +| 102 | 103.104.105.106.107.108.109 | +| 103 | 104.105.106.107.108.109 | +| 104 | 105.106.107.108.109 | + +# Window frame between values + +- dataset: AllProperties.bim + +```sql +SELECT + te.i, + group_concat(te.i, '.') OVER ( + ORDER BY + te.i ROWS BETWEEN 2 + 1 PRECEDING AND + 1 + 1 FOLLOWING EXCLUDE TIES + ) AS [group] +FROM + aps.TestElement te +LIMIT + 5 +``` + +| className | accessString | generated | index | jsonName | name | extendedType | typeName | type | originPropertyName | +| ------------------------ | ------------ | --------- | ----- | -------- | ----- | ------------ | -------- | ------ | ------------------ | +| AllProperties:IPrimitive | i | false | 0 | i | i | undefined | int | Int | i | +| | group | true | 1 | group | group | undefined | string | String | undefined | + +| i | group | +| --- | ------------------- | +| 100 | "101.102" | +| 101 | 100.102.103 | +| 102 | 100.101.103.104 | +| 103 | 100.101.102.104.105 | +| 104 | 101.102.103.105.106 | diff --git a/core/backend/src/test/ecsql/src/ECSqlTestGenerator.ts b/core/backend/src/test/ecsql/src/ECSqlTestGenerator.ts new file mode 100644 index 000000000000..28ac61d08c51 --- /dev/null +++ b/core/backend/src/test/ecsql/src/ECSqlTestGenerator.ts @@ -0,0 +1,152 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ + +import { IModelDb, SnapshotDb } from "../../../core-backend"; +import { DbResult, ECSqlValueType, QueryOptionsBuilder, QueryPropertyMetaData, QueryRowFormat } from "@itwin/core-common"; +import * as path from "path"; +import * as fs from "fs"; +import * as crypto from "crypto"; +import { ECSqlDatasets } from "../dataset/ECSqlDatasets"; +import { KnownTestLocations } from "../../KnownTestLocations"; +import { format } from "sql-formatter"; + +// Call like this: +// node lib\cjs\test\ecsql\src\ECSqlTestGenerator.js AllProperties.bim "SELECT * FROM meta.ECSchemaDef LIMIT 2" -t +// node lib\cjs\test\ecsql\src\ECSqlTestGenerator.js AllProperties.bim "SELECT te.ECInstanceId [MyId], te.s, te.DT [Date], row_number() over(PARTITION BY te.DT ORDER BY te.ECInstanceId) as [RowNumber] from aps.TestElement te WHERE te.i < 106" -t +async function runConcurrentQuery(imodel: IModelDb, sql: string): Promise<{metadata: any[], rows: any[] }> { + const queryOptions: QueryOptionsBuilder = new QueryOptionsBuilder(); + queryOptions.setRowFormat(QueryRowFormat.UseECSqlPropertyNames); + const reader = imodel.createQueryReader(sql, undefined, queryOptions.getOptions()); + const rows = await reader.toArray(); + const metadata = await reader.getMetaData(); + metadata.forEach((value: QueryPropertyMetaData)=> delete (value as any).extendType); + return {metadata, rows }; +} + +function pullAdditionalMetadataThroughECSqlStatement(imodel: IModelDb, metadata: any[], sql: string): void { + const stmt = imodel.prepareStatement(sql); + if (stmt.step() === DbResult.BE_SQLITE_ROW) { + const colCount = stmt.getColumnCount(); + if(colCount !== metadata.length) { + // eslint-disable-next-line no-console + console.error(`Column count mismatch: ${colCount} != ${metadata.length}. Not generating metadata from statement.`); + stmt.dispose(); + return; + } + for (let i = 0; i < colCount; i++) { + const colInfo = stmt.getValue(i).columnInfo; + metadata[i].type = ECSqlValueType[colInfo.getType()]; + const originPropertyName = colInfo.getOriginPropertyName(); + if (originPropertyName !== undefined) + metadata[i].originPropertyName = originPropertyName; + } + stmt.dispose(); + } +} + +function arrayToMarkdownTable(data: any[]): string { + if (data.length === 0) { + return ""; + } + + const headers: string[] = Array.from(data.reduce((headersSet, row) => { + Object.keys(row).forEach(header => headersSet.add(header)); + return headersSet; + }, new Set())); + + const columnWidths = headers.map(header => + Math.max(header.length, ...data.map(row => String(row[header]).length)) + ); + + const formatRow = (row: any) => + `| ${headers.map((header, i) => String(row[header]).padEnd(columnWidths[i])).join(" | ")} |`; + + const headerRow = formatRow(headers.reduce((acc, header) => ({ ...acc, [header]: header }), {})); + const separatorRow = `| ${columnWidths.map(width => "-".repeat(width)).join(" | ")} |`; + const dataRows = data.map(formatRow); + + return [headerRow, separatorRow, ...dataRows].join("\n"); +} + +function generateHash(input: string): string { + return crypto.createHash('sha256').update(input).digest('hex').substring(0, 8); +} + +function writeMarkdownFile(dataset: string, sql: string, columns: any[], results: any[], useTables: boolean): void { + const hash = generateHash(sql); + if (sql.length > 100) { // we format the SQL if it's too long + sql = format(sql, {language: "sqlite", keywordCase: "upper", "tabWidth": 2, indentStyle: "standard", logicalOperatorNewline: "after"}); + } + + let markdownContent = `# GeneratedTest #${dataset} - ${hash} + +- dataset: ${dataset} + +\`\`\`sql +${sql} +\`\`\` +`; + + if (useTables) { + markdownContent += ` +${arrayToMarkdownTable(columns)} + +${arrayToMarkdownTable(results)} + +`; + } else { + markdownContent += ` +\`\`\`json +${JSON.stringify({columns}, null, 2)} +\`\`\` + +\`\`\`json +${JSON.stringify(results, null, 2)} +\`\`\` + +`; + } + + const outputFilePath = path.join(__dirname, "generated.ecsql.md"); + fs.appendFileSync(outputFilePath, markdownContent, "utf-8"); + // eslint-disable-next-line no-console + console.log(`Results written to ${outputFilePath}`); +} + +async function main() { + const args = process.argv.slice(2); + if (args.length < 2) { + // eslint-disable-next-line no-console + console.error("Usage: ts-node ECDbMarkdownTestGenerator.ts "); + process.exit(1); + } + + const [dataset, sql, tablesFlag] = args; + const useTables = tablesFlag === "-t"; + let imodel: IModelDb | undefined; + try { + await ECSqlDatasets.generateFiles(); + const datasetFilePath = path.join(KnownTestLocations.outputDir, "ECSqlTests", dataset); + imodel = SnapshotDb.openFile(datasetFilePath); + const { metadata, rows } = await runConcurrentQuery(imodel, sql); + pullAdditionalMetadataThroughECSqlStatement(imodel, metadata, sql); + writeMarkdownFile(dataset, sql, metadata, rows, useTables); + imodel.close(); + imodel = undefined; + } catch (error) { + // eslint-disable-next-line no-console + console.error("Error running query:", error); + if (imodel) { + imodel.close(); + } + process.exit(1); + } +} + +main().catch((error) => { + // eslint-disable-next-line no-console + console.error("Unhandled error in main:", error); + process.exit(1); +}); \ No newline at end of file diff --git a/core/backend/src/test/ecsql/src/ECSqlTestParser.ts b/core/backend/src/test/ecsql/src/ECSqlTestParser.ts new file mode 100644 index 000000000000..3d095714b6d1 --- /dev/null +++ b/core/backend/src/test/ecsql/src/ECSqlTestParser.ts @@ -0,0 +1,473 @@ +/*--------------------------------------------------------------------------------------------- +* Copyright (c) Bentley Systems, Incorporated. All rights reserved. +* See LICENSE.md in the project root for license terms and full copyright notice. +*--------------------------------------------------------------------------------------------*/ +import * as path from "path"; +import * as fs from "fs"; +import { marked, Tokens } from "marked"; + +export interface ECDbTestProps { + fileName: string; + title: string; + + // Things from properties: + only?: boolean; // This flag handles the only property to filter tests + skip?: string; // This flag handles the skip property to filter tests + dataset?: string; + mode: ECDbTestMode; + rowFormat: ECDbTestRowFormat; + abbreviateBlobs: boolean; + convertClassIdsToClassNames: boolean; + errorDuringPrepare?: boolean; + + // TODO: implement, it's currently being parsed but not used + stepStatus?: string; + + // Things from code blocks or tables + sql?: string; + expectedResults?: { [key: string]: any }[] | any[]; + columnInfo?: ColumnInfoProps[]; + + // Things from lists + binders?: ECDbTestBinderProps[]; +} + +export interface ECDbTestBinderProps { + indexOrName: string; + type: string; + value: string; +} + +export interface ColumnInfoProps{ + name: string; + className?: string; + accessString?: string; + generated?: boolean; + index?: number; + jsonName?: string; + // expected extendedType value should be given when we know that the actual column info extendedType will be a valid non empty string for test to pass. + // This extendedType value is internally used to check both extendType and extendedType values of column metadata. + extendedType?: string; + type?: string; // type is used on ECSqlStatement because it can differ from TypeName + typeName?: string; // typeName is used on ConcurrentQuery + originPropertyName?: string; // only supported for ECSqlStatement +} + +export const columnInfoPropsKeys: Set = new Set([ + "name", + "className", + "accessString", + "generated", + "index", + "jsonName", + "extendedType", + "type", + "typeName", + "originPropertyName", +]); + +/* interface QueryPropertyMetaData + className: string; + accessString?: string; + generated: boolean; + index: number; + jsonName: string; + name: string; + extendType: string; + typeName: string; +*/ + +function isColumnInfoProps(obj: any): obj is ColumnInfoProps { + const numberOfKeys = typeof obj === "object" ? Object.keys(obj).length : 0; + const isValid = typeof obj === "object" && + typeof obj.name === "string" && + (obj.className === undefined || typeof obj.className === "string") && + (obj.accessString === undefined || typeof obj.accessString === "string") && + (obj.generated === undefined || typeof obj.generated === "boolean") && + (obj.index === undefined || typeof obj.index === "number") && + (obj.jsonName === undefined || typeof obj.jsonName === "string") && + (obj.extendedType === undefined || typeof obj.extendedType === "string") && + (obj.type === undefined || typeof obj.type === "string") && + (obj.typeName === undefined || typeof obj.typeName === "string"); + + if (!isValid) { + const errors: string[] = []; + if (typeof obj !== "object") errors.push("Object is not of type 'object'"); + if (numberOfKeys < 1 || numberOfKeys > 7) errors.push("Number of keys is not between 1 and 7"); + if (typeof obj.name !== "string") errors.push("Property 'name' is not of type 'string'"); + if (obj.className !== undefined && typeof obj.className !== "string") errors.push("Property 'className' is not of type 'string'"); + if (obj.accessString !== undefined && typeof obj.accessString !== "string") errors.push("Property 'accessString' is not of type 'string'"); + if (obj.generated !== undefined && typeof obj.generated !== "boolean") errors.push("Property 'generated' is not of type 'boolean'"); + if (obj.index !== undefined && typeof obj.index !== "number") errors.push("Property 'index' is not of type 'number'"); + if (obj.jsonName !== undefined && typeof obj.jsonName !== "string") errors.push("Property 'jsonName' is not of type 'string'"); + if (obj.extendedType !== undefined && typeof obj.extendedType !== "string") errors.push("Property 'extendedType' is not of type 'string'"); + if (obj.type !== undefined && typeof obj.type !== "string") errors.push("Property 'type' is not of type 'string'"); + if (obj.typeName !== undefined && typeof obj.typeName !== "string") errors.push("Property 'typeName' is not of type 'string'"); + logWarning(`Validation failed for ColumnInfoProps. Object: ${JSON.stringify(obj)}. Errors: ${errors.join(", ")}`); + } + + return isValid; +} + +export enum ECDbTestMode{ + Both = "Both", + Statement = "Statement", + ConcurrentQuery = "ConcurrentQuery", +}; + +export enum ECDbTestRowFormat { + ECSqlNames = "ECSqlNames", + ECSqlIndexes = "ECSqlIndexes", + JsNames = "JsNames", +} + +function tableTextToValue(text: string) : any { + if(text.startsWith("\"") && text.endsWith("\"")) + return text.slice(1,text.length-1); + if(text === "null") + return null; + if(text === "undefined") + return undefined; + if(text.startsWith("{") || text.startsWith("[")) + return JSON.parse(text); + if(text === "true" || text === "false") + return text === "true"; + if(text.startsWith("0x")) + return text; // we use this for IDs and they are handled as strings, the parseInt below would attempt to convert them to numbers + if(/^-?\d+(\.\d+)?$/.test(text)) { + const flt = parseFloat(text); + if(!Number.isNaN(flt)) + return flt; + } + + if(/^-?\d+$/.test(text)) { + // eslint-disable-next-line radix + const asInt = parseInt(text); + if(!Number.isNaN(asInt)) + return asInt; + } + + return text; +} + +export function buildBinaryData(obj: any): any { //TODO: we should do this during table parsing + for(const key in obj) { + if(typeof obj[key] === "string" && obj[key].startsWith("BIN(") && obj[key].endsWith(")")) + obj[key] = understandAndReplaceBinaryData(obj[key]) + else if(typeof obj[key] === "object" || Array.isArray(obj[key])) + obj[key] = buildBinaryData(obj[key]) + } + return obj; +} + +function understandAndReplaceBinaryData(str: string): any{ + const startInd = str.indexOf("(") + 1; + const endInd = str.indexOf(")"); + str = str.slice(startInd, endInd); + const ans: number[] = [] + const numbers: string[] = str.split(","); + numbers.forEach((value:string)=> + { + value = value.trim(); + // eslint-disable-next-line radix + ans.push(parseInt(value)); + } + ); + return Uint8Array.of(...ans); +} + + +export class ECDbMarkdownTestParser { + public static parse(): ECDbTestProps[] { + const testAssetsDir = path.join(__dirname ,"..","queries"); + const testFiles = fs.readdirSync(testAssetsDir, "utf-8").filter((fileName) => fileName.toLowerCase().endsWith("ecsql.md")); + const out: ECDbTestProps[] = []; + + for (const fileName of testFiles) { + try { + const tests = this.parseFile(testAssetsDir, fileName); + out.push(...tests); + } catch (error) { + logWarning(`Failed to parse file ${fileName}. Error: ${error instanceof Error ? error.message : "Unknown error"}`); + } + } + return out; + } + + private static parseFile(testAssetsDir: string, fileName: string): ECDbTestProps[] { + const markdownFilePath = path.join(testAssetsDir, fileName); + const baseFileName = fileName.replace(/\.ecdbtest\.md$/i, ""); + const markdownContent = fs.readFileSync(markdownFilePath, "utf-8"); + const tokens = marked.lexer(markdownContent); + + const out: ECDbTestProps[] = []; + let currentTest: ECDbTestProps | undefined; + + for (const token of tokens) { + switch (token.type) { + case "space": + case "html": + case "paragraph": + case "hr": + continue; + case "heading": + if (currentTest !== undefined) { + out.push(currentTest); + } + currentTest = { title: token.text, mode: ECDbTestMode.Both, fileName: baseFileName, + rowFormat: ECDbTestRowFormat.ECSqlNames, abbreviateBlobs: false, convertClassIdsToClassNames: false }; + break; + case "list": + this.handleListToken(token as Tokens.List, currentTest, markdownFilePath); + break; + case "code": + this.handleCodeToken(token as Tokens.Code, currentTest, markdownFilePath); + break; + case "table": + this.handleTableToken(token as Tokens.Table, currentTest, markdownFilePath); + break; + default: + logWarning(`Unknown token type ${token.type} found in file ${markdownFilePath}. Skipping.`); + break; + } + } + + if (currentTest !== undefined) { + out.push(currentTest); + } + return out; + } + + + private static handleListToken(token: Tokens.List, currentTest: ECDbTestProps | undefined, markdownFilePath: string) { + if (currentTest === undefined) { + logWarning(`List token found without a test title in file ${markdownFilePath}. Skipping.`); + return; + } + + const variableRegex = /^(\w+):\s*(.+)$/; + const bindRegex = /^bind(\w+)\s([^,\s]+),\s?(.+)$/; + for (const item of token.items) { + const match = item.text.match(variableRegex); + if (match) { + const key = match[1]; + const value = match[2]; + switch (key.toLowerCase()) { + case "dataset": + currentTest.dataset = value; + continue; + case "errorduringprepare": + currentTest.errorDuringPrepare = value.toLowerCase() === "true"; + continue; + case "stepstatus": + currentTest.stepStatus = value; + continue; + case "only": + currentTest.only = value.toLowerCase() === "true"; + continue; + case "skip": + currentTest.skip = value; + continue; + case "mode": + this.handleMode(value, currentTest, markdownFilePath); + continue; + case "rowformat": + this.handleRowFormat(value, currentTest, markdownFilePath); + continue; + case "abbreviateblobs": + currentTest.abbreviateBlobs = value.toLowerCase() === "true"; + continue; + case "convertclassidstoclassnames": + currentTest.convertClassIdsToClassNames = value.toLowerCase() === "true"; + continue; + } + } + const bindMatch = item.text.match(bindRegex); + if (bindMatch) { + currentTest.binders = currentTest.binders || []; + currentTest.binders.push({ indexOrName: bindMatch[2], type: bindMatch[1], value: bindMatch[3] }); + continue; + } + } + } + + private static handleMode(value: string, currentTest: ECDbTestProps, markdownFilePath: string) { + switch(value.toLowerCase()) { + case "statement": + currentTest.mode = ECDbTestMode.Statement; + break; + case "concurrentquery": + currentTest.mode = ECDbTestMode.ConcurrentQuery; + break; + case "both": + currentTest.mode = ECDbTestMode.Both; + break; + default: + logWarning(`Mode value (${value}) is not recognized in file ${markdownFilePath} and test ${currentTest.title}. Skipping.`); + } + } + + private static handleRowFormat(value: string, currentTest: ECDbTestProps, markdownFilePath: string) { + switch(value.toLowerCase()) { + case "ecsqlnames": + currentTest.rowFormat = ECDbTestRowFormat.ECSqlNames; + break; + case "ecsqlindexes": + currentTest.rowFormat = ECDbTestRowFormat.ECSqlIndexes; + break; + case "jsnames": + currentTest.rowFormat = ECDbTestRowFormat.JsNames; + break; + default: + logWarning(`Row Format value (${value}) is not recognized in file ${markdownFilePath} and test ${currentTest.title}. Skipping.`); + } + } + + private static handleCodeToken(token: Tokens.Code, currentTest: ECDbTestProps | undefined, markdownFilePath: string) { + if (currentTest === undefined) { + logWarning(`Code token found without a test title in file ${markdownFilePath}. Skipping.`); + return; + } + + if (token.lang === "sql") { + currentTest.sql = token.text; + } else if (token.lang === "json") { + let json: any; + try { + json = JSON.parse(token.text); + } catch (error) { + if (error instanceof Error) { + logWarning(`Failed to parse JSON ${token.text} in file ${markdownFilePath}. ${error.message} Skipping.`); + } else { + logWarning(`Failed to parse SON ${token.text} in file ${markdownFilePath}. Unknown error. Skipping.`); + } + } + + if (typeof json === "object" && Array.isArray(json.columns)) { + this.handleJSONColumnMetadata(json, currentTest, markdownFilePath); + return; + } + + this.handleJSONExpectedResults(json, currentTest); // TODO: validate the expected results + } else { + logWarning(`Unknown code language ${token.lang} found in file ${markdownFilePath}. Skipping.`); + } + } + + private static handleJSONColumnMetadata(json: any, currentTest: ECDbTestProps, markdownFilePath: string) { + const extraProps: Set = new Set(); + + if (json.columns.every(isColumnInfoProps)) { + currentTest.columnInfo = json.columns; + for (const column of json.columns) { + for (const key in column) { + if (!columnInfoPropsKeys.has(key as keyof ColumnInfoProps)) { + extraProps.add(key); + } + } + } + + if (extraProps.size > 0) { + logWarning(`Found extra properties in column infos: ${Array.from(extraProps).join(", ")} in file '${markdownFilePath}' test '${currentTest.title}'.`); + } + } else { + logWarning(`Columns format in file '${markdownFilePath}' test '${currentTest.title}' failed type guard. Skipping.`); + } + } + + private static handleJSONExpectedResults(json: any, currentTest: ECDbTestProps) { + currentTest.expectedResults = json + } + + private static handleTableToken(token: Tokens.Table, currentTest: ECDbTestProps | undefined, markdownFilePath: string) { + if (currentTest === undefined) { + logWarning(`Table token found without a test title in file ${markdownFilePath}. Skipping.`); + return; + } + + this.handleTable(token, currentTest, markdownFilePath); + } + + private static handleTable(token: Tokens.Table, currentTest: ECDbTestProps, markdownFilePath: string) { + if (token.header.length > 0 && currentTest.columnInfo === undefined && columnInfoPropsKeys.has(token.header[0].text as keyof ColumnInfoProps)) { + this.handleColumnTable(token, currentTest, markdownFilePath); + return; + } + else if(token.header.length > 0 && token.header[0].text === ""){ + this.handleExpectedResultsTableForECSqlPropertyIndexesOption(token, currentTest, markdownFilePath); + } else { + this.handleExpectedResultsTable(token, currentTest, markdownFilePath); + } + } + + private static handleColumnTable(token: Tokens.Table, currentTest: ECDbTestProps, markdownFilePath: string) { + const columnInfos: any[] = []; + for (const row of token.rows) { + if (row.length < 1 || row.length !== token.header.length) { + logWarning(`Rows in a expected result table must have a minimum of 1 cell, and as many cells as there are headers. ${markdownFilePath}. Skipping.`); + continue; + } + const columnInfo: { [key: string]: any } = {}; + for (let i = 0; i < token.header.length; i++) { + const header = token.header[i].text; + const cell = row[i].text; + columnInfo[header] = tableTextToValue(cell); + } + columnInfos.push(columnInfo); + } + + this.handleJSONColumnMetadata({columns: columnInfos}, currentTest, markdownFilePath); + } + + private static handleExpectedResultsTable(token: Tokens.Table, currentTest: ECDbTestProps, markdownFilePath: string) { + if(currentTest.expectedResults !== undefined) { + logWarning(`Expected results already set for test ${currentTest.title} in file ${markdownFilePath}. Skipping.`); + return; + } + currentTest.expectedResults = []; + for (const row of token.rows) { + if (row.length < 1 || row.length !== token.header.length) { + logWarning(`Rows in a expected result table must have a minimum of 1 cell, and as many cells as there are headers. ${markdownFilePath}. Skipping.`); + continue; + } + + const expectedResult: { [key: string]: any } = {}; + for (let i = 0; i < token.header.length; i++) { + const header = token.header[i].text; + const cell = row[i].text; + const value = tableTextToValue(cell); + if (value !== undefined) + expectedResult[header] = value; + } + currentTest.expectedResults.push(expectedResult); + } + } + + private static handleExpectedResultsTableForECSqlPropertyIndexesOption(token: Tokens.Table, currentTest: ECDbTestProps, markdownFilePath: string) { + if(currentTest.expectedResults !== undefined) { + logWarning(`Expected results already set for test ${currentTest.title} in file ${markdownFilePath}. Skipping.`); + return; + } + currentTest.expectedResults = []; + for (const row of token.rows) { + if (row.length < 1 || row.length !== token.header.length) { + logWarning(`Rows in a expected result table must have a minimum of 1 cell, and as many cells as there are headers. ${markdownFilePath}. Skipping.`); + continue; + } + + const expectedResult: any[] = []; + for (let i = 0; i < token.header.length; i++) { + const cell = row[i].text; + const value = tableTextToValue(cell); + if (value !== undefined) + expectedResult.push(value); + } + currentTest.expectedResults.push(expectedResult); + } + } +} + +function logWarning(message: string) { + // eslint-disable-next-line no-console + console.log(`\x1b[33m${message}\x1b[0m`); +} \ No newline at end of file diff --git a/core/backend/src/test/ecsql/src/ECSqlTestRunner.test.ts b/core/backend/src/test/ecsql/src/ECSqlTestRunner.test.ts new file mode 100644 index 000000000000..a266cd3d41d9 --- /dev/null +++ b/core/backend/src/test/ecsql/src/ECSqlTestRunner.test.ts @@ -0,0 +1,387 @@ +/*--------------------------------------------------------------------------------------------- +* 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 { DbResult } from "@itwin/core-bentley"; +import { ECSqlRowArg, ECSqlStatement, SnapshotDb } from "../../../core-backend"; +import { KnownTestLocations } from "../../KnownTestLocations"; +import { ECSqlReader, ECSqlValueType, QueryBinder, QueryOptions, QueryRowFormat } from "@itwin/core-common"; +import { buildBinaryData, ECDbMarkdownTestParser, ECDbTestMode, ECDbTestProps, ECDbTestRowFormat } from "./ECSqlTestParser"; +import * as path from "path"; +import * as fs from "fs"; +import { ECSqlDatasets } from "../dataset/ECSqlDatasets"; +import { Point2d, Point3d } from "@itwin/core-geometry"; + +enum TestDataset { + AllProperties = "AllProperties.bim" +} + +const snapshotDbs: { [key in TestDataset]?: SnapshotDb } = {}; + +describe("Markdown based ECDb test runner", async () => { + before(async () => { + await ECSqlDatasets.generateFiles(); + const datasetFilePath = path.join(KnownTestLocations.outputDir, "ECSqlTests", TestDataset.AllProperties); + if (!fs.existsSync(datasetFilePath)) { + throw new Error(`Dataset file ${datasetFilePath} does not exist`); + } + snapshotDbs[TestDataset.AllProperties] = SnapshotDb.openFile(datasetFilePath); + }); + + after(() => { + for (const key in snapshotDbs) { + if (snapshotDbs.hasOwnProperty(key)) { + (snapshotDbs[key as keyof typeof snapshotDbs])?.close(); + } + } + }); + const tests: ECDbTestProps[] = ECDbMarkdownTestParser.parse(); + + //TODO: Mechanism to run a single test, put something like it.only into the test md which causes this loop to only run those tests + for (const test of tests) { + if(!test.dataset) { + logWarning(`Skipping test ${test.title} because it does not have a dataset`); + continue; + } + + if(test.dataset.toLowerCase() !== TestDataset.AllProperties.toLowerCase()) { + logWarning(`Skipping test ${test.title} because dataset ${test.dataset} is not recognized`); + continue; + } + const dataset = TestDataset.AllProperties; + + if(test.mode === ECDbTestMode.Both || test.mode === ECDbTestMode.Statement) { + if(test.skip) + it(`${test.fileName}: ${test.title} (Statement) skipped. Reason: ${test.skip}`); + else if(test.only) + it.only(`${test.fileName}: ${test.title} (Statement)`, () => { + runECSqlStatementTest(test, dataset); + }); + else + it(`${test.fileName}: ${test.title} (Statement)`, () => { + runECSqlStatementTest(test, dataset); + }); + } + + if(test.mode === ECDbTestMode.Both || test.mode === ECDbTestMode.ConcurrentQuery) { + if(test.skip) + it(`${test.fileName}: ${test.title} (ConcurrentQuery) skipped. Reason: ${test.skip}`); + else if(test.only) + it.only(`${test.fileName}: ${test.title} (ConcurrentQuery)`, async () => { + await runConcurrentQueryTest(test, dataset); + }); + else + it(`${test.fileName}: ${test.title} (ConcurrentQuery)`, async () => { + await runConcurrentQueryTest(test, dataset); + }); + } + } +}); + +function runECSqlStatementTest(test: ECDbTestProps, dataset: TestDataset) { + const imodel = snapshotDbs[dataset]; + if (!imodel) { + assert.fail(`Dataset ${dataset} is not loaded`); + } + let stmt: ECSqlStatement | undefined; + if (test.sql === undefined) { + assert.fail("Test does not have an ECSql statement"); + } + + try { + // TODO: statement options should be exposed through the markdown + stmt = imodel.prepareStatement(test.sql); // TODO: Wire up logic for tests we expect to fail during prepare + } catch (error: any) { + if(test.errorDuringPrepare) + return; + else + assert.fail(`Error during prepare of Statement: ${error.message}`); + } + + if(test.errorDuringPrepare) + assert.fail(`Statement is expected to fail during prepare`); + + try { + if(test.binders !== undefined) { + for (const binder of test.binders) { + // eslint-disable-next-line radix + let id: number | string = Number.parseInt(binder.indexOrName); + if (isNaN(id)) + id = binder.indexOrName; + + switch(binder.type.toLowerCase()) { // TODO: replace props variables in binder.value + case "null": + stmt.bindNull(id); + break; + case "string": + stmt.bindString(id, binder.value); + break; + case "int": + // eslint-disable-next-line radix + stmt.bindInteger(id, Number.parseInt(binder.value)); + break; + case "double": + stmt.bindDouble(id, Number.parseFloat(binder.value)); + break; + case "id": + stmt.bindId(id, binder.value); + break; + case "idset": + const values: string[] = binder.value.slice(1,-1).split(","); + const trimmedValues = values.map((value:string)=> + value.trim() + ); + stmt.bindIdSet(id, trimmedValues); + break; + case "datetime": + stmt.bindDateTime(id, binder.value); + break; + case "point2d": + const parsedVal2d = JSON.parse(binder.value); + stmt.bindPoint2d(id, {x: parsedVal2d.X, y: parsedVal2d.Y}); + break; + case "point3d": + const parsedVal3d = JSON.parse(binder.value); + stmt.bindPoint3d(id, {x: parsedVal3d.X, y: parsedVal3d.Y, z: parsedVal3d.Z}); + break; + case "blob": + const arrayValues: string[] = binder.value.slice(1,-1).split(","); + const numbers = arrayValues.map((value:string)=> + // eslint-disable-next-line radix + parseInt(value.trim()) + ); + stmt.bindBlob(id, Uint8Array.of(...numbers)); + break; + case "navigation": + stmt.bindNavigation(id, JSON.parse(binder.value)); + break; + case "array": + stmt.bindArray(id, JSON.parse(binder.value)); + break; + case "struct": + stmt.bindStruct(id, JSON.parse(binder.value)); + break; + default: + assert.fail(`Unsupported binder type ${binder.type}`); + } // switch binder.type + } // for binder + } // if test.binders + + let resultCount = 0; + let stepResult: DbResult; + while ((stepResult = stmt.step()) === DbResult.BE_SQLITE_ROW) { + if (resultCount === 0 && test.columnInfo) { + // Verify the columns on the first result row (TODO: for dynamic columns we have to do this every item) + const colCount = stmt.getColumnCount(); + assert.strictEqual(colCount, test.columnInfo.length, `Expected ${test.columnInfo.length} columns but got ${colCount}`); + for (let i = 0; i < colCount; i++) { + const colInfo = stmt.getValue(i).columnInfo; + const expectedColInfo = test.columnInfo[i]; + // cannot directly compare against colInfo because it has methods instead of getters + assert.strictEqual(colInfo.getPropertyName(), expectedColInfo.name, `Expected property name ${expectedColInfo.name} but got ${colInfo.getPropertyName()} for column index ${i}`); + //if (expectedColInfo.isDynamicProp !== undefined) TODO: Is this not exposed? + // assert.strictEqual(colInfo..isDynamicProperty, expectedColInfo.isDynamicProp, `Expected dynamic property ${expectedColInfo.isDynamicProp} but got ${colInfo.isDynamicProperty} for column index ${i}`); + // TODO: Extended type name not exposed?? + if (expectedColInfo.generated !== undefined) + assert.strictEqual(colInfo.isGeneratedProperty(), expectedColInfo.generated, `Expected generated property ${expectedColInfo.generated} but got ${colInfo.isGeneratedProperty()} for column index ${i}`); + if (expectedColInfo.accessString !== undefined) + assert.strictEqual(colInfo.getAccessString(), expectedColInfo.accessString, `Expected access string ${expectedColInfo.accessString} but got ${colInfo.getAccessString()} for column index ${i}`); + if (expectedColInfo.type !== undefined) + assert.strictEqual(ECSqlValueType[colInfo.getType()], expectedColInfo.type, `Expected type ${expectedColInfo.type} but got ${ECSqlValueType[colInfo.getType()]} for column index ${i}`); + if (expectedColInfo.originPropertyName !== undefined) + assert.strictEqual(colInfo.getOriginPropertyName(), expectedColInfo.originPropertyName, `Expected extended type ${expectedColInfo.originPropertyName} but got ${colInfo.getOriginPropertyName()} for column index ${i}`); + } + } + + if (test.expectedResults !== undefined && test.expectedResults.length > resultCount) { + let expectedResult = test.expectedResults[resultCount]; + expectedResult = buildBinaryData(expectedResult); + const rowArgs: ECSqlRowArg = { rowFormat: getRowFormat(test.rowFormat), classIdsToClassNames: test.convertClassIdsToClassNames }; + // TODO: abbreviate blobs is not supported here? + if(test.abbreviateBlobs) + logWarning("Abbreviate blobs is not supported for statement tests"); + + const actualResult = stmt.getRow(rowArgs); + assert.deepEqual(actualResult, expectedResult, `Expected ${JSON.stringify(expectedResult)} but got ${JSON.stringify(actualResult)}`); + } + resultCount++; + } + stmt.dispose(); + stmt = undefined; + + if (resultCount === 0 && test.stepStatus) { + const stepResultString = DbResult[stepResult]; + assert.strictEqual(stepResultString, test.stepStatus, `Expected step status ${test.stepStatus} but got ${stepResultString}`); + } + + if (test.expectedResults && test.expectedResults.length !== resultCount) { + assert.fail(`Expected ${test.expectedResults.length} rows but got ${resultCount}`); + } + } finally { + if(stmt !== undefined) + stmt.dispose(); + } +} + +function getRowFormat(rowFormat: ECDbTestRowFormat) : QueryRowFormat { + switch(rowFormat) { + case ECDbTestRowFormat.ECSqlNames: + return QueryRowFormat.UseECSqlPropertyNames; + case ECDbTestRowFormat.ECSqlIndexes: + return QueryRowFormat.UseECSqlPropertyIndexes; + case ECDbTestRowFormat.JsNames: + return QueryRowFormat.UseJsPropertyNames; + default: + return QueryRowFormat.UseECSqlPropertyNames; + } +} + +async function runConcurrentQueryTest(test: ECDbTestProps, dataset: TestDataset): Promise { + const imodel = snapshotDbs[dataset]; + if (!imodel) { + assert.fail(`Dataset ${dataset} is not loaded`); + } + + let reader: ECSqlReader; + if (test.sql === undefined) { + assert.fail("Test does not have an ECSql statement"); + } + let params: QueryBinder | undefined; + if(test.binders !== undefined) { + params = new QueryBinder(); + for (const binder of test.binders) { + // eslint-disable-next-line radix + let id: number | string = Number.parseInt(binder.indexOrName); + if (isNaN(id)) + id = binder.indexOrName; + + switch(binder.type.toLowerCase()) { // TODO: replace props variables in binder.value + case "null": + params.bindNull(id); + break; + case "string": + params.bindString(id, binder.value); + break; + case "int": + // eslint-disable-next-line radix + params.bindInt(id, Number.parseInt(binder.value)); + break; + case "long": + // eslint-disable-next-line radix + params.bindLong(id, Number.parseInt(binder.value)); + break; + case "double": + params.bindDouble(id, Number.parseFloat(binder.value)); + break; + case "id": + params.bindId(id, binder.value); + break; + case "idset": + const values: string[] = binder.value.slice(1,-1).split(","); + const trimmedValues = values.map((value:string)=> + value.trim() + ); + params.bindIdSet(id, trimmedValues); + break; + case "point2d": + const parsedVal2d = JSON.parse(binder.value); + params.bindPoint2d(id, new Point2d(parsedVal2d.X, parsedVal2d.Y)); + break; + case "point3d": + const parsedVal3d = JSON.parse(binder.value); + params.bindPoint3d(id, new Point3d(parsedVal3d.X, parsedVal3d.Y, parsedVal3d.Z)); + break; + case "blob": + const arrayValues: string[] = binder.value.slice(1,-1).split(","); + const numbers = arrayValues.map((value:string)=> + // eslint-disable-next-line radix + parseInt(value.trim()) + ); + params.bindBlob(id, Uint8Array.of(...numbers)); + break; + case "struct": + params.bindStruct(id, JSON.parse(binder.value)); + break; + default: + assert.fail(`Unsupported binder type ${binder.type}`); + } // switch binder.type + } // for binder + } // if test.binders + + const queryOptions: QueryOptions = {}; + queryOptions.rowFormat = getRowFormat(test.rowFormat); + if (test.abbreviateBlobs) + queryOptions.abbreviateBlobs = true; + if (test.convertClassIdsToClassNames) + queryOptions.convertClassIdsToClassNames = true; + + try { + reader = imodel.createQueryReader(test.sql, params, queryOptions); // TODO: Wire up logic for tests we expect to fail during prepare + } catch (error: any) { + assert.fail(`Error during creating QueryReader: ${error.message}`); + } + + let resultCount = 0; + let rows; + try{ + rows = await reader.toArray(); + } + catch (error: any) { + if(test.errorDuringPrepare) + return; + else + assert.fail(`Error during prepare of Concurrent Query: ${error.message}`); + } + + if(test.errorDuringPrepare) + assert.fail(`Statement is expected to fail during prepare`); + + const colMetaData = await reader.getMetaData(); + while (resultCount < rows.length) { + if (resultCount === 0 && test.columnInfo) { + // Verify the columns on the first result row (TODO: for dynamic columns we have to do this every item) + assert.strictEqual(colMetaData.length, test.columnInfo.length, `Expected ${test.columnInfo.length} columns but got ${colMetaData.length}`); + for (let i = 0; i < colMetaData.length; i++) { + const colInfo = colMetaData[i]; + const expectedColInfo = test.columnInfo[i]; + // cannot directly compare against colInfo because it has methods instead of getters + assert.strictEqual(colInfo.name, expectedColInfo.name, `Expected name ${expectedColInfo.name} but got ${colInfo.name} for column index ${i}`); + if (expectedColInfo.generated !== undefined) + assert.strictEqual(colInfo.generated, expectedColInfo.generated, `Expected generated property ${expectedColInfo.generated} but got ${colInfo.generated} for column index ${i}`); + if (expectedColInfo.accessString !== undefined) + assert.strictEqual(colInfo.accessString, expectedColInfo.accessString, `Expected access string ${expectedColInfo.accessString} but got ${colInfo.accessString} for column index ${i}`); + if (expectedColInfo.typeName !== undefined) + assert.strictEqual(colInfo.typeName, expectedColInfo.typeName, `Expected type name ${expectedColInfo.typeName} but got ${colInfo.typeName} for column index ${i}`); + if(expectedColInfo.className !== undefined) + assert.strictEqual(colInfo.className, expectedColInfo.className, `Expected class name ${expectedColInfo.className} but got ${colInfo.className} for column index ${i}`); + assert.strictEqual(colInfo.extendedType, expectedColInfo.extendedType, `Expected extended type ${expectedColInfo.extendedType} but got ${colInfo.extendedType} for column index ${i}`); + assert.strictEqual(colInfo.extendType, expectedColInfo.extendedType === undefined ? "" : expectedColInfo.extendedType, `Expected extend type ${expectedColInfo.extendedType === undefined ? "" : expectedColInfo.extendedType} but got ${colInfo.extendType} for column index ${i}`); // eslint-disable-line @typescript-eslint/no-deprecated + } + } + + if (test.expectedResults !== undefined && test.expectedResults.length > resultCount) { + let expectedResult = test.expectedResults[resultCount]; + // replace props in expected result, TODO: optimize this + expectedResult = buildBinaryData(expectedResult); + + const actualResult = rows[resultCount] // TODO: should we test getValue() as well? + assert.deepEqual(actualResult, expectedResult, `Expected ${JSON.stringify(expectedResult)} but got ${JSON.stringify(actualResult)}`); + } + resultCount++; + } + + // if (resultCount === 0 && test.stepStatus) { + // const stepResultString = DbResult[stepResult]; + // assert.strictEqual(stepResultString, test.stepStatus, `Expected step status ${test.stepStatus} but got ${stepResultString}`); + // } + + if (test.expectedResults && test.expectedResults.length !== resultCount) { + assert.fail(`Expected ${test.expectedResults.length} rows but got ${resultCount}`); + } +} + +function logWarning(message: string) { + // eslint-disable-next-line no-console + console.log(`\x1b[33m${message}\x1b[0m`); +} \ No newline at end of file