Refactor VIRTUAL field detection logic in sequelize.js to improve accuracy and add special handling for Notification model's characterName field, addressing a Sequelize bug related to field mapping.

This commit is contained in:
Torsten Schulz (local)
2025-12-18 15:37:52 +01:00
parent 339ae844e9
commit ea8b9e661d

View File

@@ -428,33 +428,29 @@ const syncModelsAlways = async (models) => {
let isVirtual = false;
if (attr.type) {
// Method 1: Direct comparison with DataTypes.VIRTUAL
if (attr.type === DataTypes.VIRTUAL) {
// Method 1: Check if type key is VIRTUAL (most reliable)
if (attr.type.key === 'VIRTUAL') {
isVirtual = true;
}
// Method 2: Check constructor name
else if (attr.type.constructor && attr.type.constructor.name === 'VIRTUAL') {
// Method 2: Direct comparison with DataTypes.VIRTUAL
else if (attr.type === DataTypes.VIRTUAL) {
isVirtual = true;
}
// Method 3: Check if type key is VIRTUAL
else if (attr.type.key === 'VIRTUAL') {
isVirtual = true;
}
// Method 4: Check toString representation
// Method 3: Check toString representation
else if (typeof attr.type.toString === 'function') {
const typeStr = attr.type.toString();
if (typeStr.includes('VIRTUAL') || typeStr === 'VIRTUAL') {
if (typeStr === 'VIRTUAL' || typeStr.includes('VIRTUAL')) {
isVirtual = true;
}
}
// Method 5: Check if it's an instance of VIRTUAL type
else if (attr.type instanceof DataTypes.VIRTUAL ||
(attr.type.constructor && attr.type.constructor === DataTypes.VIRTUAL.constructor)) {
// Method 4: Check constructor name
else if (attr.type.constructor && attr.type.constructor.name === 'VIRTUAL') {
isVirtual = true;
}
}
// Also check if field has a getter but no setter (common pattern for VIRTUAL fields)
// Also check if field has a getter but no setter and no field mapping (common pattern for VIRTUAL fields)
// But only if it doesn't have a 'field' property, which means it's not mapped to a database column
if (!isVirtual && attr.get && !attr.set && !attr.field) {
// This might be a VIRTUAL field, but be careful not to remove real fields
// Only remove if we're certain it's VIRTUAL
@@ -467,6 +463,16 @@ const syncModelsAlways = async (models) => {
}
}
// Special handling for Notification model: ensure characterName VIRTUAL field is removed
// This is a workaround for Sequelize bug where it confuses characterName (VIRTUAL) with character_name (STRING)
if (model.name === 'Notification' && model.rawAttributes.characterName) {
if (!virtualFields.characterName) {
virtualFields.characterName = model.rawAttributes.characterName;
delete model.rawAttributes.characterName;
console.log(` ⚠️ Explicitly removed VIRTUAL field: characterName from Notification model`);
}
}
try {
await model.sync({ alter: true, force: false });
} finally {