var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
    if (value !== null && value !== void 0) {
        if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
        var dispose, inner;
        if (async) {
            if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
            dispose = value[Symbol.asyncDispose];
        }
        if (dispose === void 0) {
            if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
            dispose = value[Symbol.dispose];
            if (async) inner = dispose;
        }
        if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
        if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
        env.stack.push({ value: value, dispose: dispose, async: async });
    }
    else if (async) {
        env.stack.push({ async: true });
    }
    return value;
};
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
    return function (env) {
        function fail(e) {
            env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
            env.hasError = true;
        }
        var r, s = 0;
        function next() {
            while (r = env.stack.pop()) {
                try {
                    if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
                    if (r.dispose) {
                        var result = r.dispose.call(r.value);
                        if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
                    }
                    else s |= 1;
                }
                catch (e) {
                    fail(e);
                }
            }
            if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
            if (env.hasError) throw env.error;
        }
        return next();
    };
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
    var e = new Error(message);
    return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
});
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { assert, expect } from "chai";
import * as path from "path";
import * as sinon from "sinon";
import { DbResult, Id64, Logger, LogLevel } from "@itwin/core-bentley";
import { IModelJsFs } from "../../IModelJsFs";
import { ECDb, ECDbOpenMode, SqliteValueType } from "../../core-backend";
import { KnownTestLocations } from "../KnownTestLocations";
import { ECDbTestHelper } from "./ECDbTestHelper";
import { QueryOptionsBuilder } from "@itwin/core-common";
import { EntityClass, SchemaContext, SchemaJsonLocater, SchemaKey } from "@itwin/ecschema-metadata";
describe("ECDb", () => {
    const outDir = KnownTestLocations.outputDir;
    it("should be able to create a new ECDb", () => {
        const env_1 = { stack: [], error: void 0, hasError: false };
        try {
            const ecdb = __addDisposableResource(env_1, ECDbTestHelper.createECDb(outDir, "create.ecdb"), false);
            assert.isTrue(ecdb.isOpen);
        }
        catch (e_1) {
            env_1.error = e_1;
            env_1.hasError = true;
        }
        finally {
            __disposeResources(env_1);
        }
    });
    it("should be able to close an ECDb", () => {
        const ecdb = ECDbTestHelper.createECDb(outDir, "close.ecdb");
        assert.isTrue(ecdb.isOpen);
        ecdb.closeDb();
        assert.isFalse(ecdb.isOpen);
    });
    it("should be able to open an ECDb", () => {
        const env_2 = { stack: [], error: void 0, hasError: false };
        try {
            const fileName = "open.ecdb";
            const ecdbPath = path.join(outDir, fileName);
            {
                const env_3 = { stack: [], error: void 0, hasError: false };
                try {
                    const testECDb = __addDisposableResource(env_3, ECDbTestHelper.createECDb(outDir, fileName), false);
                    assert.isTrue(testECDb.isOpen);
                }
                catch (e_2) {
                    env_3.error = e_2;
                    env_3.hasError = true;
                }
                finally {
                    __disposeResources(env_3);
                }
            }
            const ecdb = __addDisposableResource(env_2, new ECDb(), false);
            ecdb.openDb(ecdbPath, ECDbOpenMode.ReadWrite);
            assert.isTrue(ecdb.isOpen);
        }
        catch (e_3) {
            env_2.error = e_3;
            env_2.hasError = true;
        }
        finally {
            __disposeResources(env_2);
        }
    });
    it("Open ECDb with upgrade option", () => {
        const fileName = "open.ecdb";
        const ecdbPath = path.join(outDir, fileName);
        {
            const env_4 = { stack: [], error: void 0, hasError: false };
            try {
                const testECDb = __addDisposableResource(env_4, ECDbTestHelper.createECDb(outDir, fileName), false);
                assert.isTrue(testECDb.isOpen);
            }
            catch (e_4) {
                env_4.error = e_4;
                env_4.hasError = true;
            }
            finally {
                __disposeResources(env_4);
            }
        }
        {
            const env_5 = { stack: [], error: void 0, hasError: false };
            try {
                const ecdb = __addDisposableResource(env_5, new ECDb(), false);
                assert.doesNotThrow(() => ecdb.openDb(ecdbPath, ECDbOpenMode.Readonly));
            }
            catch (e_5) {
                env_5.error = e_5;
                env_5.hasError = true;
            }
            finally {
                __disposeResources(env_5);
            }
        }
        {
            const env_6 = { stack: [], error: void 0, hasError: false };
            try {
                const ecdb = __addDisposableResource(env_6, new ECDb(), false);
                assert.doesNotThrow(() => ecdb.openDb(ecdbPath, ECDbOpenMode.ReadWrite));
            }
            catch (e_6) {
                env_6.error = e_6;
                env_6.hasError = true;
            }
            finally {
                __disposeResources(env_6);
            }
        }
        {
            const env_7 = { stack: [], error: void 0, hasError: false };
            try {
                const ecdb = __addDisposableResource(env_7, new ECDb(), false);
                assert.doesNotThrow(() => ecdb.openDb(ecdbPath, ECDbOpenMode.FileUpgrade));
            }
            catch (e_7) {
                env_7.error = e_7;
                env_7.hasError = true;
            }
            finally {
                __disposeResources(env_7);
            }
        }
    });
    it("attach/detach newer profile version", async () => {
        const env_8 = { stack: [], error: void 0, hasError: false };
        try {
            const fileName1 = "source_file.ecdb";
            const ecdbPath1 = path.join(outDir, fileName1);
            const testECDb = __addDisposableResource(env_8, ECDbTestHelper.createECDb(outDir, fileName1, `<ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
      <ECEntityClass typeName="Person" modifier="Sealed">
        <ECProperty propertyName="Name" typeName="string"/>
        <ECProperty propertyName="Age" typeName="int"/>
      </ECEntityClass>
      </ECSchema>`), false);
            assert.isTrue(testECDb.isOpen);
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            testECDb.withPreparedStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt) => {
                const res = stmt.stepForInsert();
                assert.equal(res.status, DbResult.BE_SQLITE_DONE);
                assert.isDefined(res.id);
                assert.isTrue(Id64.isValidId64(res.id));
                return res.id;
            });
            // override profile version to 55.0.0 which is currently not supported
            testECDb.withSqliteStatement(`
        UPDATE be_Prop SET
          StrData = '{"major":55,"minor":0,"sub1":0,"sub2":0}'
        WHERE Namespace = 'ec_Db' AND Name = 'SchemaVersion'`, (stmt) => { stmt.step(); });
            testECDb.saveChanges();
            const runDbListPragmaUsingStatement = (ecdb) => {
                // eslint-disable-next-line @typescript-eslint/no-deprecated
                return ecdb.withPreparedStatement("PRAGMA db_list", (stmt) => {
                    const result = [];
                    while (stmt.step() === DbResult.BE_SQLITE_ROW) {
                        result.push(stmt.getRow());
                    }
                    return result;
                });
            };
            const runDbListPragmaCCQ = async (ecdb) => {
                const reader = ecdb.createQueryReader("PRAGMA db_list");
                const result = [];
                while (await reader.step()) {
                    result.push(reader.current.toRow());
                }
                return result;
            };
            const testECDb0 = __addDisposableResource(env_8, ECDbTestHelper.createECDb(outDir, "file2.ecdb"), false);
            // following call will not fail but unknow ECDb profile will cause it to be attach as SQLite.
            testECDb0.attachDb(ecdbPath1, "source");
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            expect(() => testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", () => { })).to.throw("ECClass 'source.test.Person' does not exist or could not be loaded.");
            expect(runDbListPragmaUsingStatement(testECDb0)).deep.equals([
                {
                    sno: 0,
                    alias: "main",
                    fileName: path.join(outDir, "file2.ecdb"),
                    profile: "ECDb"
                },
                {
                    sno: 1,
                    alias: "source",
                    fileName: path.join(outDir, "source_file.ecdb"),
                    profile: "SQLite"
                }
            ]);
            testECDb0.detachDb("source");
            expect(runDbListPragmaUsingStatement(testECDb0)).deep.equals([
                {
                    sno: 0,
                    alias: "main",
                    fileName: path.join(outDir, "file2.ecdb"),
                    profile: "ECDb"
                },
            ]);
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            expect(() => testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", () => { })).to.throw("ECClass 'source.test.Person' does not exist or could not be loaded.");
            const testECDb1 = __addDisposableResource(env_8, ECDbTestHelper.createECDb(outDir, "file4.ecdb"), false);
            testECDb1.attachDb(ecdbPath1, "source");
            const reader1 = testECDb1.createQueryReader("SELECT Name, Age FROM source.test.Person");
            let expectThrow = false;
            try {
                await reader1.step();
            }
            catch (err) {
                if (err instanceof Error) {
                    assert.equal(err.message, "ECClass 'source.test.Person' does not exist or could not be loaded.");
                    expectThrow = true;
                }
            }
            assert.isTrue(expectThrow);
            expect(await runDbListPragmaCCQ(testECDb1)).deep.equals([
                {
                    sno: 0,
                    alias: "main",
                    fileName: path.join(outDir, "file4.ecdb"),
                    profile: "ECDb"
                },
                {
                    sno: 1,
                    alias: "source",
                    fileName: path.join(outDir, "source_file.ecdb"),
                    profile: "SQLite"
                }
            ]);
            testECDb1.detachDb("source");
            expect(await runDbListPragmaCCQ(testECDb1)).deep.equals([
                {
                    sno: 0,
                    alias: "main",
                    fileName: path.join(outDir, "file4.ecdb"),
                    profile: "ECDb"
                },
            ]);
        }
        catch (e_8) {
            env_8.error = e_8;
            env_8.hasError = true;
        }
        finally {
            __disposeResources(env_8);
        }
    });
    it("attach/detach file & db_list pragma", async () => {
        const env_9 = { stack: [], error: void 0, hasError: false };
        try {
            const fileName1 = "source_file.ecdb";
            const ecdbPath1 = path.join(outDir, fileName1);
            const testECDb = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, fileName1, `<ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
      <ECEntityClass typeName="Person" modifier="Sealed">
        <ECProperty propertyName="Name" typeName="string"/>
        <ECProperty propertyName="Age" typeName="int"/>
      </ECEntityClass>
      </ECSchema>`), false);
            assert.isTrue(testECDb.isOpen);
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            testECDb.withPreparedStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt) => {
                const res = stmt.stepForInsert();
                assert.equal(res.status, DbResult.BE_SQLITE_DONE);
                assert.isDefined(res.id);
                assert.isTrue(Id64.isValidId64(res.id));
                return res.id;
            });
            testECDb.saveChanges();
            const runDbListPragma = (ecdb) => {
                // eslint-disable-next-line @typescript-eslint/no-deprecated
                return ecdb.withPreparedStatement("PRAGMA db_list", (stmt) => {
                    const result = [];
                    while (stmt.step() === DbResult.BE_SQLITE_ROW) {
                        result.push(stmt.getRow());
                    }
                    return result;
                });
            };
            const testECDb0 = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, "file2.ecdb"), false);
            testECDb0.attachDb(ecdbPath1, "source");
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", (stmt) => {
                assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW);
                const row = stmt.getRow();
                assert.equal(row.name, "Mary");
                assert.equal(row.age, 45);
            });
            expect(runDbListPragma(testECDb0)).deep.equals([
                {
                    sno: 0,
                    alias: "main",
                    fileName: path.join(outDir, "file2.ecdb"),
                    profile: "ECDb"
                },
                {
                    sno: 1,
                    alias: "source",
                    fileName: path.join(outDir, "source_file.ecdb"),
                    profile: "ECDb"
                }
            ]);
            testECDb0.detachDb("source");
            expect(runDbListPragma(testECDb0)).deep.equals([
                {
                    sno: 0,
                    alias: "main",
                    fileName: path.join(outDir, "file2.ecdb"),
                    profile: "ECDb"
                },
            ]);
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            expect(() => testECDb0.withPreparedStatement("SELECT Name, Age FROM source.test.Person", () => { })).to.throw("ECClass 'source.test.Person' does not exist or could not be loaded.");
            const testECDb1 = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, "file3.ecdb"), false);
            testECDb1.attachDb(ecdbPath1, "source");
            const reader1 = testECDb1.createQueryReader("SELECT Name, Age FROM source.test.Person", undefined, new QueryOptionsBuilder().setUsePrimaryConnection(true).getOptions());
            assert.equal(await reader1.step(), true);
            assert.equal(reader1.current.name, "Mary");
            assert.equal(reader1.current.age, 45);
            testECDb1.detachDb("source");
            const testECDb2 = __addDisposableResource(env_9, ECDbTestHelper.createECDb(outDir, "file4.ecdb"), false);
            testECDb2.attachDb(ecdbPath1, "source");
            const reader2 = testECDb2.createQueryReader("SELECT Name, Age FROM source.test.Person");
            assert.equal(await reader2.step(), true);
            assert.equal(reader2.current.name, "Mary");
            assert.equal(reader2.current.age, 45);
            testECDb2.detachDb("source");
            const reader3 = testECDb2.createQueryReader("SELECT Name, Age FROM source.test.Person");
            let expectThrow = false;
            try {
                await reader3.step();
            }
            catch (err) {
                if (err instanceof Error) {
                    assert.equal(err.message, "ECClass 'source.test.Person' does not exist or could not be loaded.");
                    expectThrow = true;
                }
            }
            assert.isTrue(expectThrow);
        }
        catch (e_9) {
            env_9.error = e_9;
            env_9.hasError = true;
        }
        finally {
            __disposeResources(env_9);
        }
    });
    it("should be able to import a schema", () => {
        const env_10 = { stack: [], error: void 0, hasError: false };
        try {
            const fileName = "schemaimport.ecdb";
            const ecdbPath = path.join(outDir, fileName);
            let id;
            {
                const env_11 = { stack: [], error: void 0, hasError: false };
                try {
                    const testECDb = __addDisposableResource(env_11, ECDbTestHelper.createECDb(outDir, fileName, `<ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
      <ECEntityClass typeName="Person" modifier="Sealed">
      <ECProperty propertyName="Name" typeName="string"/>
        <ECProperty propertyName="Age" typeName="int"/>
        </ECEntityClass>
        </ECSchema>`), false);
                    assert.isTrue(testECDb.isOpen);
                    id = testECDb.withCachedWriteStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt) => {
                        const res = stmt.stepForInsert();
                        assert.equal(res.status, DbResult.BE_SQLITE_DONE);
                        assert.isDefined(res.id);
                        assert.isTrue(Id64.isValidId64(res.id));
                        return res.id;
                    });
                    testECDb.saveChanges();
                }
                catch (e_10) {
                    env_11.error = e_10;
                    env_11.hasError = true;
                }
                finally {
                    __disposeResources(env_11);
                }
            }
            const ecdb = __addDisposableResource(env_10, new ECDb(), false);
            ecdb.openDb(ecdbPath, ECDbOpenMode.Readonly);
            assert.isTrue(ecdb.isOpen);
            // eslint-disable-next-line @typescript-eslint/no-deprecated
            ecdb.withPreparedStatement("SELECT Name, Age FROM test.Person WHERE ECInstanceId=?", (stmt) => {
                stmt.bindId(1, id);
                assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW);
                const row = stmt.getRow();
                assert.equal(row.name, "Mary");
                assert.equal(row.age, 45);
            });
        }
        catch (e_11) {
            env_10.error = e_11;
            env_10.hasError = true;
        }
        finally {
            __disposeResources(env_10);
        }
    });
    it("should be able to get schema props", () => {
        const env_12 = { stack: [], error: void 0, hasError: false };
        try {
            const fileName = "schema-props.ecdb";
            const ecdbPath = path.join(outDir, fileName);
            {
                const env_13 = { stack: [], error: void 0, hasError: false };
                try {
                    const testECDb = __addDisposableResource(env_13, ECDbTestHelper.createECDb(outDir, fileName), false);
                    assert.isTrue(testECDb.isOpen);
                }
                catch (e_12) {
                    env_13.error = e_12;
                    env_13.hasError = true;
                }
                finally {
                    __disposeResources(env_13);
                }
            }
            const ecdb = __addDisposableResource(env_12, new ECDb(), false);
            ecdb.openDb(ecdbPath);
            const schema = ecdb.getSchemaProps("ECDbMeta");
            assert.equal(schema.name, "ECDbMeta");
        }
        catch (e_13) {
            env_12.error = e_13;
            env_12.hasError = true;
        }
        finally {
            __disposeResources(env_12);
        }
    });
    it("Run plain SQL", () => {
        const env_14 = { stack: [], error: void 0, hasError: false };
        try {
            const fileName = "plainseql.ecdb";
            const ecdbPath = path.join(outDir, fileName);
            {
                const env_15 = { stack: [], error: void 0, hasError: false };
                try {
                    const testECDb = __addDisposableResource(env_15, ECDbTestHelper.createECDb(outDir, fileName), false);
                    assert.isTrue(testECDb.isOpen);
                    testECDb.withPreparedSqliteStatement("CREATE TABLE Test(Id INTEGER PRIMARY KEY, Name TEXT NOT NULL, Code INTEGER)", (stmt) => {
                        assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
                    });
                    testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(?,?)", (stmt) => {
                        stmt.bindValue(1, "Dummy 1");
                        stmt.bindValue(2, 100);
                        assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
                    });
                    testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(?,?)", (stmt) => {
                        stmt.bindValues(["Dummy 2", 200]);
                        assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
                    });
                    testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(:p1,:p2)", (stmt) => {
                        stmt.bindValue(":p1", "Dummy 3");
                        stmt.bindValue(":p2", 300);
                        assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
                    });
                    testECDb.withPreparedSqliteStatement("INSERT INTO Test(Name,Code) VALUES(:p1,:p2)", (stmt) => {
                        stmt.bindValues({ ":p1": "Dummy 4", ":p2": 400 });
                        assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
                    });
                    testECDb.saveChanges();
                }
                catch (e_14) {
                    env_15.error = e_14;
                    env_15.hasError = true;
                }
                finally {
                    __disposeResources(env_15);
                }
            }
            const ecdb = __addDisposableResource(env_14, new ECDb(), false);
            ecdb.openDb(ecdbPath, ECDbOpenMode.Readonly);
            assert.isTrue(ecdb.isOpen);
            ecdb.withPreparedSqliteStatement("SELECT Id,Name,Code FROM Test ORDER BY Id", (stmt) => {
                for (let i = 1; i <= 4; i++) {
                    assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW);
                    assert.equal(stmt.getColumnCount(), 3);
                    const val0 = stmt.getValue(0);
                    assert.equal(val0.columnName, "Id");
                    assert.equal(val0.type, SqliteValueType.Integer);
                    assert.isFalse(val0.isNull);
                    assert.equal(val0.getInteger(), i);
                    const val1 = stmt.getValue(1);
                    assert.equal(val1.columnName, "Name");
                    assert.equal(val1.type, SqliteValueType.String);
                    assert.isFalse(val1.isNull);
                    assert.equal(val1.getString(), `Dummy ${i}`);
                    const val2 = stmt.getValue(2);
                    assert.equal(val2.columnName, "Code");
                    assert.equal(val2.type, SqliteValueType.Integer);
                    assert.isFalse(val2.isNull);
                    assert.equal(val2.getInteger(), i * 100);
                    const row = stmt.getRow();
                    assert.equal(row.id, i);
                    assert.equal(row.name, `Dummy ${i}`);
                    assert.equal(row.code, i * 100);
                }
                assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE);
            });
        }
        catch (e_15) {
            env_14.error = e_15;
            env_14.hasError = true;
        }
        finally {
            __disposeResources(env_14);
        }
    });
    it("test unit labels in composite formats", () => {
        const ecdb = ECDbTestHelper.createECDb(outDir, "TestCompositeFormats.ecdb");
        const xmlpathOriginal = path.join(outDir, "compositeFormats1.ecschema.xml");
        IModelJsFs.writeFileSync(xmlpathOriginal, `<?xml version="1.0" encoding="utf-8" ?>
    <ECSchema schemaName="TestCompositeFormats" alias="tcf" version="1.0.0" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
      <ECSchemaReference name="Units" version="01.00.00" alias="u" />
      <Unit typeName="TestUnit" displayLabel="Test Unit" definition="u:M" numerator="1.0" phenomenon="u:LENGTH" unitSystem="u:METRIC" />
      <Format typeName="TestFormat" displayLabel="TestFormat" roundFactor="0.3" type="Fractional" showSignOption="OnlyNegative" formatTraits="TrailZeroes|KeepSingleZero" precision="4" decimalSeparator="." thousandSeparator="," uomSeparator=" ">
        <Composite>
          <Unit>u:KM</Unit>
          <Unit label="m">TestUnit</Unit>
          <Unit label="">u:CM</Unit>
          <Unit label="mm">u:MM</Unit>
        </Composite>
      </Format>
      <KindOfQuantity typeName="TestKOQ2" description="Test KOQ2" displayLabel="TestKOQ2" persistenceUnit="u:M" presentationUnits="TestFormat" relativeError="10e-3" />
    </ECSchema>`);
        ecdb.importSchema(xmlpathOriginal);
        ecdb.saveChanges();
        const expectedLabels = [undefined, "m", "", "mm"];
        let index = 0;
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        ecdb.withStatement("select label from meta.FormatCompositeUnitDef where Format.Id=0x1", (stmt) => {
            for (let i = 1; i <= 4; i++) {
                assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW);
                expect(stmt.getRow().label).to.eql(expectedLabels[index++]);
            }
        });
        const xmlpathUpdated = path.join(outDir, "compositeFormats2.ecschema.xml");
        IModelJsFs.writeFileSync(xmlpathUpdated, `<?xml version="1.0" encoding="utf-8" ?>
    <ECSchema schemaName="TestCompositeFormats" alias="tcf" version="1.0.1" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
      <ECSchemaReference name="Units" version="01.00.00" alias="u" />
      <Unit typeName="TestUnit" displayLabel="Test Unit" definition="u:M" numerator="1.0" phenomenon="u:LENGTH" unitSystem="u:METRIC" />
      <Format typeName="TestFormat" displayLabel="TestFormat" roundFactor="0.3" type="Fractional" showSignOption="OnlyNegative" formatTraits="TrailZeroes|KeepSingleZero" precision="4" decimalSeparator="." thousandSeparator="," uomSeparator=" ">
        <Composite spacer="=" includeZero="False">
          <Unit label="">u:KM</Unit>
          <Unit label="m">TestUnit</Unit>
          <Unit>u:CM</Unit>
          <Unit label="mm">u:MM</Unit>
        </Composite>
      </Format>
      <KindOfQuantity typeName="TestKOQ2" description="Test KOQ2" displayLabel="TestKOQ2" persistenceUnit="u:M" presentationUnits="TestFormat" relativeError="10e-3" />
    </ECSchema>`);
        ecdb.importSchema(xmlpathUpdated);
        ecdb.saveChanges();
        const expectedLabelsUpdated = ["", "m", undefined, "mm"];
        index = 0;
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        ecdb.withStatement("select label from meta.FormatCompositeUnitDef where Format.Id=0x1", (stmt) => {
            for (let i = 1; i <= 4; i++) {
                assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW);
                expect(stmt.getRow().label).to.eql(expectedLabelsUpdated[index++]);
            }
        });
        ecdb.closeDb();
    });
    it("should log warning but continue if new schema changes are observed without version bump", async () => {
        const ecdb = ECDbTestHelper.createECDb(outDir, "importSchemaNoVersionBump.ecdb");
        const xmlpathOriginal = path.join(outDir, "importSchemaNoVersionBump1.ecschema.xml");
        IModelJsFs.writeFileSync(xmlpathOriginal, `<?xml version="1.0" encoding="UTF-8"?>
    <ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
      <ECEntityClass typeName="Person" modifier="Sealed">
        <ECProperty propertyName="Name" typeName="string"/>
        <ECProperty propertyName="Age" typeName="int"/>
      </ECEntityClass>
    </ECSchema>`);
        ecdb.importSchema(xmlpathOriginal);
        ecdb.saveChanges();
        const xmlpathUpdated = path.join(outDir, "importSchemaNoVersionBump2.ecschema.xml");
        IModelJsFs.writeFileSync(xmlpathUpdated, `<?xml version="1.0" encoding="UTF-8"?>
    <ECSchema schemaName="Test" alias="test" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
      <ECEntityClass typeName="Person" modifier="Sealed">
        <ECProperty propertyName="Name" typeName="string"/>
        <ECProperty propertyName="Age" typeName="int"/>
        <ECProperty propertyName="Height" typeName="int"/>
      </ECEntityClass>
    </ECSchema>`);
        let calledCategory = "";
        let calledMessage = "";
        const stubbedLogWarning = sinon.stub(Logger, "logWarning").callsFake((category, message) => {
            calledCategory = category;
            calledMessage = message;
        });
        const prevLevel = Logger.getLevel("ECDb");
        try {
            Logger.setLevel("ECDb", LogLevel.Warning);
            // We do not want this behavior (just logs a warning and proceeds), initially we intended to throw an error
            // We will wait for the next major change to make this a hard error
            expect(ecdb.importSchema(xmlpathUpdated)).to.not.throw;
            expect(calledCategory).to.equal("ECDb");
            expect(calledMessage).to.equal("Schema 'Test' has changes but its version was not incremented. Proceeding with import, but this may lead to unexpected behavior.");
            stubbedLogWarning.restore();
        }
        finally {
            if (prevLevel !== undefined)
                Logger.setLevel("ECDb", prevLevel);
            else
                delete Logger._categoryFilter.ECDb;
        }
        const context = new SchemaContext();
        const locater = new SchemaJsonLocater((name) => ecdb.getSchemaProps(name));
        context.addLocater(locater);
        const schema = await context.getSchema(new SchemaKey("Test", 1, 0, 0));
        assert.isDefined(schema);
        const personClass = await schema.getItem("Person", EntityClass);
        assert.isDefined(personClass);
        const heightProp = personClass.getProperty("Height");
        assert.isDefined(heightProp);
        ecdb.closeDb();
    });
    it("should drop a single schema", () => {
        const env_16 = { stack: [], error: void 0, hasError: false };
        try {
            const ecdb = __addDisposableResource(env_16, ECDbTestHelper.createECDb(outDir, "test.ecdb", `<ECSchema schemaName="Test" alias="ts" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
        <ECEntityClass typeName="Foo" modifier="Sealed">
          <ECProperty propertyName="n" typeName="int"/>
        </ECEntityClass>
      </ECSchema>`), false);
            assert.isTrue(ecdb.isOpen);
            ecdb.saveChanges();
            const schemaProps = ecdb.getSchemaProps("Test");
            expect(schemaProps.name).to.equal("Test");
            ecdb.dropSchemas(["Test"]);
            expect(() => ecdb.getSchemaProps("Test")).to.throw();
        }
        catch (e_16) {
            env_16.error = e_16;
            env_16.hasError = true;
        }
        finally {
            __disposeResources(env_16);
        }
    });
    it("should drop multiple schemas", () => {
        const env_17 = { stack: [], error: void 0, hasError: false };
        try {
            const testSchema1Xml = `<?xml version="1.0" encoding="utf-8"?>
      <ECSchema schemaName="TestSchema1" alias="ts1" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
        <ECEntityClass typeName="TestClass1">
          <ECProperty propertyName="Prop1" typeName="string"/>
        </ECEntityClass>
      </ECSchema>`;
            const testSchema2Xml = `<?xml version="1.0" encoding="utf-8"?>
      <ECSchema schemaName="TestSchema2" alias="ts2" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
        <ECSchemaReference name="TestSchema1" version="01.00.00" alias="ts1"/>
        <ECEntityClass typeName="TestClass2">
          <ECProperty propertyName="Prop2" typeName="string"/>
        </ECEntityClass>
      </ECSchema>`;
            const ecdb = __addDisposableResource(env_17, ECDbTestHelper.createECDb(outDir, "drop-multiple-schemas.ecdb"), false);
            assert.isTrue(ecdb.isOpen);
            const schema1Path = path.join(outDir, "TestSchema1.ecschema.xml");
            IModelJsFs.writeFileSync(schema1Path, testSchema1Xml);
            ecdb.importSchema(schema1Path);
            const schema2Path = path.join(outDir, "TestSchema2.ecschema.xml");
            IModelJsFs.writeFileSync(schema2Path, testSchema2Xml);
            ecdb.importSchema(schema2Path);
            ecdb.saveChanges();
            const schema1Props = ecdb.getSchemaProps("TestSchema1");
            expect(schema1Props.name).to.equal("TestSchema1");
            const schema2Props = ecdb.getSchemaProps("TestSchema2");
            expect(schema2Props.name).to.equal("TestSchema2");
            expect(() => ecdb.dropSchemas(["TestSchema1"])).to.throw();
            const stillExistsSchema1 = ecdb.getSchemaProps("TestSchema1");
            expect(stillExistsSchema1.name).to.equal("TestSchema1");
            ecdb.dropSchemas(["TestSchema2", "TestSchema1"]);
            expect(() => ecdb.getSchemaProps("TestSchema2")).to.throw();
            expect(() => ecdb.getSchemaProps("TestSchema1")).to.throw();
            IModelJsFs.removeSync(schema1Path);
            IModelJsFs.removeSync(schema2Path);
        }
        catch (e_17) {
            env_17.error = e_17;
            env_17.hasError = true;
        }
        finally {
            __disposeResources(env_17);
        }
    });
});
//# sourceMappingURL=ECDb.test.js.map