Files
Omika/docs/diagnostics/hfsql-schema-detector.md
T
2026-10-23 18:46:50 +02:00

130 lines
4.9 KiB
Markdown

# Détecteur de schéma HFSQL (DatabaseSchemaDetector)
## Stratégie générale
Le détecteur détermine la version réelle du schéma de base (Batik ou Omika) à
partir de la **structure physique** exposée par HFSQL OLE DB, et uniquement à
partir de celle-ci.
La décision ne repose **jamais** sur :
- le nom de la base (`BATIK_TEST`, `OMIKA_TEST`, ou tout autre nom client) ;
- le nom du serveur ;
- la présence d'un mot de passe ;
- le nombre de tables ;
- OpenSchema (`GetSchema`).
Chaque canari est testé par une requête structurelle réelle et contrôlée :
```sql
SELECT TOP 0 <colonne> FROM <table>
```
Le **succès / échec structurel** de la requête indique la présence ou l'absence
de la colonne. Aucune donnée métier n'est lue (`TOP 0` ne retourne aucune ligne).
## Canaris utilisés
### Socle commun (présent dans Batik et Omika)
| Table | Colonne | Rôle |
|-------|---------|------|
| `Client` | `CL_PKID` | Confirme que la base est une base Omika/Batik compatible |
### Canaris Omika (colonnes Omika-only de `Client`)
| Table | Colonne | Rôle |
|-------|---------|------|
| `Client` | `CL_CleType` | Marqueur Omika (colonne absente de Batik) |
| `Client` | `GUID` | Marqueur Omika (colonne absente de Batik) |
### Canari de confirmation Omika (table Omika-only)
| Table | Colonne | Rôle |
|-------|---------|------|
| `Role` | `R_PKID` | Confirme la migration Omika en cas d'ambiguïté |
## Pourquoi ces canaris discriminent Batik / Omika
Les colonnes `CL_CleType` et `GUID` de la table `Client` sont marquées
`IsOmikaOnly` dans les modèles physiques générés et ont été **confirmées par le
model-audit** :
- présentes physiquement dans `OMIKA_TEST` (statut `VERIFIED`) ;
- absentes de `BATIK_TEST`.
La table `Role` est une table réellement Omika-only (absente de Batik), confirmée
par le model-audit. Elle sert de canari de confirmation indépendant.
La table `Client` est accessible en accès direct dans les deux bases, ce qui rend
la détection possible sans dépendre des mots de passe de fichiers protégés.
## Algorithme de décision
1. **Socle commun** : `SELECT TOP 0 CL_PKID FROM Client` doit réussir.
Sinon → échec explicite (base non reconnue).
2. **Canaris Omika** : tester `CL_CleType` et `GUID` dans `Client`.
3. **Canari de confirmation** : tester `R_PKID` dans `Role`.
Décision :
- `CL_CleType` **et** `GUID` présents → **Omika**.
- Un seul des deux présent → ambiguïté :
- si `Role` présent → **Omika** ;
- sinon → échec explicite (structure incohérente).
- Aucun canari Omika présent (socle commun valide) → **Batik**.
La base n'est jamais déclarée Batik ou Omika par défaut : la décision repose
toujours sur la structure réellement observée.
## Résultats d'intégration
| Base | Résultat attendu | Résultat observé |
|------|------------------|------------------|
| `BATIK_TEST` | `DatabaseSchemaVersion.Batik` | `Batik` |
| `OMIKA_TEST` | `DatabaseSchemaVersion.Omika` | `Omika` |
Les tests d'intégration réels utilisent `config/hfsql-test.local.json` et le
provider OLE DB `PCSOFT.HFSQL`. Ils sont ignorés automatiquement si la
configuration locale ou le serveur sont indisponibles.
Aucun secret, aucune chaîne de connexion, aucune donnée métier n'est exposée.
## Tests d'intégration du chemin de création (CreateAsync)
En complément de la détection de schéma, des tests d'intégration réels couvrent
le chemin d'écriture `CreateAsync` sur les deux schémas (Batik et Omika) :
- `CreateAsync_Batik_PersistsAndRollsBack`
- `CreateAsync_Omika_PersistsAndRollsBack`
### Principe
1. Les mots de passe de fichiers (Extended Properties) sont résolus par
`HfSqlFileAccessResolver` pour les fichiers nécessaires au chemin Create
(`Client`, `ParametreMetier`, `Adresse`, `Client_Adresse`).
2. Une connexion physique OLE DB est ouverte avec ces mots de passe.
3. Une **transaction externe** est créée sur cette connexion.
4. `CreateAsync` est exécuté **dans cette transaction** via le repository
(Batik ou Omika).
5. Le client canonique retourné est vérifié (nom, identifiant non vide).
6. La transaction est **annulée (rollback)** : aucune trace n'est laissée en base.
### Pourquoi une transaction externe
Les repositories `BatikClientRepository` et `OmikaClientRepository` exposent une
surcharge `CreateAsync(command, DbTransaction?, cancellationToken)` qui réutilise
une transaction externe fournie par l'appelant. En production, la surcharge
standard `CreateAsync(command, cancellationToken)` est utilisée et une transaction
interne est créée puis commitée. Dans les tests, la transaction externe permet de
**vérifier la persistance réelle puis de l'annuler** sans polluer la base.
### Garanties
- Aucune donnée métier n'est laissée en base (rollback systématique).
- Aucun secret, aucune chaîne de connexion, aucun mot de passe n'est exposé.
- Les tests sont ignorés automatiquement si la configuration locale ou le
serveur sont indisponibles.