Chercher une chaîne dans l'intégralité d'une base de données est une demande fréquente : retrouver un enregistrement orphelin, suivre la trace d'une donnée personnelle, déboguer un identifiant qui apparaît à plusieurs endroits. Quand on connaît la table et la colonne, un simple LIKE suffit. Quand on ne les connaît pas, le problème devient celui du parcours de schéma.
Trois approches sont possibles : écrire un script SQL qui itère sur le catalogue, utiliser les capacités full-text natives du moteur, ou déléguer le travail à un client desktop qui sait scanner toutes les tables en parallèle. Chacune a son cas d'usage. Cet article les passe en revue, puis décrit comment QoreDB articule les trois.
L'approche script avec information_schema
Le catalogue SQL standard expose la liste des colonnes via information_schema.columns. Sur PostgreSQL, on peut générer dynamiquement une union de SELECT pour chaque colonne texte d'une base. On filtre les colonnes pertinentes (text, varchar, character), on assemble une requête UNION ALL et on injecte le terme recherché dans un ILIKE.
Cette méthode fonctionne et reste portable d'un projet à l'autre. Elle a deux qualités. La première : aucune dépendance, juste du SQL. La seconde : on contrôle exactement ce qui est scanné. Son coût est proportionnel au volume balayé. Chaque colonne texte de chaque table est lue intégralement, sans utiliser d'index. Sur une base de quelques dizaines de tables et quelques gigaoctets, le résultat tombe en quelques secondes. Au-delà, le script devient un outil de debug ponctuel plutôt qu'un mécanisme de recherche au quotidien.
Les capacités natives full-text des moteurs
PostgreSQL propose deux mécanismes complémentaires. L'extension pg_trgm permet une recherche par similarité via des index GIN sur trigrammes : utile pour la recherche approchée et les ILIKE sur de gros volumes. Le module full-text natif s'appuie sur tsvector et tsquery, avec un index GIN pré-calculé qui transforme la recherche en lookup quasi instantané.
MySQL a son propre index FULLTEXT interrogeable via MATCH ... AGAINST. MongoDB expose l'opérateur $text et les index text. SQL Server offre les CONTAINS et FREETEXT. Chaque moteur a sa propre sémantique pour le stemming, les opérateurs booléens et la pertinence.
Ces solutions sont rapides quand l'index existe et qu'on cible une table précise. Elles couvrent moins bien le cas qui nous intéresse ici : balayer toute la base sans savoir où la donnée se trouve. Il faudrait avoir créé les index full-text sur chaque colonne texte de chaque table en amont, ce qui est rarement fait en pratique.
Le scan global comme fonction du client
QoreDB intègre une recherche full-text qui scanne automatiquement toutes les tables d'une base. L'idée est simple : tant que le client connaît le schéma via le catalogue, il peut générer les requêtes nécessaires et les exécuter en parallèle. Le développeur n'écrit rien, il tape une chaîne et obtient les correspondances.
La logique est implémentée côté Rust. Elle commence par lister les namespaces non système, exclut les schémas internes (information_schema, pg_catalog, pg_toast, mysql.sys, etc.) et récupère pour chaque table la liste des colonnes texte. Ce filtrage prend en compte les types text, varchar, char, json, xml, uuid, et les types équivalents côté MongoDB.
Stratégies par driver et fallback
Avant de générer la requête, QoreDB détecte les index full-text disponibles sur la table cible. Sur PostgreSQL, une requête sur pg_indexes identifie les index GIN sur tsvector. Sur MySQL, SHOW INDEX remonte les index FULLTEXT. Quand un index existe, la requête utilise la syntaxe native et profite de l'accélération. Sinon, le client retombe sur un LIKE ou ILIKE classique sur les colonnes texte.
Cette détection est mise en cache par table pendant cinq minutes : on ne paye pas le coût de l'inspection à chaque recherche. Le statut de la recherche, NativeFulltext, PatternMatch ou Hybrid, est remonté à l'interface pour que l'utilisateur sache si l'index a servi.
Exécution parallèle, timeout et streaming
Le scan parallélise jusqu'à cinq tables à la fois via un buffer_unordered de tokio. Chaque table dispose d'un timeout de cinq secondes par défaut, dépassé lequel le résultat partiel est conservé et la table est marquée comme expirée dans les statistiques. Un compteur d'avancement est émis vers le frontend Tauri sous forme d'événements, ce qui permet d'afficher les résultats au fil de l'eau plutôt que d'attendre la fin complète.
Les limites sont explicites : dix correspondances par table, cent au total par défaut, ajustables dans les options. Quand le seuil est atteint, le résultat est marqué tronqué. Ce cadre évite de saturer la mémoire du client sur une base où le terme recherché est très fréquent.
Comment l'utiliser au quotidien
Dans QoreDB, la recherche full-text est accessible depuis la sidebar de chaque connexion. On choisit la base, on saisit la chaîne, on lance. Les résultats apparaissent regroupés par table avec la colonne concernée, un aperçu de la valeur tronqué à cent caractères, et la ligne complète à la demande. Un clic ouvre la table sur l'enregistrement en question, prête à être éditée ou exportée.
Pour les cas où l'on connaît déjà la zone à fouiller, on peut restreindre la recherche à un sous-ensemble de tables ou de namespaces via les options. C'est utile sur des bases volumineuses où on veut éviter de scanner les tables d'archive ou de log.
Synthèse
La recherche full-text sur toutes les tables d'une base n'a pas de solution unique. Le script ad hoc reste pertinent pour un debug ponctuel ou un audit ciblé. Les index full-text natifs sont irremplaçables quand on sait où chercher et qu'on a anticipé le besoin. Le scan transparent au niveau du client comble le terrain entre les deux : il évite d'écrire le script à chaque fois, profite des index quand ils existent, et reste assez rapide pour devenir un réflexe quotidien. C'est cette approche que QoreDB pousse, avec la transparence de remonter la méthode effectivement utilisée pour chaque table.
Restez informé des nouveautés
Rejoignez notre newsletter pour recevoir les mises à jour majeures, les nouveaux drivers et nos coulisses techniques.

