> ## 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.

> Codec Rust compilé et optionnel pour ClickHouse Connect

# Codec natif Rust

ClickHouse Connect peut décoder les résultats de requête et encoder les insertions à l'aide d'un codec Rust compilé plutôt qu'avec l'implémentation Python et Cython par défaut. Le codec Rust s'applique uniquement au trafic `FORMAT Native` géré par le client, ce qui couvre `query`, `query_np`, `query_df`, leurs variantes de streaming par bloc et par ligne, ainsi que les insertions, y compris `insert_df`. Les méthodes Arrow utilisent `FORMAT Arrow` et ne sont donc pas concernées, pas plus que les requêtes raw, les insertions raw et les formats non natifs.

Le codec est expérimental et son utilisation est optionnelle. Le codec Python reste celui utilisé par défaut.

## Installation

Le codec compilé est fourni sous la forme d'un paquet wheel distinct, nommé `clickhouse-connect-core`, qui contient le module d'extension `_ch_core`. Installez le codec avec les intégrations utilisées par votre application :

```bash theme={null}
pip install "clickhouse-connect[rust]"         # Python rows and Native inserts
pip install "clickhouse-connect[rust,numpy]"   # NumPy results
pip install "clickhouse-connect[rust,pandas]"  # Pandas results and inserts
```

Des wheels Core sont publiés pour CPython 3.10 à 3.14 ainsi que pour CPython 3.14t en mode free-threaded, sous Linux, macOS et Windows. Sous Python free-threaded, l'importation de l'extension Core ne réactive pas le GIL.

La sortie NumPy et Pandas standard en Rust ne nécessite ni PyArrow ni aucun autre paquet Arrow. Cela concerne `query_np`, `query_df`, leurs variantes en streaming, ainsi que `query(..., use_numpy=True)`. Les requêtes NumPy ne nécessitent pas Pandas. Ajoutez l'extra `async` pour utiliser le client asynchrone.

PyArrow reste nécessaire pour les méthodes Arrow et le stockage Pandas basé sur Arrow. Installez l'extra `arrow` pour bénéficier de ces fonctionnalités :

```bash theme={null}
pip install "clickhouse-connect[rust,pandas,arrow]"
```

La sortie étendue des strings Pandas suit l'option `mode.string_storage` de Pandas. Lorsque PyArrow est installé, les strings utilisent la conversion Arrow existante, avec une validation UTF-8 complète, quel que soit le backend de stockage. Sans PyArrow, le driver utilise la conversion d'objets Rust, et le stockage par défaut de Pandas utilise des strings Python. Demander explicitement le stockage de strings Arrow sans PyArrow lève une erreur de dépendance. Les données UTF-8 invalides conservent le rendu hexadécimal existant, quel que soit le backend de stockage.

Le codec, son empaquetage et ses dépendances sont expérimentaux. La conversion directe par tampon prend désormais en charge les colonnes d'integers non nullable de 8 à 64 bits, ainsi que les colonnes Float32/64, Boolean, BFloat16, Interval, Date, Date32, DateTime et DateTime64. Les colonnes scalaires Time et Time64, y compris les valeurs nullable, utilisent également des tampons directs, tout comme BFloat16 nullable et la sortie Pandas étendue des integers, flottants et Interval nullable. BFloat16 conserve une sortie float32 ainsi que sa politique actuelle de gestion des valeurs manquantes Float32 dans Pandas. Les valeurs Interval restent des décomptes signés exprimés dans leur unité déclarée. La conversion temporelle conserve les unités déclarées et les règles de fuseau horaire existantes. Les alias SimpleAggregateFunction nullable de Time64 renvoient désormais des durées correctes, et NaT pour les valeurs NULL. Les colonnes scalaires nullable DateTime64(9) utilisent également des tampons afin de préserver les nanosecondes dans la sortie NumPy et Pandas. Les autres dates et timestamp nullable conservent leurs chemins de conversion d'objets.

Les tableaux de Time/Time64, y compris les tableaux imbriqués et les feuilles nullable, ainsi que LowCardinality(Time), y compris les valeurs nullable, utilisent également des tampons directs. Leur imbrication, leurs unités de durée et leur représentation des valeurs nulles restent inchangées. LowCardinality(Time64) n'est toujours pas pris en charge par le cœur Rust.

Pour les colonnes scalaires nullable DateTime64(9), `query_df` et `query_df_stream` préservent les neuf chiffres fractionnaires, y compris via les alias SimpleAggregateFunction. Sous Pandas 3, les colonnes datetime de la sortie par défaut utilisent désormais la nanoseconde comme unité, et non plus la microseconde. L'inférence existante du dtype object pour les blocs entièrement NULL reste inchangée. Si un fuseau horaire nommé fait sortir une valeur de la plage en nanosecondes de Pandas, la colonne concernée conserve sa conversion d'objets et son comportement de plage antérieurs.

