[SQLDB-Migration] Collation Validation (#21572)

Adding collation validation in target database selection page.

collecting source database info including state, size, collation etc in the step 1 (select databases to assess and migrate)
comparing source database collation and target database collation in target selection page.
image
This commit is contained in:
siyang yao
2023-01-12 09:45:02 -08:00
committed by GitHub
parent 52f9a476a0
commit 37f81d9ec2
6 changed files with 74 additions and 4 deletions

View File

@@ -11,7 +11,7 @@ import * as constants from '../constants/strings';
import { debounce } from '../api/utils';
import * as styles from '../constants/styles';
import { IconPathHelper } from '../constants/iconPathHelper';
import { getDatabasesList, excludeDatabases } from '../api/sqlUtils';
import { getDatabasesList, excludeDatabases, SourceDatabaseInfo } from '../api/sqlUtils';
export class DatabaseSelectorPage extends MigrationWizardPage {
private _view!: azdata.ModelView;
@@ -236,10 +236,12 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
databaseList.sort((a, b) => a.options.name.localeCompare(b.options.name));
this._dbNames = [];
stateMachine._databaseInfosForMigration = [];
this._databaseTableValues = databaseList.map(database => {
const databaseName = database.options.name;
this._dbNames.push(databaseName);
stateMachine._databaseInfosForMigration.push(this.getSourceDatabaseInfo(database));
return [
selectedDatabases?.indexOf(databaseName) > -1,
<azdata.IconColumnCellValue>{
@@ -271,4 +273,13 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
});
this.migrationStateModel._databasesForAssessment = selectedDatabases;
}
private getSourceDatabaseInfo(database: azdata.DatabaseInfo): SourceDatabaseInfo {
return {
databaseName: database.options.name,
databaseCollation: database.options.collation,
databaseSizeInMB: database.options.sizeInMB,
databaseState: database.options.state
};
}
}

View File

@@ -1039,17 +1039,23 @@ export class TargetSelectionPage extends MigrationWizardPage {
private _getSourceTargetMappingErrors(): string[] {
// Validate source/target database mappings:
const errors: string[] = [];
var errors: string[] = [];
const collationErrors: string[] = [];
const targetDatabaseKeys = new Map<string, string>();
const migrationDatabaseCount = this._azureResourceTable.dataValues?.length ?? 0;
this.migrationStateModel._targetDatabaseNames = [];
const databaseInfosForMigration = new Map(this.migrationStateModel._databaseInfosForMigration.map(o => [o.databaseName, o]));
if (migrationDatabaseCount === 0) {
errors.push(constants.SQL_TARGET_MAPPING_ERROR_MISSING_TARGET);
} else {
for (let i = 0; i < this.migrationStateModel._databasesForMigration.length; i++) {
const sourceDatabaseName = this.migrationStateModel._databasesForMigration[i];
const sourceDatabaseInfo = databaseInfosForMigration.get(sourceDatabaseName);
const targetDatabaseInfo = this.migrationStateModel._sourceTargetMapping.get(sourceDatabaseName);
const targetDatabaseName = targetDatabaseInfo?.databaseName;
const sourceDatabaseCollation = sourceDatabaseInfo?.databaseCollation;
const targetDatabaseCollation = targetDatabaseInfo?.databaseCollation;
if (targetDatabaseName && targetDatabaseName.length > 0) {
if (!targetDatabaseKeys.has(targetDatabaseName)) {
targetDatabaseKeys.set(targetDatabaseName, sourceDatabaseName);
@@ -1063,12 +1069,28 @@ export class TargetSelectionPage extends MigrationWizardPage {
sourceDatabaseName,
mappedSourceDatabaseName));
}
// Collation validation
if (!this._isCollationSame(sourceDatabaseCollation, targetDatabaseCollation)) {
collationErrors.push(
constants.SQL_TARGET_SOURCE_COLLATION_NOT_SAME(
sourceDatabaseName,
targetDatabaseName,
sourceDatabaseCollation,
targetDatabaseCollation));
}
} else {
// source/target has mapping
errors.push(constants.SQL_TARGET_CONNECTION_SOURCE_NOT_MAPPED(sourceDatabaseName));
}
}
}
if (collationErrors.length > 0) {
collationErrors.push(constants.SQL_MIGRATION_TROUBLESHOOTING_LINK);
errors = errors.concat(collationErrors);
}
return errors;
}
@@ -1083,4 +1105,12 @@ export class TargetSelectionPage extends MigrationWizardPage {
await this._targetUserNameInputBox.validate();
await this._azureResourceTable.validate();
}
private _isCollationSame(sourceDatabaseCollation: string | undefined, targetDatabaseCollation: string | undefined): boolean {
return sourceDatabaseCollation !== undefined &&
sourceDatabaseCollation.length > 0 &&
targetDatabaseCollation !== undefined &&
targetDatabaseCollation.length > 0 &&
sourceDatabaseCollation.toLocaleLowerCase() === targetDatabaseCollation.toLocaleLowerCase();
}
}