From 48110e9a6fc3fc329d92bd225dad12aa727e364f Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 19 Dec 2025 07:56:07 +0100 Subject: [PATCH] Improve error handling and logging for duplicate pg_description cleanup in sequelize.js. Update comments for clarity on permission requirements and provide detailed instructions for manual cleanup by database administrators. Enhance user feedback during synchronization attempts to address potential permission issues. --- backend/utils/sequelize.js | 43 +++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 14 deletions(-) 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