feat(database): finalize database architecture v1
This commit is contained in:
parent
fbe1cd11fb
commit
142088da87
16 changed files with 5287 additions and 56 deletions
6
Makefile
6
Makefile
|
|
@ -62,12 +62,14 @@ $(TEST_TREE_BUILDER): \
|
||||||
$(TEST_PROJECT): \
|
$(TEST_PROJECT): \
|
||||||
tests/test_investigation_project.c \
|
tests/test_investigation_project.c \
|
||||||
src/core/investigation_project.c \
|
src/core/investigation_project.c \
|
||||||
src/database/database.c
|
src/database/database.c \
|
||||||
|
src/database/schema.c
|
||||||
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
||||||
|
|
||||||
$(TEST_DATABASE): \
|
$(TEST_DATABASE): \
|
||||||
tests/test_database.c \
|
tests/test_database.c \
|
||||||
src/database/database.c
|
src/database/database.c \
|
||||||
|
src/database/schema.c
|
||||||
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
$(CC) $(TEST_CFLAGS) $^ -o $@ $(TEST_LDFLAGS) -lsqlite3
|
||||||
|
|
||||||
test: \
|
test: \
|
||||||
|
|
|
||||||
1231
database/schema_v1.sql
Normal file
1231
database/schema_v1.sql
Normal file
File diff suppressed because it is too large
Load diff
302
docs/CONVENTIONS.md
Normal file
302
docs/CONVENTIONS.md
Normal file
|
|
@ -0,0 +1,302 @@
|
||||||
|
# Conventions de développement
|
||||||
|
|
||||||
|
Version : 1.0
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Philosophie
|
||||||
|
|
||||||
|
Labfy Investigation est développé comme un logiciel d'enquête numérique.
|
||||||
|
|
||||||
|
Les choix d'architecture privilégient :
|
||||||
|
|
||||||
|
- la lisibilité ;
|
||||||
|
- la maintenabilité ;
|
||||||
|
- la robustesse ;
|
||||||
|
- la traçabilité ;
|
||||||
|
- la simplicité.
|
||||||
|
|
||||||
|
Une solution simple et cohérente est toujours préférée à une solution
|
||||||
|
complexe.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Langue
|
||||||
|
|
||||||
|
Le domaine métier est écrit en français.
|
||||||
|
|
||||||
|
Exemples :
|
||||||
|
|
||||||
|
- preuve
|
||||||
|
- entite
|
||||||
|
- personne
|
||||||
|
- source
|
||||||
|
- chronologie
|
||||||
|
- journal
|
||||||
|
- hypothese
|
||||||
|
- recherche
|
||||||
|
|
||||||
|
Les standards techniques conservent leur nom d'origine.
|
||||||
|
|
||||||
|
Exemples :
|
||||||
|
|
||||||
|
- uuid
|
||||||
|
- sha256
|
||||||
|
- mime_type
|
||||||
|
- sqlite
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- relative_path
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Architecture
|
||||||
|
|
||||||
|
Le projet est organisé par domaine métier.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```
|
||||||
|
preuve
|
||||||
|
↓
|
||||||
|
preuve.h
|
||||||
|
preuve.c
|
||||||
|
|
||||||
|
entite
|
||||||
|
↓
|
||||||
|
entite.h
|
||||||
|
entite.c
|
||||||
|
```
|
||||||
|
|
||||||
|
Chaque module possède une responsabilité unique.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# SQL
|
||||||
|
|
||||||
|
Une table représente un objet métier.
|
||||||
|
|
||||||
|
Une table importante possède :
|
||||||
|
|
||||||
|
- une structure C ;
|
||||||
|
- un module C ;
|
||||||
|
- des tests.
|
||||||
|
|
||||||
|
Les objets métier utilisent :
|
||||||
|
|
||||||
|
```
|
||||||
|
TEXT PRIMARY KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
contenant un UUID.
|
||||||
|
|
||||||
|
Les tables de référence utilisent :
|
||||||
|
|
||||||
|
```
|
||||||
|
INTEGER PRIMARY KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# UUID
|
||||||
|
|
||||||
|
Tous les objets métier utilisent un UUID.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```
|
||||||
|
preuve
|
||||||
|
entite
|
||||||
|
personne
|
||||||
|
source
|
||||||
|
chronologie
|
||||||
|
journal
|
||||||
|
```
|
||||||
|
|
||||||
|
Il n'existe pas simultanément :
|
||||||
|
|
||||||
|
```
|
||||||
|
id
|
||||||
|
uuid
|
||||||
|
```
|
||||||
|
|
||||||
|
La colonne :
|
||||||
|
|
||||||
|
```
|
||||||
|
id
|
||||||
|
```
|
||||||
|
|
||||||
|
contient directement l'UUID.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Dates
|
||||||
|
|
||||||
|
Toutes les dates sont enregistrées en UTC.
|
||||||
|
|
||||||
|
Format :
|
||||||
|
|
||||||
|
```
|
||||||
|
YYYY-MM-DDTHH:MM:SSZ
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Chemins
|
||||||
|
|
||||||
|
Les chemins sont toujours relatifs à la racine de l'enquête.
|
||||||
|
|
||||||
|
Autorisé :
|
||||||
|
|
||||||
|
```
|
||||||
|
01_Preuves_Originales/Documents/facture.pdf
|
||||||
|
```
|
||||||
|
|
||||||
|
Interdit :
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/user/Documents/...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Suppression
|
||||||
|
|
||||||
|
Les objets métier importants ne sont jamais supprimés immédiatement.
|
||||||
|
|
||||||
|
Une suppression est une modification d'état.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```
|
||||||
|
active
|
||||||
|
archived
|
||||||
|
deleted
|
||||||
|
```
|
||||||
|
|
||||||
|
Une purge physique éventuelle devra être explicite.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Nommage
|
||||||
|
|
||||||
|
Le SQL utilise :
|
||||||
|
|
||||||
|
- snake_case
|
||||||
|
- minuscules
|
||||||
|
- aucun accent
|
||||||
|
- aucun espace
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Code C
|
||||||
|
|
||||||
|
Norme :
|
||||||
|
|
||||||
|
```
|
||||||
|
C17
|
||||||
|
```
|
||||||
|
|
||||||
|
Variables :
|
||||||
|
|
||||||
|
Toujours explicites.
|
||||||
|
|
||||||
|
Autorisé :
|
||||||
|
|
||||||
|
```c
|
||||||
|
relative_path
|
||||||
|
description
|
||||||
|
commentaire
|
||||||
|
created_at
|
||||||
|
```
|
||||||
|
|
||||||
|
Interdit :
|
||||||
|
|
||||||
|
```c
|
||||||
|
path
|
||||||
|
desc
|
||||||
|
comm
|
||||||
|
crt
|
||||||
|
```
|
||||||
|
|
||||||
|
Les fonctions utilisent le nom du module.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```c
|
||||||
|
preuve_create()
|
||||||
|
preuve_load()
|
||||||
|
preuve_update()
|
||||||
|
preuve_delete()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Structures
|
||||||
|
|
||||||
|
Une structure représente un objet métier.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef struct Preuve Preuve;
|
||||||
|
```
|
||||||
|
|
||||||
|
Les structures publiques sont opaques lorsque cela est possible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
Toute nouvelle fonctionnalité importante possède un test.
|
||||||
|
|
||||||
|
Le développement suit toujours l'ordre :
|
||||||
|
|
||||||
|
```
|
||||||
|
Conception
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Implémentation
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Tests
|
||||||
|
|
||||||
|
↓
|
||||||
|
|
||||||
|
Commit
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Git
|
||||||
|
|
||||||
|
Un ticket terminé correspond à un commit.
|
||||||
|
|
||||||
|
Le message de commit est rédigé en anglais.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```
|
||||||
|
feat(database): initialize investigation database
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
|
Les décisions importantes sont documentées.
|
||||||
|
|
||||||
|
Les changements de schéma SQLite sont précédés d'un audit.
|
||||||
|
|
||||||
|
Aucune décision importante ne doit exister uniquement dans le code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Objectif
|
||||||
|
|
||||||
|
Le projet doit rester compréhensible plusieurs années après sa création.
|
||||||
|
|
||||||
|
La priorité est donnée à la qualité du code plutôt qu'à la rapidité de
|
||||||
|
développement.
|
||||||
2909
docs/database/SCHEMA_AUDIT_V1.md
Normal file
2909
docs/database/SCHEMA_AUDIT_V1.md
Normal file
File diff suppressed because it is too large
Load diff
643
docs/tickets/closed/TICKET-023.md
Normal file
643
docs/tickets/closed/TICKET-023.md
Normal file
|
|
@ -0,0 +1,643 @@
|
||||||
|
# Ticket #023
|
||||||
|
|
||||||
|
## Titre
|
||||||
|
|
||||||
|
Consolider le schéma métier initial de l'enquête.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
|
||||||
|
Transformer le schéma SQLite préparé lors des premières phases du projet en
|
||||||
|
un schéma métier officiel, cohérent, documenté et testable.
|
||||||
|
|
||||||
|
La base existante sert de fondation.
|
||||||
|
|
||||||
|
Le travail ne consiste pas à repartir de zéro, mais à :
|
||||||
|
|
||||||
|
- conserver les concepts métier déjà définis ;
|
||||||
|
- corriger les incohérences ;
|
||||||
|
- renforcer les contraintes ;
|
||||||
|
- uniformiser les conventions ;
|
||||||
|
- intégrer le schéma au module `Database`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Base de travail
|
||||||
|
|
||||||
|
La base historique contient notamment les tables suivantes :
|
||||||
|
|
||||||
|
```text
|
||||||
|
preuves
|
||||||
|
entites
|
||||||
|
personnes
|
||||||
|
chronologie
|
||||||
|
sources
|
||||||
|
recherche
|
||||||
|
hypotheses
|
||||||
|
journal
|
||||||
|
tags
|
||||||
|
types_preuve
|
||||||
|
types_entite
|
||||||
|
types_source
|
||||||
|
types_outils
|
||||||
|
associations
|
||||||
|
personnes_entites
|
||||||
|
entite_tags
|
||||||
|
preuves_tag
|
||||||
|
```
|
||||||
|
|
||||||
|
Les tables créées au ticket #022 restent également obligatoires :
|
||||||
|
|
||||||
|
```text
|
||||||
|
metadata
|
||||||
|
investigation
|
||||||
|
```
|
||||||
|
|
||||||
|
Le schéma officiel doit donc préserver ces concepts tout en les consolidant.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```text
|
||||||
|
InvestigationProject
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Database
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Schéma SQLite versionné
|
||||||
|
│
|
||||||
|
├── Métadonnées
|
||||||
|
├── Enquête
|
||||||
|
├── Preuves
|
||||||
|
├── Entités
|
||||||
|
├── Personnes
|
||||||
|
├── Sources
|
||||||
|
├── Chronologie
|
||||||
|
├── Recherches
|
||||||
|
├── Hypothèses
|
||||||
|
├── Journal
|
||||||
|
└── Tags et relations
|
||||||
|
```
|
||||||
|
|
||||||
|
Le module `Database` reste le seul autorisé à exécuter du SQL.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Décisions de conception à officialiser
|
||||||
|
|
||||||
|
### Identifiants
|
||||||
|
|
||||||
|
Les entités métier utiliseront des identifiants texte de type UUID.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```text
|
||||||
|
550e8400-e29b-41d4-a716-446655440000
|
||||||
|
```
|
||||||
|
|
||||||
|
Les identifiants sont générés par l'application avec :
|
||||||
|
|
||||||
|
```c
|
||||||
|
g_uuid_string_random()
|
||||||
|
```
|
||||||
|
|
||||||
|
Les tables de référence simples peuvent utiliser des identifiants entiers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Dates
|
||||||
|
|
||||||
|
Les dates techniques sont stockées en UTC au format ISO 8601 :
|
||||||
|
|
||||||
|
```text
|
||||||
|
YYYY-MM-DDTHH:MM:SSZ
|
||||||
|
```
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```text
|
||||||
|
2026-07-15T08:42:17Z
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Nommage
|
||||||
|
|
||||||
|
Les noms SQL utilisent uniquement :
|
||||||
|
|
||||||
|
- des minuscules ;
|
||||||
|
- du `snake_case` ;
|
||||||
|
- aucun accent ;
|
||||||
|
- aucun espace.
|
||||||
|
|
||||||
|
Les noms des tables de liaison sont uniformisés.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```text
|
||||||
|
preuve_tags
|
||||||
|
entite_tags
|
||||||
|
personne_entites
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucune forme singulier/pluriel incohérente ne doit subsister.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Clés étrangères
|
||||||
|
|
||||||
|
Toutes les relations métier doivent utiliser des clés étrangères explicites.
|
||||||
|
|
||||||
|
Le module `Database` doit activer :
|
||||||
|
|
||||||
|
```sql
|
||||||
|
PRAGMA foreign_keys = ON;
|
||||||
|
```
|
||||||
|
|
||||||
|
à chaque ouverture de connexion.
|
||||||
|
|
||||||
|
Les comportements `ON DELETE` doivent être décidés pour chaque relation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Tables de liaison
|
||||||
|
|
||||||
|
Chaque table de liaison doit empêcher les doublons grâce à :
|
||||||
|
|
||||||
|
- une clé primaire composite ;
|
||||||
|
- ou une contrainte `UNIQUE`.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```sql
|
||||||
|
PRIMARY KEY (preuve_id, tag_id)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tables métier à consolider
|
||||||
|
|
||||||
|
### `preuves`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- représenter un élément de preuve ;
|
||||||
|
- mémoriser son nom ;
|
||||||
|
- son chemin relatif ;
|
||||||
|
- son type ;
|
||||||
|
- sa description ;
|
||||||
|
- ses dates ;
|
||||||
|
- son hash éventuel ;
|
||||||
|
- son statut.
|
||||||
|
|
||||||
|
Contraintes minimales :
|
||||||
|
|
||||||
|
- identifiant obligatoire ;
|
||||||
|
- nom obligatoire ;
|
||||||
|
- chemin relatif obligatoire ;
|
||||||
|
- type obligatoire ;
|
||||||
|
- date de création obligatoire ;
|
||||||
|
- chemin unique au sein d'une enquête.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `entites`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- représenter une entité identifiée pendant l'enquête.
|
||||||
|
|
||||||
|
Exemples :
|
||||||
|
|
||||||
|
- adresse email ;
|
||||||
|
- compte bancaire ;
|
||||||
|
- profil social ;
|
||||||
|
- pseudonyme ;
|
||||||
|
- téléphone ;
|
||||||
|
- document d'identité.
|
||||||
|
|
||||||
|
Contraintes minimales :
|
||||||
|
|
||||||
|
- identifiant obligatoire ;
|
||||||
|
- type obligatoire ;
|
||||||
|
- valeur obligatoire ;
|
||||||
|
- date de création obligatoire.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `personnes`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- représenter une personne physique ou un profil humain étudié.
|
||||||
|
|
||||||
|
Le modèle ne doit pas obliger à connaître l'identité civile complète.
|
||||||
|
|
||||||
|
Une personne peut n'avoir qu'un pseudonyme ou une désignation temporaire.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `sources`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- représenter l'origine d'une information ou d'une preuve.
|
||||||
|
|
||||||
|
Exemples :
|
||||||
|
|
||||||
|
- site web ;
|
||||||
|
- email ;
|
||||||
|
- réseau social ;
|
||||||
|
- document ;
|
||||||
|
- témoignage ;
|
||||||
|
- outil OSINT.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `chronologie`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- mémoriser les événements importants de l'enquête ;
|
||||||
|
- relier éventuellement un événement à une preuve, une entité ou une source.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `recherches`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- documenter une opération de recherche ;
|
||||||
|
- mémoriser la requête ;
|
||||||
|
- l'outil employé ;
|
||||||
|
- la date ;
|
||||||
|
- le résultat ;
|
||||||
|
- les observations.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `hypotheses`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- enregistrer une hypothèse de travail ;
|
||||||
|
- mémoriser son statut ;
|
||||||
|
- sa justification ;
|
||||||
|
- les éléments qui la soutiennent ou la contredisent.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `journal`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- conserver la trace des actions significatives réalisées dans l'enquête.
|
||||||
|
|
||||||
|
Exemples :
|
||||||
|
|
||||||
|
- création d'une preuve ;
|
||||||
|
- modification d'une entité ;
|
||||||
|
- calcul d'un hash ;
|
||||||
|
- génération d'un rapport ;
|
||||||
|
- import d'un fichier.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `tags`
|
||||||
|
|
||||||
|
Responsabilité :
|
||||||
|
|
||||||
|
- permettre une classification libre des preuves et des entités.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tables de référence
|
||||||
|
|
||||||
|
Les tables suivantes doivent être consolidées :
|
||||||
|
|
||||||
|
```text
|
||||||
|
types_preuve
|
||||||
|
types_entite
|
||||||
|
types_source
|
||||||
|
types_outils
|
||||||
|
```
|
||||||
|
|
||||||
|
Elles doivent comporter au minimum :
|
||||||
|
|
||||||
|
```sql
|
||||||
|
id INTEGER PRIMARY KEY
|
||||||
|
code TEXT NOT NULL UNIQUE
|
||||||
|
label TEXT NOT NULL
|
||||||
|
description TEXT
|
||||||
|
```
|
||||||
|
|
||||||
|
Les valeurs initiales sont insérées lors de la création de la base.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tables de liaison
|
||||||
|
|
||||||
|
Les relations suivantes doivent être prévues :
|
||||||
|
|
||||||
|
```text
|
||||||
|
preuve_tags
|
||||||
|
entite_tags
|
||||||
|
personne_entites
|
||||||
|
```
|
||||||
|
|
||||||
|
Le schéma existant contient également une table générique :
|
||||||
|
|
||||||
|
```text
|
||||||
|
associations
|
||||||
|
```
|
||||||
|
|
||||||
|
Cette table doit être auditée avant conservation.
|
||||||
|
|
||||||
|
Elle ne doit être gardée que si son rôle est clairement défini et ne fait pas
|
||||||
|
doublon avec des relations spécialisées.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Audit obligatoire
|
||||||
|
|
||||||
|
Avant d'écrire le schéma définitif, chaque table de la base historique doit
|
||||||
|
être classée dans l'une des catégories suivantes :
|
||||||
|
|
||||||
|
```text
|
||||||
|
CONSERVER
|
||||||
|
MODIFIER
|
||||||
|
RENOMMER
|
||||||
|
FUSIONNER
|
||||||
|
SUPPRIMER
|
||||||
|
```
|
||||||
|
|
||||||
|
La décision doit être documentée dans :
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs/database/SCHEMA_AUDIT_V1.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Le document doit contenir au minimum :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Nom historique
|
||||||
|
Décision
|
||||||
|
Nom final
|
||||||
|
Justification
|
||||||
|
Modifications prévues
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Organisation du module Database
|
||||||
|
|
||||||
|
Le code SQL est organisé par domaine métier.
|
||||||
|
|
||||||
|
```
|
||||||
|
include/
|
||||||
|
└── database/
|
||||||
|
├── database.h
|
||||||
|
├── schema.h
|
||||||
|
├── preuve.h
|
||||||
|
├── entite.h
|
||||||
|
├── personne.h
|
||||||
|
├── source.h
|
||||||
|
├── chronologie.h
|
||||||
|
├── recherche.h
|
||||||
|
├── hypothese.h
|
||||||
|
├── journal.h
|
||||||
|
├── tag.h
|
||||||
|
├── type_preuve.h
|
||||||
|
├── type_entite.h
|
||||||
|
├── type_source.h
|
||||||
|
└── type_outil.h
|
||||||
|
|
||||||
|
src/
|
||||||
|
└── database/
|
||||||
|
├── database.c
|
||||||
|
├── schema.c
|
||||||
|
├── preuve.c
|
||||||
|
├── entite.c
|
||||||
|
├── personne.c
|
||||||
|
├── source.c
|
||||||
|
├── chronologie.c
|
||||||
|
├── recherche.c
|
||||||
|
├── hypothese.c
|
||||||
|
├── journal.c
|
||||||
|
├── tag.c
|
||||||
|
├── type_preuve.c
|
||||||
|
├── type_entite.c
|
||||||
|
├── type_source.c
|
||||||
|
└── type_outil.c
|
||||||
|
|
||||||
|
database/
|
||||||
|
├── schema_v1.sql
|
||||||
|
├── indexes.sql
|
||||||
|
├── triggers.sql
|
||||||
|
└── reference_data.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Responsabilités
|
||||||
|
|
||||||
|
`database.c`
|
||||||
|
|
||||||
|
- ouverture de SQLite ;
|
||||||
|
- fermeture ;
|
||||||
|
- transactions ;
|
||||||
|
- erreurs ;
|
||||||
|
- point d'entrée du module Database.
|
||||||
|
|
||||||
|
`schema.c`
|
||||||
|
|
||||||
|
- installation du schéma ;
|
||||||
|
- migrations ;
|
||||||
|
- exécution des scripts SQL.
|
||||||
|
|
||||||
|
Chaque module métier est responsable exclusivement de son objet métier.
|
||||||
|
|
||||||
|
Exemple :
|
||||||
|
|
||||||
|
```
|
||||||
|
preuve.c
|
||||||
|
```
|
||||||
|
|
||||||
|
gère uniquement :
|
||||||
|
|
||||||
|
- création ;
|
||||||
|
- lecture ;
|
||||||
|
- modification ;
|
||||||
|
- suppression logique ;
|
||||||
|
- gestion des tags de la preuve.
|
||||||
|
|
||||||
|
Les tables de liaison simples ne possèdent pas de module dédié.
|
||||||
|
|
||||||
|
Exemples :
|
||||||
|
|
||||||
|
```
|
||||||
|
preuve_tags
|
||||||
|
personne_entites
|
||||||
|
entite_tags
|
||||||
|
```
|
||||||
|
|
||||||
|
Leur manipulation est réalisée par le module métier correspondant.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Intégration dans `Database`
|
||||||
|
|
||||||
|
Le module `database_initialize()` doit exécuter le schéma officiel contenu
|
||||||
|
dans :
|
||||||
|
|
||||||
|
```text
|
||||||
|
database/schema_v1.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
Deux approches sont acceptables :
|
||||||
|
|
||||||
|
1. intégrer le schéma au binaire via une ressource GLib ;
|
||||||
|
2. générer une chaîne C depuis le fichier SQL lors de la compilation.
|
||||||
|
|
||||||
|
Le logiciel installé ne doit pas dépendre d'un chemin relatif fragile vers le
|
||||||
|
dépôt source.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principe d'organisation
|
||||||
|
|
||||||
|
Une table métier importante implique systématiquement :
|
||||||
|
|
||||||
|
- une structure C ;
|
||||||
|
- un module C ;
|
||||||
|
- des tests ;
|
||||||
|
- une documentation.
|
||||||
|
|
||||||
|
La correspondance est la suivante :
|
||||||
|
|
||||||
|
| SQL | C |
|
||||||
|
|-----|---|
|
||||||
|
| preuves | preuve.c |
|
||||||
|
| entites | entite.c |
|
||||||
|
| personnes | personne.c |
|
||||||
|
| sources | source.c |
|
||||||
|
| chronologie | chronologie.c |
|
||||||
|
| journal | journal.c |
|
||||||
|
| recherches | recherche.c |
|
||||||
|
| hypotheses | hypothese.c |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Version du schéma
|
||||||
|
|
||||||
|
Le numéro de version reste :
|
||||||
|
|
||||||
|
```text
|
||||||
|
1
|
||||||
|
```
|
||||||
|
|
||||||
|
tant que Labfy Investigation n'a pas produit de base officiellement publiée.
|
||||||
|
|
||||||
|
Une fois le schéma V1 considéré comme stable et distribué, toute modification
|
||||||
|
incompatible nécessitera :
|
||||||
|
|
||||||
|
- une nouvelle version ;
|
||||||
|
- une migration dédiée ;
|
||||||
|
- une mise à jour de `schema_version`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hors périmètre
|
||||||
|
|
||||||
|
Ce ticket ne doit pas :
|
||||||
|
|
||||||
|
- développer les fonctions CRUD ;
|
||||||
|
- créer les structures C `Preuve`, `Entite` ou `Personne` ;
|
||||||
|
- connecter les tables à GTK ;
|
||||||
|
- importer les anciennes données automatiquement ;
|
||||||
|
- créer les migrations V2 ;
|
||||||
|
- produire un rapport ;
|
||||||
|
- ajouter la recherche plein texte.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contraintes techniques
|
||||||
|
|
||||||
|
- C17 ;
|
||||||
|
- SQLite3 ;
|
||||||
|
- GLib ;
|
||||||
|
- aucune dépendance GTK ;
|
||||||
|
- toutes les tables utilisent des contraintes explicites ;
|
||||||
|
- toutes les clés étrangères sont documentées ;
|
||||||
|
- toutes les tables de liaison empêchent les doublons ;
|
||||||
|
- aucun SQL métier hors du module `Database` ;
|
||||||
|
- aucun identifiant généré par SQLite pour les objets métier en UUID ;
|
||||||
|
- compilation sans warning.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Faire évoluer :
|
||||||
|
|
||||||
|
```text
|
||||||
|
tests/test_database.c
|
||||||
|
```
|
||||||
|
|
||||||
|
Les tests doivent vérifier :
|
||||||
|
|
||||||
|
- la présence de toutes les tables officielles ;
|
||||||
|
- la présence des tables de référence ;
|
||||||
|
- l'insertion des valeurs initiales ;
|
||||||
|
- l'activation des clés étrangères ;
|
||||||
|
- le refus d'une clé étrangère invalide ;
|
||||||
|
- le refus d'un doublon dans une table de liaison ;
|
||||||
|
- le refus des colonnes obligatoires manquantes ;
|
||||||
|
- l'unicité des codes des tables de référence ;
|
||||||
|
- la valeur `schema_version = 1` ;
|
||||||
|
- l'intégrité SQLite avec :
|
||||||
|
|
||||||
|
```sql
|
||||||
|
PRAGMA integrity_check;
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critères d'acceptation
|
||||||
|
|
||||||
|
- [ ] Le schéma historique a été audité.
|
||||||
|
- [ ] Chaque table possède une décision documentée.
|
||||||
|
- [ ] Un schéma V1 officiel existe.
|
||||||
|
- [ ] Les conventions de nommage sont uniformes.
|
||||||
|
- [ ] Toutes les clés primaires sont explicites.
|
||||||
|
- [ ] Toutes les clés étrangères sont explicites.
|
||||||
|
- [ ] Les relations empêchent les doublons.
|
||||||
|
- [ ] Les colonnes obligatoires utilisent `NOT NULL`.
|
||||||
|
- [ ] Les tables de référence sont initialisées.
|
||||||
|
- [ ] `database_initialize()` installe le schéma complet.
|
||||||
|
- [ ] `PRAGMA integrity_check` retourne `ok`.
|
||||||
|
- [ ] Tous les tests restent valides.
|
||||||
|
- [ ] Aucune dépendance GTK.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Livrables
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs/database/SCHEMA_AUDIT_V1.md
|
||||||
|
database/schema_v1.sql
|
||||||
|
include/database/database.h
|
||||||
|
src/database/database.c
|
||||||
|
tests/test_database.c
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Commit attendu
|
||||||
|
|
||||||
|
```text
|
||||||
|
feat(database): consolidate initial investigation schema
|
||||||
|
```
|
||||||
|
|
@ -11,19 +11,10 @@
|
||||||
/**
|
/**
|
||||||
* @brief Initialise la base SQLite d'une enquête.
|
* @brief Initialise la base SQLite d'une enquête.
|
||||||
*
|
*
|
||||||
* La fonction crée ou ouvre le fichier SQLite indiqué, puis initialise
|
* La fonction crée ou ouvre le fichier SQLite indiqué, installe le schéma
|
||||||
* transactionnellement le schéma minimal de l'enquête.
|
* courant, puis enregistre les métadonnées de l'enquête.
|
||||||
*
|
*
|
||||||
* Les informations suivantes sont enregistrées :
|
* Aucun handle SQLite n'est exposé au code appelant.
|
||||||
*
|
|
||||||
* - version du schéma ;
|
|
||||||
* - nom de l'application ;
|
|
||||||
* - date de création UTC ;
|
|
||||||
* - UUID de l'enquête ;
|
|
||||||
* - nom de l'enquête ;
|
|
||||||
* - chemin racine de l'enquête.
|
|
||||||
*
|
|
||||||
* Aucun handle sqlite3 n'est exposé au code appelant.
|
|
||||||
*
|
*
|
||||||
* @param database_path
|
* @param database_path
|
||||||
* Chemin complet du fichier Enquete.sqlite.
|
* Chemin complet du fichier Enquete.sqlite.
|
||||||
|
|
|
||||||
34
include/database/schema.h
Normal file
34
include/database/schema.h
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file schema.h
|
||||||
|
* @brief Interface interne d'installation du schéma SQLite.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef LABFY_INVESTIGATION_SCHEMA_H
|
||||||
|
#define LABFY_INVESTIGATION_SCHEMA_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Installe le schéma SQLite V1 dans une base ouverte.
|
||||||
|
*
|
||||||
|
* La connexion doit être valide et une transaction doit déjà être active.
|
||||||
|
*
|
||||||
|
* Cette fonction crée :
|
||||||
|
*
|
||||||
|
* - les tables ;
|
||||||
|
* - les index ;
|
||||||
|
* - les valeurs de référence.
|
||||||
|
*
|
||||||
|
* Elle ne réalise ni COMMIT ni ROLLBACK.
|
||||||
|
*
|
||||||
|
* @param database Connexion SQLite ouverte.
|
||||||
|
*
|
||||||
|
* @return true si le schéma a été correctement installé, sinon false.
|
||||||
|
*/
|
||||||
|
bool schema_install_v1(
|
||||||
|
sqlite3 *database
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
Binary file not shown.
8
resources/database.gresource.xml
Normal file
8
resources/database.gresource.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/com/labfytools/investigation/database">
|
||||||
|
<file alias="schema_v1.sql">
|
||||||
|
../database/schema_v1.sql
|
||||||
|
</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
|
#include "database/schema.h"
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
|
@ -18,28 +19,6 @@
|
||||||
*/
|
*/
|
||||||
#define DATABASE_APPLICATION_NAME "Labfy Investigation"
|
#define DATABASE_APPLICATION_NAME "Labfy Investigation"
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Crée la table contenant les métadonnées de l'enquête.
|
|
||||||
*/
|
|
||||||
static const char *const database_create_metadata_table_sql =
|
|
||||||
"CREATE TABLE metadata"
|
|
||||||
"("
|
|
||||||
" key TEXT PRIMARY KEY,"
|
|
||||||
" value TEXT NOT NULL"
|
|
||||||
");";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Crée la table représentant l'enquête courante.
|
|
||||||
*/
|
|
||||||
static const char *const database_create_investigation_table_sql =
|
|
||||||
"CREATE TABLE investigation"
|
|
||||||
"("
|
|
||||||
" id INTEGER PRIMARY KEY CHECK (id = 1),"
|
|
||||||
" name TEXT NOT NULL,"
|
|
||||||
" root_path TEXT NOT NULL,"
|
|
||||||
" created_at TEXT NOT NULL"
|
|
||||||
");";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Requête d'insertion d'une métadonnée.
|
* @brief Requête d'insertion d'une métadonnée.
|
||||||
*/
|
*/
|
||||||
|
|
@ -55,11 +34,13 @@ static const char *const database_insert_investigation_sql =
|
||||||
" id,"
|
" id,"
|
||||||
" name,"
|
" name,"
|
||||||
" root_path,"
|
" root_path,"
|
||||||
" created_at"
|
" created_at,"
|
||||||
|
" updated_at"
|
||||||
")"
|
")"
|
||||||
"VALUES"
|
"VALUES"
|
||||||
"("
|
"("
|
||||||
" 1,"
|
" ?,"
|
||||||
|
" ?,"
|
||||||
" ?,"
|
" ?,"
|
||||||
" ?,"
|
" ?,"
|
||||||
" ?"
|
" ?"
|
||||||
|
|
@ -319,6 +300,7 @@ static bool database_insert_all_metadata(
|
||||||
*/
|
*/
|
||||||
static bool database_insert_investigation(
|
static bool database_insert_investigation(
|
||||||
sqlite3 *database,
|
sqlite3 *database,
|
||||||
|
const char *investigation_uuid,
|
||||||
const char *investigation_name,
|
const char *investigation_name,
|
||||||
const char *investigation_root_path,
|
const char *investigation_root_path,
|
||||||
const char *created_at
|
const char *created_at
|
||||||
|
|
@ -329,6 +311,7 @@ static bool database_insert_investigation(
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
if (database == NULL ||
|
if (database == NULL ||
|
||||||
|
investigation_uuid == NULL ||
|
||||||
investigation_name == NULL ||
|
investigation_name == NULL ||
|
||||||
investigation_root_path == NULL ||
|
investigation_root_path == NULL ||
|
||||||
created_at == NULL)
|
created_at == NULL)
|
||||||
|
|
@ -357,7 +340,7 @@ static bool database_insert_investigation(
|
||||||
result = sqlite3_bind_text(
|
result = sqlite3_bind_text(
|
||||||
statement,
|
statement,
|
||||||
1,
|
1,
|
||||||
investigation_name,
|
investigation_uuid,
|
||||||
-1,
|
-1,
|
||||||
SQLITE_TRANSIENT
|
SQLITE_TRANSIENT
|
||||||
);
|
);
|
||||||
|
|
@ -370,7 +353,7 @@ static bool database_insert_investigation(
|
||||||
result = sqlite3_bind_text(
|
result = sqlite3_bind_text(
|
||||||
statement,
|
statement,
|
||||||
2,
|
2,
|
||||||
investigation_root_path,
|
investigation_name,
|
||||||
-1,
|
-1,
|
||||||
SQLITE_TRANSIENT
|
SQLITE_TRANSIENT
|
||||||
);
|
);
|
||||||
|
|
@ -383,6 +366,32 @@ static bool database_insert_investigation(
|
||||||
result = sqlite3_bind_text(
|
result = sqlite3_bind_text(
|
||||||
statement,
|
statement,
|
||||||
3,
|
3,
|
||||||
|
investigation_root_path,
|
||||||
|
-1,
|
||||||
|
SQLITE_TRANSIENT
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_text(
|
||||||
|
statement,
|
||||||
|
4,
|
||||||
|
created_at,
|
||||||
|
-1,
|
||||||
|
SQLITE_TRANSIENT
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_bind_text(
|
||||||
|
statement,
|
||||||
|
5,
|
||||||
created_at,
|
created_at,
|
||||||
-1,
|
-1,
|
||||||
SQLITE_TRANSIENT
|
SQLITE_TRANSIENT
|
||||||
|
|
@ -530,18 +539,7 @@ bool database_initialize(
|
||||||
|
|
||||||
transaction_started = true;
|
transaction_started = true;
|
||||||
|
|
||||||
if (!database_execute_sql(
|
if (!schema_install_v1(database))
|
||||||
database,
|
|
||||||
database_create_metadata_table_sql
|
|
||||||
))
|
|
||||||
{
|
|
||||||
goto rollback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!database_execute_sql(
|
|
||||||
database,
|
|
||||||
database_create_investigation_table_sql
|
|
||||||
))
|
|
||||||
{
|
{
|
||||||
goto rollback;
|
goto rollback;
|
||||||
}
|
}
|
||||||
|
|
@ -557,6 +555,7 @@ bool database_initialize(
|
||||||
|
|
||||||
if (!database_insert_investigation(
|
if (!database_insert_investigation(
|
||||||
database,
|
database,
|
||||||
|
investigation_uuid,
|
||||||
investigation_name,
|
investigation_name,
|
||||||
investigation_root_path,
|
investigation_root_path,
|
||||||
created_at
|
created_at
|
||||||
|
|
|
||||||
91
src/database/schema.c
Normal file
91
src/database/schema.c
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* @file schema.c
|
||||||
|
* @brief Installation du schéma SQLite de Labfy Investigation.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "database/schema.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Charge le schéma SQL V1 depuis les ressources intégrées.
|
||||||
|
*
|
||||||
|
* @return Une nouvelle chaîne terminée par zéro, à libérer avec g_free(),
|
||||||
|
* ou NULL en cas d'échec.
|
||||||
|
*/
|
||||||
|
static char *schema_load_v1_sql(void)
|
||||||
|
{
|
||||||
|
char *schema_sql = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (!g_file_get_contents(
|
||||||
|
"database/schema_v1.sql",
|
||||||
|
&schema_sql,
|
||||||
|
NULL,
|
||||||
|
&error
|
||||||
|
))
|
||||||
|
{
|
||||||
|
g_warning(
|
||||||
|
"Impossible de charger database/schema_v1.sql : %s",
|
||||||
|
error != NULL
|
||||||
|
? error->message
|
||||||
|
: "erreur inconnue"
|
||||||
|
);
|
||||||
|
|
||||||
|
g_clear_error(&error);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return schema_sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool schema_install_v1(
|
||||||
|
sqlite3 *database
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char *schema_sql = NULL;
|
||||||
|
char *error_message = NULL;
|
||||||
|
|
||||||
|
int result = SQLITE_ERROR;
|
||||||
|
|
||||||
|
if (database == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
schema_sql = schema_load_v1_sql();
|
||||||
|
|
||||||
|
if (schema_sql == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = sqlite3_exec(
|
||||||
|
database,
|
||||||
|
schema_sql,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&error_message
|
||||||
|
);
|
||||||
|
|
||||||
|
g_free(schema_sql);
|
||||||
|
|
||||||
|
if (result != SQLITE_OK)
|
||||||
|
{
|
||||||
|
g_warning(
|
||||||
|
"Impossible d'installer le schéma SQLite V1 : %s",
|
||||||
|
error_message != NULL
|
||||||
|
? error_message
|
||||||
|
: sqlite3_errmsg(database)
|
||||||
|
);
|
||||||
|
|
||||||
|
sqlite3_free(error_message);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3_free(error_message);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -131,6 +131,8 @@ static void test_database_initialize_valid_database(void)
|
||||||
char *investigation_name = NULL;
|
char *investigation_name = NULL;
|
||||||
char *investigation_root_path = NULL;
|
char *investigation_root_path = NULL;
|
||||||
char *investigation_created_at = NULL;
|
char *investigation_created_at = NULL;
|
||||||
|
char *investigation_id = NULL;
|
||||||
|
char *investigation_count = NULL;
|
||||||
|
|
||||||
sqlite3 *database = NULL;
|
sqlite3 *database = NULL;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
@ -214,19 +216,31 @@ static void test_database_initialize_valid_database(void)
|
||||||
investigation_name = test_database_read_single_text(
|
investigation_name = test_database_read_single_text(
|
||||||
database,
|
database,
|
||||||
"SELECT name FROM investigation "
|
"SELECT name FROM investigation "
|
||||||
"WHERE id = 1;"
|
"LIMIT 1;"
|
||||||
);
|
);
|
||||||
|
|
||||||
investigation_root_path = test_database_read_single_text(
|
investigation_root_path = test_database_read_single_text(
|
||||||
database,
|
database,
|
||||||
"SELECT root_path FROM investigation "
|
"SELECT root_path FROM investigation "
|
||||||
"WHERE id = 1;"
|
"LIMIT 1;"
|
||||||
);
|
);
|
||||||
|
|
||||||
investigation_created_at = test_database_read_single_text(
|
investigation_created_at = test_database_read_single_text(
|
||||||
database,
|
database,
|
||||||
"SELECT created_at FROM investigation "
|
"SELECT created_at FROM investigation "
|
||||||
"WHERE id = 1;"
|
"LIMIT 1;"
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_id = test_database_read_single_text(
|
||||||
|
database,
|
||||||
|
"SELECT id FROM investigation "
|
||||||
|
"LIMIT 1;"
|
||||||
|
);
|
||||||
|
|
||||||
|
investigation_count = test_database_read_single_text(
|
||||||
|
database,
|
||||||
|
"SELECT CAST(COUNT(*) AS TEXT) "
|
||||||
|
"FROM investigation;"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert(strcmp(schema_version, "1") == 0);
|
assert(strcmp(schema_version, "1") == 0);
|
||||||
|
|
@ -246,6 +260,11 @@ static void test_database_initialize_valid_database(void)
|
||||||
assert(g_remove(database_path) == 0);
|
assert(g_remove(database_path) == 0);
|
||||||
assert(g_rmdir(temporary_directory) == 0);
|
assert(g_rmdir(temporary_directory) == 0);
|
||||||
|
|
||||||
|
assert(investigation_id[0] != '\0');
|
||||||
|
assert(g_uuid_string_is_valid(investigation_id));
|
||||||
|
|
||||||
|
assert(strcmp(investigation_count, "1") == 0);
|
||||||
|
|
||||||
g_free(investigation_created_at);
|
g_free(investigation_created_at);
|
||||||
g_free(investigation_root_path);
|
g_free(investigation_root_path);
|
||||||
g_free(investigation_name);
|
g_free(investigation_name);
|
||||||
|
|
@ -255,6 +274,8 @@ static void test_database_initialize_valid_database(void)
|
||||||
g_free(schema_version);
|
g_free(schema_version);
|
||||||
g_free(database_path);
|
g_free(database_path);
|
||||||
g_free(temporary_directory);
|
g_free(temporary_directory);
|
||||||
|
g_free(investigation_id);
|
||||||
|
g_free(investigation_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in a new issue