# 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 FROM ``` 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.