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

> Requêtes avancées avec ClickHouse Connect

# Requêtes avancées

<div id="querycontexts">
  ## QueryContexts
</div>

ClickHouse Connect exécute les requêtes standard dans un `QueryContext`. Le `QueryContext` contient les structures clés utilisées pour construire des requêtes sur la base de données ClickHouse, ainsi que la configuration utilisée pour traiter le résultat en `QueryResult` ou dans une autre structure de données de réponse. Cela inclut la requête elle-même, les paramètres, les réglages, les formats de lecture et d'autres propriétés.

Un `QueryContext` peut être obtenu à l'aide de la méthode `create_query_context` du client. Cette méthode accepte les mêmes paramètres que la méthode de requête principale. Ce contexte de requête peut ensuite être transmis aux méthodes `query`, `query_df` ou `query_np` comme argument nommé `context`, à la place de tout ou partie des autres arguments de ces méthodes. Notez que les arguments supplémentaires spécifiés lors de l'appel de la méthode remplaceront toutes les propriétés du QueryContext.

Le cas d'utilisation le plus évident d'un `QueryContext` consiste à envoyer la même requête avec différentes valeurs de paramètres liés. Toutes les valeurs de paramètres peuvent être mises à jour en appelant la méthode `QueryContext.set_parameters` avec un dictionnaire, ou chaque valeur individuellement peut être mise à jour en appelant `QueryContext.set_parameter` avec la paire `key`, `value` souhaitée.

```python theme={null}
client.create_query_context(query='SELECT value1, value2 FROM data_table WHERE key = {k:Int32}',
                            parameters={'k': 2},
                            column_oriented=True)
result = client.query(context=qc)
assert result.result_set[1][0] == 'second_value2'
qc.set_parameter('k', 1)
result = test_client.query(context=qc)
assert result.result_set[1][0] == 'first_value2'
```

Notez que les `QueryContext` ne sont pas thread-safe, mais qu'il est possible d'en obtenir une copie dans un environnement multithread en appelant la méthode `QueryContext.updated_copy`.

<div id="streaming-queries">
  ## Requêtes en streaming
</div>

Le ClickHouse Connect Client fournit plusieurs méthodes pour récupérer des données sous forme de flux (implémenté sous la forme d’un générateur Python) :

* `query_column_block_stream` -- renvoie les données de la requête par blocs sous forme de séquence de colonnes à l’aide d’objets Python natifs
* `query_row_block_stream` -- renvoie les données de la requête sous forme de bloc de lignes à l’aide d’objets Python natifs
* `query_rows_stream` -- renvoie les données de la requête sous forme de séquence de lignes à l’aide d’objets Python natifs
* `query_np_stream` -- renvoie chaque bloc ClickHouse de données de requête sous la forme d’un tableau NumPy
* `query_df_stream` -- renvoie chaque bloc ClickHouse de données de requête sous la forme d’un Pandas DataFrame
* `query_arrow_stream` -- renvoie les données de la requête sous forme de PyArrow RecordBlocks
* `query_df_arrow_stream` -- renvoie chaque bloc ClickHouse de données de requête sous la forme d’un Pandas DataFrame basé sur Arrow ou d’un Polars DataFrame selon le kwarg `dataframe_library` (la valeur par défaut est "pandas").

Chacune de ces méthodes renvoie un objet `ContextStream` qui doit être ouvert dans une instruction `with` pour commencer à consommer le flux.

<div id="data-blocks">
  ### Blocs de données
</div>

ClickHouse Connect traite toutes les données de la méthode `query` principale comme un flux de blocs reçus du serveur ClickHouse. Ces blocs sont transmis vers et depuis ClickHouse au format personnalisé « Native ». Un « bloc » est simplement une séquence de colonnes de données binaires, où chaque colonne contient le même nombre de valeurs du type de données spécifié. (En tant que base de données columnaire, ClickHouse stocke ces données sous une forme similaire.) La taille d’un bloc renvoyé par une requête dépend de deux paramètres utilisateur qui peuvent être définis à plusieurs niveaux (profil, utilisateur, session ou requête). Il s’agit de :

