Files
Data-Coupler/ODBC_CUSTOM_QUERY_ONLY.md
2026-02-03 09:27:23 +01:00

353 lines
11 KiB
Markdown

# 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
/// <summary>
/// Verifica se la credenziale database selezionata è di tipo ODBC
/// </summary>
/// <returns>True se la credenziale è ODBC, altrimenti False</returns>
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))
{
<div class="mb-3">
<button class="btn btn-success btn-sm" @onclick="ConnectToDatabase">
<i class="fas fa-plug"></i> Connetti e Scopri Schema
</button>
</div>
}
```
**Dopo:**
```razor
@if (!string.IsNullOrEmpty(selectedDatabaseCredential))
{
<!-- Per ODBC: mostra messaggio esplicativo, niente discovery -->
@if (IsOdbcConnection())
{
<div class="alert alert-info" role="alert">
<i class="oi oi-info"></i> <strong>Connessione ODBC rilevata</strong><br>
Per le connessioni ODBC, il discovery automatico delle tabelle non è disponibile.<br>
Procedi direttamente con l'inserimento di una <strong>query SQL custom</strong> nella sezione sottostante.
</div>
}
else
{
<!-- Per database standard: mostra pulsante di connessione -->
<div class="mb-3">
<button class="btn btn-success btn-sm" @onclick="ConnectToDatabase">
<i class="fas fa-plug"></i> Connetti e Scopri Schema
</button>
</div>
}
}
```
**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
<!-- Per ODBC: mostra direttamente la sezione Query Custom -->
@if (IsOdbcConnection())
{
<!-- Sezione Query Custom per ODBC -->
<div class="mb-3">
<h6>Query SQL Custom:</h6>
<div class="mb-2">
<label class="form-label">Scrivi la tua query SELECT:</label>
<textarea class="form-control" rows="6"
placeholder="SELECT * FROM your_table WHERE condition..."
@bind="customQuery" @bind:event="oninput"></textarea>
<!-- Alert sicurezza -->
</div>
<div class="mb-2">
<button class="btn btn-primary btn-sm me-2" @onclick="ValidateCustomQuery">
<i class="fas fa-check-circle"></i> Valida Query
</button>
<!-- Altri pulsanti preview, ecc. -->
</div>
</div>
}
```
**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)
{
<!-- Lista tabelle e query custom switch -->
}
```
**Dopo:**
```razor
<!-- Lista Tabelle (solo per database NON ODBC) -->
@if (isDatabaseConnected && !IsOdbcConnection())
{
<!-- Selezione modalità: Tabelle o Query Custom -->
<!-- Lista tabelle -->
}
```
**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