@itwin/core-backend
Version:
iTwin.js backend components
187 lines • 9.35 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { IModelStatus } from "@itwin/core-bentley";
import { IModelError } from "@itwin/core-common";
/**
* Information about each integrity check type, including the name, expected result type, and SQL query to execute
* @internal
*/
export const integrityCheckTypeMap = {
checkDataColumns: {
name: "Check Data Columns",
resultType: "CheckDataColumnsResultRow",
sqlCommand: "check_data_columns",
sqlQuery: `PRAGMA integrity_check(check_data_columns) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkECProfile: {
name: "Check EC Profile",
resultType: "CheckECProfileResultRow",
sqlCommand: "check_ec_profile",
sqlQuery: `PRAGMA integrity_check(check_ec_profile) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkNavigationClassIds: {
name: "Check Navigation Class Ids",
resultType: "CheckNavClassIdsResultRow",
sqlCommand: "check_nav_class_ids",
sqlQuery: `PRAGMA integrity_check(check_nav_class_ids) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkNavigationIds: {
name: "Check Navigation Ids",
resultType: "CheckNavIdsResultRow",
sqlCommand: "check_nav_ids",
sqlQuery: `PRAGMA integrity_check(check_nav_ids) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkLinktableForeignKeyClassIds: {
name: "Check Link Table Foreign Key Class Ids",
resultType: "CheckLinkTableFkClassIdsResultRow",
sqlCommand: "check_linktable_fk_class_ids",
sqlQuery: `PRAGMA integrity_check(check_linktable_fk_class_ids) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkLinktableForeignKeyIds: {
name: "Check Link Table Foreign Key Ids",
resultType: "CheckLinkTableFkIdsResultRow",
sqlCommand: "check_linktable_fk_ids",
sqlQuery: `PRAGMA integrity_check(check_linktable_fk_ids) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkClassIds: {
name: "Check Class Ids",
resultType: "CheckClassIdsResultRow",
sqlCommand: "check_class_ids",
sqlQuery: `PRAGMA integrity_check(check_class_ids) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkDataSchema: {
name: "Check Data Schema",
resultType: "CheckDataSchemaResultRow",
sqlCommand: "check_data_schema",
sqlQuery: `PRAGMA integrity_check(check_data_schema) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkSchemaLoad: {
name: "Check Schema Load",
resultType: "CheckSchemaLoadResultRow",
sqlCommand: "check_schema_load",
sqlQuery: `PRAGMA integrity_check(check_schema_load) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
checkMissingChildRows: {
name: "Check Missing Child Rows",
resultType: "CheckMissingChildRowsResultRow",
sqlCommand: "check_missing_child_rows",
sqlQuery: `PRAGMA integrity_check(check_missing_child_rows) ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES`,
},
};
/**
* Gets the user-friendly name of an integrity check based on its key or SQL command.
* It first attempts to find a direct match for the key in the integrityCheckTypeMap. If not found, it searches for a match based on the SQL command.
* If still not found, it returns the original check string.
* @param check - The integrity check key or SQL command to get the name of
* @returns The user-friendly name of the integrity check, or the original check string if no match is found
* @internal
*/
export function getIntegrityCheckName(check) {
// First try direct lookup by key
const directLookup = integrityCheckTypeMap[check];
if (directLookup) {
return directLookup.name;
}
// If not found, search by sqlCommand
for (const [, value] of Object.entries(integrityCheckTypeMap)) {
if (value.sqlCommand === check) {
return value.name;
}
}
// Fallback to the original check string
return check;
}
/**
* Performs a quick integrity check on the given iModel.
* @param iModel The IModelDb instance to perform the integrity check on
* @returns An array of results for each check performed, including the check name, whether it passed, and the elapsed time in seconds
* @internal
*/
export async function performQuickIntegrityCheck(iModel) {
const integrityCheckQuery = "PRAGMA integrity_check ECSQLOPTIONS ENABLE_EXPERIMENTAL_FEATURES";
const integrityCheckResults = [];
for await (const row of iModel.createQueryReader(integrityCheckQuery, undefined, { usePrimaryConn: true })) {
integrityCheckResults.push({ check: getIntegrityCheckName(row.check), passed: row.result, elapsedSeconds: row.elapsed_sec });
}
;
return integrityCheckResults;
}
export async function performSpecificIntegrityCheck(iModel, check) {
switch (check) {
case "checkDataColumns": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkDataColumns.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, table: row.table, column: row.column });
}
return results;
}
case "checkECProfile": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkECProfile.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, type: row.type, name: row.name, issue: row.issue });
}
return results;
}
case "checkNavigationClassIds": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkNavigationClassIds.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, id: row.id, class: row.class, property: row.property, navId: row.nav_id, navClassId: row.nav_classId });
}
return results;
}
case "checkNavigationIds": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkNavigationIds.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, id: row.id, class: row.class, property: row.property, navId: row.nav_id, primaryClass: row.primary_class });
}
return results;
}
case "checkLinktableForeignKeyClassIds": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkLinktableForeignKeyClassIds.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, id: row.id, relationship: row.relationship, property: row.property, keyId: row.key_id, keyClassId: row.key_classId });
}
return results;
}
case "checkLinktableForeignKeyIds": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkLinktableForeignKeyIds.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, id: row.id, relationship: row.relationship, property: row.property, keyId: row.key_id, primaryClass: row.primary_class });
}
return results;
}
case "checkClassIds": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkClassIds.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, class: row.class, id: row.id, classId: row.class_id, type: row.type });
}
return results;
}
case "checkDataSchema": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkDataSchema.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, type: row.type, name: row.name });
}
return results;
}
case "checkSchemaLoad": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkSchemaLoad.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, schema: row.schema });
}
return results;
}
case "checkMissingChildRows": {
const results = [];
for await (const row of iModel.createQueryReader(integrityCheckTypeMap.checkMissingChildRows.sqlQuery, undefined, { usePrimaryConn: true })) {
results.push({ sno: row.sno, class: row.class, id: row.id, classId: row.class_id, missingRowInTables: row.MissingRowInTables });
}
return results;
}
default:
throw new IModelError(IModelStatus.BadRequest, `Unknown integrity check type`);
}
}
//# sourceMappingURL=IntegrityCheck.js.map