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;
|
let isVirtual = false;
|
||||||
|
|
||||||
if (attr.type) {
|
if (attr.type) {
|
||||||
// Method 1: Direct comparison with DataTypes.VIRTUAL
|
// Method 1: Check if type key is VIRTUAL (most reliable)
|
||||||
if (attr.type === DataTypes.VIRTUAL) {
|
if (attr.type.key === 'VIRTUAL') {
|
||||||
isVirtual = true;
|
isVirtual = true;
|
||||||
}
|
}
|
||||||
// Method 2: Check constructor name
|
// Method 2: Direct comparison with DataTypes.VIRTUAL
|
||||||
else if (attr.type.constructor && attr.type.constructor.name === 'VIRTUAL') {
|
else if (attr.type === DataTypes.VIRTUAL) {
|
||||||
isVirtual = true;
|
isVirtual = true;
|
||||||
}
|
}
|
||||||
// Method 3: Check if type key is VIRTUAL
|
// Method 3: Check toString representation
|
||||||
else if (attr.type.key === 'VIRTUAL') {
|
|
||||||
isVirtual = true;
|
|
||||||
}
|
|
||||||
// Method 4: Check toString representation
|
|
||||||
else if (typeof attr.type.toString === 'function') {
|
else if (typeof attr.type.toString === 'function') {
|
||||||
const typeStr = attr.type.toString();
|
const typeStr = attr.type.toString();
|
||||||
if (typeStr.includes('VIRTUAL') || typeStr === 'VIRTUAL') {
|
if (typeStr === 'VIRTUAL' || typeStr.includes('VIRTUAL')) {
|
||||||
isVirtual = true;
|
isVirtual = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Method 5: Check if it's an instance of VIRTUAL type
|
// Method 4: Check constructor name
|
||||||
else if (attr.type instanceof DataTypes.VIRTUAL ||
|
else if (attr.type.constructor && attr.type.constructor.name === 'VIRTUAL') {
|
||||||
(attr.type.constructor && attr.type.constructor === DataTypes.VIRTUAL.constructor)) {
|
|
||||||
isVirtual = true;
|
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) {
|
if (!isVirtual && attr.get && !attr.set && !attr.field) {
|
||||||
// This might be a VIRTUAL field, but be careful not to remove real fields
|
// This might be a VIRTUAL field, but be careful not to remove real fields
|
||||||
// Only remove if we're certain it's VIRTUAL
|
// 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 {
|
try {
|
||||||
await model.sync({ alter: true, force: false });
|
await model.sync({ alter: true, force: false });
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user