> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Les enregistrements insérés dans une table `QueryRunner` correspondent à des requêtes que le moteur exécute, soit localement, soit sur un cluster distant, en mode « fire and forget ».

# Moteur de table QueryRunner

Les enregistrements insérés dans une table `QueryRunner` correspondent à des requêtes que le moteur exécute.
Le moteur peut être utilisé pour l'exécution asynchrone de requêtes, l'exécution par lots de requêtes générées,
l'acheminement de requêtes vers des clusters distants, les tests de performance, le fuzzing et les tests sur trafic miroir.

<div id="creating-a-table">
  ## Créer une table
</div>

```sql theme={null}
CREATE TABLE runner
(
    query String,
    database String,
    settings Map(LowCardinality(String), String)
)
ENGINE = QueryRunner
SETTINGS
    cluster = 'cluster_name',
    shard = '1',
    mode = 'asynchronous',
    threads = 4,
    max_queue_size = 1000
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }];
```

La table doit être créée avec un sous-ensemble des colonnes autorisées : `query`, `database`, `settings`.
La colonne `query` est obligatoire, les autres colonnes étant facultatives.

| Colonne    | Type                  | Signification                                                                                                         |
| ---------- | --------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `query`    | `String`              | La requête à exécuter.                                                                                                |
| `database` | `String`              | La base de données par défaut de la requête. Si elle est vide, la base de données par défaut du serveur est utilisée. |
| `settings` | `Map(String, String)` | Les paramètres appliqués à la requête.                                                                                |

<div id="engine-settings">
  ## Paramètres du moteur
</div>

| Paramètre        | Défaut           | Signification                                                                                                                                                                                                                                         |
| ---------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cluster`        | `''`             | Nom du cluster auquel envoyer les requêtes. S'il est vide, les requêtes sont exécutées localement.                                                                                                                                                    |
| `shard`          | `'1'`            | Indice, indexé à partir de 1, du shard du cluster auquel envoyer les requêtes, ou `'random'` pour sélectionner un shard aléatoire pour chaque requête, ou `'all'` pour exécuter chaque requête sur tous les shards. Nécessite le paramètre `cluster`. |
| `mode`           | `'asynchronous'` | En mode `synchronous`, INSERT renvoie une fois que toutes les requêtes du lot inséré sont terminées. En mode `asynchronous`, INSERT renvoie dès que les requêtes sont placées en file d'attente.                                                      |
| `threads`        | `4`              | Nombre de threads en arrière-plan qui exécutent les requêtes.                                                                                                                                                                                         |
| `max_queue_size` | `1000`           | Nombre maximal de requêtes en file d'attente. Lorsque la file d'attente est pleine, les nouvelles requêtes insérées sont ignorées et une erreur est consignée.                                                                                        |

<div id="details">
  ## Détails
</div>

La table autorise uniquement les requêtes INSERT.
Les requêtes sont exécutées en mode « fire and forget » : en cas d'exception, aucune nouvelle tentative n'est effectuée,
et les résultats des requêtes SELECT sont ignorés (la seule façon de conserver les résultats est `INSERT SELECT`).
Le succès de chaque requête peut être vérifié dans la table `system.query_log`, où les requêtes initiées par
ce moteur sont marquées avec `is_internal = 1` sur le serveur initiateur.

Les requêtes en file d'attente sont conservées en mémoire et ne survivent pas à un redémarrage du serveur. Lors de l'arrêt du serveur
(ou d'un `DROP`/`DETACH` de la table), les requêtes qui n'ont pas encore démarré sont ignorées. Parmi les
requêtes déjà en cours d'exécution, celles envoyées à un cluster sont annulées, tandis que celles exécutées
localement sont attendues jusqu'à la fin de leur exécution.

Lorsqu'une requête à exécuter est elle-même un `INSERT`, ses données doivent être intégrées — `INSERT ... VALUES (...)`,
`INSERT ... SELECT ...`, ou `INSERT ... FORMAT ...` avec les données dans le texte de la requête. Un `INSERT` qui
attend ses données d'un flux distinct n'est pas pris en charge.

<div id="local-mode-and-sql-security">
  ## Mode local et SQL SECURITY
</div>

Sans le paramètre `cluster`, les requêtes sont exécutées sur le serveur local.
L'utilisateur sous l'identité duquel elles s'exécutent est déterminé par la clause `SQL SECURITY` :

* `INVOKER` (par défaut) : les requêtes s'exécutent au nom de l'utilisateur qui a effectué l'`INSERT`.
* `DEFINER` : les requêtes s'exécutent au nom de l'utilisateur `DEFINER` spécifié. Comme les requêtes insérées peuvent être arbitraires, accorder `INSERT` sur une telle table délègue tous les privilèges de cet utilisateur.
* `NONE` : les requêtes s'exécutent avec un accès complet, sans utilisateur. Nécessite le privilège `ALLOW_SQL_SECURITY_NONE` lors de la création de la table.

<div id="cluster-mode">
  ## Mode cluster
</div>

Lorsque le paramètre `cluster` est spécifié, les requêtes sont envoyées au cluster indiqué.

Le shard cible est sélectionné par `shard` : un index fixe indexé à partir de 1 (`'1'` par défaut), `'random'` pour choisir un
shard aléatoire pour chaque requête, ou `'all'` pour exécuter chaque requête sur tous les shards du cluster. Une réplique au sein
du shard est choisie selon le paramètre `load_balancing` du serveur.

La colonne `database` définit la base de données par défaut de la connexion au serveur distant. Comme la
base de données par défaut n'est définie qu'une seule fois par connexion, chaque valeur distincte de `database` utilise son propre
pool de connexions, qui est créé lors de la première utilisation puis réutilisé pendant toute la durée de vie de la table.

`DEFINER` et `SQL SECURITY` n'ont d'effet qu'en mode local, et les combiner avec le
paramètre `cluster` constitue une erreur. Sur les serveurs distants, les requêtes sont authentifiées à l'aide des
informations d'identification de la configuration du cluster et s'exécutent comme des requêtes initiales ordinaires : elles sont consignées dans
`system.query_log` avec `is_initial_query = 1` et leur propre `query_id` (sans lien avec l'INSERT qui
les a produites). Sur le serveur initiateur, les requêtes envoyées sont consignées dans `system.query_log`
avec `is_internal = 1`.

Comme le moteur ignore le résultat de la requête, il exécute toujours les requêtes envoyées avec
`discard_query_data = 1`, de sorte que les données de résultat des requêtes SELECT ne sont pas transférées sur le réseau
(cela remplace toute valeur `discard_query_data` définie dans la colonne `settings`).

<div id="waiting-for-queries-to-finish">
  ## Attendre la fin des requêtes
</div>

En mode asynchrone, vous pouvez utiliser la requête suivante pour bloquer jusqu’à ce que toutes les requêtes soumises à la table jusqu’à présent soient terminées :

```sql theme={null}
SYSTEM WAIT QUERY RUNNER runner;
```

<div id="example">
  ## Exemple
</div>

Réexécuter des requêtes `SELECT` récentes à partir du journal des requêtes :

```sql theme={null}
INSERT INTO runner (query, database, settings)
SELECT query, current_database, Settings
FROM system.query_log
WHERE type = 'QueryFinish' AND is_initial_query AND NOT is_internal AND query_kind = 'Select'
  AND event_time > now() - INTERVAL 1 HOUR;
```
