mirror of
https://github.com/immich-app/immich.git
synced 2026-02-14 04:47:57 +03:00
feat: schema-check (#25904)
This commit is contained in:
@@ -1,98 +1,99 @@
|
||||
import { asRenameKey, getColumnType, isDefaultEqual } from 'src/sql-tools/helpers';
|
||||
import { Comparer, DatabaseColumn, Reason, SchemaDiff } from 'src/sql-tools/types';
|
||||
|
||||
export const compareColumns = {
|
||||
getRenameKey: (column) => {
|
||||
return asRenameKey([
|
||||
column.tableName,
|
||||
column.type,
|
||||
column.nullable,
|
||||
column.default,
|
||||
column.storage,
|
||||
column.primary,
|
||||
column.isArray,
|
||||
column.length,
|
||||
column.identity,
|
||||
column.enumName,
|
||||
column.numericPrecision,
|
||||
column.numericScale,
|
||||
]);
|
||||
},
|
||||
onRename: (source, target) => [
|
||||
{
|
||||
type: 'ColumnRename',
|
||||
tableName: source.tableName,
|
||||
oldName: target.name,
|
||||
newName: source.name,
|
||||
reason: Reason.Rename,
|
||||
export const compareColumns = () =>
|
||||
({
|
||||
getRenameKey: (column) => {
|
||||
return asRenameKey([
|
||||
column.tableName,
|
||||
column.type,
|
||||
column.nullable,
|
||||
column.default,
|
||||
column.storage,
|
||||
column.primary,
|
||||
column.isArray,
|
||||
column.length,
|
||||
column.identity,
|
||||
column.enumName,
|
||||
column.numericPrecision,
|
||||
column.numericScale,
|
||||
]);
|
||||
},
|
||||
],
|
||||
onMissing: (source) => [
|
||||
{
|
||||
type: 'ColumnAdd',
|
||||
column: source,
|
||||
reason: Reason.MissingInTarget,
|
||||
onRename: (source, target) => [
|
||||
{
|
||||
type: 'ColumnRename',
|
||||
tableName: source.tableName,
|
||||
oldName: target.name,
|
||||
newName: source.name,
|
||||
reason: Reason.Rename,
|
||||
},
|
||||
],
|
||||
onMissing: (source) => [
|
||||
{
|
||||
type: 'ColumnAdd',
|
||||
column: source,
|
||||
reason: Reason.MissingInTarget,
|
||||
},
|
||||
],
|
||||
onExtra: (target) => [
|
||||
{
|
||||
type: 'ColumnDrop',
|
||||
tableName: target.tableName,
|
||||
columnName: target.name,
|
||||
reason: Reason.MissingInSource,
|
||||
},
|
||||
],
|
||||
onCompare: (source, target) => {
|
||||
const sourceType = getColumnType(source);
|
||||
const targetType = getColumnType(target);
|
||||
|
||||
const isTypeChanged = sourceType !== targetType;
|
||||
|
||||
if (isTypeChanged) {
|
||||
// TODO: convert between types via UPDATE when possible
|
||||
return dropAndRecreateColumn(source, target, `column type is different (${sourceType} vs ${targetType})`);
|
||||
}
|
||||
|
||||
const items: SchemaDiff[] = [];
|
||||
if (source.nullable !== target.nullable) {
|
||||
items.push({
|
||||
type: 'ColumnAlter',
|
||||
tableName: source.tableName,
|
||||
columnName: source.name,
|
||||
changes: {
|
||||
nullable: source.nullable,
|
||||
},
|
||||
reason: `nullable is different (${source.nullable} vs ${target.nullable})`,
|
||||
});
|
||||
}
|
||||
|
||||
if (!isDefaultEqual(source, target)) {
|
||||
items.push({
|
||||
type: 'ColumnAlter',
|
||||
tableName: source.tableName,
|
||||
columnName: source.name,
|
||||
changes: {
|
||||
default: String(source.default ?? 'NULL'),
|
||||
},
|
||||
reason: `default is different (${source.default ?? 'null'} vs ${target.default})`,
|
||||
});
|
||||
}
|
||||
|
||||
if (source.comment !== target.comment) {
|
||||
items.push({
|
||||
type: 'ColumnAlter',
|
||||
tableName: source.tableName,
|
||||
columnName: source.name,
|
||||
changes: {
|
||||
comment: String(source.comment),
|
||||
},
|
||||
reason: `comment is different (${source.comment} vs ${target.comment})`,
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
],
|
||||
onExtra: (target) => [
|
||||
{
|
||||
type: 'ColumnDrop',
|
||||
tableName: target.tableName,
|
||||
columnName: target.name,
|
||||
reason: Reason.MissingInSource,
|
||||
},
|
||||
],
|
||||
onCompare: (source, target) => {
|
||||
const sourceType = getColumnType(source);
|
||||
const targetType = getColumnType(target);
|
||||
|
||||
const isTypeChanged = sourceType !== targetType;
|
||||
|
||||
if (isTypeChanged) {
|
||||
// TODO: convert between types via UPDATE when possible
|
||||
return dropAndRecreateColumn(source, target, `column type is different (${sourceType} vs ${targetType})`);
|
||||
}
|
||||
|
||||
const items: SchemaDiff[] = [];
|
||||
if (source.nullable !== target.nullable) {
|
||||
items.push({
|
||||
type: 'ColumnAlter',
|
||||
tableName: source.tableName,
|
||||
columnName: source.name,
|
||||
changes: {
|
||||
nullable: source.nullable,
|
||||
},
|
||||
reason: `nullable is different (${source.nullable} vs ${target.nullable})`,
|
||||
});
|
||||
}
|
||||
|
||||
if (!isDefaultEqual(source, target)) {
|
||||
items.push({
|
||||
type: 'ColumnAlter',
|
||||
tableName: source.tableName,
|
||||
columnName: source.name,
|
||||
changes: {
|
||||
default: String(source.default ?? 'NULL'),
|
||||
},
|
||||
reason: `default is different (${source.default ?? 'null'} vs ${target.default})`,
|
||||
});
|
||||
}
|
||||
|
||||
if (source.comment !== target.comment) {
|
||||
items.push({
|
||||
type: 'ColumnAlter',
|
||||
tableName: source.tableName,
|
||||
columnName: source.name,
|
||||
changes: {
|
||||
comment: String(source.comment),
|
||||
},
|
||||
reason: `comment is different (${source.comment} vs ${target.comment})`,
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
} satisfies Comparer<DatabaseColumn>;
|
||||
}) satisfies Comparer<DatabaseColumn>;
|
||||
|
||||
const dropAndRecreateColumn = (source: DatabaseColumn, target: DatabaseColumn, reason: string): SchemaDiff[] => {
|
||||
return [
|
||||
|
||||
Reference in New Issue
Block a user