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:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user