Conversiones de tipos
El cliente busca ser lo más flexible posible a la hora de aceptar tipos de variables, tanto para la inserción como para la serialización de respuestas. En la mayoría de los casos, existe un tipo de Golang equivalente para un tipo de columna de ClickHouse; por ejemplo, UInt64 corresponde a uint64. Estas correspondencias lógicas siempre deberían ser compatibles. También es posible que quiera utilizar tipos de variables que puedan insertarse en columnas o emplearse para recibir una respuesta, siempre que antes se realice la conversión de la variable o de los datos recibidos. El cliente busca admitir estas conversiones de forma transparente, para que los usuarios no tengan que convertir sus datos para ajustarlos con exactitud antes de la inserción, y para ofrecer una serialización flexible en tiempo de consulta. Esta conversión transparente no permite pérdida de precisión. Por ejemplo, un uint32 no puede usarse para recibir datos de una columna UInt64. En cambio, se puede insertar una cadena en un campo datetime64 siempre que cumpla los requisitos de formato. Las conversiones de tipos admitidas actualmente para tipos primitivos se recogen aquí. Este trabajo sigue en curso y puede dividirse entre la inserción (Append/AppendRow) y la lectura (mediante Scan). Si necesita compatibilidad con una conversión específica, abra un issue.
La interfaz estándar database/sql debería admitir los mismos tipos que la ClickHouse API. Hay algunas excepciones, principalmente en los tipos complejos, que se documentan en las secciones siguientes. Al igual que la ClickHouse API, el cliente busca ser lo más flexible posible a la hora de aceptar tipos de variables, tanto para la inserción como para la serialización de respuestas.
Tipos complejos
Date/DateTime
El cliente de Go para ClickHouse admite los tipos de fecha y fecha-horaDate, Date32, DateTime y DateTime64. Las fechas pueden insertarse como una cadena con el formato 2006-01-02 o mediante los tipos nativos de Go time.Time{} o sql.NullTime. Los tipos DateTime también admiten estos últimos tipos, pero las cadenas deben pasarse en el formato 2006-01-02 15:04:05, con un desplazamiento de zona horaria opcional; por ejemplo, 2006-01-02 15:04:05 +08:00. Tanto time.Time{} como sql.NullTime también se admiten en la lectura, así como cualquier implementación de la interfaz sql.Scanner.
El tratamiento de la información de zona horaria depende del tipo de ClickHouse y de si el valor se inserta o se lee:
- DateTime/DateTime64
- En el momento de insert, el valor se envía a ClickHouse en formato de marca temporal Unix. Si no se proporciona ninguna zona horaria, el cliente asumirá la zona horaria local del cliente.
time.Time{}osql.NullTimese convertirán a epoch en consecuencia. - En el momento de select, se usará la zona horaria de la columna, si está configurada, al devolver un valor
time.Time. En caso contrario, se usará la zona horaria del servidor.
- En el momento de insert, el valor se envía a ClickHouse en formato de marca temporal Unix. Si no se proporciona ninguna zona horaria, el cliente asumirá la zona horaria local del cliente.
- Date/Date32
- En el momento de insert, la zona horaria de cualquier fecha se tiene en cuenta al convertir la fecha en una marca temporal Unix; es decir, se aplicará el desplazamiento de la zona horaria antes de almacenarla como fecha, ya que los tipos
Dateno tienen configuración regional en ClickHouse. Si esto no se especifica en un valor de cadena, se usará la zona horaria local. - En el momento de select, las fechas que se lean en instancias
time.Time{}osql.NullTime{}se devolverán sin información de zona horaria.
- En el momento de insert, la zona horaria de cualquier fecha se tiene en cuenta al convertir la fecha en una marca temporal Unix; es decir, se aplicará el desplazamiento de la zona horaria antes de almacenarla como fecha, ya que los tipos
Tipos Time/Time64
Los tipos de columnaTime y Time64 almacenan valores de hora del día sin componente de fecha. Ambos se corresponden con time.Duration de Go.
Timealmacena la hora con precisión de segundos.Time64(precision)admite precisión por debajo del segundo (comoDateTime64), donde la precisión va de 0 a 9.
Array
Los Array deben insertarse como slices. Las reglas de tipado de los elementos son coherentes con las del tipo primitivo; es decir, cuando sea posible, los elementos se convertirán. En el momento de Scan, se debe proporcionar un puntero a un slice.Map
Los valores de tipo Map deben insertarse como mapas de Golang, con claves y valores que cumplan las reglas de tipo definidas anteriormente.Al usar la API
database/sql, los valores de tipo Map requieren un tipado estricto: no puedes usar interface{} como tipo de valor. Por ejemplo, no puedes pasar un map[string]interface{} para un campo Map(String,String); en su lugar, debes usar un map[string]string. Una variable interface{} siempre será compatible y puede usarse para estructuras más complejas.Ejemplo completoTuplas
Las tuplas representan un grupo de columnas de longitud arbitraria. Las columnas pueden tener un nombre explícito o solo especificar un tipo; p. ej.Nested
Un campo Nested equivale a un Array de Tuplas con nombre. Su uso depende de si el usuario ha configurado flatten_nested en 1 o en 0. Al configurar flatten_nested en 0, las columnas Nested se mantienen como un único array de tuplas. Esto le permite usar slices de mapas para la inserción y la recuperación, así como niveles arbitrarios de anidación. La clave del mapa debe ser igual al nombre de la columna, como se muestra en el ejemplo siguiente. Nota: como los mapas representan una tupla, deben ser del tipomap[string]interface{}. Actualmente, los valores no están fuertemente tipados.
flatten_tested=0
Si se usa el valor predeterminado de 1 para flatten_nested, las columnas anidadas se aplanan en arrays independientes. Esto requiere usar slices anidados para la inserción y la lectura. Aunque los niveles arbitrarios de anidación pueden funcionar, esto no tiene soporte oficial.
flatten_nested=1
Nota: Las columnas anidadas deben tener las mismas dimensiones. Por ejemplo, en el ejemplo anterior, Col_2_2 y Col_2_1 deben tener el mismo número de elementos.
Debido a que ofrece una interfaz más sencilla y soporte oficial para estructuras anidadas, recomendamos flatten_nested=0.
Tipos Geo
El cliente admite los tipos Geo Point, Ring, LineString, Polygon, MultiPolygon y MultiLineString. Estos tipos se representan en Go mediante el paquete github.com/paulmach/orb.UUID
El tipo UUID es compatible con el paquete github.com/google/uuid. También puede enviar y serializar un UUID como una cadena o como cualquier tipo que implementesql.Scanner o Stringify.
Decimal
Dado que Go no tiene un tipo Decimal integrado, recomendamos usar el paquete de terceros github.com/shopspring/decimal para trabajar con tipos Decimal de forma nativa sin modificar las consultas originales.Puede resultar tentador usar Float en su lugar para evitar dependencias de terceros. Sin embargo, tenga en cuenta que los tipos Float en ClickHouse no se recomiendan cuando se requieren valores precisos.Si aun así decide usar el tipo Float integrado de Go del lado del cliente, debe convertir Decimal a Float explícitamente mediante la función toFloat64() o sus variantes en las consultas de ClickHouse. Tenga en cuenta que esta conversión puede provocar una pérdida de precisión.
Nullable
El valor Nil de Go representa un NULL de ClickHouse. Puede usarse si un campo está declarado como Nullable. En el momento de insert, se puede pasar Nil tanto para la versión normal como para la Nullable de una columna. En el primer caso, se conservará el valor predeterminado del tipo; por ejemplo, una cadena vacía para string. En la versión Nullable, se almacenará un valor NULL en ClickHouse. Al escanear, el usuario debe pasar un puntero a un tipo que admita nil, por ejemplo, *string, para poder representar el valor nil de un campo Nullable. En el ejemplo siguiente, col1, que es un Nullable(String), recibe por tanto un **string. Esto permite representar nil.sql.Null*, por ejemplo, sql.NullInt64. Estos son compatibles con los tipos equivalentes en ClickHouse.
Enteros grandes
Los tipos numéricos de más de 64 bits se representan mediante el paquete big nativo de Go.BFloat16
BFloat16 es un tipo de punto flotante brain de 16 bits utilizado en cargas de trabajo de aprendizaje automático. En Go, los valores de BFloat16 se insertan y se leen como float32. Las variantes Nullable usan sql.NullFloat64.
QBit
QBit es un tipo de columna experimental para almacenar embeddings en formato bit-sliced, optimizado para la búsqueda de similitud vectorial. Requiere que la configuración allow_experimental_qbit_type esté habilitada.
En Go, una columna QBit(Float32, N) se inserta y se lee como []float32, donde N es la dimensión del vector.