feat: include comments in contentHash for mssql

This commit is contained in:
Pavel
2025-08-01 05:44:41 +02:00
parent 795992fb42
commit 32b1a5b22d

View File

@@ -1,4 +1,5 @@
const _ = require('lodash');
const crypto = require('crypto');
const sql = require('./sql');
const { DatabaseAnalyser, isTypeString, isTypeNumeric } = global.DBGATE_PACKAGES['dbgate-tools'];
@@ -55,6 +56,7 @@ function getColumnInfo({
defaultConstraint,
computedExpression,
columnComment,
objectId,
}) {
const fullDataType = getFullDataTypeName({
dataType,
@@ -72,6 +74,7 @@ function getColumnInfo({
}
return {
objectId,
columnName,
dataType: fullDataType,
notNull: !isNullable,
@@ -84,6 +87,31 @@ function getColumnInfo({
};
}
/**
* @param {ReturnType<objectTypeToField>} fieldType
* @param {any} item
* @param {Array<ReturnType<getColumnInfo>>} columns
* @returns {string|null}
*/
function createObjectContentHash(fieldType, item, columns) {
if (!fieldType) return null;
const { modifyDate } = item;
if ((columns?.length && fieldType === 'tables') || fieldType === 'views') {
const modifyDateStr = modifyDate ? modifyDate.toISOString() : '';
const objectColumns = columns.filter(col => col.objectId == item.objectId);
const colsComments = objectColumns.map(i => i.columnComment).join(',');
return crypto
.createHash('sha256')
.update(modifyDateStr + colsComments)
.digest('hex');
}
if (!modifyDate) return null;
return modifyDate.toISOString();
}
class MsSqlAnalyser extends DatabaseAnalyser {
constructor(dbhan, driver, version) {
super(dbhan, driver, version);
@@ -106,6 +134,7 @@ class MsSqlAnalyser extends DatabaseAnalyser {
const tablesRows = await this.analyserQuery('tables', ['tables']);
this.feedback({ analysingMessage: 'Loading columns' });
const columnsRows = await this.analyserQuery('columns', ['tables']);
const columns = columnsRows.rows.map(getColumnInfo);
this.feedback({ analysingMessage: 'Loading primary keys' });
const pkColumnsRows = await this.analyserQuery('primaryKeys', ['tables']);
@@ -145,8 +174,8 @@ class MsSqlAnalyser extends DatabaseAnalyser {
this.feedback({ analysingMessage: 'Finalizing DB structure' });
const tables = tablesRows.rows.map(row => ({
...row,
contentHash: row.modifyDate && row.modifyDate.toISOString(),
columns: columnsRows.rows.filter(col => col.objectId == row.objectId).map(getColumnInfo),
contentHash: createObjectContentHash('tables', row, columns),
columns: columns.filter(col => col.objectId == row.objectId),
primaryKey: DatabaseAnalyser.extractPrimaryKeys(row, pkColumnsRows.rows),
foreignKeys: DatabaseAnalyser.extractForeignKeys(row, fkColumnsRows.rows),
indexes: indexesRows.rows
@@ -174,7 +203,7 @@ class MsSqlAnalyser extends DatabaseAnalyser {
const views = viewsRows.rows.map(row => ({
...row,
contentHash: row.modifyDate && row.modifyDate.toISOString(),
contentHash: createObjectContentHash('views', row, columns),
createSql: getCreateSql(row),
columns: viewColumnRows.rows.filter(col => col.objectId == row.objectId).map(getColumnInfo),
}));
@@ -195,7 +224,7 @@ class MsSqlAnalyser extends DatabaseAnalyser {
.filter(x => x.sqlObjectType.trim() == 'P')
.map(row => ({
...row,
contentHash: row.modifyDate && row.modifyDate.toISOString(),
contentHash: createObjectContentHash('procedures', row),
createSql: getCreateSql(row),
parameters: prodceureToParameters[row.objectId],
}));
@@ -216,14 +245,14 @@ class MsSqlAnalyser extends DatabaseAnalyser {
.filter(x => ['FN', 'IF', 'TF'].includes(x.sqlObjectType.trim()))
.map(row => ({
...row,
contentHash: row.modifyDate && row.modifyDate.toISOString(),
contentHash: createObjectContentHash('functions', row),
createSql: getCreateSql(row),
parameters: functionToParameters[row.objectId],
}));
const triggers = triggerRows.rows.map(row => ({
objectId: `triggers:${row.objectId}`,
contentHash: row.modifyDate && row.modifyDate.toISOString(),
contentHash: createObjectContentHash('triggers', row),
createSql: row.definition,
triggerTiming: row.triggerTiming,
eventType: row.eventType,
@@ -244,17 +273,19 @@ class MsSqlAnalyser extends DatabaseAnalyser {
async _getFastSnapshot() {
const modificationsQueryData = await this.analyserQuery('modifications');
const columnsRows = await this.analyserQuery('columns', ['tables']);
const columns = columnsRows.rows.map(getColumnInfo);
const tableSizes = await this.analyserQuery('tableSizes');
const res = DatabaseAnalyser.createEmptyStructure();
for (const item of modificationsQueryData.rows) {
const { type, objectId, modifyDate, schemaName, pureName } = item;
const { type, objectId, schemaName, pureName } = item;
const field = objectTypeToField(type);
if (!field || !res[field]) continue;
res[field].push({
objectId,
contentHash: modifyDate && modifyDate.toISOString(),
contentHash: createObjectContentHash(field, item, columns),
schemaName,
pureName,
});