diff --git a/backend/utils/sequelize.js b/backend/utils/sequelize.js index 3cd79ae..2c9511d 100644 --- a/backend/utils/sequelize.js +++ b/backend/utils/sequelize.js @@ -530,7 +530,8 @@ const syncModelsAlways = async (models) => { console.log(` 🔄 Syncing model ${model.name} with constraints: false`); try { - // Bereinige doppelte pg_description Einträge vor dem Sync, um "mehr als eine Zeile" Fehler zu vermeiden + // Versuche doppelte pg_description Einträge vor dem Sync zu bereinigen + // Hinweis: Benötigt Superuser-Rechte oder spezielle Berechtigungen try { const tableName = model.tableName; const schema = model.options?.schema || 'public'; @@ -554,19 +555,27 @@ const syncModelsAlways = async (models) => { ) `); } catch (descError) { - console.warn(` ⚠️ Could not clean up duplicate pg_description entries for ${model.name}:`, descError.message); + // Ignoriere Berechtigungsfehler - das ist normal, wenn der Benutzer keine Superuser-Rechte hat + if (descError.message && descError.message.includes('Berechtigung')) { + console.log(` ℹ️ Cannot clean up duplicate pg_description entries (requires superuser privileges): ${model.name}`); + } else { + console.warn(` ⚠️ Could not clean up duplicate pg_description entries for ${model.name}:`, descError.message); + } } await model.sync({ alter: true, force: false, constraints: false }); } catch (syncError) { - // Wenn Sequelize einen "mehr als eine Zeile" Fehler hat, bereinige pg_description und versuche erneut + // Wenn Sequelize einen "mehr als eine Zeile" Fehler hat, versuche pg_description zu bereinigen if (syncError.message && (syncError.message.includes('mehr als eine Zeile') || syncError.message.includes('more than one row'))) { - console.log(` ⚠️ Sequelize encountered duplicate pg_description entries, cleaning up and retrying...`); + console.log(` ⚠️ Sequelize encountered duplicate pg_description entries for ${model.name}`); + console.log(` ⚠️ This requires manual cleanup by a database administrator with superuser privileges.`); + console.log(` ⚠️ SQL to fix (run as superuser):`); + const tableName = model.tableName; + const schema = model.options?.schema || 'public'; + console.log(` ⚠️ DELETE FROM pg_catalog.pg_description d1 WHERE d1.objoid IN (SELECT c.oid FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = '${tableName}' AND n.nspname = '${schema}') AND EXISTS (SELECT 1 FROM pg_catalog.pg_description d2 WHERE d2.objoid = d1.objoid AND d2.objsubid = d1.objsubid AND d2.ctid < d1.ctid);`); + + // Versuche trotzdem zu bereinigen (falls Berechtigung vorhanden) try { - const tableName = model.tableName; - const schema = model.options?.schema || 'public'; - // Verwende direkte Parameter-Einsetzung, da DO $$ keine Parameterbindung unterstützt - // Die Parameter sind sicher, da sie von Sequelize-Modell-Eigenschaften kommen await sequelize.query(` DELETE FROM pg_catalog.pg_description d1 WHERE d1.objoid IN ( @@ -588,12 +597,18 @@ const syncModelsAlways = async (models) => { console.log(` 🔄 Retrying sync after cleaning duplicate pg_description entries...`); await model.sync({ alter: true, force: false, constraints: false }); } catch (retryError) { - console.error(` ❌ Retry after pg_description cleanup failed:`, retryError.message); - // Kombiniere beide Fehler für besseres Debugging - const combinedError = new Error(`Sync failed: ${syncError.message}. Retry after pg_description cleanup also failed: ${retryError.message}`); - combinedError.originalError = syncError; - combinedError.retryError = retryError; - throw combinedError; + // Wenn Berechtigungsfehler, informiere den Benutzer + if (retryError.message && retryError.message.includes('Berechtigung')) { + console.error(` ❌ Cannot clean up pg_description entries - requires superuser privileges`); + console.error(` ❌ Please run the SQL command above as a database superuser, then retry the sync`); + throw syncError; // Wirf den ursprünglichen Fehler + } else { + console.error(` ❌ Retry after pg_description cleanup failed:`, retryError.message); + const combinedError = new Error(`Sync failed: ${syncError.message}. Retry after pg_description cleanup also failed: ${retryError.message}`); + combinedError.originalError = syncError; + combinedError.retryError = retryError; + throw combinedError; + } } } // Wenn Sequelize versucht, Foreign Keys zu erstellen, entferne sie nach dem Fehler