@itwin/core-backend 5.14.0-dev.2 → 5.14.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/BriefcaseManager.d.ts.map +1 -1
- package/lib/cjs/BriefcaseManager.js +11 -5
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts.map +1 -1
- package/lib/cjs/CloudSqlite.js +9 -2
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/lib/cjs/ECDb.d.ts.map +1 -1
- package/lib/cjs/ECDb.js +1 -0
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +42 -7
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +175 -74
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/SchemaSync.d.ts +126 -18
- package/lib/cjs/SchemaSync.d.ts.map +1 -1
- package/lib/cjs/SchemaSync.js +303 -81
- package/lib/cjs/SchemaSync.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts.map +1 -1
- package/lib/cjs/TxnManager.js +2 -5
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/internal/SchemaSyncReservations.d.ts.map +1 -1
- package/lib/cjs/internal/SchemaSyncReservations.js +13 -3
- package/lib/cjs/internal/SchemaSyncReservations.js.map +1 -1
- package/lib/esm/BriefcaseManager.d.ts.map +1 -1
- package/lib/esm/BriefcaseManager.js +11 -5
- package/lib/esm/BriefcaseManager.js.map +1 -1
- package/lib/esm/CloudSqlite.d.ts.map +1 -1
- package/lib/esm/CloudSqlite.js +10 -3
- package/lib/esm/CloudSqlite.js.map +1 -1
- package/lib/esm/ECDb.d.ts.map +1 -1
- package/lib/esm/ECDb.js +1 -0
- package/lib/esm/ECDb.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +42 -7
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +175 -74
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/SchemaSync.d.ts +126 -18
- package/lib/esm/SchemaSync.d.ts.map +1 -1
- package/lib/esm/SchemaSync.js +304 -82
- package/lib/esm/SchemaSync.js.map +1 -1
- package/lib/esm/TxnManager.d.ts.map +1 -1
- package/lib/esm/TxnManager.js +2 -5
- package/lib/esm/TxnManager.js.map +1 -1
- package/lib/esm/internal/SchemaSyncReservations.d.ts.map +1 -1
- package/lib/esm/internal/SchemaSyncReservations.js +13 -3
- package/lib/esm/internal/SchemaSyncReservations.js.map +1 -1
- package/lib/esm/test/hubaccess/Rebase.test.js +3 -1
- package/lib/esm/test/hubaccess/Rebase.test.js.map +1 -1
- package/lib/esm/test/hubaccess/SemanticRebase.test.js +29 -28
- package/lib/esm/test/hubaccess/SemanticRebase.test.js.map +1 -1
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts +3 -0
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.d.ts.map +1 -0
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js +15 -0
- package/lib/esm/test/hubaccess/SemanticRebaseTestUtils.js.map +1 -0
- package/lib/esm/test/standalone/SchemaSyncDb.test.js +5 -25
- package/lib/esm/test/standalone/SchemaSyncDb.test.js.map +1 -1
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js +1 -0
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js.map +1 -1
- package/package.json +13 -13
package/lib/esm/IModelDb.js
CHANGED
|
@@ -317,7 +317,9 @@ export class IModelDb extends IModel {
|
|
|
317
317
|
db[_nativeDb].abandonChanges();
|
|
318
318
|
db.close();
|
|
319
319
|
}
|
|
320
|
-
catch {
|
|
320
|
+
catch {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
321
323
|
});
|
|
322
324
|
});
|
|
323
325
|
}
|
|
@@ -383,12 +385,20 @@ export class IModelDb extends IModel {
|
|
|
383
385
|
this._codeService = undefined;
|
|
384
386
|
this[_nativeDb].closeFile();
|
|
385
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Save any unsaved schema changes in this iModel.
|
|
390
|
+
* @internal
|
|
391
|
+
*/
|
|
386
392
|
saveSchemaChanges(args) {
|
|
387
393
|
if (!this[_nativeDb].hasUnsavedChanges())
|
|
388
394
|
return;
|
|
389
395
|
const saveArgs = typeof args === "string" ? { description: args } : args;
|
|
390
396
|
saveArgs === undefined ? this[_nativeDb].saveChanges() : this[_nativeDb].saveChanges(JSON.stringify(saveArgs));
|
|
391
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Abandon any unsaved schema changes in this iModel.
|
|
400
|
+
* @internal
|
|
401
|
+
*/
|
|
392
402
|
abandonSchemaChanges() {
|
|
393
403
|
if (!this[_nativeDb].hasUnsavedChanges())
|
|
394
404
|
return;
|
|
@@ -935,7 +945,7 @@ export class IModelDb extends IModel {
|
|
|
935
945
|
async dropSchemas(schemaNames) {
|
|
936
946
|
if (schemaNames.length === 0)
|
|
937
947
|
return;
|
|
938
|
-
if (
|
|
948
|
+
if (SchemaSync.isEnabled(this))
|
|
939
949
|
throw new IModelError(DbResult.BE_SQLITE_ERROR, "Cannot drop schemas when schema sync is enabled");
|
|
940
950
|
if (this[_nativeDb].hasUnsavedChanges())
|
|
941
951
|
throw new IModelError(ChangeSetStatus.HasUncommittedChanges, "Cannot drop schemas with unsaved changes");
|
|
@@ -1021,26 +1031,34 @@ export class IModelDb extends IModel {
|
|
|
1021
1031
|
this.cleanupSnapshot(context.resources);
|
|
1022
1032
|
}
|
|
1023
1033
|
}
|
|
1024
|
-
/**
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1034
|
+
/** Refuse a schema import this briefcase is in no state to run. Shared by [[importSchemas]] and
|
|
1035
|
+
* [[BriefcaseDb.upgradeSchemas]], which reach the native importer by different routes.
|
|
1036
|
+
* @internal
|
|
1037
|
+
*/
|
|
1038
|
+
assertCanImportSchemas() {
|
|
1039
|
+
if (!this.isBriefcaseDb())
|
|
1040
|
+
return;
|
|
1041
|
+
if (this.txns.rebaser.isRebasing) {
|
|
1042
|
+
throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas while rebasing");
|
|
1043
|
+
}
|
|
1044
|
+
if (this.txns.isIndirectChanges) {
|
|
1045
|
+
throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas while in an indirect change scope");
|
|
1046
|
+
}
|
|
1047
|
+
// Additional checks when semantic rebase is enabled
|
|
1048
|
+
if (IModelHost.useSemanticRebase) {
|
|
1049
|
+
if (this[_nativeDb].hasUnsavedChanges()) {
|
|
1050
|
+
throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas with unsaved changes when useSemanticRebase flag is on");
|
|
1051
|
+
}
|
|
1052
|
+
if (SchemaSync.isEnabled(this)) {
|
|
1053
|
+
throw new IModelError(IModelStatus.BadRequest, "Cannot import schemas when schema sync is enabled and also useSemanticRebase flag is on");
|
|
1042
1054
|
}
|
|
1043
1055
|
}
|
|
1056
|
+
}
|
|
1057
|
+
/** Shared implementation for importing schemas from file or string.
|
|
1058
|
+
* @internal
|
|
1059
|
+
*/
|
|
1060
|
+
async importSchemasInternal(schemas, options, nativeImportOp) {
|
|
1061
|
+
this.assertCanImportSchemas();
|
|
1044
1062
|
if (options?.channelUpgrade) {
|
|
1045
1063
|
const channelUpgrade = options.channelUpgrade;
|
|
1046
1064
|
try {
|
|
@@ -1058,30 +1076,52 @@ export class IModelDb extends IModel {
|
|
|
1058
1076
|
if (options?.schemaImportCallbacks?.preSchemaImportCallback)
|
|
1059
1077
|
preSchemaImportCallbackResult = await this.preSchemaImportCallback(options.schemaImportCallbacks, { iModel: this, data: options.data, schemaData: schemas });
|
|
1060
1078
|
const maybeCustomNativeContext = options?.ecSchemaXmlContext?.nativeContext;
|
|
1061
|
-
if (
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
this.
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
+
if (SchemaSync.isEnabled(this)) {
|
|
1080
|
+
// The shared lock lets concurrent updates through while blocking anyone taking the exclusive lock for an upgrade.
|
|
1081
|
+
if (this[_nativeDb].getITwinId() !== Guid.empty)
|
|
1082
|
+
await this.locks.acquireLocks({ shared: IModel.repositoryModelId });
|
|
1083
|
+
// The native import adopts rows from the attached SchemaSyncDb. Attach and detach commit
|
|
1084
|
+
// implicitly, so abandoning changes cannot undo the adoption. A later failure must roll the
|
|
1085
|
+
// briefcase back before those ec_ rows can be pushed.
|
|
1086
|
+
let txnBeforeAdopt;
|
|
1087
|
+
// Set once the caller's own work is committed. Getting a token or the container write lock happens
|
|
1088
|
+
// before that, and abandonSchemaChanges discards every unsaved change rather than only this import's,
|
|
1089
|
+
// so abandoning on a failure from that window would throw away work the import never touched.
|
|
1090
|
+
let callerChangesSaved = false;
|
|
1091
|
+
try {
|
|
1092
|
+
await SchemaSync.withLockedAccess(this, { openMode: OpenMode.Readonly, operationName: "schema sync" }, async (syncAccess) => {
|
|
1093
|
+
const schemaSyncDbUri = syncAccess.getUri();
|
|
1094
|
+
this.saveSchemaChanges();
|
|
1095
|
+
callerChangesSaved = true;
|
|
1096
|
+
// After saveSchemaChanges, so rolling back cannot reach the caller's own work.
|
|
1097
|
+
if (this.isBriefcaseDb())
|
|
1098
|
+
txnBeforeAdopt = this.txns.getCurrentTxnId();
|
|
1099
|
+
try {
|
|
1100
|
+
nativeImportOp(schemas, { schemaLockHeld: false, ecSchemaXmlContext: maybeCustomNativeContext, schemaSyncDbUri });
|
|
1079
1101
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1102
|
+
catch (err) {
|
|
1103
|
+
if (SchemaSync.requiresUpgrade(err))
|
|
1104
|
+
throw new IModelError(err.errorNumber, `${err.message} - this schema change needs the upgrade path. Use BriefcaseDb.upgradeSchemas, which takes the exclusive schema lock and pushes the result.`);
|
|
1105
|
+
throw new IModelError(err.errorNumber, err.message);
|
|
1082
1106
|
}
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
catch (err) {
|
|
1110
|
+
if (callerChangesSaved)
|
|
1111
|
+
this.abandonSchemaChanges();
|
|
1112
|
+
if (this.isBriefcaseDb() && undefined !== txnBeforeAdopt && this.txns.getCurrentTxnId() !== txnBeforeAdopt) {
|
|
1113
|
+
// Saving the adopt's txn started a new undo session, because schema changes are kept out of the
|
|
1114
|
+
// user's undo stack, so this reverses across that boundary. The changes themselves reverse like
|
|
1115
|
+
// any other - a rebase does it to every local txn on every pull. It does not reverse DDL: a table
|
|
1116
|
+
// or column the adopt created stays behind with no ec_ row describing it, which is the state a
|
|
1117
|
+
// briefcase already tolerates, and the next successful import finds the table up to date and
|
|
1118
|
+
// carries on. Cancel rather than reverse, so the rows cannot come back through undo either.
|
|
1119
|
+
const status = this[_nativeDb].cancelTo(txnBeforeAdopt, true);
|
|
1120
|
+
if (IModelStatus.Success !== status)
|
|
1121
|
+
Logger.logError(loggerCategory, `Failed to roll back the adopted schema rows after a failed import: ${IModelStatus[status] ?? status}`);
|
|
1083
1122
|
}
|
|
1084
|
-
|
|
1123
|
+
throw err;
|
|
1124
|
+
}
|
|
1085
1125
|
}
|
|
1086
1126
|
else {
|
|
1087
1127
|
const nativeImportOptions = {
|
|
@@ -2846,7 +2886,9 @@ function processSchemaWriteStatus(status) {
|
|
|
2846
2886
|
try {
|
|
2847
2887
|
props.push(imodel.elements.getElementProps(id));
|
|
2848
2888
|
}
|
|
2849
|
-
catch {
|
|
2889
|
+
catch {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2850
2892
|
});
|
|
2851
2893
|
return props;
|
|
2852
2894
|
}
|
|
@@ -2869,7 +2911,9 @@ function processSchemaWriteStatus(status) {
|
|
|
2869
2911
|
break;
|
|
2870
2912
|
}
|
|
2871
2913
|
}
|
|
2872
|
-
catch {
|
|
2914
|
+
catch {
|
|
2915
|
+
continue;
|
|
2916
|
+
}
|
|
2873
2917
|
}
|
|
2874
2918
|
return finished;
|
|
2875
2919
|
}
|
|
@@ -3079,9 +3123,6 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3079
3123
|
get isBriefcase() { return true; }
|
|
3080
3124
|
/* the BriefcaseId of the briefcase opened with this BriefcaseDb */
|
|
3081
3125
|
briefcaseId;
|
|
3082
|
-
_skipSyncSchemasOnPullAndPush;
|
|
3083
|
-
/** @internal */
|
|
3084
|
-
get skipSyncSchemasOnPullAndPush() { return this._skipSyncSchemasOnPullAndPush ?? false; }
|
|
3085
3126
|
/**
|
|
3086
3127
|
* Event raised just before a BriefcaseDb is opened. Supplies the arguments that will be used to open the BriefcaseDb.
|
|
3087
3128
|
* Throw an exception to stop the open.
|
|
@@ -3164,6 +3205,8 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3164
3205
|
}
|
|
3165
3206
|
constructor(args) {
|
|
3166
3207
|
super({ ...args, changeset: args.nativeDb.getCurrentChangeset() });
|
|
3208
|
+
// Native invokes this private callback dynamically through the object registered by IModelDb.
|
|
3209
|
+
void this.onChangesetConflict;
|
|
3167
3210
|
this._openMode = args.openMode;
|
|
3168
3211
|
this.briefcaseId = args.briefcaseId;
|
|
3169
3212
|
this.makeLockControl();
|
|
@@ -3176,26 +3219,33 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3176
3219
|
wasChanges = nativeDb.hasPendingTxns();
|
|
3177
3220
|
nativeDb.closeFile();
|
|
3178
3221
|
};
|
|
3179
|
-
const
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
}
|
|
3183
|
-
|
|
3222
|
+
const push = async () => {
|
|
3223
|
+
if (wasChanges)
|
|
3224
|
+
await withBriefcaseDb(briefcase, async (db) => db.pushChanges({ ...briefcase, description, retainLocks: true }));
|
|
3225
|
+
};
|
|
3226
|
+
// Asked of the closed file, so an iModel without schema sync never gets opened for this.
|
|
3227
|
+
if (SchemaSync.isEnabled(briefcase)) {
|
|
3228
|
+
await withBriefcaseDb(briefcase, async (db) => SchemaSync.updateDbSchema(db));
|
|
3184
3229
|
await SchemaSync.withLockedAccess(briefcase, { openMode: OpenMode.Readonly, operationName: "schema sync" }, async (syncAccess) => {
|
|
3185
3230
|
const schemaSyncDbUri = syncAccess.getUri();
|
|
3186
3231
|
executeUpgrade();
|
|
3232
|
+
// Overwriting advances the SchemaSync data version, so a no-op upgrade must not call it.
|
|
3233
|
+
if (!wasChanges)
|
|
3234
|
+
return;
|
|
3187
3235
|
await withBriefcaseDb(briefcase, async (db) => {
|
|
3188
|
-
db[_nativeDb].
|
|
3236
|
+
db[_nativeDb].schemaSyncOverwrite(schemaSyncDbUri);
|
|
3189
3237
|
db[_nativeDb].saveChanges();
|
|
3190
3238
|
});
|
|
3191
|
-
|
|
3239
|
+
// Publish the sync db before the changeset while retaining both locks.
|
|
3240
|
+
syncAccess.closeDb();
|
|
3241
|
+
await syncAccess.container.uploadChanges();
|
|
3242
|
+
await push();
|
|
3192
3243
|
});
|
|
3193
3244
|
}
|
|
3194
3245
|
else {
|
|
3195
3246
|
executeUpgrade();
|
|
3247
|
+
await push();
|
|
3196
3248
|
}
|
|
3197
|
-
if (wasChanges)
|
|
3198
|
-
await withBriefcaseDb(briefcase, async (db) => db.pushChanges({ ...briefcase, description, retainLocks: true }));
|
|
3199
3249
|
}
|
|
3200
3250
|
/** Upgrades the schemas in the iModel based on the current version of the software. Follows a sequence of operations -
|
|
3201
3251
|
* * Acquires a schema lock to prevent other users from making any other changes while upgrade is happening
|
|
@@ -3215,6 +3265,22 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3215
3265
|
// - push changes
|
|
3216
3266
|
// - release schema lock
|
|
3217
3267
|
// good thing computers are fast. Fortunately upgrading should be rare (and the push time will dominate anyway.) Don't try to optimize any of this away.
|
|
3268
|
+
// schemaSyncOverwrite can discard unpushed imports, so hold the exclusive lock across both upgrades.
|
|
3269
|
+
if (SchemaSync.isEnabled(briefcase)) {
|
|
3270
|
+
try {
|
|
3271
|
+
await withBriefcaseDb(briefcase, async (db) => {
|
|
3272
|
+
if (!db.locks.isServerBased)
|
|
3273
|
+
throw new IModelError(DbResult.BE_SQLITE_ERROR, "Cannot upgrade schemas with SchemaSync without server-based locking");
|
|
3274
|
+
await db.acquireSchemaLock();
|
|
3275
|
+
});
|
|
3276
|
+
await this.doUpgrade(briefcase, { profile: ProfileOptions.Upgrade, schemaLockHeld: true }, "Upgraded profile");
|
|
3277
|
+
await this.doUpgrade(briefcase, { domain: DomainOptions.Upgrade, schemaLockHeld: true }, "Upgraded domain schemas");
|
|
3278
|
+
}
|
|
3279
|
+
finally {
|
|
3280
|
+
await withBriefcaseDb(briefcase, async (db) => db.locks[_releaseAllLocks]());
|
|
3281
|
+
}
|
|
3282
|
+
return;
|
|
3283
|
+
}
|
|
3218
3284
|
try {
|
|
3219
3285
|
await this.doUpgrade(briefcase, { profile: ProfileOptions.Upgrade }, "Upgraded profile");
|
|
3220
3286
|
}
|
|
@@ -3515,8 +3581,7 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3515
3581
|
async pullChanges(arg) {
|
|
3516
3582
|
await this.executeWritable(async () => {
|
|
3517
3583
|
await BriefcaseManager.pullAndApplyChangesets(this, arg ?? {});
|
|
3518
|
-
|
|
3519
|
-
await SchemaSync.pull(this);
|
|
3584
|
+
SchemaSync.updateDbSchema(this);
|
|
3520
3585
|
this.initializeIModelDb("pullMerge");
|
|
3521
3586
|
});
|
|
3522
3587
|
// If this pull enabled or disabled SchemaSync for this briefcase, its reservations must now be re-initialized
|
|
@@ -3601,24 +3666,10 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3601
3666
|
if (nativeDb.hasPendingTxns()) {
|
|
3602
3667
|
throw new IModelError(ChangeSetStatus.HasLocalChanges, "Cannot revert with pending txns");
|
|
3603
3668
|
}
|
|
3604
|
-
const skipSchemaSyncPull = async (func) => {
|
|
3605
|
-
if (nativeDb.schemaSyncEnabled()) {
|
|
3606
|
-
this._skipSyncSchemasOnPullAndPush = true;
|
|
3607
|
-
try {
|
|
3608
|
-
return await func();
|
|
3609
|
-
}
|
|
3610
|
-
finally {
|
|
3611
|
-
this._skipSyncSchemasOnPullAndPush = undefined;
|
|
3612
|
-
}
|
|
3613
|
-
}
|
|
3614
|
-
else {
|
|
3615
|
-
return func();
|
|
3616
|
-
}
|
|
3617
|
-
};
|
|
3618
3669
|
this.clearCaches();
|
|
3619
|
-
await
|
|
3670
|
+
await this.pullChanges({ ...arg, toIndex: undefined });
|
|
3620
3671
|
await this.acquireSchemaLock();
|
|
3621
|
-
if (
|
|
3672
|
+
if (SchemaSync.isEnabled(this)) {
|
|
3622
3673
|
arg.skipSchemaChanges = true;
|
|
3623
3674
|
}
|
|
3624
3675
|
// The native side enables file-based txns during revert. Restore the original setting afterward.
|
|
@@ -3639,7 +3690,7 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3639
3690
|
pushRetryDelay: arg.pushRetryDelay,
|
|
3640
3691
|
retainLocks: arg.retainLocks,
|
|
3641
3692
|
};
|
|
3642
|
-
await
|
|
3693
|
+
await this.pushChanges(pushArgs);
|
|
3643
3694
|
this.clearCaches();
|
|
3644
3695
|
}
|
|
3645
3696
|
catch (err) {
|
|
@@ -3716,6 +3767,56 @@ export class BriefcaseDb extends IModelDb {
|
|
|
3716
3767
|
this.txns._onChangesPushed(this.changeset);
|
|
3717
3768
|
BriefcaseManager.deleteRebaseFolders(this);
|
|
3718
3769
|
}
|
|
3770
|
+
/** Import schemas while allowing changes that move or delete data.
|
|
3771
|
+
*
|
|
3772
|
+
* Takes the exclusive schema lock, requires the briefcase to be at the timeline tip, imports, updates the sync db, and pushes the result.
|
|
3773
|
+
* @note The briefcase must have no local changes.
|
|
3774
|
+
* @see [[BriefcaseDb.upgradeSchemas]] (static) for upgrading the software's profile and domain schemas.
|
|
3775
|
+
* @alpha
|
|
3776
|
+
*/
|
|
3777
|
+
async upgradeSchemas(schemaFileNames, arg) {
|
|
3778
|
+
return this.upgradeSchemasInternal(schemaFileNames, arg, (schemas, importOptions) => this[_nativeDb].importSchemas(schemas, importOptions));
|
|
3779
|
+
}
|
|
3780
|
+
/** The [[importSchemaStrings]] counterpart of [[upgradeSchemas]].
|
|
3781
|
+
* @alpha
|
|
3782
|
+
*/
|
|
3783
|
+
async upgradeSchemaStrings(serializedXmlSchemas, arg) {
|
|
3784
|
+
return this.upgradeSchemasInternal(serializedXmlSchemas, arg, (schemas, importOptions) => this[_nativeDb].importXmlSchemas(schemas, importOptions));
|
|
3785
|
+
}
|
|
3786
|
+
async upgradeSchemasInternal(schemas, arg, nativeImportOp) {
|
|
3787
|
+
if (schemas.length === 0)
|
|
3788
|
+
return;
|
|
3789
|
+
this.assertCanImportSchemas();
|
|
3790
|
+
if (this[_nativeDb].hasUnsavedChanges() || this.txns.hasLocalChanges)
|
|
3791
|
+
throw new IModelError(ChangeSetStatus.HasLocalChanges, "Cannot upgrade schemas while there are local changes");
|
|
3792
|
+
if (SchemaSync.isEnabled(this) && !this.locks.isServerBased)
|
|
3793
|
+
throw new IModelError(DbResult.BE_SQLITE_ERROR, "Cannot upgrade schemas with SchemaSync without server-based locking");
|
|
3794
|
+
await this.acquireSchemaLock();
|
|
3795
|
+
await this.pullChanges({ accessToken: arg.accessToken });
|
|
3796
|
+
if (!SchemaSync.isEnabled(this)) {
|
|
3797
|
+
await this.importSchemasInternal(schemas, { ecSchemaXmlContext: arg.ecSchemaXmlContext }, nativeImportOp);
|
|
3798
|
+
await this.pushChanges(arg);
|
|
3799
|
+
return;
|
|
3800
|
+
}
|
|
3801
|
+
await SchemaSync.withLockedAccess(this, { openMode: OpenMode.Readonly, operationName: "schema upgrade" }, async (syncAccess) => {
|
|
3802
|
+
this.saveSchemaChanges();
|
|
3803
|
+
try {
|
|
3804
|
+
nativeImportOp(schemas, {
|
|
3805
|
+
schemaLockHeld: true,
|
|
3806
|
+
ecSchemaXmlContext: arg.ecSchemaXmlContext?.nativeContext,
|
|
3807
|
+
schemaSyncDbUri: syncAccess.getUri(),
|
|
3808
|
+
});
|
|
3809
|
+
}
|
|
3810
|
+
catch (err) {
|
|
3811
|
+
this.abandonSchemaChanges();
|
|
3812
|
+
throw new IModelError(err.errorNumber, err.message);
|
|
3813
|
+
}
|
|
3814
|
+
this.clearCaches();
|
|
3815
|
+
syncAccess.closeDb();
|
|
3816
|
+
await syncAccess.container.uploadChanges();
|
|
3817
|
+
await this.pushChanges(arg);
|
|
3818
|
+
});
|
|
3819
|
+
}
|
|
3719
3820
|
close(options) {
|
|
3720
3821
|
if (this.isBriefcase && this.isOpen && !this.isReadonly && this.txns.rebaser.inProgress()) {
|
|
3721
3822
|
this[_nativeDb].abandonChanges();
|