* [max\_block\_size](/docs/fr/reference/settings/session-settings#max_block_size) -- Limite de la taille du bloc en lignes. Valeur par défaut : 65536.
* [preferred\_block\_size\_bytes](/docs/fr/reference/settings/session-settings#preferred_block_size_bytes) -- Limite souple de la taille du bloc en octets. Valeur par défaut : 1,000,0000.

Indépendamment de `preferred_block_size_setting`, chaque bloc ne dépassera jamais `max_block_size` lignes. Selon le type de requête, les blocs réellement renvoyés peuvent être de taille quelconque. Par exemple, les requêtes sur une table distribuée couvrant de nombreux shards peuvent contenir des blocs plus petits récupérés directement depuis chaque shard.

Lors de l’utilisation de l’une des méthodes `query_*_stream` du Client, les résultats sont renvoyés bloc par bloc. ClickHouse Connect ne charge qu’un seul bloc à la fois. Cela permet de traiter de grands volumes de données sans devoir charger en mémoire l’ensemble d’un jeu de résultats volumineux. Notez que l’application doit être prête à traiter un nombre quelconque de blocs et que la taille exacte de chaque bloc ne peut pas être contrôlée.

<div id="http-data-buffer-for-slow-processing">
  ### Buffer de données HTTP pour un traitement lent
</div>

En raison des limitations du protocole HTTP, si les blocs sont traités à un rythme nettement inférieur à celui auquel le serveur ClickHouse diffuse les données en streaming, le serveur ClickHouse fermera la connexion, ce qui provoquera la levée d'une exception dans le thread de traitement. Il est possible d'atténuer partiellement ce problème en augmentant la taille du buffer de streaming HTTP (10 mégaoctets par défaut) à l'aide du paramètre commun `http_buffer_size`. Des valeurs élevées de `http_buffer_size` conviennent dans cette situation si l'application dispose de suffisamment de mémoire. Les données du buffer sont stockées sous forme compressée lors de l'utilisation de la compression `lz4` ou `zstd` ; l'utilisation de ces types de compression augmente donc la capacité globale du buffer disponible.

<div id="streamcontexts">
  ### StreamContexts
</div>

Chacune des méthodes `query_*_stream` (comme `query_row_block_stream`) renvoie un objet ClickHouse `StreamContext`, qui combine un contexte Python et un générateur. Voici l’usage de base :

```python theme={null}
with client.query_row_block_stream('SELECT pickup, dropoff, pickup_longitude, pickup_latitude FROM taxi_trips') as stream:
    for block in stream:
        for row in block:
            <do something with each row of Python trip data>
```

Notez qu’essayer d’utiliser un StreamContext sans instruction `with` provoquera une erreur. L’utilisation d’un contexte Python garantit que le flux (dans ce cas, une réponse HTTP en streaming) sera correctement fermé, même si toutes les données ne sont pas consommées et/ou si une exception est levée pendant le traitement. De plus, les `StreamContext` ne peuvent être utilisés qu’une seule fois pour consommer le flux. Essayer d’utiliser un `StreamContext` après sa sortie du contexte produira une `StreamClosedError`.

Vous pouvez utiliser la propriété `source` du `StreamContext` pour accéder à l’objet parent `QueryResult`, qui inclut les noms de colonnes et les types.

<div id="stream-types">
  ### Types de flux
</div>

La méthode `query_column_block_stream` renvoie le bloc sous la forme d'une séquence de données de colonnes stockées dans des types de données Python natifs. Avec les requêtes `taxi_trips` ci-dessus, les données renvoyées seront une liste dont chaque élément est une autre liste (ou un tuple) contenant toutes les données de la colonne correspondante. Ainsi, `block[0]` serait un tuple ne contenant que des chaînes de caractères. Les formats orientés colonnes sont surtout utilisés pour effectuer des opérations d'agrégation sur toutes les valeurs d'une colonne, comme additionner le total des tarifs.

La méthode `query_row_block_stream` renvoie le bloc sous la forme d'une séquence de lignes, comme dans une base de données relationnelle traditionnelle. Pour les trajets en taxi, les données renvoyées seront une liste dont chaque élément est une autre liste représentant une ligne de données. Ainsi, `block[0]` contiendrait tous les champs (dans l'ordre) du premier trajet en taxi, `block[1]` contiendrait tous les champs du deuxième trajet en taxi, et ainsi de suite. Les résultats orientés lignes sont généralement utilisés pour l'affichage ou les traitements de transformation.

`query_row_stream` est une méthode utilitaire qui passe automatiquement au bloc suivant lors de l'itération sur le flux. À part cela, elle est identique à `query_row_block_stream`.

La méthode `query_np_stream` renvoie chaque bloc sous la forme d'un Array NumPy à deux dimensions. En interne, les Arrays NumPy sont (généralement) stockés sous forme de colonnes ; il n'est donc pas nécessaire de disposer de méthodes distinctes pour les lignes et les colonnes. La "shape" du Array NumPy sera exprimée sous la forme (colonnes, lignes). La bibliothèque NumPy fournit de nombreuses méthodes pour manipuler les Arrays NumPy. Notez que si toutes les colonnes de la requête partagent le même Dtype NumPy, le Array NumPy renvoyé n'aura lui aussi qu'un seul Dtype et pourra être redimensionné ou pivoté sans modifier réellement sa structure interne.

La méthode `query_df_stream` renvoie chaque bloc ClickHouse sous la forme d'un Pandas DataFrame à deux dimensions. Voici un exemple montrant que l'objet `StreamContext` peut être utilisé comme contexte de manière différée (mais une seule fois).

```python theme={null}
df_stream = client.query_df_stream('SELECT * FROM hits')
column_names = df_stream.source.column_names
with df_stream:
    for df in df_stream:
        <do something with the pandas DataFrame>
```

La méthode `query_df_arrow_stream` renvoie chaque bloc ClickHouse sous forme de DataFrame avec le backend Dtype de PyArrow. Cette méthode prend en charge les DataFrames Pandas (2.x ou version ultérieure) et Polars via le paramètre `dataframe_library` (par défaut, `"pandas"`). À chaque itération, elle produit un DataFrame converti à partir de record batches PyArrow, ce qui offre de meilleures performances et une meilleure efficacité mémoire pour certains types de données.

Enfin, la méthode `query_arrow_stream` renvoie un résultat ClickHouse au format `ArrowStream` sous la forme d’un `pyarrow.ipc.RecordBatchStreamReader` encapsulé dans `StreamContext`. Chaque itération du flux renvoie un RecordBlock PyArrow.

<div id="streaming-examples">
  ### Exemples en streaming
</div>

<div id="stream-rows">
  #### Lignes en continu
</div>

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Stream large result sets row by row
with client.query_rows_stream("SELECT number, number * 2 as doubled FROM system.numbers LIMIT 100000") as stream:
    for row in stream:
        print(row)  # Process each row
        # Output:
        # (0, 0)
        # (1, 2)
        # (2, 4)
        # ....
```

<div id="stream-row-blocks">
  #### Diffuser des blocs de lignes en continu
</div>

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Stream in blocks of rows (more efficient than row-by-row)
with client.query_row_block_stream("SELECT number, number * 2 FROM system.numbers LIMIT 100000") as stream:
    for block in stream:
        print(f"Received block with {len(block)} rows")
        # Output:
        # Received block with 65409 rows
        # Received block with 34591 rows
```

<div id="stream-pandas-dataframes">
  #### Transmettre des DataFrames Pandas en flux
</div>

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Stream query results as Pandas DataFrames
with client.query_df_stream("SELECT number, toString(number) AS str FROM system.numbers LIMIT 100000") as stream:
    for df in stream:
        # Process each DataFrame block
        print(f"Received DataFrame with {len(df)} rows")
        print(df.head(3))
        # Output:
        # Received DataFrame with 65409 rows
        #    number str
        # 0       0   0
        # 1       1   1
        # 2       2   2
        # Received DataFrame with 34591 rows
        #    number    str
        # 0   65409  65409
        # 1   65410  65410
        # 2   65411  65411
```

<div id="stream-arrow-batches">
  #### Transmettre des lots Arrow en continu
</div>

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Stream query results as Arrow record batches
with client.query_arrow_stream("SELECT * FROM large_table") as stream:
    for arrow_batch in stream:
        # Process each Arrow batch
        print(f"Received Arrow batch with {arrow_batch.num_rows} rows")
        # Output:
        # Received Arrow batch with 65409 rows
        # Received Arrow batch with 34591 rows
```

<div id="numpy-pandas-and-arrow-queries">
  ## Requêtes NumPy, Pandas et Arrow
</div>

ClickHouse Connect propose des méthodes de requête spécialisées pour travailler avec les structures de données NumPy, Pandas et Arrow. Ces méthodes vous permettent de récupérer le résultat de la requête directement dans ces formats de données courants, sans conversion manuelle.

<div id="numpy-queries">
  ### Requêtes NumPy
</div>

La méthode `query_np` renvoie les résultats de la requête sous forme de tableau NumPy au lieu d’un `QueryResult` de ClickHouse Connect.

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Query returns a NumPy array
np_array = client.query_np("SELECT number, number * 2 AS doubled FROM system.numbers LIMIT 5")

print(type(np_array))
# Output:
# <class "numpy.ndarray">

print(np_array)
# Output:
# [[0 0]
#  [1 2]
#  [2 4]
#  [3 6]
#  [4 8]]
```

<div id="pandas-queries">
  ### Requêtes avec Pandas
</div>

La méthode `query_df` renvoie le résultat de la requête sous la forme d’un Pandas DataFrame plutôt que d’un `QueryResult` ClickHouse Connect.

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Query returns a Pandas DataFrame
df = client.query_df("SELECT number, number * 2 AS doubled FROM system.numbers LIMIT 5")

print(type(df))
# Output: <class "pandas.core.frame.DataFrame">
print(df)
# Output:
#    number  doubled
# 0       0        0
# 1       1        2
# 2       2        4
# 3       3        6
# 4       4        8
```

<div id="pyarrow-queries">
  ### Requêtes PyArrow
</div>

La méthode `query_arrow` renvoie le résultat de la requête sous forme de table PyArrow. Comme elle s’appuie directement sur le format `Arrow` de ClickHouse, elle n’accepte que trois arguments communs avec la méthode principale `query` : `query`, `parameters` et `settings`. Elle accepte en outre un argument supplémentaire, `use_strings`, qui détermine si la table Arrow représentera les types String de ClickHouse sous forme de chaînes (si True) ou d’octets (si False).

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Query returns a PyArrow Table
arrow_table = client.query_arrow("SELECT number, toString(number) AS str FROM system.numbers LIMIT 3")

print(type(arrow_table))
# Output:
# <class "pyarrow.lib.Table">

print(arrow_table)
# Output:
# pyarrow.Table
# number: uint64 not null
# str: string not null
# ----
# number: [[0,1,2]]
# str: [["0","1","2"]]
```

<div id="arrow-backed-dataframes">
  ### DataFrames adossés à Arrow
</div>

ClickHouse Connect prend en charge la création rapide et économe en mémoire de DataFrames à partir de résultats Arrow via les méthodes `query_df_arrow` et `query_df_arrow_stream`. Il s'agit de wrappers légers autour des méthodes de requête Arrow, avec conversion sans copie vers des DataFrames lorsque cela est possible :

* `query_df_arrow` : exécute la requête en utilisant le format de sortie ClickHouse `Arrow` et renvoie un DataFrame.
  * Pour `dataframe_library='pandas'`, renvoie un DataFrame pandas 2.x utilisant des Dtype adossés à Arrow (`pd.ArrowDtype`). Cela nécessite pandas 2.x et exploite des buffers sans copie lorsque cela est possible, pour d'excellentes performances et un faible surcoût mémoire.
  * Pour `dataframe_library='polars'`, renvoie un DataFrame Polars créé à partir de l'Arrow Table (`pl.from_arrow`), avec une efficacité comparable et, selon les données, sans copie.
* `query_df_arrow_stream` : diffuse les résultats sous forme d'une séquence de DataFrames (pandas 2.x ou Polars) convertis à partir de batches de flux Arrow.

<div id="query-to-arrow-backed-dataframe">
  #### Requête vers un DataFrame adossé à Arrow
</div>

```python theme={null}
import clickhouse_connect

client = clickhouse_connect.get_client()

# Query returns a Pandas DataFrame with Arrow dtypes (requires pandas 2.x)
df = client.query_df_arrow(
    "SELECT number, toString(number) AS str FROM system.numbers LIMIT 3",
    dataframe_library="pandas"
)

print(df.dtypes)
# Output:
# number    uint64[pyarrow]
# str       string[pyarrow]
# dtype: object

# Or use Polars
polars_df = client.query_df_arrow(
    "SELECT number, toString(number) AS str FROM system.numbers LIMIT 3",
    dataframe_library="polars"
)
print(df.dtypes)
# Output:
# [UInt64, String]

# Streaming into batches of DataFrames (polars shown)
with client.query_df_arrow_stream(
    "SELECT number, toString(number) AS str FROM system.numbers LIMIT 100000", dataframe_library="polars"
) as stream:
    for df_batch in stream:
        print(f"Received {type(df_batch)} batch with {len(df_batch)} rows and dtypes: {df_batch.dtypes}")
        # Output:
        # Received <class 'polars.dataframe.frame.DataFrame'> batch with 65409 rows and dtypes: [UInt64, String]
        # Received <class 'polars.dataframe.frame.DataFrame'> batch with 34591 rows and dtypes: [UInt64, String]
```

<div id="notes-and-caveats">
  #### Remarques et points de vigilance
</div>

* Correspondance des types Arrow : lors du renvoi de données au format Arrow, ClickHouse associe les types aux types Arrow pris en charge les plus proches. Certains types ClickHouse n'ont pas d'équivalent Arrow natif et sont renvoyés sous forme d'octets bruts dans des champs Arrow (généralement `BINARY` ou `FIXED_SIZE_BINARY`).
  * Exemples : `IPv4` est représenté par Arrow `UINT32` ; `IPv6` et les grands entiers (`Int128/UInt128/Int256/UInt256`) sont souvent représentés sous la forme `FIXED_SIZE_BINARY`/`BINARY`, avec des octets bruts.
  * Dans ces cas, la colonne du DataFrame contient des valeurs d'octets associées au champ Arrow ; c'est au code client d'interpréter/convertir ces octets conformément à la sémantique de ClickHouse.
* Les data types Arrow non pris en charge (par exemple, UUID/ENUM en tant que véritables types Arrow) ne sont pas émis ; pour la sortie, les valeurs sont représentées à l'aide du type Arrow pris en charge le plus proche (souvent sous forme d'octets binaires).
* Prérequis Pandas : les `dtypes` adossés à Arrow nécessitent pandas 2.x. Pour les anciennes versions de pandas, utilisez plutôt `query_df` (sans Arrow).
* Chaînes vs binaire : l'option `use_strings` (lorsqu'elle est prise en charge par le server setting `output_format_arrow_string_as_string`) détermine si les colonnes ClickHouse `String` sont renvoyées comme chaînes Arrow ou comme données binaires.

<div id="mismatched-clickhousearrow-type-conversion-examples">
  #### Exemples de conversion entre types ClickHouse/Arrow incompatibles
</div>

Lorsque ClickHouse renvoie des colonnes sous forme de données binaires brutes (par ex. `FIXED_SIZE_BINARY` ou `BINARY`), c’est au code de l’application de convertir ces octets dans les types Python appropriés. Les exemples ci-dessous montrent que certaines conversions peuvent être effectuées à l’aide des API des bibliothèques de DataFrame, tandis que d’autres peuvent nécessiter des approches en Python pur, comme `struct.unpack` (au prix de performances moindres, mais avec davantage de flexibilité).

Les colonnes `Date` peuvent être renvoyées en `UINT16` (nombre de jours depuis l’époque Unix, 1970‑01‑01). La conversion dans le DataFrame est efficace et simple :

```python theme={null}
# Polars
df = df.with_columns(pl.col("event_date").cast(pl.Date))

# Pandas
df["event_date"] = pd.to_datetime(df["event_date"], unit="D")
```

Des colonnes comme `Int128` peuvent être reçues sous forme de `FIXED_SIZE_BINARY` avec des octets bruts. Polars prend en charge nativement les entiers sur 128 bits :

```python theme={null}
# Polars - native support
df = df.with_columns(pl.col("data").bin.reinterpret(dtype=pl.Int128, endianness="little"))
```

À partir de NumPy 2.3, il n’existe pas de `dtype` entier public sur 128 bits. Nous devons donc recourir à du Python pur et pouvons faire quelque chose comme :

```python theme={null}
# Assuming we have a pandas dataframe with an Int128 column of dtype fixed_size_binary[16][pyarrow]

print(df)
# Output:
#   str_col                                        int_128_col
# 0    num1  b'\\x15}\\xda\\xeb\\x18ZU\\x0fn\\x05\\x01\\x00\\x00\\x00...
# 1    num2  b'\\x08\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00...
# 2    num3  b'\\x15\\xdfp\\x81r\\x9f\\x01\\x00\\x00\\x00\\x00\\x00\\x...

print([int.from_bytes(n, byteorder="little") for n in df["int_128_col"].to_list()])
# Output:
# [1234567898765432123456789, 8, 456789123456789]
```

Point essentiel : le code d'application doit gérer ces conversions en fonction des fonctionnalités de la bibliothèque DataFrame choisie et des compromis de performance acceptables. Lorsque des conversions propres à DataFrame ne sont pas disponibles, les approches en Python pur restent possibles.

<div id="read-formats">
  ## Formats de lecture
</div>

Les formats de lecture contrôlent les types de données des valeurs renvoyées par les méthodes `query`, `query_np` et `query_df` du client. (`raw_query` et `query_arrow` ne modifient pas les données reçues de ClickHouse ; le contrôle du format ne s’y applique donc pas.) Par exemple, si le format de lecture d’un UUID passe du format `native` par défaut au format alternatif `string`, les valeurs d’une colonne `UUID` renvoyées par une requête ClickHouse seront des chaînes (au format RFC 1422 standard 8-4-4-4-12) au lieu d’objets UUID Python.

L’argument « data type » de toute fonction de formatage peut inclure des caractères génériques. Le format est une chaîne unique en minuscules.

Les formats de lecture peuvent être définis à plusieurs niveaux :

* Globalement, à l’aide des méthodes définies dans le paquet `clickhouse_connect.datatypes.format`. Cela contrôle le format du type de données configuré pour toutes les requêtes.

```python theme={null}
from clickhouse_connect.datatypes.format import set_read_format

# Return both IPv6 and IPv4 values as strings
set_read_format('IPv*', 'string')

# Return all Date types as the underlying epoch second or epoch day
set_read_format('Date*', 'int')
```

* Pour l’ensemble d’une requête, en utilisant l’argument de dictionnaire facultatif `query_formats`. Dans ce cas, toute colonne (ou sous-colonne) des types de données spécifiés utilisera le format configuré.

```python theme={null}
# Return any UUID column as a string
client.query('SELECT user_id, user_uuid, device_uuid from users', query_formats={'UUID': 'string'})
```

* Pour les valeurs d'une colonne spécifique, à l'aide de l'argument dictionnaire facultatif `column_formats`. La clé correspond au nom de colonne tel que renvoyé par ClickHouse, et la valeur correspond soit au format de la colonne de données, soit à un dictionnaire de second niveau "format" contenant un nom de type ClickHouse et une valeur de formats de requête. Ce dictionnaire secondaire peut être utilisé pour des types de colonnes imbriqués tels que les Tuples ou les Maps.

```python theme={null}
# Return IPv6 values in the `dev_address` column as strings
client.query('SELECT device_id, dev_address, gw_address from devices', column_formats={'dev_address':'string'})
```

<div id="read-format-options-python-types">
  ### Options du format de lecture (types Python)
</div>

| Type ClickHouse         | Type Python natif       | Formats de lecture | Commentaires                                                                                                                                          |
| ----------------------- | ----------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| Int\[8-64], UInt\[8-32] | int                     | -                  |                                                                                                                                                       |
| UInt64                  | int                     | signed             | Superset ne gère pas encore les grandes valeurs UInt64 non signées                                                                                    |
| \[U]Int\[128,256]       | int                     | string             | Les valeurs int de Pandas et NumPy sont limitées à 64 bits ; elles peuvent donc être renvoyées sous forme de chaînes                                  |
| BFloat16                | float                   | -                  | En interne, tous les float Python sont sur 64 bits                                                                                                    |
| Float32                 | float                   | -                  | En interne, tous les float Python sont sur 64 bits                                                                                                    |
| Float64                 | float                   | -                  |                                                                                                                                                       |
| Decimal                 | decimal.Decimal         | -                  |                                                                                                                                                       |
| String                  | string                  | bytes              | Les colonne de type String ClickHouse n'ont pas d'encodage intrinsèque ; elles servent donc aussi à stocker des données binaires de longueur variable |
| FixedString             | bytes                   | string             | Les FixedString sont des tableaux d'octets de taille fixe, mais sont parfois traités comme des chaînes Python                                         |
| Enum\[8,16]             | string                  | string, int        | Les enum Python n'acceptent pas les chaînes vides ; tous les enum sont donc renvoyés soit comme des chaînes, soit comme leur valeur int sous-jacente  |
| Date                    | datetime.date           | int                | ClickHouse stocke les Date comme un nombre de jours depuis le 01/01/1970. Cette valeur est disponible sous forme d'int                                |
| Date32                  | datetime.date           | int                | Identique à Date, mais pour une plage de dates plus étendue                                                                                           |
| DateTime                | datetime.datetime       | int                | ClickHouse stocke DateTime en secondes depuis l'époque Unix. Cette valeur est disponible sous forme d'int                                             |
| DateTime64              | datetime.datetime       | int                | Python datetime.datetime est limité à une précision à la microseconde. La valeur int brute sur 64 bits est disponible                                 |
| Time                    | datetime.timedelta      | int, string, time  | L'instant est stocké sous forme de timestamp Unix. Cette valeur est disponible sous forme d'int                                                       |
| Time64                  | datetime.timedelta      | int, string, time  | Python datetime.timedelta est limité à une précision à la microseconde. La valeur int brute sur 64 bits est disponible                                |
| IPv4                    | `ipaddress.IPv4Address` | string             | Les adresses IP peuvent être lues sous forme de chaînes, et des chaînes correctement formatées peuvent être insérées comme adresses IP                |
| IPv6                    | `ipaddress.IPv6Address` | string             | Les adresses IP peuvent être lues sous forme de chaînes, et des chaînes correctement formatées peuvent être insérées comme adresses IP                |
| Tuple                   | dict or tuple           | tuple, json        | Les named tuple sont renvoyés sous forme de dictionnaires par défaut. Les named tuple peuvent aussi être renvoyés sous forme de chaînes JSON          |
| Map                     | dict                    | -                  |                                                                                                                                                       |
| Nested                  | Sequence\[dict]         | -                  |                                                                                                                                                       |
| UUID                    | uuid.UUID               | string             | Les UUID peuvent être lus sous forme de chaînes formatées conformément à la RFC 4122<br />                                                            |
| JSON                    | dict                    | string             | Un dictionnaire Python est renvoyé par défaut. Le format `string` renvoie une chaîne JSON                                                             |
| Variant                 | object                  | -                  | Renvoie le type Python correspondant au type de données ClickHouse stocké pour la valeur                                                              |
| Dynamic                 | object                  | -                  | Renvoie le type Python correspondant au type de données ClickHouse stocké pour la valeur                                                              |

<div id="external-data">
  ## Données externes
</div>

Les requêtes ClickHouse peuvent accepter des données externes dans n’importe quel format ClickHouse. Ces données binaires sont envoyées avec la chaîne de requête afin d’être utilisées pour le traitement des données. Les détails de la fonctionnalité External Data sont disponibles [ici](/docs/fr/reference/engines/table-engines/special/external-data). Les méthodes `query*` du client acceptent un paramètre facultatif `external_data` pour tirer parti de cette fonctionnalité. La valeur du paramètre `external_data` doit être un objet `clickhouse_connect.driver.external.ExternalData`. Le constructeur de cet objet accepte les arguments suivants :

| Nom        | Type              | Description                                                                                                                                                                     |
| ---------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| file\_path | str               | Chemin d’accès à un fichier sur le système local à partir duquel lire les données externes. `file_path` ou `data` est requis                                                    |
| file\_name | str               | Nom du « fichier » de données externes. S’il n’est pas fourni, il sera déterminé à partir de `file_path` (sans extension)                                                       |
| data       | bytes             | Les données externes sous forme binaire (au lieu d’être lues depuis un fichier). `data` ou `file_path` est requis                                                               |
| fmt        | str               | Le [format d’entrée](/docs/fr/reference/formats) ClickHouse des données. La valeur par défaut est `TSV`                                                                              |
| types      | str or seq of str | Liste des types de données des colonnes dans les données externes. S’il s’agit d’une chaîne, les types doivent être séparés par des virgules. `types` ou `structure` est requis |
| structure  | str or seq of str | Liste des noms de colonnes et des types de données dans les données (voir les exemples). `structure` ou `types` est requis                                                      |
| mime\_type | str               | Type MIME facultatif des données du fichier. Actuellement, ClickHouse ignore ce sous-en-tête HTTP                                                                               |

Pour envoyer une requête avec un fichier CSV externe contenant des données sur des « films » et combiner ces données avec une table `directors` déjà présente sur le serveur ClickHouse :

```python theme={null}
import clickhouse_connect
from clickhouse_connect.driver.external import ExternalData

client = clickhouse_connect.get_client()
ext_data = ExternalData(file_path='/data/movies.csv',
                        fmt='CSV',
                        structure=['movie String', 'year UInt16', 'rating Decimal32(3)', 'director String'])
result = client.query('SELECT name, avg(rating) FROM directors INNER JOIN movies ON directors.name = movies.director GROUP BY directors.name',
                      external_data=ext_data).result_rows
```

Des fichiers de données externes supplémentaires peuvent être ajoutés à l’objet `ExternalData` initial à l’aide de la méthode `add_file`, qui prend les mêmes paramètres que le constructeur. En HTTP, toutes les données externes sont transmises dans le cadre d’un téléversement de fichier `multi-part/form-data`.

<div id="time-zones">
  ## Fuseaux horaires
</div>

Il existe plusieurs mécanismes permettant d’appliquer un fuseau horaire aux valeurs ClickHouse DateTime et DateTime64. En interne, le serveur ClickHouse stocke toujours tout objet DateTime ou `DateTime64` sous la forme d’un nombre dépourvu d’information de fuseau horaire, représentant le nombre de secondes écoulées depuis l’epoch, soit 1970-01-01 00:00:00 UTC. Pour les valeurs `DateTime64`, cette représentation peut être en millisecondes, microsecondes ou nanosecondes depuis l’epoch, selon la précision. Par conséquent, toute information de fuseau horaire est toujours appliquée côté client. Notez que cela implique un surcroît de calcul non négligeable ; dans les applications où les performances sont critiques, il est donc recommandé de traiter les types DateTime comme des timestamps epoch, sauf pour l’affichage à l’utilisateur et les conversions (par exemple, les timestamps Pandas sont toujours des entiers 64 bits représentant des nanosecondes depuis l’epoch afin d’améliorer les performances).

Lors de l’utilisation, dans les requêtes, de types de données tenant compte du fuseau horaire — en particulier l’objet Python `datetime.datetime` — `clickhouse-connect` applique un fuseau horaire côté client selon les règles de préséance suivantes :

1. Si le paramètre de méthode de requête `client_tzs` est spécifié pour la requête, le fuseau horaire de la colonne concernée est appliqué
2. Si la colonne ClickHouse possède des métadonnées de fuseau horaire (c’est-à-dire si son type est, par exemple, DateTime64(3, 'America/Denver')), le fuseau horaire de la colonne ClickHouse est appliqué. (Notez que ces métadonnées de fuseau horaire ne sont pas disponibles pour clickhouse-connect pour les colonnes DateTime avant la version 23.2 de ClickHouse)
3. Si le paramètre de méthode de requête `query_tz` est spécifié pour la requête, le « fuseau horaire de la requête » est appliqué.
4. Si un paramètre de fuseau horaire est appliqué à la requête ou à la session, ce fuseau horaire est appliqué. (Cette fonctionnalité n’est pas encore disponible dans le serveur ClickHouse)
5. Enfin, si le paramètre client `apply_server_timezone` a été défini sur True (valeur par défaut), le fuseau horaire du serveur ClickHouse est appliqué.

Notez que si le fuseau horaire appliqué selon ces règles est UTC, `clickhouse-connect` renverra *toujours* un objet Python `datetime.datetime` sans fuseau horaire. Des informations de fuseau horaire supplémentaires peuvent ensuite être ajoutées à cet objet par le code de l’application si nécessaire.
