Conversions de types
Le client se veut aussi flexible que possible quant aux types de variables acceptés, aussi bien pour l’insertion que pour la sérialisation des réponses. Dans la plupart des cas, il existe un type Golang équivalent à un type de colonne ClickHouse, par exemple UInt64 vers uint64. Ces correspondances logiques doivent toujours être prises en charge. Vous pouvez également vouloir utiliser des types de variables pouvant être insérés dans des colonnes ou utilisés pour recevoir une réponse, à condition que la conversion de la variable ou des données reçues soit effectuée au préalable. Le client vise à prendre en charge ces conversions de manière transparente, afin que les utilisateurs n’aient pas à convertir leurs données pour qu’elles correspondent exactement avant l’insertion, tout en offrant une sérialisation flexible au moment de la requête. Cette conversion transparente n’autorise aucune perte de précision. Par exemple, un uint32 ne peut pas être utilisé pour recevoir des données d’une colonne UInt64. À l’inverse, une chaîne peut être insérée dans un champ datetime64, à condition de respecter le format requis. Les conversions de types actuellement prises en charge pour les types primitifs sont répertoriées ici. Ce travail est toujours en cours et peut être scindé entre l’insertion (Append/AppendRow) et la lecture (via un Scan). Si vous avez besoin de la prise en charge d’une conversion spécifique, veuillez ouvrir une issue.
L’interface standard database/sql doit prendre en charge les mêmes types que la ClickHouse API. Il existe quelques exceptions, principalement pour les types complexes, qui sont documentées dans les sections ci-dessous. Comme avec la ClickHouse API, le client se veut aussi flexible que possible quant aux types de variables acceptés, aussi bien pour l’insertion que pour la sérialisation des réponses.
Types complexes
Date/DateTime
Le client Go de ClickHouse prend en charge les types de date/date-heureDate, Date32, DateTime et DateTime64. Les dates peuvent être insérées sous forme de chaîne au format 2006-01-02, ou à l’aide des types Go natifs time.Time{} ou sql.NullTime. Les types DateTime prennent également en charge ces derniers, mais les chaînes doivent alors être transmises au format 2006-01-02 15:04:05, avec un décalage de fuseau horaire facultatif, par exemple 2006-01-02 15:04:05 +08:00. time.Time{} et sql.NullTime sont également pris en charge à la lecture, ainsi que toute implémentation de l’interface sql.Scanner.
La gestion des informations de fuseau horaire dépend du type ClickHouse et du fait que la valeur soit insérée ou lue :
- DateTime/DateTime64
- À l’insertion, la valeur est envoyée à ClickHouse au format de timestamp Unix. Si aucun fuseau horaire n’est fourni, le client utilisera par défaut son fuseau horaire local.
time.Time{}ousql.NullTimeseront convertis en époque Unix en conséquence. - À la lecture, le fuseau horaire de la colonne sera utilisé s’il est défini lors du renvoi d’une valeur
time.Time. Sinon, le fuseau horaire du serveur sera utilisé.
- À l’insertion, la valeur est envoyée à ClickHouse au format de timestamp Unix. Si aucun fuseau horaire n’est fourni, le client utilisera par défaut son fuseau horaire local.
- Date/Date32
- À l’insertion, le fuseau horaire de toute date est pris en compte lors de la conversion de la date en timestamp Unix, c’est-à-dire qu’un décalage correspondant au fuseau horaire est appliqué avant le stockage sous forme de date, car les types Date n’ont pas de paramètre régional dans ClickHouse. Si ce fuseau n’est pas indiqué dans une valeur chaîne, le fuseau horaire local sera utilisé.
- À la lecture, les dates lues dans des instances
time.Time{}ousql.NullTime{}seront renvoyées sans information de fuseau horaire.
Types Time/Time64
Les types de colonnesTime et Time64 stockent des valeurs d’heure sans composante de date. Tous deux correspondent à time.Duration en Go.
Timestocke l’heure avec une précision à la seconde.Time64(precision)prend en charge une précision inférieure à la seconde (commeDateTime64), où la précision va de 0 à 9.
Array
Les valeurs de type Array doivent être insérées sous forme de slices. Les règles de typage des éléments sont les mêmes que pour le type primitif : lorsque c’est possible, les éléments sont convertis. Un pointeur vers une slice doit être fourni au moment du Scan.Map
Les maps doivent être insérées sous forme de maps Go, dont les clés et les valeurs respectent les règles de type définies précédemment.Avec l’API database/sql, les valeurs de type Map doivent être strictement typées : vous ne pouvez pas utiliser
interface{} comme type de valeur. Par exemple, vous ne pouvez pas passer un map[string]interface{} pour un champ Map(String,String) ; vous devez utiliser un map[string]string à la place. En revanche, une variable interface{} sera toujours compatible et peut être utilisée pour des structures plus complexes.Exemple completTuples
Les tuples représentent un groupe de colonnes de taille arbitraire. Les colonnes peuvent être soit explicitement nommées, soit définies uniquement par un type, par exemple.Nested
Un champ Nested équivaut à un Array de Tuples nommés. Son utilisation dépend de la valeur 1 ou 0 définie par l’utilisateur pour flatten_nested. Lorsque flatten_nested est défini sur 0, les colonnes Nested restent un seul tableau de tuples. Cela vous permet d’utiliser des slices de maps pour l’insertion et la récupération, ainsi que des niveaux d’imbrication arbitraires. La clé de la map doit être identique au nom de la colonne, comme indiqué dans l’exemple ci-dessous. Remarque : puisque les maps représentent un tuple, elles doivent être de typemap[string]interface{}. Les valeurs ne sont actuellement pas fortement typées.
flatten_tested=0
Si la valeur par défaut de 1 est utilisée pour flatten_nested, les colonnes imbriquées sont aplaties en tableaux séparés. Cela nécessite l’utilisation de slices imbriquées pour l’insertion et la lecture. Bien que des niveaux d’imbrication arbitraires puissent fonctionner, cela n’est pas officiellement pris en charge.
flatten_nested=1
Remarque : les colonnes Nested doivent avoir les mêmes dimensions. Par exemple, dans l’exemple ci-dessus, Col_2_2 et Col_2_1 doivent contenir le même nombre d’éléments.
Grâce à une interface plus simple et à la prise en charge officielle de l’imbrication, nous recommandons flatten_nested=0.
Types géo
Le client prend en charge les types géo Point, Ring, LineString, Polygon, MultiPolygon et MultiLineString. Ces types sont représentés en Go à l’aide du paquet github.com/paulmach/orb.UUID
Le type UUID est pris en charge par le paquet github.com/google/uuid. Vous pouvez également envoyer et sérialiser un UUID sous forme de chaîne de caractères, ou de tout type qui implémentesql.Scanner ou Stringify.
Decimal
En raison de l’absence d’un type Decimal intégré en Go, nous recommandons d’utiliser le paquet tiers github.com/shopspring/decimal afin de manipuler nativement les types Decimal sans modifier vos requêtes d’origine.Vous pourriez être tenté d’utiliser Float à la place afin d’éviter des dépendances tierces. Toutefois, gardez à l’esprit que les types Float dans ClickHouse ne sont pas recommandés lorsque des valeurs exactes sont nécessaires.Si vous choisissez malgré tout d’utiliser le type Float intégré de Go côté client, vous devez convertir explicitement Decimal en Float à l’aide de la fonction toFloat64() ou de ses variantes dans vos requêtes ClickHouse. Gardez à l’esprit que cette conversion peut entraîner une perte de précision.
Nullable
La valeur Nil en Go représente un NULL dans ClickHouse. Elle peut être utilisée si un champ est déclaré Nullable. Lors de l’insertion, Nil peut être transmis aussi bien pour la version normale que pour la version Nullable d’une colonne. Dans le premier cas, la valeur par défaut du type sera conservée, par exemple une chaîne vide pour string. Pour la version nullable, une valeur NULL sera stockée dans ClickHouse. Lors de la lecture, l’utilisateur doit transmettre un pointeur vers un type qui prend en charge nil, par exemple *string, afin de représenter la valeur nil pour un champ Nullable. Dans l’exemple ci-dessous, col1, qui est un Nullable(String), reçoit donc un **string. Cela permet de représenter nil.sql.Null*, par exemple sql.NullInt64. Ils sont compatibles avec les types ClickHouse équivalents.
Grands entiers
Les types numériques de plus de 64 bits sont représentés à l’aide du paquet big natif de Go.BFloat16
BFloat16 est un type à virgule flottante brain sur 16 bits utilisé dans les charges de travail de machine learning. En Go, les valeurs BFloat16 sont insérées et lues comme des float32. Les variantes Nullable utilisent sql.NullFloat64.
QBit
QBit est un type de colonne expérimental permettant de stocker des représentations vectorielles au format bit-sliced, optimisé pour la recherche de similarité vectorielle. Il nécessite que le paramètre allow_experimental_qbit_type soit activé.
En Go, une colonne QBit(Float32, N) est insérée et lue sous forme de []float32, où N est la dimension du vecteur.