Migrer l’initialisation vers la couche Database #27

Closed
opened 2026-07-18 08:45:42 +02:00 by fy59 · 0 comments
Owner

Ticket #026 — Migrer l’initialisation vers la couche Database

Contexte

Le ticket #025 a introduit l’infrastructure principale de la couche Database :

  • contexte opaque Database ;
  • ouverture et fermeture des connexions ;
  • requêtes préparées avec DatabaseStatement ;
  • bindings et lecture typée ;
  • gestion des transactions ;
  • infrastructure d’erreurs.

Cependant, database_initialize() utilise encore directement plusieurs fonctions de l’API SQLite :

sqlite3_open_v2()
sqlite3_prepare_v2()
sqlite3_bind_text()
sqlite3_step()
sqlite3_reset()
sqlite3_clear_bindings()
sqlite3_finalize()
sqlite3_close()

La fonction exécute également directement les commandes SQL suivantes :

```sql

BEGIN IMMEDIATE;
COMMIT;
ROLLBACK;

De son côté, schema_install_v1() reçoit toujours directement un sqlite3 *, ce qui contourne l’abstraction Database.

Objectif

Réécrire l’initialisation d’une nouvelle enquête afin qu’elle utilise l’infrastructure créée au ticket #025.

L’initialisation doit rester atomique :

  • soit la base est entièrement initialisée ;
  • soit aucune donnée partielle n’est conservée.

Travail à réaliser

Adapter l’installation du schéma

Modifier la signature actuelle :

bool schema_install_v1(
    sqlite3 *database
);

afin qu’elle reçoive un contexte Database :

bool schema_install_v1(
    Database *database
);

L’installation du fichier SQL complet pourra continuer à utiliser sqlite3_exec() en interne, car le schéma contient plusieurs instructions SQL.

L’accès au handle SQLite devra passer par l’API interne :

database_get_handle()

La fonction ne devra réaliser ni COMMIT ni ROLLBACK.

Migrer l’insertion des métadonnées

Réécrire les fonctions responsables de l’insertion dans la table metadata avec DatabaseStatement.

Les opérations devront utiliser l’API suivante :

database_statement_prepare()
database_statement_bind_text()
database_statement_step()
database_statement_reset()
database_statement_clear_bindings()
database_statement_finalize()

Les métadonnées obligatoires restent :

schema_version
application
created_at
investigation_uuid

Une seule requête préparée devra pouvoir être réutilisée pour insérer les quatre métadonnées.

Migrer l’insertion de l’enquête

Réécrire l’insertion dans la table investigation avec DatabaseStatement.

Les champs insérés restent :

database_open()
database_transaction_begin()
schema_install_v1()
database_transaction_commit()
database_transaction_rollback()
database_close()

Le déroulement attendu est :

validation des paramètres
        ↓
création du timestamp UTC
        ↓
création de l’UUID
        ↓
ouverture de Database
        ↓
début de transaction
        ↓
installation du schéma V1
        ↓
insertion des métadonnées
        ↓
insertion de l’enquête
        ↓
commit
        ↓
fermeture de Database

Tout échec après le début de la transaction doit provoquer un rollback.

Utiliser l’infrastructure d’erreurs

Les erreurs rencontrées pendant :

  • l’installation du schéma ;
  • la préparation d’une requête ;
  • le binding d’un paramètre ;
  • l’exécution d’une requête ;
  • le début d’une transaction ;
  • le commit ;
  • le rollback ;

doivent être enregistrées dans le contexte Database lorsque celui-ci est disponible.

L’infrastructure interne existante pourra être utilisée :

database_set_error()
database_clear_error_internal()
DATABASE_ERROR_SQLITE
DATABASE_ERROR_INVALID_ARGUMENT
DATABASE_ERROR_INVALID_STATE

Nettoyer l’ancien code SQLite

Supprimer de la logique d’initialisation les appels directs à :

sqlite3_open_v2()
sqlite3_prepare_v2()
sqlite3_bind_text()
sqlite3_step()
sqlite3_reset()
sqlite3_clear_bindings()
sqlite3_finalize()
sqlite3_close()

Supprimer également les commandes manuelles :

BEGIN IMMEDIATE;
COMMIT;
ROLLBACK;

La fonction utilitaire database_execute_sql() pourra être conservée uniquement si elle reste nécessaire à database_open() pour l’activation des clés étrangères.

Mettre à jour la documentation publique

Dans include/database/database.h, supprimer la mention temporaire :

Cette fonction conserve temporairement son rôle actuel pendant le
refactoring du ticket #025.

La documentation de database_initialize() devra préciser que :

  • l’initialisation est transactionnelle ;
  • un échec provoque un rollback ;
  • la base est fermée avant le retour de la fonction.

Tests à ajouter ou adapter

Initialisation réussie

Vérifier qu’une initialisation valide crée :

  • le schéma V1 ;
  • les tables attendues ;
  • les métadonnées obligatoires ;
  • une seule ligne dans investigation ;
  • le bon nom d’enquête ;
  • le bon chemin racine ;
  • un UUID non vide ;
  • une date de création non vide ;
  • une date de modification non vide.

Paramètres invalides

Vérifier le refus des cas suivants :

database_path == NULL
database_path vide
investigation_name == NULL
investigation_name vide
investigation_root_path == NULL
investigation_root_path vide

Rollback

Provoquer un échec après le démarrage de la transaction.

Une seconde tentative d’initialisation sur une base déjà initialisée pourra être utilisée pour provoquer une erreur de contrainte ou de création de schéma.

Après l’échec, vérifier que :

  • aucune donnée partielle supplémentaire n’est conservée ;
  • aucune seconde enquête n’est ajoutée ;
  • les métadonnées existantes ne sont pas dupliquées ;
  • la transaction est annulée ;
  • la base reste lisible ;
  • la connexion peut être fermée proprement.

Régression

Tous les tests existants doivent rester valides :

InvestigationNode
InvestigationTreeModel
InvestigationTreeBuilder
InvestigationProject
Database
DatabaseStatement
DatabaseTransaction
DatabaseError

Critères d’acceptation

  • database_initialize() n’appelle plus directement sqlite3_open_v2().
  • database_initialize() utilise database_open().
  • database_initialize() utilise database_close().
  • Les transactions utilisent le module transaction.
  • Les insertions utilisent DatabaseStatement.
  • InvestigationNode Investigation schema_install_v1() reçoit un Database *.
    InvestigationNode
    Investigation schema_install_v1() reçoit un Database *.
  • schema_install_v1() récupère le handle avec l’API interne.
  • Aucun sqlite3_stmt * n’est manipulé dans le code d’initialisation.
  • Aucun BEGIN, COMMIT ou ROLLBACK manuel ne reste dans database.c.
  • Tout échec après le début de la transaction provoque un rollback.
  • Les erreurs sont enregistrées dans la couche Database.
  • Les tests de réussite sont valides.
  • Les tests de paramètres invalides sont valides.
  • Les tests de rollback sont valides.
  • Les tests de régression sont valides.
  • make réussit sans erreur.
  • make test réussit.
  • git diff --check ne retourne aucune erreur.

Hors périmètre

Ce ticket ne doit pas ajouter :

  • de CRUD métier ;
  • de dépôt ou repository métier ;
  • de migration entre plusieurs versions de schéma ;
  • de système GResource pour embarquer schema_v1.sql ;
  • de création automatique des dossiers parents ;
  • de modification du schéma SQL V1 ;
  • de nouvelles tables ;
  • de logique d’interface graphique ;
  • de nouvelles fonctionnalités utilisateur.

Fichiers principalement concernés

include/database/database.h
include/database/schema.h

src/database/database.c
src/database/database_internal.h
src/database/schema.c

tests/test_database.c

Makefile

Résultat attendu

À la fin du ticket, database_initialize() doit être un utilisateur normal de la couche Database.

La fonction ne doit plus contourner cette couche avec des appels SQLite directs.

L’initialisation d’une enquête doit être entièrement transactionnelle, testée et cohérente avec l’architecture mise en place au ticket #025.

Commit attendu

Une fois tous les critères d’acceptation validés, le ticket pourra être enregistré avec le commit suivant :

refactor(database): migrate initialization to database layer

Le commit doit principalement contenir :

include/database/database.h
include/database/schema.h

src/database/database.c
src/database/database_internal.h
src/database/schema.c

tests/test_database.c

Makefile

Avant le commit, exécuter :

make clean
make
make test
git diff --check
git status --short
# Ticket #026 — Migrer l’initialisation vers la couche Database ## Contexte Le ticket #025 a introduit l’infrastructure principale de la couche Database : - contexte opaque `Database` ; - ouverture et fermeture des connexions ; - requêtes préparées avec `DatabaseStatement` ; - bindings et lecture typée ; - gestion des transactions ; - infrastructure d’erreurs. Cependant, `database_initialize()` utilise encore directement plusieurs fonctions de l’API SQLite : ```c sqlite3_open_v2() sqlite3_prepare_v2() sqlite3_bind_text() sqlite3_step() sqlite3_reset() sqlite3_clear_bindings() sqlite3_finalize() sqlite3_close() La fonction exécute également directement les commandes SQL suivantes : ```sql BEGIN IMMEDIATE; COMMIT; ROLLBACK; ``` De son côté, `schema_install_v1()` reçoit toujours directement un `sqlite3 *`, ce qui contourne l’abstraction `Database`. ## Objectif Réécrire l’initialisation d’une nouvelle enquête afin qu’elle utilise l’infrastructure créée au ticket #025. L’initialisation doit rester atomique : - soit la base est entièrement initialisée ; - soit aucune donnée partielle n’est conservée. ## Travail à réaliser ### Adapter l’installation du schéma Modifier la signature actuelle : ```C bool schema_install_v1( sqlite3 *database ); ``` afin qu’elle reçoive un contexte Database : ```C bool schema_install_v1( Database *database ); ``` L’installation du fichier SQL complet pourra continuer à utiliser `sqlite3_exec()` en interne, car le schéma contient plusieurs instructions SQL. L’accès au handle SQLite devra passer par l’API interne : ```C database_get_handle() ``` La fonction ne devra réaliser ni `COMMIT` ni `ROLLBACK`. ### Migrer l’insertion des métadonnées Réécrire les fonctions responsables de l’insertion dans la table `metadata` avec `DatabaseStatement`. Les opérations devront utiliser l’API suivante : ```C database_statement_prepare() database_statement_bind_text() database_statement_step() database_statement_reset() database_statement_clear_bindings() database_statement_finalize() ``` Les métadonnées obligatoires restent : ``` schema_version application created_at investigation_uuid ``` Une seule requête préparée devra pouvoir être réutilisée pour insérer les quatre métadonnées. ### Migrer l’insertion de l’enquête Réécrire l’insertion dans la table `investigation` avec `DatabaseStatement`. Les champs insérés restent : ```C database_open() database_transaction_begin() schema_install_v1() database_transaction_commit() database_transaction_rollback() database_close() ``` Le déroulement attendu est : ``` validation des paramètres ↓ création du timestamp UTC ↓ création de l’UUID ↓ ouverture de Database ↓ début de transaction ↓ installation du schéma V1 ↓ insertion des métadonnées ↓ insertion de l’enquête ↓ commit ↓ fermeture de Database ``` Tout échec après le début de la transaction doit provoquer un rollback. ### Utiliser l’infrastructure d’erreurs Les erreurs rencontrées pendant : - l’installation du schéma ; - la préparation d’une requête ; - le binding d’un paramètre ; - l’exécution d’une requête ; - le début d’une transaction ; - le commit ; - le rollback ; doivent être enregistrées dans le contexte Database lorsque celui-ci est disponible. L’infrastructure interne existante pourra être utilisée : ```C database_set_error() database_clear_error_internal() ``` ```C DATABASE_ERROR_SQLITE ``` ```C DATABASE_ERROR_INVALID_ARGUMENT ``` ```C DATABASE_ERROR_INVALID_STATE ``` ### Nettoyer l’ancien code SQLite Supprimer de la logique d’initialisation les appels directs à : ```C sqlite3_open_v2() sqlite3_prepare_v2() sqlite3_bind_text() sqlite3_step() sqlite3_reset() sqlite3_clear_bindings() sqlite3_finalize() sqlite3_close() ``` Supprimer également les commandes manuelles : ```SQL BEGIN IMMEDIATE; COMMIT; ROLLBACK; ``` La fonction utilitaire `database_execute_sql()` pourra être conservée uniquement si elle reste nécessaire à `database_open()` pour l’activation des clés étrangères. ### Mettre à jour la documentation publique Dans `include/database/database.h`, supprimer la mention temporaire : ``` Cette fonction conserve temporairement son rôle actuel pendant le refactoring du ticket #025. ``` La documentation de `database_initialize()` devra préciser que : - l’initialisation est transactionnelle ; - un échec provoque un rollback ; - la base est fermée avant le retour de la fonction. ## Tests à ajouter ou adapter ### Initialisation réussie Vérifier qu’une initialisation valide crée : - le schéma V1 ; - les tables attendues ; - les métadonnées obligatoires ; - une seule ligne dans investigation ; - le bon nom d’enquête ; - le bon chemin racine ; - un UUID non vide ; - une date de création non vide ; - une date de modification non vide. ### Paramètres invalides Vérifier le refus des cas suivants : ``` database_path == NULL database_path vide investigation_name == NULL investigation_name vide investigation_root_path == NULL investigation_root_path vide ``` ### Rollback Provoquer un échec après le démarrage de la transaction. Une seconde tentative d’initialisation sur une base déjà initialisée pourra être utilisée pour provoquer une erreur de contrainte ou de création de schéma. Après l’échec, vérifier que : - aucune donnée partielle supplémentaire n’est conservée ; - aucune seconde enquête n’est ajoutée ; - les métadonnées existantes ne sont pas dupliquées ; - la transaction est annulée ; - la base reste lisible ; - la connexion peut être fermée proprement. ### Régression Tous les tests existants doivent rester valides : ``` InvestigationNode InvestigationTreeModel InvestigationTreeBuilder InvestigationProject Database DatabaseStatement DatabaseTransaction DatabaseError ``` ## Critères d’acceptation - [x] `database_initialize()` n’appelle plus directement `sqlite3_open_v2()`. - [x] `database_initialize()` utilise `database_open()`. - [x] `database_initialize()` utilise `database_close()`. - [x] Les transactions utilisent le module `transaction`. - [x] Les insertions utilisent `DatabaseStatement`. - [x] `InvestigationNode` Investigation `schema_install_v1()` reçoit un `Database *`. InvestigationNode Investigation `schema_install_v1()` reçoit un `Database *`. - [x] `schema_install_v1()` récupère le handle avec l’API interne. - [x] Aucun `sqlite3_stmt *` n’est manipulé dans le code d’initialisation. - [x] Aucun `BEGIN`, `COMMIT` ou `ROLLBACK` manuel ne reste dans `database.c`. - [x] Tout échec après le début de la transaction provoque un rollback. - [x] Les erreurs sont enregistrées dans la couche Database. - [x] Les tests de réussite sont valides. - [x] Les tests de paramètres invalides sont valides. - [x] Les tests de rollback sont valides. - [x] Les tests de régression sont valides. - [x] `make` réussit sans erreur. - [x] `make test` réussit. - [x] `git diff --check` ne retourne aucune erreur. ## Hors périmètre Ce ticket ne doit pas ajouter : - de CRUD métier ; - de dépôt ou repository métier ; - de migration entre plusieurs versions de schéma ; - de système GResource pour embarquer `schema_v1.sql` ; - de création automatique des dossiers parents ; - de modification du schéma SQL V1 ; - de nouvelles tables ; - de logique d’interface graphique ; - de nouvelles fonctionnalités utilisateur. ## Fichiers principalement concernés ```text include/database/database.h include/database/schema.h src/database/database.c src/database/database_internal.h src/database/schema.c tests/test_database.c Makefile ``` ## Résultat attendu À la fin du ticket, `database_initialize()` doit être un utilisateur normal de la couche Database. La fonction ne doit plus contourner cette couche avec des appels SQLite directs. L’initialisation d’une enquête doit être entièrement transactionnelle, testée et cohérente avec l’architecture mise en place au ticket #025. ## Commit attendu Une fois tous les critères d’acceptation validés, le ticket pourra être enregistré avec le commit suivant : ```text refactor(database): migrate initialization to database layer ``` Le commit doit principalement contenir : ``` include/database/database.h include/database/schema.h src/database/database.c src/database/database_internal.h src/database/schema.c tests/test_database.c Makefile ``` Avant le commit, exécuter : ```bash make clean make make test git diff --check git status --short ```
fy59 closed this issue 2026-07-18 08:46:36 +02:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: fy59/labfy-investigation#27
No description provided.