Dans un client de base de données multi-moteur, chaque driver a ses spécificités. PostgreSQL et MySQL sont des serveurs réseau avec des protocoles bien définis. MongoDB expose une API document. Redis fonctionne par commandes clé-valeur. SQLite est différent : c'est un moteur embarqué qui lit et écrit directement dans un fichier sur disque. Cette particularité change tout, de la connexion jusqu'à la gestion de la concurrence.
Le driver SQLite de QoreDB est conçu pour respecter cette nature. Pas de configuration serveur, pas de credentials réseau. Un chemin de fichier, un pool de connexions local, et un ensemble de capacités exposées via le même trait DataEngine que les autres drivers.
Un driver fichier, pas un driver réseau
La première différence visible se situe à la connexion. Là où PostgreSQL attend un host, un port et des credentials, SQLite attend un chemin vers un fichier. Le driver valide ce chemin strictement : seules les extensions reconnues sont acceptées (.db, .sqlite, .sqlite3, .db3, .s3db, .sl3). Cette validation empêche d'ouvrir accidentellement un fichier qui n'est pas une base SQLite.
Le driver supporte aussi le mode in-memory avec la syntaxe :memory:, utile pour les tests ou les manipulations temporaires. Si le fichier cible n'existe pas encore, le driver peut le créer automatiquement, ce qui correspond au comportement natif de SQLite.
Côté pooling, le driver utilise SQLx avec un pool configurable : 5 connexions maximum par défaut, un timeout d'acquisition de 30 secondes, et un minimum de 0 connexions au repos. Ces valeurs sont ajustables par connexion. Le pool est dimensionné pour un usage desktop, pas pour un serveur web avec des centaines de requêtes concurrentes.
Pourquoi le WAL est activé par défaut
SQLite propose plusieurs modes de journalisation. Le mode par défaut (rollback journal) verrouille le fichier entier pendant une écriture, ce qui bloque toutes les lectures concurrentes. Le mode WAL (Write-Ahead Logging) inverse cette logique : les écritures vont dans un fichier journal séparé, et les lectures continuent sur la version stable du fichier principal.
Pour un client de base de données, c'est un choix naturel. Le pool de connexions de QoreDB peut avoir plusieurs lecteurs simultanés (le data grid, l'arbre de navigation, l'autocomplétion) pendant qu'une écriture est en cours. Sans WAL, ces lectures seraient bloquées le temps de chaque transaction. Le driver active donc le WAL systématiquement sur chaque connexion, avec un busy timeout de 30 secondes pour gérer les contentions de verrou sans échouer immédiatement.
Un namespace unique par fichier
Le modèle de données universel de QoreDB repose sur trois niveaux : Namespace, Collection, Record. Pour PostgreSQL, un namespace correspond à un schéma. Pour MySQL, c'est une base de données. Pour SQLite, c'est le fichier lui-même. Chaque fichier SQLite constitue un unique namespace, nommé d'après le fichier (ou "memory" pour les bases in-memory).
Ce mapping est fidèle à la réalité de SQLite. Il n'y a pas de concept de schéma ou de base de données multiple dans un même fichier. Le driver ne simule pas quelque chose qui n'existe pas : il expose un seul namespace, avec les tables et vues listées depuis sqlite_master, en filtrant les tables système (celles préfixées sqlite_).
Inspection du schéma via PRAGMA
SQLite n'expose pas ses métadonnées de la même façon que les moteurs SQL traditionnels. Pas de information_schema standardisé. Le mécanisme natif, ce sont les instructions PRAGMA. Le driver les utilise systématiquement : PRAGMA table_info pour les colonnes (nom, type, nullabilité, valeur par défaut, clé primaire), PRAGMA foreign_key_list pour les clés étrangères, PRAGMA index_list et PRAGMA index_info pour les index.
Le résultat est le même objet TableSchema que pour les autres drivers. L'interface ne sait pas si les métadonnées viennent d'un PRAGMA ou d'une requête sur pg_catalog. C'est le rôle du trait DataEngine : exposer une surface uniforme sans masquer les différences sous-jacentes.
Typage dynamique et extraction des valeurs
SQLite utilise un typage dynamique, contrairement à PostgreSQL ou MySQL où chaque colonne a un type fixe. Une colonne déclarée INTEGER peut contenir du texte. Le driver gère cette réalité en essayant plusieurs types dans l'ordre lors de l'extraction : entier (i64 puis i32), flottant (f64), booléen (mapping 0/1), texte, blob, puis null en dernier recours. Cette approche garantit que les données sont lues correctement même quand le contenu ne correspond pas au type déclaré.
Transactions, mutations et streaming
Le driver SQLite implémente l'ensemble des capacités de mutation du trait DataEngine. L'inline edit dans le data grid génère des UPDATE avec des clauses WHERE sur les clés primaires, les insertions utilisent des requêtes paramétrées avec des placeholders ?, et les suppressions ciblent les lignes par leur clé primaire (composite ou non). Toutes ces opérations passent par des requêtes paramétrées pour éviter toute injection SQL.
Les transactions sont gérées via une connexion dédiée extraite du pool au moment du BEGIN. Cette connexion est maintenue dans un Mutex jusqu'au COMMIT ou ROLLBACK, puis rendue au pool. Ce mécanisme garantit que toutes les requêtes d'une transaction passent par la même connexion, ce qui est indispensable avec SQLite.
Le streaming de résultats est aussi supporté. Les lignes sont envoyées une par une via un canal tokio::sync::mpsc, ce qui permet d'afficher les résultats dans le data grid au fur et à mesure sans charger l'intégralité du dataset en mémoire.
Maintenance et intégrité du fichier
Le driver expose quatre opérations de maintenance via l'interface graphique. VACUUM compacte le fichier en reconstruisant la base entière, ce qui récupère l'espace des lignes supprimées. ANALYZE met à jour les statistiques internes utilisées par l'optimiseur de requêtes. REINDEX reconstruit les index d'une table donnée. PRAGMA integrity_check vérifie la cohérence structurelle de la base.
Ces opérations sont particulièrement utiles pour SQLite car le fichier peut accumuler de l'espace inutilisé au fil des suppressions et modifications. Sur un fichier de développement utilisé quotidiennement, un VACUUM régulier maintient la taille du fichier raisonnable et les performances de lecture optimales.
En pratique : les cas d'usage du driver SQLite
Le driver SQLite dans QoreDB couvre trois scénarios principaux. Le premier est l'exploration de bases de données existantes : une app mobile qui stocke ses données dans un fichier .db, un projet Electron avec SQLite embarqué, ou un outil CLI qui persiste son état localement. Avec QoreDB, on ouvre le fichier, on navigue dans les tables, on inspecte le schéma et on exécute des requêtes, exactement comme on le ferait avec une base PostgreSQL distante.
Le deuxième est le prototypage rapide. Créer un fichier SQLite, définir quelques tables, insérer des données via l'inline edit du data grid, le tout sans installer quoi que ce soit. SQLite est disponible partout, et le driver en tire parti.
Le troisième est la fédération inter-bases. Via le moteur DuckDB intégré à QoreDB, on peut joindre les données d'un fichier SQLite avec celles d'un serveur PostgreSQL dans une seule requête. Le driver SQLite fournit les données sources, DuckDB orchestre la jointure.
Le driver SQLite de QoreDB traite un moteur fichier comme un moteur à part entière. WAL activé par défaut pour la concurrence, PRAGMA pour l'inspection, typage dynamique géré proprement, et toutes les capacités de mutation et de streaming du trait DataEngine. C'est un driver conçu pour les développeurs qui travaillent avec des fichiers SQLite au quotidien, sans compromis sur les fonctionnalités.
Restez informé des nouveautés
Rejoignez notre newsletter pour recevoir les mises à jour majeures, les nouveaux drivers et nos coulisses techniques.

