From 9e48666306e1aa9dd6831eb88bf9fff04f3e5d47 Mon Sep 17 00:00:00 2001 From: Alessio Dal Santo Date: Tue, 3 Feb 2026 09:27:23 +0100 Subject: [PATCH] [Docs] Documentazione implementazione ODBC query custom only --- ODBC_CUSTOM_QUERY_ONLY.md | 352 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 352 insertions(+) create mode 100644 ODBC_CUSTOM_QUERY_ONLY.md diff --git a/ODBC_CUSTOM_QUERY_ONLY.md b/ODBC_CUSTOM_QUERY_ONLY.md new file mode 100644 index 0000000..af735e6 --- /dev/null +++ b/ODBC_CUSTOM_QUERY_ONLY.md @@ -0,0 +1,352 @@ +# Implementazione ODBC Query Custom Only + +## 📋 Panoramica + +Data la natura generica dei driver ODBC e le limitazioni del discovery automatico delle tabelle, è stato implementato un comportamento speciale per le connessioni ODBC nel DataCoupler: **le connessioni ODBC utilizzano esclusivamente query SQL custom**, bypassando completamente il sistema di discovery delle tabelle. + +## 🎯 Motivazione + +I driver ODBC sono estremamente eterogenei e spesso: +- Non supportano query standard di discovery delle tabelle +- Hanno sintassi SQL non standardizzate +- Richiedono permessi specifici per accedere ai metadati del database +- Possono avere limitazioni sulla lettura dello schema + +Per questi motivi, è più sicuro e affidabile richiedere all'utente di specificare direttamente la query SQL da eseguire. + +## 🔧 Modifiche Implementate + +### 1. **DatabaseMethod.cs** + +#### Nuovo Metodo Helper: `IsOdbcConnection()` +```csharp +/// +/// Verifica se la credenziale database selezionata è di tipo ODBC +/// +/// True se la credenziale è ODBC, altrimenti False +protected bool IsOdbcConnection() +{ + if (string.IsNullOrEmpty(selectedDatabaseCredential)) + return false; + + var credential = databaseCredentials.FirstOrDefault(c => c.Name == selectedDatabaseCredential); + return credential?.DatabaseType == DatabaseType.Odbc; +} +``` + +**Funzionalità:** +- Verifica rapidamente se la credenziale corrente è ODBC +- Utilizzato in tutta l'UI per condizionare la visualizzazione degli elementi + +#### Modificato: `OnDatabaseCredentialChanged()` +```csharp +protected void OnDatabaseCredentialChanged(ChangeEventArgs e) +{ + selectedDatabaseCredential = e.Value?.ToString() ?? ""; + ResetDatabaseState(); + + // Se è una connessione ODBC, forza l'uso di query custom + if (IsOdbcConnection()) + { + useCustomQuery = true; + } +} +``` + +**Comportamento:** +- Quando l'utente seleziona una credenziale ODBC, `useCustomQuery` viene automaticamente impostato a `true` +- Questo forza l'applicazione a mostrare solo la sezione query custom + +#### Modificato: `ValidateCustomQuery()` + +**Problema originale:** Il metodo richiedeva `currentDatabaseManager` già creato, ma per ODBC non si fa connessione preliminare. + +**Soluzione implementata:** +```csharp +protected async Task ValidateCustomQuery() +{ + // ... + IDatabaseManager? tempManager = null; + + try + { + // Per ODBC, crea un database manager temporaneo se non esiste + var managerToUse = currentDatabaseManager; + if (managerToUse == null && IsOdbcConnection()) + { + Logger.LogInformation("Creando database manager temporaneo per validazione query ODBC"); + tempManager = await ConnectionFactory.CreateDatabaseManagerAsync(selectedDatabaseCredential); + managerToUse = tempManager; + } + + // Valida la query con il manager + var testResults = await managerToUse.ExecuteRawQueryAsync(testQuery); + + // Se validazione OK, salva il manager per ODBC + if (IsOdbcConnection() && currentDatabaseManager == null && tempManager != null) + { + currentDatabaseManager = tempManager; + tempManager = null; // Non distruggerlo nel finally + } + } + finally + { + // Pulisci il manager temporaneo se non è stato salvato + if (tempManager != null) + { + try { tempManager.Dispose(); } catch { /* Ignora errori di dispose */ } + } + } +} +``` + +**Funzionalità:** +- Crea temporaneamente un `OdbcDatabaseManager` se non esiste +- Usa questo manager per testare la query +- Se la validazione ha successo, salva il manager in `currentDatabaseManager` per riutilizzarlo +- Gestisce correttamente il dispose del manager temporaneo in caso di errore + +### 2. **DataCoupler.razor** + +#### Modificata: Sezione Pulsante Connessione + +**Prima:** +```razor +@if (!string.IsNullOrEmpty(selectedDatabaseCredential)) +{ +
+ +
+} +``` + +**Dopo:** +```razor +@if (!string.IsNullOrEmpty(selectedDatabaseCredential)) +{ + + @if (IsOdbcConnection()) + { + + } + else + { + +
+ +
+ } +} +``` + +**Funzionalità:** +- Per ODBC: mostra un messaggio informativo che spiega la situazione +- Per altri database: mostra il pulsante di connessione standard +- L'utente comprende immediatamente che deve usare query custom + +#### Aggiunta: Sezione Query Custom per ODBC (sempre visibile) + +```razor + +@if (IsOdbcConnection()) +{ + +
+
Query SQL Custom:
+ +
+ + + +
+ +
+ + +
+
+} +``` + +**Funzionalità:** +- Sezione query custom **sempre visibile** quando si seleziona ODBC +- Non richiede connessione preliminare +- Include tutti i controlli per validazione, preview, ecc. + +#### Modificata: Condizione Lista Tabelle + +**Prima:** +```razor +@if (isDatabaseConnected) +{ + +} +``` + +**Dopo:** +```razor + +@if (isDatabaseConnected && !IsOdbcConnection()) +{ + + +} +``` + +**Funzionalità:** +- La sezione lista tabelle **non viene mai mostrata** per ODBC +- Anche se `isDatabaseConnected` è `true` (non dovrebbe mai succedere per ODBC), la sezione resta nascosta + +## 🔄 Flusso Utente ODBC + +### Prima dell'implementazione: +1. Seleziona credenziale ODBC +2. Clicca "Connetti e Scopri Schema" +3. **Errore**: discovery tabelle fallisce +4. User frustrato, deve capire come fare + +### Dopo l'implementazione: +1. ✅ Seleziona credenziale ODBC +2. ✅ Vede immediatamente messaggio informativo +3. ✅ Vede la sezione query custom già pronta +4. ✅ Scrive la query SQL +5. ✅ Clicca "Valida Query" (crea automaticamente `OdbcDatabaseManager`) +6. ✅ Vede preview dei dati +7. ✅ Procede con il mapping + +**Nessun pulsante di connessione, nessun discovery, solo query diretta.** + +## 🎨 Esperienza Utente + +### Per Database Standard (SQL Server, MySQL, ecc.) +- **Mostra:** Pulsante "Connetti e Scopri Schema" +- **Discovery:** Automatico con lista tabelle +- **Query Custom:** Opzionale, via switch + +### Per Database ODBC +- **Mostra:** Messaggio informativo + textarea query +- **Discovery:** Disabilitato completamente +- **Query Custom:** Obbligatoria, sempre visibile + +## 📊 Vantaggi dell'Implementazione + +### 1. **Affidabilità** +- Nessun rischio di errori nel discovery delle tabelle ODBC +- L'utente ha il controllo completo della query SQL + +### 2. **Semplicità** +- Flusso chiaro: seleziona ODBC → scrivi query → valida → preview +- Nessun passo intermedio confusionario + +### 3. **Performance** +- Nessun tentativo di discovery che può essere lento o fallire +- Connessione ODBC creata solo quando serve (alla validazione) + +### 4. **Flessibilità** +- L'utente può scrivere qualsiasi query SELECT +- Supporta JOIN, WHERE, GROUP BY, ecc. +- Nessuna limitazione del discovery automatico + +## 🔒 Sicurezza + +Tutti i controlli di sicurezza esistenti restano attivi: + +- ✅ Solo query `SELECT` permesse +- ✅ Query multiple (separate da `;`) bloccate +- ✅ Operazioni `INSERT`, `UPDATE`, `DELETE`, `DROP` bloccate +- ✅ Query pulita da caratteri pericolosi + +## 🧪 Test Manuali Suggeriti + +### Test 1: Selezione Credenziale ODBC +1. Vai a DataCoupler +2. Seleziona sorgente Database +3. Seleziona una credenziale ODBC +4. **Verifica:** + - ✅ Nessun pulsante "Connetti e Scopri Schema" + - ✅ Messaggio informativo visibile + - ✅ Sezione query custom visibile + - ✅ Textarea query pronta per input + +### Test 2: Validazione Query ODBC +1. Seleziona credenziale ODBC +2. Scrivi query: `SELECT * FROM MyTable` +3. Clicca "Valida Query" +4. **Verifica:** + - ✅ Creazione automatica `OdbcDatabaseManager` + - ✅ Query eseguita con successo + - ✅ Colonne rilevate mostrate + - ✅ Messaggio "Query valida - N colonne rilevate" + +### Test 3: Preview Dati ODBC +1. Dopo validazione query (Test 2) +2. Clicca "Anteprima Risultati" +3. **Verifica:** + - ✅ Preview tabella con 10 righe + - ✅ Colonne corrette + - ✅ Dati visualizzati correttamente + +### Test 4: Mapping e Trasferimento ODBC +1. Dopo validazione e preview (Test 2-3) +2. Procedi con configurazione destinazione +3. Crea mapping campi +4. Esegui trasferimento +5. **Verifica:** + - ✅ Trasferimento dati completato + - ✅ Record copiati correttamente + +### Test 5: Confronto con Database Standard +1. Seleziona credenziale SQL Server +2. **Verifica:** + - ✅ Pulsante "Connetti e Scopri Schema" visibile + - ✅ Discovery tabelle funziona + - ✅ Switch query custom disponibile + - ✅ Nessun messaggio ODBC + +## 📝 Note Tecniche + +### Manager ODBC Temporaneo +- Creato **on-demand** durante la validazione query +- Salvato in `currentDatabaseManager` se validazione OK +- Riutilizzato per preview e trasferimento dati +- Disposto correttamente in caso di errore + +### Compatibilità con Profili Esistenti +- Profili ODBC con query custom salvate continuano a funzionare +- Al caricamento profilo, se ODBC + query custom → valida automaticamente +- Nessuna breaking change per profili esistenti + +### Dipendenze +- `OdbcDatabaseManager` (già implementato) +- `DataConnectionFactory` con supporto ODBC (già implementato) +- `DatabaseType.Odbc` enum (già implementato) + +## 🚀 Future Improvements + +Possibili miglioramenti futuri (non implementati ora): + +1. **Syntax Highlighting** per query SQL nella textarea +2. **Query Templates** predefiniti per ODBC comuni (SAP HANA, DB2, ecc.) +3. **Salvataggio Query Recenti** per riutilizzo rapido +4. **Auto-complete Tabelle** (se driver ODBC lo supporta) +5. **Explain Plan** per query complesse + +--- + +**Versione**: 2.2.0 +**Data Implementazione**: 2 Febbraio 2026 +**Commit**: `8a8ccec` +**Branch**: `development` +**Sviluppatore**: Alessio Dalsanto