Pour ces colonnes, les champs object de `query_np` et `query_np_stream` contiennent désormais des cellules `numpy.datetime64` au lieu de cellules Python `datetime`, avec `None` pour les NULL SQL. Les valeurs associées à un fuseau nommé utilisent des ticks UTC sans métadonnées de fuseau horaire, comme le codec Python. Les nanosecondes sont ainsi préservées sans nécessiter Pandas. Utilisez `query_df` si vous avez besoin de timestamp tenant compte du fuseau horaire. Les autres types de cellules temporelles NumPy nullable restent inchangés.

Les requêtes NumPy et Pandas sur des DateTime64 scalaires rejettent toute précision autre que 0, 3, 6 et 9 avec une `ProgrammingError`, y compris pour les colonnes nullable et les alias SimpleAggregateFunction.

Si un codec Rust est sélectionné alors que le module compilé n'est pas installé, la création du client lève une `NotSupportedError` indiquant cette commande d'installation.

## Activation du codec

Sélectionnez le codec via l'option client `native_codec` :

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client(host="localhost", native_codec="rust")
```

Valeurs acceptées :

| Value | Comportement |
| - | - |
| `python` | Valeur par défaut. Le codec Python et Cython existant. |
| `rust` | Privilégie le codec Rust. Les requêtes comportant des options non prises en charge et les insertions de types non pris en charge sont redirigées vers le codec Python. |
| `rust_strict` | Impose le codec Rust. Les options et les types non pris en charge déclenchent une erreur au lieu d'être redirigés. |

La valeur par défaut peut également être définie via le paramètre commun `native_codec` ou la variable d'environnement `CLICKHOUSE_CONNECT_NATIVE_CODEC`. L'ordre de préséance est le suivant : l'argument nommé du client, puis le paramètre commun, puis la variable d'environnement.

L'option est ignorée pour les clients `interface="chdb"`, qui utilisent toujours le codec Python.

## Quand utiliser le codec Rust

Le codec Rust est particulièrement utile pour les résultats DataFrame volumineux comportant du texte, des conteneurs et des types complexes tels que `String`, `LowCardinality`, `Map`, `Array`, `JSON`, `Decimal` et `UUID`. Il peut également bénéficier aux flux volumineux de blocs de lignes et de colonnes, aux charges de travail de requêtes concurrentes et aux insertions en masse.

Les petits résultats et les requêtes limitées par le réseau ne montreront sans doute que peu de différence. Les résultats numériques plats empruntent déjà des chemins d'accès en masse efficaces dans le codec Python : le gain y sera donc lui aussi plus limité.

Les tampons directs évitent de passer par des tableaux Arrow intermédiaires pour les types pris en charge. L'assemblage final des résultats NumPy et Pandas peut toutefois encore nécessiter des allocations et des copies : tous les résultats de requête ne sont donc pas pour autant zero-copy.

Sans PyArrow, la conversion des strings par Rust construit des objets string Python à partir de chaque bloc décodé. Avec les tailles de bloc par défaut, le pic de mémoire pour les résultats `String` volumineux est proche de celui du codec Python. Les très grands blocs, par exemple un bloc unique contenant un million de lignes, maintiennent l'intégralité du bloc décodé en mémoire pendant la construction de ses strings et peuvent entraîner un pic de mémoire supérieur à celui du codec Python. Pour les résultats Pandas `StringDtype` volumineux, installez l'extra `arrow` et utilisez le stockage de strings Arrow. Pandas 3 sélectionne le stockage Arrow par défaut lorsque PyArrow est installé. Pandas 2 nécessite `pd.options.mode.string_storage = "pyarrow"`.

Les appels `query()` bufferisés portant sur des résultats très larges ou entièrement numériques peuvent actuellement s'avérer plus lents et consommer davantage de mémoire de pointe avec le codec Rust. Pour ces charges de travail, privilégiez `query_df`, `query_row_block_stream` ou `query_column_block_stream`. Pour NumPy et Pandas, `query_np_stream` et `query_df_stream` permettent également de réduire le pic de mémoire. Traitez et libérez chaque bloc au fur et à mesure plutôt que de collecter l'intégralité du flux. La consommation de mémoire reste fonction de la taille de chaque bloc : diffuser en streaming un seul bloc volumineux n'apporte donc pas le même avantage.

Évaluez les performances sur votre propre charge de travail avant d'adopter le codec. Utilisez `native_codec="rust_strict"` pendant vos mesures afin qu'une option non prise en charge ou une dépendance manquante lève une erreur au lieu de rediriger silencieusement la requête vers Python.

## Règles de fallback

Les décisions de fallback sont prises avant que le moindre octet ne soit lu ou envoyé : aucun changement de codec ne survient donc en cours de stream. Pour les requêtes, le choix intervient avant la consommation du response body. Pour les insertions, l'encodeur Rust n'est retenu que si tous les types de colonnes sont pris en charge ; sinon, l'insertion s'exécute intégralement avec le codec Python.

Lorsque `naive_datetime_insert="server"` est actif, `rust` route vers le codec Python toute insertion contenant une colonne `DateTime` ou `DateTime64`, afin que la timezone déclarée de la colonne ou la server timezone soit appliquée. `rust_strict` rejette cette combinaison. Le mode par défaut `naive_datetime_insert="local"` continue d'utiliser l'encodeur Rust.

Les requêtes de metadata internes au driver, y compris les statements de reflection du dialect SQLAlchemy, passent toujours par le codec Python, de façon silencieuse, quel que soit le mode.

Les payloads Native malformés détectés par le codec Rust lèvent `DataError`.

## Versioning

`clickhouse-connect-core` est versionné indépendamment de `clickhouse-connect`. L'extra `rust` requiert `clickhouse-connect-core>=0.2.1,<0.3`. Le driver vérifie à la fois la version de l'API de binding et la capability column-buffer lorsqu'un codec Rust est sélectionné. Le wheel core 0.2.0 publié ne dispose pas de la capability column-buffer. Si le wheel installé est incompatible, la création du client lève une `NotSupportedError` pour `rust` comme pour `rust_strict`, indiquant la commande d'upgrade suivante :

```bash theme={null}
pip install --upgrade clickhouse-connect-core
```

Les corrections et les améliorations de performances du codec compilé sont livrées dans les releases de `clickhouse-connect-core` et peuvent être obtenues par une simple mise à niveau vers un wheel core compatible. Les modifications de l'intégration Rust du driver nécessitent en revanche une mise à niveau de `clickhouse-connect`.

## Différences de comportement connues

Le codec Rust vise une parité cellule par cellule avec le codec Python. Les différences suivantes sont connues.

* Les résultats de `query_np` et `query_df` pour les colonnes `Variant` contiennent des objets Python simples plutôt que des valeurs scalaires numpy. Les valeurs sont identiques, mais les types de cellules diffèrent.
* Les valeurs `Dynamic` contenant `Time64` sont matérialisées sous la forme `datetime.timedelta` dans les résultats Rust de `query_np` et `query_df`. Aux échelles 0, 3, 6 et 9, les valeurs sont égales aux cellules `numpy.timedelta64` du codec Python, mais les types de cellules diffèrent. Aux autres échelles, le codec Rust renvoie `datetime.timedelta` alors que le codec Python lève `ProgrammingError`, car NumPy n'a pas d'unité correspondante. Les métadonnées des membres Dynamic ne sont pas exposées au driver après le décodage Rust : utilisez donc `native_codec="python"` lorsque les types de cellules NumPy ou la validation des échelles non prises en charge sont nécessaires.
* Pour `query_df`, le codec Python peut convertir en chaîne les valeurs Compound stockées dans les shared data JSON. Le codec Rust renvoie des objets décodés, ce qui correspond aux résultats de `query_np` des deux codecs.
* Une alternative `LowCardinality` placée dans un conteneur qui se matérialise cellule par cellule, comme `Array(Variant(...))`, produit des cellules de valeurs égales qui ne partagent pas l'identité d'objet par slot de dictionary observée avec le codec Python.
* Les colonnes `Nullable(Tuple(...))` comportant un ou plusieurs elements sont décodées correctement par le codec Rust. Le codec Python interprète mal ce layout ; le résultat Rust constitue donc le comportement de référence. Les deux codecs prennent en charge `Nullable(Tuple())`.
* `rust_strict` rejette les options de requête que le chemin Rust n'implémente pas, telles que des `query_formats` custom par requête, plutôt que de modifier silencieusement le comportement.
* Les erreurs de conversion et de validation lors d'une insertion Rust peuvent lever `DataError` là où le codec Python lève `ValueError`, et le texte du message peut différer. Exemples : valeurs `Time` et `Time64` invalides, adresses IPv6, dimensions QBit, longueurs `FixedString`, chaînes `Float64` et tentatives d'insertion d'elements dans une colonne `Tuple()`.
* L'encodeur Rust rejette `b""` pour `FixedString(N)` ainsi que les chaînes numériques telles que `"2"` pour les colonnes integer. Le codec Python, lui, complète par des zéros une valeur `FixedString` vide et convertit les chaînes numériques.
* Le codec Rust décode certaines valeurs de variante partagée `Dynamic` vers leurs types Python là où le codec Python laisse la valeur en raw bytes. Par exemple, un `Decimal` stocké peut être renvoyé comme `decimal.Decimal` par Rust et comme valeur binaire par Python.
* Pour les valeurs `Date` dans le stockage partagé `Dynamic`, `query_np` et `query_df` renvoient des cellules `datetime.date` avec le codec Rust et des cellules `numpy.datetime64` avec le codec Python. Les deux codecs renvoient `datetime.date` depuis `query`.
