Skip to main content

Cambios incompatibles con versiones anteriores

Cambios en consultas, funciones y sintaxis

  • Para las vistas cuyo cuerpo es un SELECT simple sobre una única tabla Distributed, ahora toda la consulta externa se delega a los segmentos (nuevo ajuste optimize_trivial_view_pushdown_to_distributed, habilitado de forma predeterminada). Esto cambia el comportamiento observable de dichas vistas: FINAL y SAMPLE indicados en la referencia a la vista ahora se propagan a la tabla local del segmento en lugar de ignorarse, y extremes no se devuelve en clústeres de un solo segmento. Establezca optimize_trivial_view_pushdown_to_distributed = 0 para restaurar el comportamiento anterior. #101791 (simonmichal).
  • Las partes de parche de UPDATE ligero ahora usan un nuevo formato en disco v2, ordenado por (sorting_key..., _block_number, _block_offset) y aplicado con un nuevo algoritmo de fusión. El pico de memoria queda limitado por la secuencia más larga con la misma clave de ordenación, en lugar de por el parche completo, y las actualizaciones que atraviesan límites de fusión ya no recurren a aplicarse mediante Join en memoria. Las partes de parche con el formato antiguo siguen siendo legibles. Durante una actualización progresiva desde una versión anterior a la 26.8, mantenga patch_parts_version = 'v1' o utilice el ajuste compatibility hasta que todas las réplicas se hayan actualizado. #103182 (CurtizJ).
  • AggregatingMergeTree ahora rechaza, al crear la tabla, los esquemas en los que alguna columna no forma parte de la clave de ordenación ni es una medida de estado de agregación (AggregateFunction/SimpleAggregateFunction). Durante las fusiones en segundo plano, estas columnas se reducen silenciosamente a un valor arbitrario, lo que produce resultados incorrectos en las consultas que aplican GROUP BY o filtran por ellas. Establezca allow_dimensions_outside_sorting_key = 1 para restaurar el comportamiento anterior. #108087 (alexey-milovidov).
  • ClickHouse ahora utiliza siempre el hash unificado de deduplicación de inserciones tanto en las inserciones síncronas como en las asíncronas; se eliminan los comportamientos heredados de deduplicación por inserción. El ajuste de servidor insert_deduplication_version se mantiene como salvaguarda para la migración: el servidor no se inicia si tiene asignado un valor heredado (old_separate_hashes o compatible_double_hashes). Para actualizar desde una versión que usaba un valor heredado, ejecute primero una versión que admita compatible_double_hashes (que escribe tanto los hash heredados como los unificados). En las tablas replicadas, manténgala en ejecución durante al menos replicated_deduplication_window_seconds (una hora de forma predeterminada; las ventanas predeterminadas conservan los hash unificados de todas las inserciones durante ese periodo, lo que se considera suficiente para un bucle de reintentos de inserción). En las tablas no replicadas con non_replicated_deduplication_window > 0, esa ventana se basa en un número de inserciones y no en el tiempo, por lo que debe ejecutar compatible_double_hashes durante al menos esa cantidad de inserciones. Después, elimine el ajuste (o establézcalo en new_unified_hash) antes de actualizar a esta versión. #108361 (CheSema).
  • El ajuste use_legacy_to_time ahora es 0 de forma predeterminada, por lo que toTime convierte los valores al tipo de datos Time en lugar de convertir una fecha con hora en una fecha fija. El comportamiento heredado sigue disponible mediante la función toTimeWithFixedDate o estableciendo use_legacy_to_time = 1. #108729 (alexey-milovidov).
  • Los modelos Naive Bayes (utilizados por naiveBayesClassifier) ahora se configuran como un diccionario con el layout NAIVE_BAYES, que se construye durante la carga a partir de una tabla de recuentos de n-gramas preagregados por clase, en lugar de la configuración anterior del lado del servidor (un archivo de configuración XML que hacía referencia a archivos de modelo .bin serializados), que ya no es compatible: los modelos existentes deben recrearse como diccionarios. Se añaden tres nuevas funciones junto a naiveBayesClassifier: naiveBayesClassifierWithProb devuelve la clase predicha junto con su probabilidad, naiveBayesClassifierWithAllProbs devuelve todas las clases con sus probabilidades y naiveBayesNgrams divide el texto en n-gramas del mismo modo que el diccionario, lo que permite construir los datos de entrenamiento a partir de texto etiquetado sin procesar. Además, se han aplicado varias optimizaciones de rendimiento: con un modelo de lenguaje de trigramas de puntos de código de 9.7 MiB, utiliza ~49× menos memoria (de 1.84 GiB a 38 MiB), se carga ~11× más rápido y clasifica ~11× más rápido. #108773 (nihalzp).
  • El valor predeterminado de la configuración max_insert_threads ha cambiado de 1 (sin paralelismo) a auto, que equivale al número de núcleos de CPU disponibles para el servidor (y se reduce cuando hay presión de memoria, según max_insert_threads_min_free_memory_per_thread). Esto paraleliza INSERT SELECT de forma predeterminada y también puede paralelizar la parte de escritura de un INSERT simple apto cuando la ruta de escritura de destino admite distribuirse de forma segura. Esto puede cambiar el número de partes creadas y el orden de las filas insertadas. Para restaurar el comportamiento anterior, establezca max_insert_threads en 1 o compatibility en una versión inferior a 26.8. #109000 (alexey-milovidov). #109006 (alexey-milovidov).
  • Al leer un Tuple simple en CSV, ahora se toma un campo por elemento en todas las posiciones, de modo que un \N en el campo de un elemento de nivel superior corresponde a ese elemento y se le aplica input_format_null_as_default. Anteriormente, un \N inicial se interpretaba como que toda la columna era nula, por lo que la fila se sustituía por el valor predeterminado de la columna y luego fallaba el análisis de las celdas de los elementos restantes. Este cambio es incompatible con versiones anteriores en el caso de una fila que proporciona un único campo para todo un Tuple simple: ahora le faltan los elementos restantes y se rechaza; y, en el caso de un Tuple de un solo elemento, donde el número de campos es el mismo en ambos casos, devuelve silenciosamente el valor predeterminado del elemento en lugar del DEFAULT de la columna. Establezca input_format_csv_deserialize_separate_columns_into_tuple = 0 para volver a leer dicho campo como la columna completa. #109744 (groeneai).
  • Se añadió la cláusula VALID FOR <interval> a CREATE USER y ALTER USER como forma abreviada de VALID UNTIL. La fecha límite de expiración se calcula como la hora actual más el intervalo indicado en el momento de ejecutar la consulta y se almacena con la forma VALID UNTIL. La columna valid_until de la tabla system.users ahora es de tipo Array(DateTime64(0)) en lugar de Array(DateTime), para que las fechas límite posteriores al año 2106 se representen con exactitud; las herramientas que leen esta columna deben admitir el nuevo tipo. #110171 (alexey-milovidov).
  • EXPLAIN SYNTAX ahora devuelve la consulta reformateada como un único registro String (con saltos de línea incrustados) en lugar de un registro por línea, de modo que su salida es una única fila recuperable que puede utilizarse directamente (por ejemplo, SELECT count() FROM (EXPLAIN SYNTAX ...) devuelve 1). Este comportamiento se controla mediante la nueva opción single_record, cuyo valor predeterminado es 1; establezca single_record = 0 para restaurar la salida tradicional de un registro por línea. Los demás tipos de EXPLAIN (PLAN/PIPELINE/AST) mantienen su salida en árbol línea por línea. #110479 (alexey-milovidov).
  • La función hasColumnInTable ya no acepta los argumentos opcionales hostname, username y password para comprobar una columna en un servidor remoto arbitrario; solo se mantiene la forma hasColumnInTable(database, table, column). El modo remoto eliminado suponía un problema de seguridad: permitía a cualquier usuario iniciar conexiones salientes a hosts arbitrarios, exponía credenciales en los registros de consultas y no estaba restringido por ningún privilegio. #110881 (alexey-milovidov).
  • Los motores de base de datos PostgreSQL y MaterializedPostgreSQL ahora respetan la configuración remote_url_allow_hosts del servidor, como ya hacían el motor de tabla PostgreSQL, la función de tabla postgresql y los diccionarios creados mediante DDL. La política se aplica en CREATE DATABASE y en los ATTACH DATABASE ejecutados por el usuario: si remote_url_allow_hosts está configurado en su servidor, ahora se rechaza con UNACCEPTABLE_URL la creación o el adjuntado de una base de datos PostgreSQL o MaterializedPostgreSQL que apunte a un host fuera de la lista de permitidos. Las bases de datos existentes se siguen cargando al iniciar el servidor, de modo que una actualización no puede impedir que el servidor arranque. #111135 (alexey-milovidov).
  • Se eliminaron el lector y el escritor basados en la biblioteca Apache Arrow para los formatos Arrow y ArrowStream. La implementación nativa de ClickHouse, predeterminada desde la versión 26.7, es ahora la única. Los ajustes input_format_arrow_use_native_reader y output_format_arrow_use_native_writer están obsoletos: se siguen aceptando, pero no tienen ningún efecto, por lo que una consulta que los establecía en 0 para forzar la implementación de Apache Arrow ahora utiliza la nativa. #111996 (alexey-milovidov).
  • Las credenciales TLS de un origen MySQL (ssl_ca, ssl_cert, ssl_key) ya no pueden especificarse como rutas de archivo desde SQL —en una colección con nombre creada con CREATE NAMED COLLECTION, como argumento de consulta o en una consulta CREATE DICTIONARY—, ya que el servidor abre esos archivos con sus propios privilegios. Las rutas siguen admitiéndose en el archivo de configuración del servidor. En los demás casos, pase el contenido del certificado o de la clave en los nuevos parámetros ssl_ca_pem, ssl_cert_pem y ssl_key_pem, que se enmascaran en los registros y en las consultas SHOW al igual que las contraseñas. #112070 (alexey-milovidov).
  • disable_insertion_and_mutation ahora impide el consumo en segundo plano de las tablas Kafka, RabbitMQ y NATS, pero sigue permitiendo escrituras directas en el almacenamiento externo. Las tablas Kafka2, NATS y RabbitMQ afectadas por esta restricción no inicializan consumidores para un SELECT directo. El ajuste message_queue_disable_insertion, introducido recientemente, ahora requiere reiniciar el servidor. #113660 (cwurm).
  • Un PARTITION BY u ORDER BY de ventana sobre una columna AggregateFunction ahora se rechaza con ILLEGAL_COLUMN, como ya ocurría con un ORDER BY de nivel superior sobre ese tipo de columna. Anteriormente, al menos uno de los analizadores aceptaba este tipo de consultas, y el PARTITION BY de ventana particionaba de forma distinta según max_threads. El rechazo también se aplica a un estado anidado en Array, Tuple, Map, Variant o SimpleAggregateFunction. No se ven afectados un SimpleAggregateFunction sobre un tipo ordinario, QBit, ni GROUP BY y DISTINCT sobre un estado. #113878 (groeneai).
  • Se corrigen las comprobaciones de acceso de los comandos SYSTEM ... CACHE ON CLUSTER. Exigían el grupo de privilegios SYSTEM DROP CACHE en lugar del privilegio propio de cada comando, lo que denegaba el acceso a quienes tenían un único privilegio granular de caché y, a la vez, permitía a quien tuviera el grupo ejecutar SYSTEM SYNC FILESYSTEM CACHE ON CLUSTER sin disponer de SYSTEM SYNC FILESYSTEM CACHE. #114042 (groeneai).
  • El motor de tabla NATS acepta credenciales en línea mediante el nuevo ajuste nats_credentials (con el mismo contenido que un archivo .creds) y ya no admite nats_credential_file desde SQL: la ruta hace referencia a un archivo del sistema de archivos del servidor, que este abre con sus propios privilegios, por lo que solo puede especificarse en una colección con nombre definida en el archivo de configuración del servidor o como nats.credential_file en la propia configuración del servidor. Una consulta puede sustituir esa ruta configurada por nats_credentials en línea, salvo que el operador la haya fijado con <nats_credential_file overridable="false">. Las tablas creadas antes de esta restricción siguen funcionando tras una actualización. #114644 (alexey-milovidov).

Cambios en tipos de datos y formatos

  • Se rechaza el formato de archivo de copia de seguridad zip/zipx para copias de seguridad guardadas en almacenamiento de objetos —destinos directos S3(...)/AzureBlobStorage(...) y destinos Disk(...) respaldados por S3 o Azure—, tanto para BACKUP como para RESTORE. Zip necesita realizar búsquedas aleatorias para leer su directorio central, algo muy lento en almacenamiento de objetos. Utilice en su lugar un formato basado en tar, como tar.gz. #101770 (Onyx2406).
  • Se amplió el rango admitido de DateTime64 de [1900-01-01, 2299-12-31] a [0000-01-01, 9999-12-31]. Los valores fuera del rango anterior ahora se calculan correctamente (mediante cctz) en lugar de ajustarse al límite. Con precision 8 o 9, el rango sigue siendo más reducido porque los ticks se almacenan como Int64 (con precisión de nanosegundos, el máximo sigue siendo 2262-04-11). Compatibilidad con versiones anteriores: si antes utilizaba fechas y horas fuera de rango, pero dependía de las reglas de saturación tan específicas del rango anterior, tenga en cuenta que los resultados cambian ahora para ser más correctos. #107907 (alexey-milovidov).
  • Un número JSON sin comillas destinado a una columna DateTime64/DateTime en JSONEachRow y formatos similares ahora se interpreta como una marca de tiempo Unix (segundos desde la época) con precisión opcional inferior al segundo, de forma coherente con el formato Values, CAST y toDateTime64. Anteriormente, un número con parte fraccionaria (p. ej., 1703363853.035) se rechazaba con CANNOT_PARSE_INPUT_ASSERTION_FAILED, y un entero sin más (p. ej., 1703363853) se leía como el valor escalado sin procesar de un DateTime64, lo que producía una marca de tiempo 1970-.... Se trata de un cambio incompatible con versiones anteriores para los enteros sin comillas enviados a columnas DateTime64; las cadenas entre comillas y la salida JSON propia de ClickHouse (siempre entre comillas) no se ven afectadas. #108091 (alexey-milovidov).
  • El códec experimental ALP ahora realiza la aritmética de escalado de Float32 en Float64, lo que elimina las excepciones con datos decimales y mejora notablemente las tasas de compresión. #111627 (rienath).
  • Se rechazan los valores de configuraciones de intervalo de tiempo (milisegundos/segundos) que desbordan un Int64 expresado en microsegundos #112757 (azat).
  • Las métricas asíncronas ahora pueden tener el tipo de datos Map, y las métricas por núcleo de CPU y por dispositivo se han convertido en métricas clave-valor únicas: OSUserTimeCPU0, OSUserTimeCPU1, … pasan a ser una única métrica OSUserTimeCPU con un mapa que asocia el número de núcleo de CPU con su valor (y lo mismo ocurre con las demás métricas OS*TimeCPU*, CPUFrequencyMHz_*, Temperature*, EDAC*, Block*_*, Network(Receive|Send)*_*, Disk*_*, *BlobsQueueEstimate y AsyncLogging*QueueSize). system.asynchronous_metrics tiene una nueva columna key_values Map(LowCardinality(String), Float64) (la columna value es NaN para dichas métricas), system.asynchronous_metric_log las registra como una fila por clave mediante una nueva columna key, el endpoint de Prometheus las exporta con una etiqueta (p. ej., ClickHouseAsyncMetrics_BlockReadBytes{device="sda"}) y el MetricsTransmitter de Graphite las envía como <prefix>.<Metric>.<key>. Si su sistema de monitorización lee los nombres de métricas antiguos, establezca asynchronous_metrics_key_values_mode en legacy_names para conservarlos, o en both durante la migración; esta configuración del servidor se aplica con SYSTEM RELOAD CONFIG sin necesidad de reiniciar. #115333 (alexey-milovidov). #116791 (alexey-milovidov).
  • Los discos de almacenamiento de objetos ahora usan de forma predeterminada transacciones nativas del almacenamiento de metadata, lo que mejora la consistencia de sus actualizaciones de metadata. #89658 (Michicosun).

Cambios en la configuración

  • Se eliminaron las funciones snowflakeToDateTime, snowflakeToDateTime64, dateTimeToSnowflake y dateTime64ToSnowflake, obsoletas desde hace tiempo. Se marcaron como obsoletas ya en la v24.6 en favor de snowflakeIDToDateTime, snowflakeIDToDateTime64, dateTimeToSnowflakeID y dateTime64ToSnowflakeID, que son las que deben usarse. El ajuste allow_deprecated_snowflake_conversion_functions (que permitía volver a habilitarlas) queda obsoleto y ya no tiene ningún efecto. #108711 (alexey-milovidov).
  • Se amplió el rango admitido de Date32 de [1900-01-01, 2299-12-31] a [0000-01-01, 9999-12-31], igual que el de DateTime64. El análisis y las conversiones ahora aceptan el rango ampliado en lugar de recortar silenciosamente los valores a los límites anteriores. Notas de compatibilidad con versiones anteriores: en la conversión numérica toDate32(N), los valores en [120530, 2932896] ahora se interpretan como números de día (fechas de 2300-01-01 a 9999-12-31) en lugar de como marcas temporales Unix de principios de 1970, conforme a la regla de que todo número que cabe en el rango de números de día se trata como número de día; los números inferiores al número de día de 0000-01-01 y las marcas de tiempo posteriores a 9999-12-31 se saturan en los nuevos límites. #111534 (alexey-milovidov).

Otros cambios incompatibles con versiones anteriores

  • arrayIntersect y arraySymmetricDifference ya no tratan un valor repetido dentro de un mismo argumento como si apareciera en varios argumentos. Las consultas que dependan del comportamiento anterior pueden devolver ahora resultados diferentes: arrayIntersect([1], [2], [1, 1]) devuelve [] en lugar de [1], arrayIntersect([1, 2], [2], [1, 1, 2]) devuelve [2] en lugar de [1, 2], y arraySymmetricDifference([1], [2], [1, 1]) devuelve [2, 1] en lugar de [2]. En el caso de arraySymmetricDifference, basta con dos argumentos: arraySymmetricDifference([1], [2, 2]) devuelve [2, 1] en lugar de [1]. Ahora, un valor solo se contabiliza para un argumento si estaba presente en todos los argumentos anteriores, de modo que el resultado contiene exactamente los valores presentes en todos los argumentos. Como parte del mismo cambio, arrayIntersect construye su tabla hash a partir del argumento más pequeño en lugar de hacerlo a partir de todos ellos, lo que lo hace hasta 1,85 veces más rápido y reduce en un tercio el uso de memoria cuando los argumentos tienen tamaños muy distintos. arrayUnion no se ve afectado. #113021 (alexey-milovidov).
  • Se ha marcado como obsoleto el tipo de estadísticas de columna minmax. #108680 (hanfei1991).
  • Se corrige la comprobación de acceso de SYSTEM PREWARM PRIMARY INDEX CACHE ... ON CLUSTER, que exigía erróneamente el privilegio SYSTEM PREWARM MARK CACHE en lugar de SYSTEM PREWARM PRIMARY INDEX CACHE. #109198 (Algunenano).
  • Se ha corregido un problema por el que SYSTEM STOP/START CLEANUP y SYSTEM STOP/START VIRTUAL PARTS UPDATE ON CLUSTER exigían SYSTEM PULLING REPLICATION LOG en lugar de SYSTEM CLEANUP / SYSTEM VIRTUAL PARTS UPDATE. #110289 (groeneai).
  • El glob / (cualquier número de directorios) ahora también coincide con el propio directorio. Anteriormente, / no se trataba como un caso especial en los patrones glob, por lo que data/**/file.txt no coincidía con data/file.txt (cero niveles de directorio). #97676 (alexey-milovidov).

Nuevas características

Funciones y tipos de datos

  • Se añadieron las funciones parseQueryToJSON y formatQueryFromJSON para serializar y deserializar AST como JSON, así como un dialecto experimental clickhouse_json que se habilita mediante enable_json_ast_dialect. #100412 (alexey-milovidov). #113480 (fm4v).
  • Se añadió la tabla del sistema system.stemmers, que muestra todos los idiomas de stemmers disponibles que pueden especificarse en la función stem. #100611 (Ergus).
  • Se añadió compatibilidad con los operadores posfijos de SQL estándar AT TIME ZONE y AT LOCAL como azúcar sintáctico para toTimeZone. La expresión expr AT TIME ZONE zone ahora equivale a toTimeZone(expr, zone), y expr AT LOCAL equivale a toTimeZone(expr, timeZone()). #106092 (lvzhipin03).
  • El motor de tabla URL y la función de tabla url ahora redirigen al backend adecuado según el esquema de la URL: file:// lo gestiona el motor File; s3:///gs:///gcs:///oss://, S3; az:///azure:///abfss:///abfs://, AzureBlobStorage; hdfs://, HDFS; y http(s)://, el motor URL, como hasta ahora. La configuración url_base se aplica antes de la redirección por esquema. Solo se redirigen los esquemas de S3 resueltos por los url_scheme_mappers predeterminados; otros esquemas de proveedores compatibles con S3 (cos, obs, …) no se redirigen y requieren usar directamente el motor o la función s3. #106093 (alexey-milovidov).
  • Se añadió la función dotProductTransposed (alias scalarProductTransposed), que calcula el producto interno aproximado entre una columna QBit y un vector de referencia, y complementa las funciones ya existentes L2DistanceTransposed y cosineDistanceTransposed. #108100 (alexey-milovidov).
  • Se añadió un parámetro opcional stride al tipo de datos QBit (QBit(T, dimension, stride)) que almacena grupos de dimensiones en flujos independientes, de modo que una búsqueda vectorial pueda leer de forma eficiente solo las primeras dimensiones (por ejemplo, con embeddings Matryoshka). Las funciones de distancia transpuestas aceptan un cuarto argumento opcional, used_dims, para leer un número reducido de dimensiones. #108103 (alexey-milovidov).
  • Se añadió compatibilidad con el tipo de elemento Int8 en el tipo de datos QBit, lo que permite el almacenamiento y la búsqueda vectorial por distancia transpuesta (L2DistanceTransposed, cosineDistanceTransposed) sobre vectores cuantizados de enteros de 8 bits. #108105 (alexey-milovidov).
  • Nueva función randomHadamardTransform(vector[, seed[, output_dims]]): una transformada de Hadamard aleatorizada y determinista de un vector de punto flotante, es decir, una rotación ortogonal que preserva la norma, útil para preprocesar embeddings antes de la cuantización y, si se trunca, como proyección aleatoria de Johnson–Lindenstrauss / Hadamard aleatorizada submuestreada. #108227 (alexey-milovidov).
  • Se implementó la función de agregación mergedJSONPatch para la agregación de tipo merge-patch al estilo de RFC 7396 sobre valores JSON, con compatibilidad con la fusión de estados y uso en AggregatingMergeTree. Los usuarios pueden agregar una columna JSON usando una marca de tiempo u otra columna de ordenación como clave de ordenación para obtener el estado más reciente. #108349 (larryluogit).
  • Se añadió la función xxHash64Spark, que calcula valores xxHash64 compatibles con Spark para entradas String y NULL usando la semilla 42 y devuelve Int64. #108436 (lalitium).
  • Se añadió la función digits(n, offset[, length]), que devuelve el número contenido en n que comienza en el índice offset(1-indexed) y tiene length dígitos. Si no se proporciona length, la función devuelve el número desde offset hasta el final. #109012 (1000ms).
  • Se añadió la función aritmética sqr para calcular el cuadrado de un número. #109061 (lalitium).
  • Se añadieron las funciones de distancia transpuestas cuantizadas cosineDistanceTransposedQuantized, L2DistanceTransposedQuantized y dotProductTransposedQuantized, que operan sobre un QBit(Int8) de códigos Lloyd-Max de quantizeBFloat16ToInt8 y decuantizan sobre la marcha los códigos almacenados. Un vector de referencia de coma flotante actúa como consulta de precisión completa y se compara con precisión Float32 (una consulta Float64 se convierte a una precisión menor); una referencia Array(Int8) también se decuantiza, lo que da lugar a una distancia simétrica entre cuantizado y cuantizado. #109405 (alexey-milovidov).
  • Se añadió la nueva función dictGetRoot, que devuelve el ancestro de nivel más alto (la raíz) de una clave en un diccionario jerárquico. Es un equivalente práctico de dictGetHierarchy(dict_name, key)[-1]. #109459 (alexey-milovidov).
  • Se añadió la función de tabla mergeTreeCodecBlockCounts(database, table), que indica, para cada combinación de (parte, columna, subflujo) de una tabla MergeTree, cuántos bloques comprimidos utilizan cada códec. #109623 (rienath).
  • Se añadió la función notHas, la negación de has para arrays, mapas y JSON. Cuando el pajar (haystack) es un array constante, optimize_rewrite_has_to_in (habilitado de forma predeterminada) reescribe notHas(constant_array, x) como x NOT IN constant_array, de modo que se ejecuta mediante una búsqueda en un conjunto y, al igual que NOT IN, puede aprovechar el índice de clave primaria para descartar datos. #109926 (nihalzp).
  • Se añadió el tipo de datos geoespacial MultiPoint, almacenado como Array(Point), y se incluyó en el tipo Geometry. #109951 (davidmenggx).
  • Las funciones arrayElement (el operador vec[n]) y arraySlice ahora admiten el tipo de datos QBit: qbit[n] devuelve el n-ésimo elemento del vector con precisión completa, y arraySlice(qbit, offset, length) devuelve una proyección sobre un subconjunto de dimensiones. Ambas leen únicamente los planos de bits de los grupos de stride que necesitan, y los fragmentos alineados con los límites de los grupos de stride reutilizan los streams almacenados sin copiarlos. #109953 (Utkal059).
  • Se añadió el tokenizador splitByRegexp para índices de texto y la función tokens. Divide la entrada en tokens usando una expresión regular como separador, por ejemplo tokenizer = splitByRegexp('[^\p{L}\p{N}#+]+'), lo que permite conservar tokens con caracteres especiales como C++ o C#, que otros tokenizadores dividirían. #110002 (Ergus).
  • Se añadieron las funciones geometryIntersectCartesian y geometryIntersectSpherical, que indican si dos geometrías se intersecan. A diferencia de polygonsIntersectCartesian/polygonsIntersectSpherical, aceptan cualquier tipo de dato geométrico (Point, LineString, MultiLineString, Ring, Polygon, MultiPolygon), incluido el tipo común Geometry, y los dos argumentos pueden ser de tipos distintos. #110062 (alexey-milovidov).
  • El lector nativo de ORC ahora admite el uniontype de ORC y lo asigna al tipo Variant de ClickHouse (antes, estas columnas se rechazaban con Unsupported ORC type). #110078 (alexey-milovidov).
  • El formato de salida nativo de ORC ahora puede escribir el tipo Variant de ClickHouse y lo asigna a un uniontype de ORC (antes fallaba con ILLEGAL_COLUMN). #110085 (alexey-milovidov).
  • Se añaden formatos de estructura de tramas, que se seleccionan mediante el nuevo ajuste framing_output_format: multiplexan las distintas partes de la respuesta de la consulta en un único flujo de respuesta HTTP (bloques de datos, totales y extremos, paquetes de progreso, eventos de perfil, registros del servidor y excepciones). Formatos de estructura de tramas implementados: None (predeterminado; todo funciona como antes), EventStream (eventos enviados por el servidor mediante HTTP), JSONEachPacketBase64 y JSONEachPacketString (un objeto JSON por paquete con los datos codificados en base64 o como cadena). #110127 (alexey-milovidov).
  • Se añadieron la función de tabla bigquery y el motor de tabla BigQuery para leer y escribir en tablas de Google BigQuery, incluidos los conjuntos de datos públicos. La estructura de la tabla se infiere a partir de su esquema en BigQuery. Para la autenticación se admite un token de acceso OAuth, una clave de cuenta de servicio en formato JSON y un cliente OAuth con un token de actualización. #110166 (alexey-milovidov).
  • Nueva función aiRedact, que detecta y oculta información de identificación personal (PII) en textos mediante un proveedor de LLM. Especifique las categorías que se deben ocultar (p. ej., ['email', 'name']) o pase un array vacío para usar un conjunto predeterminado de categorías de PII. Los valores detectados se reemplazan por un token ([REDACTED] de forma predeterminada). #110464 (davidmenggx).
  • Se añade la función aiFilter, que evalúa una condición en lenguaje natural sobre un texto mediante un LLM y devuelve UInt8 para usarla en WHERE, PREWHERE y JOIN ... ON. #110594 (ylw510).
  • Se admiten conexiones TLS/SSL a PostgreSQL en el motor de tabla PostgreSQL, la función de tabla postgresql, los motores de base de datos PostgreSQL y MaterializedPostgreSQL, y los diccionarios PostgreSQL: sslmode, además de los certificados y la clave, proporcionados como contenido literal (sslrootcert_pem, sslcert_pem, sslkey_pem; se enmascaran igual que las contraseñas) o como rutas (sslrootcert, sslcert, sslkey; solo se aceptan desde una colección con nombre definida en el archivo de configuración del servidor). #110615 (alexey-milovidov).
  • La función de tabla postgresql y el motor de tabla PostgreSQL ahora pueden usarse para conectarse a otro servidor ClickHouse a través del protocolo PostgreSQL (cuando se usa un nombre de tabla; la variante query(...) aún no es compatible). Se añadieron las funciones de compatibilidad con PostgreSQL format_type y current_setting. #110760 (alexey-milovidov).
  • Nueva función aiSimilarity que calcula la similitud semántica entre dos textos mediante un modelo de embeddings. Devuelve un Nullable(Float32) en [-1, 1], donde 1 significa que los textos son idénticos, o NULL si un operando es NULL o está vacío, o si falló el cálculo de su embedding. #110777 (davidmenggx).
  • Se añadieron los motores de base de datos Remote y RemoteSecure, que proporcionan acceso en tiempo real a las tablas de una base de datos en un servidor de ClickHouse remoto, al que reenvían las consultas SELECT e INSERT. Son el equivalente, entre ClickHouse y ClickHouse, de los motores de base de datos MySQL y PostgreSQL. #110975 (alexey-milovidov).
  • Compatibilidad con operadores de canalización en consultas SQL: FROM t |> WHERE x > 1 |> AGGREGATE count() AS c GROUP BY y |> ORDER BY c DESC |> LIMIT 10, de forma similar a la sintaxis de canalización de GoogleSQL. Cualquier consulta SELECT puede ir seguida de una cadena de operadores |>, y cada operador envuelve la consulta anterior en una subconsulta, por lo que el AST resultante es el mismo que el de la consulta equivalente con subconsultas anidadas. En una consulta que comienza con la cláusula FROM, la cláusula SELECT ahora es opcional y, por defecto, equivale a SELECT *. #111151 (alexey-milovidov).
  • Se añadió la función de agregación gini para calcular el coeficiente de Gini de valores numéricos finitos y no negativos, incluidas las agregaciones agrupadas y distribuidas. #112280 (amirreza1307). #114643 (groeneai).
  • Compatibilidad con PNG animado en el formato de salida PNG. Una columna t convierte el resultado de una consulta en una animación; la escala de tiempo de t se define mediante output_format_image_time_multiplier_seconds y output_format_image_time_divisor_seconds, y output_format_image_streaming_animation permite escribir los fotogramas a medida que la consulta los genera, en lugar de mantenerlos en un búfer en memoria. #112846 (alexey-milovidov).
  • Se añadió una columna finish_time a system.mutations que registra cuándo se completó una mutación. Para las mutaciones no finalizadas y aquellas cuyo momento de finalización se desconoce, el valor es cero. #113474 (nikitamikhaylov).
  • Se añade un nuevo tipo de esquema bucketed para system.metric_log, que almacena todas las métricas en una única columna Map(Enum16(...), Int64) mediante la serialización Map por buckets (128 buckets), además de una columna ALIAS por métrica para mantener la compatibilidad: la tabla consta de unas pocas columnas en lugar de miles, los valores cero no se almacenan y leer una sola métrica implica leer únicamente uno de los 128 buckets. Además, un Map con claves Enum ahora puede indexarse mediante el nombre (como cadena) del valor del enum, p. ej., map['name']. #115380 (alexey-milovidov).
  • Se añadió un tokenizador chinese para la función tokens y los índices de texto de MergeTree. Segmenta el texto chino en palabras mediante un diccionario y un modelo oculto de Markov (el algoritmo se basa en jieba), con las granularidades coarse_grained (predeterminada) y fine_grained. #89945 (amosbird).
  • Se añade la función de agregación groupFormat, que formatea las filas de cada grupo con un formato de salida especificado y devuelve el resultado como una cadena. #93201 (wandersofb).
  • Se añade el combinador de funciones de agregación -Tuple, que aplica la función de agregación subyacente a cada elemento de una columna Tuple de forma independiente y devuelve un Tuple con los resultados, conservando los nombres de los elementos: sumTuple(t) para t = (a, b) devuelve (sum(a), sum(b)). Las funciones de agregación con varios argumentos reciben una tupla por argumento, emparejadas por posición: corrTuple((a1, a2), (b1, b2)) devuelve (corr(a1, b1), corr(a2, b2)). A diferencia de -ForEach aplicado a arrays, los elementos pueden ser de tipos distintos, y se conservan el tipo de resultado y el nombre de cada elemento. #98190 (RinChanNOWWW).

Funcionalidades de SQL y de consultas

  • Se añadió compatibilidad con cláusulas WHERE en las definiciones de proyecciones. Las proyecciones con WHERE solo materializan las filas que cumplen el predicado, y el optimizador puede usarlas (en función del coste) cuando el WHERE de la consulta implica el WHERE de la proyección. #102347 (SBALAVIGNESH123).
  • Se añadió una forma de acceder a tablas y bases de datos mediante rutas URL en la interfaz HTTP (p. ej., `/database/table.format.gz?filter=a>0`), además de nuevas configuraciones (`http_allow_database_as_path`, `http_allow_table_as_file`, `http_allow_filters_as_path`, `http_allow_filters_as_unrecognized_url_parameters`, `select`, `order`, `sort`, `filter`, `page`, `compression`, `format`, `input_format`, `output_format`, `default_format`, `database`) que pueden combinarse entre sí y con el parámetro de URL `query` ya existente. #105249 (alexey-milovidov).
  • Se añadieron los motores de tabla Remote y RemoteSecure, equivalentes persistentes de las funciones de tabla remote y remoteSecure. Ahora, además de CREATE TABLE ... AS remote(...), también funciona CREATE TABLE ... ENGINE = Remote('addresses', db, table, ...). #106189 (alexey-milovidov).
  • Se añadió EXPLAIN ANALYZE para examinar el rendimiento de las consultas: la consulta se ejecuta y las métricas reales de ejecución se muestran en el habitual formato de plan de consulta. #106586 (Fgrtue). #110668 (Fgrtue).
  • Se añadieron los comandos SYSTEM STOP, SYSTEM START, SYSTEM PAUSE, SYSTEM CANCEL y SYSTEM REFRESH, independientes del motor, junto con sus variantes ... ALL BACKGROUND para todo el servidor, que permiten controlar desde una única interfaz unificada la actividad en segundo plano de las tablas Kafka, RabbitMQ, NATS y S3Queue/AzureQueue, así como de las vistas materializadas actualizables. En el caso de las vistas materializadas actualizables, actúan como alias de los comandos SYSTEM ... VIEW ya existentes. Como parte de la compatibilidad con estos controles en NATS, las tablas JetStream ahora confirman los mensajes solo después de una inserción correcta (semántica «al menos una vez»; antes, los mensajes se confirmaban automáticamente al entregarse y podían perderse si fallaba la inserción). La nueva configuración nats_wait_for_flush_interval (por defecto false, lo que mantiene el comportamiento anterior de baja latencia) permite mantener abierto un ciclo de consumo durante todo el intervalo de vaciado, en lugar de vaciar en cuanto se vacía la cola. La nueva configuración nats_commit_on_select hace que un SELECT directo sobre una tabla JetStream consuma (confirme) los mensajes que lee. #107476 (NIKTONIKTO717).
  • Las funciones de tabla y los motores de tabla mysql, postgresql y sqlite ahora admiten una consulta del usuario (en lugar de un nombre de tabla) y la envían tal cual a la base de datos externa, escrita como subconsulta (SELECT ...) o como query('SELECT ...'). La estructura de la tabla resultante se infiere a partir del resultado de la consulta, y dicha tabla es de solo lectura. #107740 (alexey-milovidov).
  • Se introduce el motor de tabla QueryRunner. Cada registro insertado en una tabla QueryRunner representa una consulta que el motor ejecuta. El motor puede utilizarse para la ejecución asíncrona de consultas, la ejecución por lotes de consultas generadas, el envío de consultas a clústeres remotos, pruebas de rendimiento, fuzzing y pruebas con tráfico en sombra. #107888 (mstetsyuk).
  • Se admite el modo de trama GROUPS para funciones de ventana (SQL:2011), p. ej. any(price) OVER (PARTITION BY symbol ORDER BY ts GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING). En una trama GROUPS, los límites se cuentan en grupos de pares completos (conjuntos de filas con el mismo valor en la clave ORDER BY), de modo que N PRECEDING/N FOLLOWING significan N grupos de pares antes/después del grupo de pares de la fila actual, en lugar de filas físicas (ROWS) o distancias entre valores de ORDER BY (RANGE). #108653 (nihalzp).
  • CREATE MATERIALIZED VIEW ... POPULATE sin más modificadores ahora es atómico a nivel local: la suscripción de la vista a las nuevas inserciones de la tabla de origen y la instantánea de los datos existentes se realizan conjuntamente bajo un breve bloqueo exclusivo sobre el origen, de modo que las filas insertadas a través del mismo servidor durante la carga inicial ya no se pierden ni se duplican (nueva configuración materialized_views_populate_atomically, habilitada de forma predeterminada). La garantía cubre solo la ruta de inserción local (las inserciones que llegan a otra réplica o a través de una ruta de escritura distribuida quedan fuera del corte) y requiere un origen capaz de proporcionar una instantánea fija (la familia MergeTree y Memory); los demás orígenes, así como CREATE OR REPLACE / REPLACE y las vistas creadas en bases de datos Replicated, siguen usando la carga inicial no atómica anterior. Además, POPULATE ahora puede usarse junto con TO para rellenar la tabla de destino con los datos existentes. #108715 (alexey-milovidov).
  • ALTER USER, ALTER ROLE y ALTER SETTINGS PROFILE ahora aceptan SET name = value como alias de MODIFY SETTING name = value. Esta sintaxis modifica configuraciones individuales sin alterar el resto, a diferencia de la cláusula SETTINGS sin modificadores, que reemplaza la lista completa de configuraciones. Así se reduce el riesgo de borrar por accidente las demás configuraciones de un usuario. #108722 (groeneai).
  • Se admite ALTER TABLE ... MODIFY CONSTRAINT [IF EXISTS] name CHECK expr para cambiar directamente la expresión de una restricción existente. #108768 (alexey-milovidov).
  • Se añadió el algoritmo IEJoin, basado en ordenación, para uniones cuya sección ON contiene dos comparaciones de desigualdad (<, <=, >, >=) entre las tablas unidas. Se habilita añadiendo ie_join a la configuración join_algorithm. Los tipos admitidos son ALL INNER/LEFT/RIGHT/FULL JOIN y SEMI/ANTILEFT/RIGHT JOIN. Anteriormente, estas consultas se ejecutaban como un CROSS JOIN con un filtro (solo INNER), lo que resulta mucho más lento en tablas grandes. #109920 (vdimir).
  • Se añadió una nueva tabla del sistema, system.user_query_log, que muestra a cada usuario sus propias entradas del registro de consultas sin necesidad de tener acceso a la tabla del registro de consultas. La idea y la implementación original son de Yue Ni (@niyue). #110156 (alexey-milovidov).
  • Nueva configuración run_query_in_background. El servidor acepta la consulta, devuelve de inmediato un resultado vacío y la ejecuta hasta el final, independientemente de lo que ocurra con la conexión. El resultado se descarta. Puede hacer el seguimiento de la consulta mediante su query_id en system.processes y system.query_log. Está pensada para consultas largas como INSERT ... SELECT, CREATE TABLE … AS SELECT o CREATE MATERIALIZED VIEW … POPULATE, que no deben interrumpirse si se pierde la conexión. #112816 (mstetsyuk).
  • Se admite ALTER TABLE … MODIFY PROJECTION para cambiar la configuración a nivel de proyección (p. ej., index_granularity) de una proyección existente sin necesidad de reconstruirla. La nueva configuración se aplica de forma diferida a medida que se producen las fusiones. #113343 (diegomestre2).
  • El catálogo del motor de tablas S3 para lagos de datos ahora admite INSERT, además de permitir consultar tablas existentes. #113505 (scanhex12).
  • El catálogo Iceberg ahora admite Snowflake Horizon Catalog mediante catalog_type = 'horizon', lo que permite leer y escribir en tablas Iceberg administradas por Snowflake. #114547 (melvynator).
  • Se agregó la configuración skip_unavailable_shards_mode (también disponible como configuración del motor Distributed) para controlar qué excepciones de un segmento remoto se ignoran sin notificación cuando skip_unavailable_shards está habilitado. Esto ofrece un control más preciso sobre el comportamiento de las consultas en entornos distribuidos. #79091 (byte-sourcerer).

Almacenamiento, lagos de datos y almacenamiento de objetos

  • Se añadió compatibilidad con el formato de archivo Puffin (https://iceberg.apache.org/puffin-spec/). Ahora este formato puede utilizarse en funciones de tabla como file, url, s3, etc. #103936 (scanhex12).
  • Se añadió el almacenamiento de partes de datos «packed» para tablas MergeTree, que guarda todos los archivos de una parte en un único archivo empaquetado (data.packed) en lugar de un archivo por stream. Se controla mediante las configuraciones min_bytes_for_full_part_storage, min_rows_for_full_part_storage y min_level_for_full_part_storage, y está deshabilitado de forma predeterminada. Nota de compatibilidad: una vez que una tabla escribe partes «packed», las versiones anteriores del servidor no pueden leerlas, por lo que habilitar este formato impide volver a una versión anterior del servidor. #108118 (Algunenano).
  • Se añadió la configuración nats_credentials al motor de tabla NATS, que permite especificar las credenciales de NATS directamente como una cadena (equivalente al contenido de un archivo .creds). #110733 (addshore).

Formatos de datos e ingestión

  • Se añadió el formato de salida HiveText, que escribe datos en el formato de texto LazySimpleSerDe de Apache Hive. Los campos se separan con \x01; las filas, con el nuevo ajuste format_hive_text_rows_delimiter (valor predeterminado: \n), y los valores anidados de tipo Array, Map y Tuple utilizan la lista de separadores de Hive. La salida está pensada para el LazySimpleSerDe predeterminado de Hive y no es simétrica con la entrada HiveText de ClickHouse en el caso de valores anidados o delimitadores de fila personalizados. #107582 (alexey-milovidov).
  • Se añadió el formato de salida GeoJSON para escribir documentos GeoJSON FeatureCollection con una entidad (feature) por fila. El nuevo ajuste format_geojson_validate_geometry (habilitado de forma predeterminada) valida las geometrías GeoJSON tanto en lectura como en escritura; además, el formato de entrada GeoJSON ahora infiere id como Nullable(String), lo que permite distinguir los ID ausentes o null de las cadenas vacías. #108065 (nihalzp).

Configuración, acceso y observabilidad

  • Se añadió una página integrada de búsqueda en la documentación, disponible en la ruta /docs de la interfaz HTTP, que ofrece búsqueda instantánea sobre la tabla system.documentation y renderiza la documentación de referencia (con resaltado de sintaxis, fórmulas matemáticas y enlaces cruzados). #108345 (alexey-milovidov).
  • Se añadió un tokenizador japonés para los índices de texto y las funciones tokens/hasAnyTokens/hasAllTokens, basado en el analizador morfológico MeCab. El diccionario se carga en tiempo de ejecución desde una ubicación definida en la configuración del servidor y se verifica con una suma de comprobación SHA-256 antes de usarse. #111420 (Ergus).
  • Se añadió un nuevo ajuste de la caché del sistema de archivos, system_cache_extensions, que controla qué archivos se almacenan en la caché del sistema cuando use_split_cache está habilitado. #111575 (kirillgarbar).
  • Se añadió el ajuste always_fetch_mutated_part, que permite a una réplica descargar partes mutadas desde otras réplicas en lugar de ejecutar las mutaciones localmente. #113020 (rorylshanks).

Otras nuevas características

  • Se añade compatibilidad con WITH TIES para valores negativos de LIMIT. #100930 (nihalzp).
  • Se añaden las configuraciones de restauración restore_table_data, restore_access_entities y restore_functions para controlar de forma granular qué se restaura. Estas pueden sobrescribir structure_only para categorías concretas; por ejemplo, structure_only=true, restore_access_entities=true restaura las definiciones de tablas y las entidades de acceso sin los datos de las tablas. #102402 (fm4v).
  • Ahora los diccionarios pueden configurarse individualmente para carga diferida con dictionary_lazy_load en la definición del diccionario, lo que sobrescribe la configuración global del servidor dictionaries_lazy_load. Así, algunos diccionarios pueden cargarse de forma diferida y otros de forma inmediata. #108314 (mstetsyuk).
  • El operador de subíndice de arrays admite un array de enteros como índice: arr[indexes] devuelve los elementos situados en todas las posiciones indicadas, lo que equivale a arrayMap(i -> arr[i], indexes). #108371 (ucasfl).
  • Se añaden las funciones geoToUTM, UTMToGeo, geoToMGRS y MGRSToGeo para convertir entre coordenadas geográficas WGS84 y los sistemas de coordenadas UTM y MGRS. #108939 (alexey-milovidov).
  • Se añaden los comandos SYSTEM UNLOAD DICTIONARY y SYSTEM UNLOAD DICTIONARIES para liberar la memoria de los diccionarios sin eliminar su definición. Los diccionarios se volverán a cargar de forma diferida en el siguiente acceso. #109639 (Manerone).
  • Se añade un nuevo tokenizador icu para los índices de texto y las funciones tokens, hasAnyTokens y hasAllTokens, que ofrece segmentación de palabras Unicode adaptada a la configuración regional (incluida la segmentación basada en diccionarios para idiomas como el chino, el japonés y el tailandés). #109940 (Ergus).
  • Se añade un nuevo códec ZXC: un códec LZ asimétrico con compresión lenta y descompresión muy rápida, cuya relación de compresión se sitúa entre la de LZ4 y la de ZSTD. #110620 (alexey-milovidov).
  • Se añade la configuración s3_base para que las URL relativas de las funciones de tabla s3, s3Cluster, gcs y oss y del motor de tabla S3 puedan resolverse con respecto a una URL base de S3. Se añade el motor de base de datos URL, que resuelve los nombres de tabla como URL con respecto a una base opcional y los redirige al backend correspondiente. #111512 (alexey-milovidov).
  • Se habilita la expansión de comodines para url() y el motor URL mediante la enumeración de páginas de índice HTTP (listados de directorios en HTML o texto plano) y la extracción de las URL coincidentes. Los comodines se comparan con el componente de ruta de la URL, con límites en el tamaño de la página de índice y en el número de directorios leídos. #95181 (niyue).
  • Se añade AWS_MSK_IAM como valor admitido para kafka_sasl_mechanism, lo que permite a ClickHouse autenticarse en Amazon MSK mediante roles de IAM sin tener que gestionar credenciales SASL/SCRAM. #96100 (kalavt).
  • Se añade al índice de texto una etapa de posprocesamiento que transforma los tokens tras la tokenización. #98939 (Ergus).

Funcionalidades experimentales

Planificación y ejecución de consultas

  • Se añadieron “controladores” para funciones definidas por el usuario de tipo executable. Un controlador declarado en <user_defined_executable_function_drivers_config> puede utilizarse en CREATE FUNCTION name ARGUMENTS (...) RETURNS T ENGINE = DriverName(...) AS '...code...' para compilar o procesar de otro modo un fragmento de código del usuario al crear la función y generar una UDF executable lista para ejecutarse. La configuración resultante se almacena en <dynamic_user_defined_executable_functions_path>, y la consulta de origen se conserva como ATTACH FUNCTION, de modo que la función se mantiene tras reiniciar el servidor. Un controlador de prueba de concepto, c_function_body, compila y ejecuta cuerpos de funciones en C dentro de contenedores Docker aislados en modo executable_pool. #105131 (alexey-milovidov).
  • Las solicitudes a la Prometheus Query API dirigidas a /api/v1/query y /api/v1/query_range ahora se registran en system.query_log con las métricas read_rows y read_bytes. #106611 (JTCunning).
  • Se admiten lecturas con plan de consulta distribuido para SELECT ... FINAL en tablas de la familia MergeTree cuando make_distributed_plan está habilitado. #108148 (davenger).
  • Se añade la ejecución experimental de réplicas paralelas basadas en el plan para consultas sobre MergeTree. #108504 (devcrafter).
  • Se añadió una función de tabla experimental, eval, que evalúa una expresión constante para obtener una cadena de consulta y ejecuta la única consulta SELECT resultante. La funcionalidad está deshabilitada de forma predeterminada y puede habilitarse con la configuración allow_experimental_eval_table_function. Autor: Yue Ni #110132 (alexey-milovidov).
  • Réplicas paralelas basadas en el plan (parallel_replicas_plan_based): la frontera entre lo local y lo remoto ahora la determina una optimización a nivel de plan sobre un plan de consulta normal, y las consultas sobre vistas con un UNION se paralelizan sin necesidad de parallel_replicas_allow_view_over_mergetree. Las consultas que usan IN (subquery) ahora recurren a un plan local en lugar de fallar. #111063 (devcrafter). #112443 (devcrafter).
  • Se refuerza la seguridad de las funciones de IA experimentales: se rechazan de forma predeterminada los endpoints inseguros (http) hacia hosts remotos (nueva configuración ai_function_allow_insecure_endpoint), se limitan de forma predeterminada las llamadas salientes a la API por consulta (ai_function_max_api_calls_per_query ahora tiene el valor predeterminado 1000) y se sanean las respuestas de error del proveedor que se escriben en los logs. #111286 (george-larionov).
  • Las réplicas paralelas basadas en el plan (parallel_replicas_plan_based) ahora distribuyen los JOIN aptos (INNER, LEFT, RIGHT, incluidos SEMI/ANTI): la unión completa se ejecuta en un fragmento de plan distribuido, con uno de los lados coordinado entre réplicas y el otro difundido a todas ellas. #112268 (devcrafter).
  • Se informa del error que provocó la cancelación de una consulta distribuida (make_distributed_plan = 1) en lugar de mostrar únicamente QUERY_WAS_CANCELLED. Hasta ahora, el error real de una tarea de worker fallida solo podía verse en el log del servidor. #112590 (davenger).
  • Se admite la ejecución distribuida de planes de consulta con IN (subquery) sin reescribirla como un JOIN. El conjunto se construye una sola vez en el iniciador y sus valores se envían junto con las tareas de los workers. Se elimina la activación forzada de rewrite_in_to_join; la reescritura sigue disponible como configuración explícita. #113826 (davenger).
  • Una consulta con plan distribuido (make_distributed_plan) ahora detiene sus etapas previas en cuanto se cumple un LIMIT, en lugar de calcular el resultado completo y descartarlo. #114806 (davenger).
  • Se corrige el error Illegal type Decimal(18, 0) of argument of function toIntervalNanosecond que se producía cuando una consulta PromQL usaba offset dentro de un selector de rango, p. ej., rate(m[2m] offset 5m). #114997 (nikitamikhaylov).
  • Se admite la agregación GROUPING SETS en los planes distribuidos generados por el optimizador Cascades (make_distributed_plan = 1, enable_cascades_optimizer = 1). #115426 (davenger).
  • Las tablas TimeSeries ahora pueden mantener una tabla de “muestras recientes”: cuando el nuevo ajuste del motor recent_samples_ttl_seconds es distinto de cero, el motor crea una copia con TTL de la tabla de muestras (particionada por recent_samples_partition_by, por día de forma predeterminada) en la que se escribe en cada inserción, y las consultas PromQL cuyo rango de tiempo cabe en la ventana de TTL leen automáticamente de ella. Esto hace que las reglas de alerta y de registro, así como los dashboards de rango corto, sean varias veces más rápidos en tablas grandes. Esta preferencia puede desactivarse con el nuevo ajuste de consulta time_series_prefer_recent_samples_table. #115441 (nikitamikhaylov).
  • Los planes de consulta distribuidos (make_distributed_plan) ahora detienen rápidamente las etapas previas inactivas una vez que se cumple un LIMIT: un sumidero de intercambio inactivo lee NoMoreDataNeeded en cuanto llega, y una fuente de intercambio inactiva detecta que su salida está cerrada y propaga la detención hacia las etapas previas. Hasta ahora, dichas etapas seguían leyendo y calculando datos que nadie consumía. #115690 (davenger).
  • Las réplicas paralelas automáticas ahora pueden recopilar estadísticas en tiempo de ejecución y activar las réplicas paralelas para las consultas compatibles cuando parallel_replicas_plan_based está habilitado. #115788 (devcrafter).
  • Se ha añadido Cascades, un optimizador experimental basado en costos para planes de consulta distribuidos, que se habilita con enable_cascades_optimizer = 1 junto con make_distributed_plan = 1. En función del costo estimado, elige entre estrategias de join shuffle, broadcast, replicada y local; agregación en dos fases, shuffle y local; top-N distribuido en dos etapas; y lecturas paralelas y replicadas, e inserta operadores de intercambio cuando es necesario. #86353 (davenger).

Almacenamiento, lagos de datos e índices

  • Se añadió una caché SLRU en memoria para los archivos de metadata de Paimon deserializados (listas de manifiestos y manifiestos). Cuando se habilita mediante el ajuste use_paimon_metadata_files_cache, las consultas repetidas sobre la misma tabla Paimon ya no tienen que volver a descargar ni a analizar la metadata desde el almacenamiento de objetos. #104657 (Binnn-MX).
  • El ReaderExecutor experimental (use_reader_executor, desactivado de forma predeterminada) ahora puede mantener abierta una conexión con el origen remoto y reutilizarla en lecturas secuenciales, lo que reduce el número de solicitudes al almacenamiento de objetos durante los escaneos. #107735 (CheSema).
  • Se añadió una caché del sistema de archivos de tipo read-through a la ruta de lectura del ReaderExecutor experimental (use_reader_executor, desactivado de forma predeterminada). #110029 (CheSema).
  • Se añadió el ajuste experimental de MergeTree allow_experimental_adaptive_codec_selection. Cuando está habilitado, las fusiones y mutaciones eligen, para cada bloque, el códec que genera la salida más pequeña en las columnas que usan el códec predeterminado. #111834 (rienath).
  • Se añadió un nivel de caché de páginas en espacio de usuario a la ruta de lectura del ReaderExecutor experimental (use_reader_executor, desactivado de forma predeterminada). Ante un fallo de caché, el ejecutor ahora puebla la caché de páginas en espacio de usuario y atiende desde ella las lecturas posteriores, sin copias (zero-copy). #114890 (CheSema).
  • La compactación de archivos de manifiesto de Iceberg ya está disponible mediante OPTIMIZE TABLE ... MANIFEST para reducir el número de archivos de metadata. Está controlada por el ajuste allow_experimental_iceberg_compaction. #98178 (SmitaRKulkarni).

Funciones, formatos e IA

  • Experimental: responder a SELECT count(*) FROM t WHERE col <op> default(col) a partir de las estadísticas de dispersión por columna en serialization.json, sin escanear datos, cuando el predicado divide exactamente la columna en valores predeterminados y no predeterminados. #105890 (Algunenano).
  • Se añadió la familia experimental de códecs vectoriales Quantize(...) y una reescritura opcional de búsqueda vectorial aproximada en dos etapas sobre flujos complementarios cuantizados. #108565 (shankar-iyer).
  • Se recupera el códec de compresión experimental SZ3, con pérdida y error acotado, para columnas Float32/Float64 (y arrays de estos tipos). Requiere allow_experimental_codecs. #108788 (alexey-milovidov).
  • Se corrigió la lectura de datos comprimidos con el códec experimental SZ3('ALGO_LORENZO_REG', ...), que antes fallaba con CORRUPTED_DATA, y se evitó el comportamiento no definido al comprimir valores de coma flotante no finitos (NaN e infinitos) con el códec experimental SZ3. #110762 (alexey-milovidov).
  • PromQL: las funciones de fecha y hora (hour(), minute(), month(), year(), day_of_week(), day_of_month(), day_of_year(), days_in_month()) ahora pueden llamarse sin argumentos, en cuyo caso usan vector(time()) de forma predeterminada, como en Prometheus. #111869 (valerypetrov).
  • PromQL: se corrigieron las operaciones sobre vectores instantáneos sin etiquetas, p. ej., vector(1) + vector(2), topk(1, vector(1)), label_replace(vector(1), ...) y los operadores binarios con on(), que fallaban con un error de tipo. #111872 (valerypetrov).
  • PromQL: se implementó la función deriv y se corrigió un error por el que su función de agregación subyacente devolvía valores 1000 veces menores con marcas de tiempo con resolución de milisegundos. #112360 (valerypetrov).
  • Se aplica la optimización de lectura en orden a las consultas con ORDER BY cuando parallel_replicas_plan_based está habilitado: la ordenación ahora se envía a las réplicas y se fusiona en el initiator, de modo que cada réplica lee en el orden de la clave de ordenación. También se corrige Unknown function __topKFilter para ORDER BY sobre una columna que no forma parte de la clave primaria cuando esta configuración está habilitada. #114315 (devcrafter).
  • Se corrigieron las lecturas de búsqueda vectorial tras recargar una parte de datos (por ejemplo, después de ATTACH o de reiniciar el servidor): las partes ya no pierden sus subcolumnas del códec Quantized, por lo que las búsquedas leen las subcolumnas cuantizadas en lugar de recurrir a la columna de precisión completa. #114763 (shankar-iyer).
  • El motor de tabla experimental TimeSeries ya no aplica el códec Gorilla a las columnas value creadas automáticamente en la tabla interna de muestras; ahora usan CODEC(ZSTD(1)) de forma predeterminada. Las columnas declaradas explícitamente conservan los códecs que haya indicado el usuario. El valor predeterminado de la columna timestamp no cambia (CODEC(DoubleDelta, ZSTD(1))). #112110 (nikitamikhaylov). #114790 (nikitamikhaylov).
  • Se admiten ROLLUP, CUBE, GROUPING SETS y la función grouping en consultas ejecutadas con make_distributed_plan = 1. #114950 (davenger).
  • Se añade una variante Real Doubles (RD) y un argumento opcional ALP(AUTO|STD|RD) al códec experimental ALP. Ahora, ALP sin argumentos elige automáticamente entre el esquema STD existente y RD, en lugar de usar siempre STD. #99654 (nazarii-piontko).

Otras funcionalidades experimentales

  • Se añade afinidad estática de partición a segmento para StorageKafka2 mediante las configuraciones kafka_partition_shard_num y kafka_shard_count, lo que permite que varios segmentos de ClickHouse consuman de forma determinista subconjuntos disjuntos de particiones de Kafka. #108886 (JingYanchao).
  • Ahora puede autenticarse en OneLake con un token bearer obtenido previamente mediante la configuración onelake_bearer_token, en lugar de onelake_client_id y onelake_client_secret. Así se evita compartir un secreto de cliente de larga duración. El token no se renueva, por lo que la base de datos debe volver a crearse cuando caduque. #109104 (asya-ch).
  • Se corrige data_uncompressed_bytes para los índices de omisión empaquetados en skp_idx.packed (mediante packed_skip_index_max_bytes): el tamaño sin comprimir que se notificaba era en realidad el tamaño comprimido, lo que además podía impedir que se activara distributed_index_analysis. #109272 (Algunenano).
  • Se añadió compatibilidad con la compresión Zstandard al HTTP handler experimental de Prometheus remote-write v1. #110907 (JTCunning).
  • PromQL: se implementaron las funciones clamp, clamp_min, clamp_max y round. #111870 (valerypetrov).
  • PromQL: quantile con un nivel de cuantil fuera de [0, 1] ahora devuelve -Inf/+Inf/NaN, igual que Prometheus, en lugar de lanzar un error, y histogram_quantile ahora ignora, también como Prometheus, las series de entrada cuya etiqueta le falta o no se puede analizar. #111871 (valerypetrov).
  • PromQL: se implementaron las funciones changes() y resets(). #112352 (valerypetrov).
  • Ahora se recopilan correctamente las estadísticas de inserción y las consultas recibidas a través del endpoint de Prometheus remote-write. #112825 (JTCunning).
  • PromQL: se conservan los valores finitos al aplicar el módulo con un divisor infinito. #113746 (fallintoplace).
  • Se rechazan los saltos de línea literales en las cadenas PromQL ordinarias entre comillas. #114381 (fallintoplace).
  • Un valor muy grande de distributed_plan_workers_num ya no hace que el servidor aborte con un std::length_error cuando están habilitadas las opciones experimentales make_distributed_plan y enable_cascades_optimizer. Ahora ese número de nodos se rechaza con INVALID_SETTING_VALUE. #115398 (groeneai).
  • Se implementa el endpoint /api/v1/series de la Prometheus HTTP API para las tablas TimeSeries: selectores de series match[] (los valores repetidos se combinan como una unión), un rango de tiempo start/end opcional y un parámetro limit opcional. #115676 (nikitamikhaylov).

Mejoras del rendimiento

Rendimiento de JOIN y de agregaciones

  • Se habilita la caché de condiciones de consulta para las consultas que pasan por el filtrado dinámico TopK (ORDER BY ... LIMIT n). La entrada de la QCC se particiona según los parámetros del plan TopK, de modo que una misma consulta reutiliza los resultados del filtro WHERE almacenados en caché, mientras que un LIMIT, una columna de ordenación o una dirección de ordenación distintos generan una entrada nueva. #104478 (alexey-milovidov).
  • Se traslada LIMIT a la agregación en orden para permitir una finalización anticipada cuando la clave de GROUP BY coincide con la clave de ORDER BY y con la clave de ordenación de la tabla, lo que reduce considerablemente el número de filas leídas. #104859 (thevar1able).
  • Se habilita allow_aggregate_partitions_independently de forma predeterminada. Cuando una clave de GROUP BY es compatible con la clave de partición, ClickHouse puede agregar cada partición de forma independiente y omitir el paso de fusión global. Unas heurísticas en tiempo de ejecución descartan automáticamente la optimización cuando la distribución de las particiones la haría desfavorable (muy pocas particiones, demasiadas particiones o tamaños de partición muy desequilibrados). #105128 (alexey-milovidov).
  • Se habilita read_in_order_use_virtual_row de forma predeterminada. Al leer en el orden de la clave primaria (p. ej., ORDER BY primary_key LIMIT n) en una tabla con muchas partes, solo se leen las partes que realmente pueden contribuir al resultado (más una ventana de lectura anticipada de, como máximo, max_threads partes que mantiene la lectura en paralelo), lo que reduce considerablemente el consumo máximo de memoria. #106215 (alexey-milovidov).
  • Se ha reducido el uso de memoria y mejorado el rendimiento de los JOIN. El lado derecho de una unión hash utiliza ahora una referencia de fila compacta de 8 bytes basada en índices, de modo que las entradas de la tabla hash de las uniones ALL son tan pequeñas como las de las uniones ANY para cualquier tipo de clave. En pruebas de rendimiento con consultas grandes de unión parallel_hash —uniones INNER y ANY de tablas de entre 100 y 300 millones de filas con claves UInt64 y String, tanto únicas como duplicadas—, la consulta mediana fue aproximadamente un 12 % más rápida y usó cerca de un 15 % menos de memoria máxima, sin que ninguna consulta se volviera más lenta. Las uniones INNER con claves UInt64 fueron las más beneficiadas (mediana aproximadamente un 21 % más rápida y con un 38 % menos de memoria). #107189 (harikrishnan94).
  • Se ha añadido el algoritmo dpsub de enumeración del orden de uniones, que proporciona planes de unión óptimos con una menor sobrecarga de optimización que dpsize y admite uniones que no son internas. #107351 (fkastrati).
  • Se evita convertir agregaciones de un solo nivel con bajo uso de memoria en agregaciones de dos niveles, asociando un rastreador de memoria al estado de agregación en lugar de usar la memoria de toda la consulta. #107490 (m-selmi).
  • Se evita construir el AST completo de la consulta durante el análisis de consultas de agregación, ya que la clave de caché de estadísticas de tamaño de la tabla hash de agregación se calcula a partir del plan de consulta en lugar del AST. #107643 (novikd).
  • Se permite pasar de la unión hash usada en la primera ejecución de una consulta a parallel_hash en las ejecuciones posteriores, en función de las estadísticas de tiempo de ejecución recopiladas en la primera ejecución. #108125 (m-selmi).
  • Se utiliza el tamaño de la tabla hash obtenido de las estadísticas de unión en tiempo de ejecución para optimizar el tamaño de los filtros en tiempo de ejecución de JOIN en ejecuciones posteriores de la consulta. Puede controlarse mediante la nueva configuración join_runtime_filter_size_from_hash_table_stats. #108313 (m-selmi).
  • Acelera y reduce el uso de memoria de las consultas DISTINCT sobre tablas MergeTree particionadas al mantener las filas de cada partición dentro de un único stream, de modo que el DISTINCT preliminar de cada stream trabaje sobre un conjunto disjunto de claves, en lugar de que el mismo conjunto de claves aparezca en varios DISTINCT preliminares. Esto se aplica cuando la expresión de partición es una función determinista de las columnas del DISTINCT, y está condicionado por una heurística de costo basada en el número de particiones y su desequilibrio (que puede activarse o desactivarse mediante el setting force_distinct_partitions_independently, deshabilitado de forma predeterminada). Esta misma propiedad de disyunción por partición se propaga a través de los pasos Expression, Filter y ARRAY JOIN hasta los consumidores finales DISTINCT, LIMIT BY y GROUP BY, para que también puedan omitir su fusión. Se controla mediante los nuevos settings allow_distinct_partitions_independently (habilitado de forma predeterminada) y max_number_of_partitions_for_independent_distinct, que permite ajustar la heurística. #108326 (nihalzp).
  • Los filtros en tiempo de ejecución ahora se construyen sobre las claves de igualdad incluso cuando la cláusula ON también contiene predicados de no igualdad, lo que reduce el número de filas que entran en la unión hash en uniones mixtas de igualdad y no igualdad. LEFT ANTI JOIN no se ve afectado. #108579 (29antonioac).
  • Se reduce el umbral de precarga por software para las tablas hash de agregación y de unión de 4 * L2 cache size a L2 cache size, de modo que la precarga se habilite en cuanto la tabla hash deje de caber en la L2. Esto corrige una regresión en GROUP BY y JOIN sobre tablas hash de tamaño medio (~1-8 MiB) en plataformas que reportan una L2 grande (p. ej., aarch64 con una L2 de 2 MiB). #108655 (groeneai).
  • Mejora del rendimiento de las funciones de ventana. Las consultas de ventana sobre tablas anchas que incluyen SELECT * ahora consumen bastante menos memoria y se ejecutan más rápido. Las agregaciones de ventana, como quantile*, uniq* y groupArray, son más rápidas con OVER () y OVER (ORDER BY ... RANGE ...). La función cume_dist también es más rápida, y las ventanas que usan PARTITION BY u ORDER BY ahora rinden mejor en columnas con muchos valores repetidos. #108688 (nihalzp).
  • Las consultas de agregación sin funciones de agregación ahora usan métodos basados en HashSet en lugar de HashMap (para los tipos de clave compatibles). Se han observado aceleraciones de hasta 1,8 veces. #108862 (nickitat).
  • Se reduce la sobrecarga causada por la contención de bloqueos en el algoritmo de unión parallel_hash. #108938 (m-selmi).
  • Se añadió un nuevo valor de join_algorithm, parallel_full_sorting_merge: para uniones de igualdad compatibles con hash, divide una full sorting merge join en segmentos según el hash de las claves de unión, lo que genera merge joins independientes por segmento que se ejecutan en todos los hilos. Conserva el bajo uso de memoria en streaming propio de una merge join y, al mismo tiempo, la paraleliza (en un benchmark, fue ~2,4 veces más rápida y usó ~3,3 veces menos memoria que parallel_hash). Las uniones ASOF recurren a un único full_sorting_merge; los tipos de clave incompatibles con hash (punto flotante, JSON, Object, Dynamic) omiten solo la reescritura de dispersión por hash y aún pueden segmentarse en el origen por rangos de clave primaria cuando query_plan_join_shard_by_pk_ranges está habilitado. El resultado no está ordenado. #109005 (alexey-milovidov).
  • Las estadísticas de columnas ahora se materializan de forma predeterminada en INSERT cuando el tamaño activo actual de la tabla más el tamaño del bloque escrito no supera el valor del nuevo ajuste materialize_statistics_on_insert_max_table_size (predeterminado: 25 GiB); la comprobación se realiza por cada bloque escrito, por lo que una primera carga masiva en una tabla vacía puede seguir materializando estadísticas para cada bloque escrito. Esto proporciona al optimizador de uniones basado en costes estimaciones precisas para tablas de dimensiones recién cargadas y evita órdenes de unión patológicos (por ejemplo, TPC-H Q5 y Q8 ya no agotan el tiempo de espera con un factor de escala de 40), mientras que las tablas de hechos grandes y consolidadas siguen materializando estadísticas durante las fusiones. #109454 (alexey-milovidov).
  • Se ha optimizado la función de agregación uniqCombined en el caso de agregación sin clave. #109794 (CurtizJ).
  • Se han optimizado las funciones de agregación uniqHLL12 y uniqCombined. #109831 (CurtizJ).
  • Se paraleliza el procesamiento de filas no unidas en el algoritmo de unión parallel_hash en dos casos más: cuando existe un filtro residual y cuando las claves de unión son pequeñas (mapa hash de un solo nivel). #110008 (m-selmi).
  • Se desplaza un filtro por debajo de una función de ventana cuando el predicado solo hace referencia a las columnas PARTITION BY de la ventana. Un predicado de este tipo escrito después de la ventana (un WHERE externo que envuelve una subconsulta con ventana, o un término de una conjunción en QUALIFY) ahora llega al almacenamiento y permite la poda por clave primaria o partición, así como el uso de índices de omisión y proyecciones. Por ejemplo, SELECT ... row_number() OVER (PARTITION BY key ORDER BY ts) AS rn ... QUALIFY rn = 1 AND key = 'x' ya no lee ni aplica la ventana a toda la tabla. #110114 (groeneai).
  • Con join_use_nulls = 1, un WHERE que rechaza valores NULL y que hace referencia a columnas de ambos lados de una unión externa (p. ej., WHERE l.k = 42 AND r.k = 42) ahora convierte la unión en INNER (o LEFT/RIGHT) y poda la clave primaria, igual que con join_use_nulls = 0. Anteriormente, la conversión se omitía en este caso y ambas tablas se leían por completo. #110121 (groeneai).
  • Se han optimizado las funciones uniq, uniqExact y uniqHLL12 en agregaciones sin clave. #110150 (CurtizJ).
  • Un JOIN cuya condición ON es siempre falsa (p. ej., ON 1 = 2, ON NULL o una condición que se reduce a falso, como a.t = 'A' AND a.t = 'B') ya no lee el lado que no aporta resultados. Una nueva optimización del plan de consulta sustituye por una fuente vacía los lados de entrada que no pueden aportar ninguna fila. Se controla mediante el ajuste query_plan_short_circuit_constant_false_join (habilitado de forma predeterminada). #110234 (groeneai).
  • Se paraleliza la fusión final de las tablas hash de agregación de un solo nivel: el espacio de claves se divide en particiones hash disjuntas que los threads fusionan de forma independiente (ajuste enable_parallel_single_level_merge, habilitado de forma predeterminada). Acelera las consultas GROUP BY cuyas tablas hash por thread no alcanzan el umbral de dos niveles, pero cuya fusión ocupaba la mayor parte del tiempo de ejecución. #110395 (nihalzp).
  • Las claves de agregación de un único String ahora usan una representación de tabla hash más compacta, lo que mejora las cargas de trabajo de GROUP BY con uso intensivo de cadenas. La nueva configuración enable_packed_string_keys_in_aggregation está habilitada de forma predeterminada; si se deshabilita, o si se establece compatibility por debajo de 26.8, se restablece la ruta heredada de StringHashTable, que puede ser más rápida para claves de cardinalidad muy baja con una longitud superior a 11 bytes. #110573 (harikrishnan94). #112089 (harikrishnan94).
  • Se mejora el rendimiento de full sorting merge join entre 1,5 y 3 veces en escenarios dispersos. #111200 (vdimir).
  • Se habilita join_runtime_filter_from_fixed_hash_table cuando los tipos de join key de sondeo y de construcción difieren (por ejemplo, una clave de sondeo Nullable con una clave de construcción no Nullable). #111244 (m-selmi).
  • Se mejora el rendimiento de las uniones RIGHT y FULL con el algoritmo parallel_hash cuando el lado derecho contiene join keys NULL o filas filtradas por la expresión ON, ya que se evita reconstruir los mapas de nulos. #111258 (m-selmi).
  • Nuevo algoritmo adaptativo para GROUP BY en paralelo (controlado mediante la configuración enable_adaptive_aggregator, habilitada de forma predeterminada): cada hilo agrega en su propia tabla hash hasta que esta contiene adaptive_aggregator_freeze_threshold claves y, en ese momento, la congela. Así, las claves frecuentes siguen actualizando las pequeñas tablas residentes en caché sin necesidad de coordinación, mientras que las claves poco frecuentes se enrutan según su hash a colas pendientes por bucket y se agregan exactamente una vez, dentro de la fusión paralela por bucket. #111459 (nihalzp).
  • Se acelera el hashing por fila de los valores de columnas JSON/Object almacenados en datos compartidos (que utilizan, por ejemplo, uniq/uniqExact sobre una columna JSON y las claves hash de GROUP BY/DISTINCT), ya que se evita reconstruir ColumnDynamic para cada valor. Los valores hash no cambian. #111501 (valerypetrov).
  • Se mejora el rendimiento de RIGHT y FULL hash JOIN con múltiples disyunciones OR en la sección ON, así como de RIGHT/FULL JOIN con condiciones residuales (de desigualdad). #111590 (m-selmi).
  • La lectura en orden a través de un JOIN ahora también funciona cuando un hash join tiene configurado un umbral automático de volcado a disco (el valor predeterminado desde 26.5). Cuando se aplica esta optimización, la unión permanece en memoria para conservar el orden del lado izquierdo; establezca query_plan_read_in_order_through_spilling_join = 0 para restaurar el comportamiento anterior, en el que dichas uniones no se utilizan para la lectura en orden y pueden volcarse a disco libremente. Además, con este cambio, un ORDER BY ... LIMIT sobre un LEFT JOIN leído en orden ya no indica la tabla completa como número de filas que prevé leer, por lo que deja de activar max_rows_to_read con read_overflow_mode = 'throw' en lecturas que terminan anticipadamente. #111973 (alexey-milovidov).
  • Se vuelve a habilitar la optimización de claves consecutivas para la agregación de TTL ... GROUP BY durante las fusiones. El agregador se construía pasando min_chunk_bytes_for_parallel_parsing (un umbral en bytes, 10 MiB de forma predeterminada) en la posición que corresponde a min_hit_rate_to_use_consecutive_keys_optimization (una tasa de aciertos en [0, 1], 0,5 de forma predeterminada), por lo que la optimización quedaba deshabilitada permanentemente en esa ruta. Los resultados no se ven afectados. #112314 (groeneai).
  • La replicación diferida de columnas para ARRAY JOIN ya no se pierde cuando se serializa un plan de consulta. Con serialize_query_plan = 1, el nodo que ejecutaba un fragmento de plan remoto ignoraba enable_lazy_columns_replication y siempre materializaba todas las copias replicadas, aunque esta configuración está habilitada de forma predeterminada. #112330 (groeneai).
  • Una igualdad en WHERE ahora se fusiona con la condición de JOIN cuando sus operandos tienen tipos distintos pero comparten un supertipo común, como Int32 y Nullable(Int32). Esto permite convertir una unión CROSS en una unión INNER. #112630 (m-selmi).
  • Se corrigió la reasignación cuadrática al replicar un Array cuyos elementos contienen valores JSON en datos compartidos, por ejemplo, un Array(JSON) constante pasado a una función de agregación. En estas consultas, la cantidad de bytes copiados crecía de forma cuadrática con el número de filas. #112897 (groeneai).
  • Se restaura la poda de partes y gránulos cuando los límites de un predicado de rango sobre una clave primaria o de partición de MergeTree se proporcionan mediante una cláusula JOIN ON contra un lado constante de una sola fila, por ejemplo, SELECT count() FROM t JOIN bounds ON t.d >= bounds.lo AND t.d <= bounds.hi. Desde la versión 25.2, una consulta de este tipo leía todas las partes, y la configuración query_plan_use_logical_join_step, que antes permitía restaurar la poda, quedó obsoleta en la 26.5, por lo que no había forma de recuperarla. #112957 (groeneai).
  • Se corrigió la complejidad cúbica de la planificación de consultas para un JOIN con una tabla Merge sobre muchas tablas con estructuras diferentes. Anteriormente, estas consultas podían pasar minutos en la fase de planificación sin responder a max_execution_time ni a KILL QUERY. #113140 (alexey-milovidov).
  • Se corrigió una regresión de rendimiento por la que una agregación sin claves GROUP BY serializaba en cada ejecución todo el subárbol de su plan de entrada, incluido el contenido completo de los literales resultantes del plegado de constantes, para calcular una clave de caché del tamaño de la tabla hash que nunca llega a utilizar. Una consulta como SELECT quantileMerge(arrayJoin(arrayMap(x -> state, range(5000000)))) dedicaba unos 63 ms por ejecución a la optimización del plan de consulta; ahora dedica 0,15 ms. #113333 (groeneai).
  • Los operadores de agregación de PromQL topk, bottomk y limitk se evalúan ahora con un plan de streaming cuyo estado de selección es O(time_steps * k), en lugar de reunir todas las series en una sola fila con una memoria intermedia de O(time_steps * series^2). Las consultas sobre métricas de alta cardinalidad que antes fallaban con MEMORY_LIMIT_EXCEEDED ahora se ejecutan con memoria acotada, y la evaluación se paraleliza en lugar de ejecutarse en un solo hilo. #113656 (nikitamikhaylov).
  • Se sustituyó el mapa hash por bucket de las funciones de agregación timeSeries*ToGrid por un array plano y ordenado de muestras: la ingesta de muestras pasa a ser una inserción al final en O(1) para entradas ordenadas (el caso más habitual con diferencia) y desaparece la copia y ordenación por bucket durante la finalización. #113681 (nikitamikhaylov).
  • Las subexpresiones de PromQL compartidas por varios pasos del plan (el operando de topk/bottomk/limitk y el lado izquierdo de or) se evalúan ahora una sola vez en lugar de dos: el SQL generado a partir de PromQL materializa las subconsultas compartidas. Esto elimina un escaneo duplicado de la tabla de muestras; topk sobre rate es aproximadamente el doble de rápido en frío, y las consultas de reglas de kubernetes-mixin mejoran entre un 10 y un 29 %. #113772 (nikitamikhaylov).
  • La caché de condiciones de consulta ahora está habilitada de forma predeterminada para las consultas que usan la optimización ORDER BY <column> LIMIT n (TopK). Establezca use_query_condition_cache_for_top_k = 0 para desactivarla. #111492 #114539 (alexey-milovidov).
  • Se paraleliza la conversión de un nivel a dos niveles de los estados de agregación por thread antes de la fusión. Esto corrige una regresión de 2-3x en consultas GROUP BY cortas con estados de agregación pesados (p. ej., COUNT(DISTINCT ...), ClickBench Q10/Q11) en máquinas con un número muy elevado de núcleos, introducida en las builds de desarrollo de la 26.7 al hacer precisa la contabilización de memoria de la agregación. #114691 (alexey-milovidov).
  • Se aceleran las funciones de ventana sobre tablas MergeTree particionadas: cada partición se lee mediante su propio stream y las ventanas se evalúan por partición, lo que evita la dispersión por hash que normalmente redistribuye todas las filas entre threads antes de ordenar la ventana. Esto se aplica cuando la expresión de partición de la tabla es una función determinista de las columnas PARTITION BY de la ventana, y está sujeto a la misma heurística de coste que GROUP BY / DISTINCT por partición (suficientes particiones en relación con max_threads y ninguna partición dominante). Se controla mediante los nuevos ajustes allow_window_partitions_independently (habilitado de forma predeterminada), force_window_partitions_independently y max_number_of_partitions_for_independent_window. #114783 (nihalzp).
  • Se aceleran las funciones de agregación timeSeries*ToGrid: el cálculo del bucket de cada muestra ya no utiliza la división Int128, y las muestras consecutivas en el mismo bucket se saltan la búsqueda en el mapa hash. #114889 (nikitamikhaylov).
  • Las funciones de agregación timeSeries*ToGrid procesan ahora las muestras en secuencias de muestras consecutivas que caen en un mismo bucket de la cuadrícula, lo que acelera entre 1,2 y 2 veces la etapa de ingesta de muestras de timeSeriesRateToGrid y funciones relacionadas sobre datos de series temporales ordenados. #115041 (nikitamikhaylov).
  • Una agregación sin claves GROUP BY ya no reparte su salida de una sola fila entre max_threads streams, por lo que las consultas cuyo plan continúa tras dicha agregación obtienen un pipeline mucho más pequeño (menos procesadores que crear, planificar y perfilar) sin perder paralelismo. #115170 (nikitamikhaylov).
  • Evaluación más rápida de las consultas instantáneas de PromQL: las funciones de agregación timeSeries*ToGrid usan la ruta vectorizada de clasificación de muestras para cuadrículas de un solo punto, y timeSeriesIdToGroup rellena directamente su columna de resultado. #115267 (nikitamikhaylov).
  • Un JOIN cuya sección ON contiene varias igualdades combinadas con OR ya no materializa las columnas de clave del lado derecho que la consulta no selecciona. #115465 (nickitat).
  • Se acelera la construcción de la tabla hash de una unión ANY, SEMI o ANTI cuando el lado derecho repite muchas veces las mismas claves de unión: la unión ya no vuelve a leer el ajuste join_any_take_last_row desde memoria para cada fila del lado derecho. #115820 (nickitat).
  • Se acelera GROUP BY sin funciones de agregación sobre claves String, FixedString y LowCardinality: la consulta ya no reescribe un marcador de posición no utilizado en la tabla hash para cada fila, sino solo para las filas que añaden una clave nueva. #115834 (nickitat).
  • Se redujeron el uso de memoria y el tiempo de optimización del plan de consulta en agregaciones con clave sobre literales grandes resultantes del plegado de constantes. La clave de caché de estadísticas de la tabla hash de agregación ahora se calcula mediante hash a medida que se serializa, en lugar de acumularse primero en memoria, de modo que un plan que contiene un literal grande ya no conserva una copia de este durante la optimización. Con un literal de 80 MB, el pico de memoria disminuye en unos 250 MB y el tiempo de optimización se reduce aproximadamente 2,5 veces. La clave calculada no cambia. #115847 (groeneai).
  • Se optimizan las consultas GROUP BY ... ORDER BY ... LIMIT y GROUP BY ... LIMIT mediante un heap acotado durante la agregación, que permite descartar los grupos que no pueden aparecer en el resultado. Esto reduce significativamente el uso de memoria y el tiempo de ejecución en agrupaciones de alta cardinalidad. Se controla mediante la configuración enable_group_by_top_k_optimization. Basado en la implementación inicial de Dmitriy Terenichev #96630 (thevar1able).

Optimización y ejecución de consultas

  • La lectura en orden con réplicas paralelas ahora utiliza la misma lógica que la lectura local para dividir la tabla en max_threads partes, lo que mejora el paralelismo. #101434 (nickitat).
  • Se añade al lector de Parquet la poda espacial de GeoParquet a nivel de grupo de filas y de página. La poda a nivel de grupo de filas omite grupos de filas completos cuyo cuadro delimitador no se solapa con la geometría de la consulta. La poda a nivel de página utiliza el índice de columna covering.bbox para omitir páginas irrelevantes dentro de los grupos de filas. Además, se generaliza el pushdown de predicados espaciales mediante IFunctionBase::isSpatialPredicate() y se añade un GeoFilter que evalúa predicados espaciales durante la lectura de filas de Parquet. #104435 (bacek).
  • Se añadió el setting use_constant_folding_in_index_analysis (deshabilitado de forma predeterminada). Cuando está habilitado, el análisis de clave primaria, MinMax e índices de omisión de MergeTree incorpora las constantes a nivel de partición en el predicado del filtro por separado para cada parte, lo que mejora la poda en filtros cuyas ramas dependen de valores de partición, p. ej., (a = 1 AND b >= 1) OR (a = 2 AND b > 10) con PARTITION BY a. #104582 (Michicosun).
  • Se aplica el posicionamiento exacto de filas en consultas de búsqueda vectorial con vector_search_with_rescoring antes de la evaluación exacta de distancias en el pipeline de la consulta. #105591 (skuznetsov).
  • Se añadió una optimización del plan de consulta que desplaza las funciones que reducen el volumen de datos (length, lengthUTF8, empty, notEmpty) por debajo de los pasos Sorting y Filter, sustituyendo el argumento amplio String / FixedString por el resultado de tamaño fijo, de modo que ni se almacena en búfer durante una ordenación ni se copia en un filtro. Se controla mediante el nuevo setting query_plan_push_down_volume_reducing_functions, habilitado de forma predeterminada. #106199 (fastio).
  • Se acelera la carga de la caché del sistema de archivos durante el arranque al codificar el tamaño de cada archivo de caché en su nombre (<offset>_<size>), lo que evita una llamada stat por archivo. Se sigue admitiendo la carga de archivos de caché escritos por versiones anteriores. #107415 (alexey-milovidov).
  • Se mejoró el rendimiento de las consultas de búsqueda de texto combinadas con un filtro de clave primaria. #108114 (CurtizJ).
  • Se mejora el rendimiento de la función pointInPolygon con un polígono constante. La caché de polígonos preprocesados ahora usa como clave los argumentos constantes sin procesar, de modo que un polígono constante se analiza una sola vez (ante un fallo de caché) en lugar de volver a analizarse en cada bloque de entrada. #108184 (groeneai).
  • Se evita mantener los contadores de selectividad de system.predicate_statistics_log en la ruta de lectura de MergeTree cuando la funcionalidad está deshabilitada (predicate_statistics_sample_rate = 0, el valor predeterminado). Esto elimina una actualización atómica por gránulo y un popcount O(rows) del filtro en cada lectura, lo que corrige una regresión de rendimiento especialmente visible en aarch64. #108190 (groeneai).
  • Se añade el setting merge_use_batch_sorting_queueMergeTree para usar opcionalmente la cola de ordenación por batch en las fusiones ordinarias de MergeTree, lo que reduce el tiempo de CPU y el tiempo real en cargas de trabajo de fusión en las que la fusión ordenada supone un coste significativo. #108468 (rorylshanks).
  • Se acelera la planificación de consultas con el analizador para expresiones que hacen referencia al mismo alias WITH o repiten la misma subexpresión muchas veces (por ejemplo, cadenas if/multiIf profundamente anidadas), ya que las subexpresiones compartidas no se reconstruyen al construir el DAG de acciones. #108523 (novikd).
  • Se aceleró el análisis de consultas que contienen muchas cadenas AND de comparaciones o cadenas muy largas: la optimización optimize_and_compare_chain ahora está limitada por un presupuesto de trabajo (nueva configuración optimize_and_compare_chain_max_hash_work) en lugar de calcular el hash de una gran parte del árbol de la consulta, y la resolución de lambdas ya no recalcula los hashes del cuerpo de la lambda para su protección contra la recursión. #108757 (alexey-milovidov).
  • Los posprocesamientos que solo filtran (if(..., '', token)) ahora construyen el gránulo a partir de los tokens sin procesar y descartan los vacíos durante la construcción, con lo que se evitan la materialización por ocurrencia y la ejecución de ActionsDAG propias de la ruta general. #109049 (ahmadov).
  • Se eliminó un cuello de botella monohilo en ShuffleSendStep del plan de consulta distribuida: ahora cada stream de origen reparte sus filas por bucket de destino de forma independiente, en lugar de canalizar todo el fragmento a través de un único ScatterByPartitionTransform. #109206 (davenger).
  • Se redujo la sobrecarga de CPU en la evaluación de expresiones para consultas con un gran número de columnas (p. ej., búsqueda vectorial sobre una columna QBit con un paso pequeño, donde cada vector se expande en cientos de subcolumnas de planos de bits que se pasan todas a una única llamada *DistanceTransposed). #109380 (alexey-milovidov).
  • Se desplaza un filtro por debajo de LIMIT BY cuando el predicado hace referencia únicamente a las columnas clave de LIMIT BY y la cláusula conserva al menos una fila por grupo no vacío (LIMIT n BY con n >= 1 y OFFSET 0). Así, estos predicados (escritos como un WHERE externo que envuelve una subconsulta con LIMIT BY) llegan al almacenamiento y pueden aprovechar la poda por clave primaria, los índices de omisión y las proyecciones, en lugar de leer toda la tabla y aplicar primero el top-N por grupo, sin cambiar la semántica de excepciones de OFFSET, LIMIT 0 BY ni las formas negativas de LIMIT BY. #110116 (groeneai).
  • Se evita una asignación en el heap por cada comprobación de hiperrectángulo en el análisis del índice de clave primaria, lo que acelera el filtrado de marcas entre un 5 y un 26 % según la forma de la consulta. #110153 (raimannma).
  • El push-down de filtros en Parquet (poda de grupos de filas e índices de columna) ahora admite conversiones entre variantes de DateTime64, variantes de Decimal y Float32/Float64. #110457 (al13n321).
  • Se optimizó la construcción de índices de omisión de texto y basados en filtro Bloom con el tokenizador sparseGrams #110541 (UnamedRus).
  • Se combina el coste de E/S con la selectividad al ordenar las condiciones de PREWHERE. Esto corrige una regresión de rendimiento en la ejecución de PREWHERE que se producía en algunos casos desde https://github.com/ClickHouse/ClickHouse/pull/101275. Parte de https://github.com/ClickHouse/ClickHouse/issues/110462 #110695 (Avogar).
  • Se reduce el cálculo de hashes de los tokens definidos en el filtro IN/NOT IN del posprocesamiento. #111690 (ahmadov).
  • Las funciones mapContainsKeyLike, mapContainsValueLike, mapExtractKeyLike y mapExtractValueLike con un patrón no constante consumen menos memoria y tiempo cuando enable_lazy_columns_replication está habilitado. El patrón ya no se copia de forma anticipada por cada entrada del mapa en el momento de la captura; la copia se aplaza hasta la ejecución de la lambda interna y se libera antes, de modo que en el pico de uso existe una copia expandida menos del patrón. #111749 (diegomestre2).
  • Se habilitaron de forma predeterminada (y se promovieron a beta) dos funcionalidades en disco: 1) packed_skip_index_max_bytes = '1M': los subflujos de índices de omisión de hasta 1 MiB ahora se escriben en un único archivo skp_idx.packed por parte, lo que reduce el número de objetos y de solicitudes de escritura en el almacenamiento de objetos. Compatibilidad: solo se ven afectadas las partes escritas a partir de ahora, que siguen siendo totalmente legibles en versiones anteriores; las versiones previas a la 26.6 simplemente no utilizan los índices empaquetados para la poda (se tratan como no materializados). Establezca packed_skip_index_max_bytes = 0 para mantener la disposición independiente de un archivo por índice. 2) compute_exact_num_defaults_for_sparse_columns junto con optimize_trivial_count_with_sparsity_filter: los contadores exactos num_defaults por columna se persisten y se utilizan para responder a SELECT count() FROM t WHERE <pred> sin escanear datos cuando el predicado divide las filas entre valores predeterminados y no predeterminados. Compatibilidad: las versiones anteriores ignoran el indicador exact_num_defaults de serialization.json, por lo que las partes siguen siendo totalmente legibles tras volver a una versión anterior; la reescritura del conteo solo se aplica a las partes que contienen contadores exactos, de modo que los resultados siguen siendo correctos en tablas con partes mixtas. #111816 (Algunenano).
  • La optimización de condiciones transitivas ahora utiliza su filtro adicional únicamente para el análisis de índices cuando no puede aplicar el filtro completo. Consulte la configuración optimize_and_compare_chain. #112076 (yariks5s).
  • La API de consultas de Prometheus (/api/v1/query, /api/v1/query_range) del motor experimental TimeSeries ahora ejecuta las consultas en paralelo en lugar de en un único hilo. #112108 (nikitamikhaylov).
  • randomHadamardTransform aplicado a un vector constante ahora se evalúa una sola vez en lugar de una vez por fila. Esto acelera las consultas de búsqueda vectorial que rotan el vector de consulta con randomHadamardTransform antes de compararlo con una columna QBit. #112921 (alexey-milovidov).
  • Se restablece el uso compartido de conjuntos entre las tareas por parte de una misma mutación que filtra con IN (subquery) sobre una columna de clave primaria. enable_sharing_sets_for_mutations está activado de forma predeterminada, pero el conjunto construido para el análisis de la clave primaria había dejado de participar en la caché compartida, por lo que una tabla con N partes materializaba el mismo conjunto N veces. #112941 (groeneai).
  • En los planes de consulta distribuidos (make_distributed_plan), ORDER BY ... LIMIT k ahora utiliza materialización diferida en cada réplica: las columnas anchas se leen solo para las k primeras filas locales de esa réplica en lugar de para cada fila candidata. #113111 (shankar-iyer).
  • Se acelera la planificación de consultas cuando se utilizan estadísticas de columna uniq_v2. El número estimado de valores distintos ahora se almacena en caché en lugar de recalcularse en cada solicitud, algo que la planificación emite muchas veces por consulta. #113357 (groeneai).
  • La aplicación anticipada de filtros (filter pushdown) ahora funciona con subcolumnas Tuple en archivos Parquet y ORC. Un predicado como WHERE tup.1 = 555555 sobre file(), s3() o url() ahora poda grupos de filas e intervalos del índice de filas utilizando las estadísticas propias del elemento de la tupla en lugar de leer el archivo completo. #113383 (groeneai).
  • Se mejora el rendimiento de las consultas PromQL sobre el motor TimeSeries: el SQL interno del selector ahora lee directamente las columnas de clave primaria de la tabla de muestras (sin conversiones de tipo superfluas) y comprueba el rango de marcas de tiempo antes que el conjunto de identificadores de series, lo que hace que las consultas en frío con uso intensivo de selectores sean entre un 30 % y un 44 % más rápidas. #113768 (nikitamikhaylov).
  • Los selectores de PromQL que coinciden con todas las series de una métrica ahora filtran la tabla de muestras de una tabla TimeSeries con un rango continuo de clave primaria sobre id durante el análisis de índices, en lugar de usar una condición id IN <set> de gran tamaño, cuando la estructura del id es una tupla de dos componentes con el generador de id canónico. Esto elimina el principal coste monohilo del análisis de índices en consultas PromQL con muchos selectores: hasta un −45 % de latencia en frío en los patrones de consulta de dashboards y reglas, y un −11 % en la media geométrica en frío sobre el conjunto completo de pruebas en una tabla de 62 000 millones de muestras. #114131 (nikitamikhaylov).
  • Los endpoints /api/v1/query y /api/v1/query_range de la Prometheus HTTP API ahora evalúan una sola vez las subconsultas PromQL compartidas por varios pasos del plan, como ya hacían las funciones de tabla prometheusQuery y prometheusQueryRange. Anteriormente, las solicitudes realizadas con enable_analyzer = 0, o por un usuario cuyo perfil lo establecía, volvían a escanear la subconsulta compartida una vez por cada paso que la referenciaba. #114261 (groeneai).
  • Se corrigió una regresión de la versión 26.7: en una tabla MergeTree ordenada por toUnixTimestamp (u otra conversión a entero) de una columna DateTime64, un filtro de rango simple sobre esa columna ya no utilizaba la clave primaria y leía todos los gránulos de las partes coincidentes. Además, un filtro como toInt64(ts) >= c sobre una tabla ordenada directamente por la columna DateTime64 ahora utiliza la clave primaria. #114413 (alexey-milovidov).
  • Se acelera la ejecución de IN sobre columnas agrupadas (por ejemplo, ordenadas por la clave primaria) reutilizando el resultado de la fila anterior cuando las filas consecutivas son iguales. #114853 (nikitamikhaylov).
  • Se corrigió el coste cuadrático en tiempo que se producía cuando las funciones h3kRing, h3ToChildren, h3PolygonToCells y h3PolygonToCellsWithContainment construían su resultado sobre muchas filas. Una consulta sobre 196 000 filas tardaba 838 segundos copiando memoria en una ejecución de pruebas de estrés de CI; ahora tarda unos 5 segundos. #115773 (groeneai).
  • Se optimizan las búsquedas inversas en diccionarios. Un predicado de igualdad constante como WHERE dictGet(dict, attr, key_expr) = value ahora se pliega como constante directamente en un filtro de clave (key_expr = const, key_expr IN [...] o WHERE 0) en lugar de reescribirse como una subconsulta IN (SELECT ... FROM dictionary(...)), y la ruta constante de dictGetKeys ahora se ejecuta en paralelo. #91164 (nihalzp).
  • Se añade una nueva configuración, merge_tree_generic_exclusion_search_max_steps, que limita el número de pasos que el algoritmo de búsqueda de exclusión genérica dedica a analizar el índice de clave primaria de cada parte de datos. El presupuesto se invierte primero en los rangos de clave restantes más grandes, de modo que incluso un presupuesto pequeño descarta la mayor parte de los datos; los rangos que no se han analizado por completo se leen enteros, por lo que los resultados de la consulta siguen siendo correctos, aunque pueden leerse más gránulos. El límite se aplica de forma aproximada: puede superarse como máximo en merge_tree_coarse_index_granularity pasos, más un paso por cada rango en que la parte ya esté dividida (por ejemplo, por la caché de condiciones de consulta). El valor predeterminado, 0, significa pasos ilimitados. #92779 (EmeraldShift).
  • Las consultas con ORDER BY y LIMIT sobre VIEWs definidas sobre tablas distribuidas ahora utilizan la optimización de fusión de flujos ordenados. El ORDER BY/LIMIT externo se traslada a la consulta interna de una vista simple, de modo que cada shard ordena sus datos localmente y el coordinador fusiona flujos ya ordenados, en lugar de realizar una ordenación completa en el coordinador. #94102 (matanper).

Rendimiento del almacenamiento, la E/S y los lagos de datos

  • Usa los límites del índice minmax de partición para podar más gránulos durante el análisis de la clave primaria en tablas MergeTree, cuando una columna de la clave primaria es también una columna de entrada de la clave de partición. Por ejemplo, en una tabla MergeTree con ORDER BY (id, event_time) y PARTITION BY toYYYYMM(event_time), ClickHouse usará el índice minmax de partición sobre event_time durante el análisis del índice de clave primaria para tomar decisiones de poda de gránulos mejor fundamentadas. Se controla mediante la nueva configuración use_partition_minmax_for_primary_key_pruning (habilitada de forma predeterminada). #103480 (UnamedRus).
  • Acelera los operadores que recorren un stream ordenado en busca de secuencias de valores de clave iguales: DISTINCT en orden, LIMIT BY en orden, LIMIT BY negativo en orden y los joins full_sorting_merge y partial_merge. #106502 (nihalzp).
  • El lector Parquet v3 ahora puede omitir grupos de filas completos mediante la página de diccionario (además de las estadísticas min/max y los filtros de Bloom) en condiciones de igualdad e IN, cuando un fragmento de columna está completamente codificado por diccionario. Se controla mediante la nueva configuración input_format_parquet_dictionary_filter_push_down. #106952 (alexey-milovidov).
  • Usa libdeflate para la compresión y descompresión gzip/zlib/deflate, lo que las hace más rápidas (compresión ~1,15× con una mejor tasa de compresión, descompresión ~1,4–1,5×) para datos .gz/HTTP/url/s3 y para el códec GZIP de Parquet. #108074 (alexey-milovidov).
  • Acelera las funciones trimLeft/trimRight/trimBoth con espacios en blanco predeterminados (y sus alias ltrim/rtrim/trim): las filas consecutivas que no necesitan recorte se copian en un único lote, y el escaneo de espacios por fila solo se ejecuta en las filas que realmente tienen un espacio inicial o final. #108177 (groeneai).
  • Acelera la lectura de tablas Iceberg precargando el siguiente archivo de manifiesto mientras se analiza el actual, de modo que la E/S se solapa con el trabajo de CPU. #108543 (asya-ch).
  • Las consultas de búsqueda vectorial que usan reevaluación ahora limitan el cálculo exacto de distancias a las filas candidatas del índice vectorial, en lugar de reevaluar por fuerza bruta las filas vecinas del mismo gránulo MergeTree. #108846 (skuznetsov).
  • Se añadió la configuración merge_tree_min_bytes_per_read_stream para reducir el exceso de streams de lectura y la sobrecarga del pipeline en escaneos MergeTree locales ordinarios, no ordenados y de columnas estrechas, en servidores con muchos núcleos. #109035 (jiebinn).
  • Acelera la serialización y las fusiones de columnas JSON cuyos datos compartidos contienen muchas rutas dispersas. Al aplanar los datos compartidos en columnas por ruta, flattenAndBucketSharedDataPaths ya no escanea todas las columnas de ruta acumuladas en cada fila ni inserta valores predeterminados celda a celda: se elimina el escaneo por fila sobre todas las rutas y los huecos se rellenan en bloque. #109341 (groeneai).
  • El protocolo nativo ahora envía las columnas String como un stream independiente de desplazamientos de bytes acumulativos (la misma disposición que usa Array para sus desplazamientos), seguido de los datos concatenados, en lugar de un prefijo de longitud varint por valor, siempre que ambos extremos usen la revisión de protocolo 54489 o posterior. Así, un cliente puede leer columnas String con una preasignación exacta del búfer y una única copia masiva, aproximadamente 4 veces más rápido que con la disposición por valor. Los clientes y servidores antiguos no se ven afectados, ya que la disposición se negocia mediante la revisión del protocolo. La misma disposición está disponible en los formatos Native y Buffers mediante las nuevas configuraciones output_format_native_write_string_with_size_stream / input_format_native_read_string_with_size_stream (desactivadas de forma predeterminada para que los formatos sigan siendo portables). #110320 (vahid-sohrabloo).
  • Las consultas con FINAL que leen en el orden de la clave primaria (ORDER BY sobre un prefijo de la clave de ordenación) con un LIMIT pequeño ya no usan split_intersecting_parts_ranges_into_layers_final. #110431 (KochetovNicolai).
  • Materialización diferida (materialización tardía) al leer archivos Parquet desde almacenamiento de objetos, incluidas las tablas Iceberg: en las consultas ORDER BY ... LIMIT n, las columnas que no se necesitan para ordenar ni filtrar solo se leen para las n filas que quedan tras aplicar el LIMIT. Con un archivo Parquet de 200 MB en S3, SELECT k, s ... ORDER BY k DESC LIMIT 10 lee 3,3 MB en lugar de 171 MB (51 veces menos IO y 8 veces más rápido). Se controla mediante la nueva configuración query_plan_optimize_lazy_materialization_for_object_storage (habilitada de forma predeterminada; también requiere query_plan_optimize_lazy_materialization). #110970 (alexey-milovidov).
  • Las consultas sobre tablas Iceberg con muchos archivos de eliminación ahora se inician más rápido. ClickHouse lee y decodifica los archivos de manifiesto de eliminación de forma concurrente en lugar de uno por uno, de modo que sus lecturas del almacenamiento se solapan. La nueva configuración iceberg_delete_manifest_decode_concurrency (valor predeterminado: 4) controla cuántos se decodifican simultáneamente. #112679 (asya-ch).
  • Se añade la serialización opcional en Parquet de UInt128/UInt256/Int128/Int256 como DECIMAL para permitir la poda de grupos de filas y de páginas. #113347 (bobrik).
  • Se corrigió la multiplicación de solicitudes de lectura en discos remotos cuando un paso de la cadena de lectores lee rangos de marcas fragmentados, por ejemplo, rangos filtrados por índices primarios o de omisión. #113584 (CurtizJ).
  • Se omite la comprobación redundante de ordenación al escribir partes de MergeTree cuyas claves de ordenación son todas constantes. #113899 (perfloop-agent).
  • La materialización diferida para las consultas ORDER BY ... LIMIT n ahora también se aplica a archivos Parquet locales leídos con la función de tabla file y el motor de tabla File: las columnas que no se necesitan para ordenar ni filtrar solo se leen para las n filas que quedan tras aplicar el LIMIT. La segunda lectura de un archivo seleccionado falla de forma segura con el nuevo error FILE_CHANGED_DURING_READ si el archivo se modificó entre las dos pasadas. Se controla mediante la nueva configuración query_plan_optimize_lazy_materialization_for_file (habilitada de forma predeterminada). También corrige un fallo de la materialización diferida para almacenamiento de objetos con el error Not found column or subcolumn ... in block cuando se difiere una subcolumna solicitada (p. ej., de una columna JSON). #114262 (alexey-milovidov).
  • Se acelera la construcción del Set para IN (subquery) en tablas MergeTree particionadas al mantener las filas de cada partición dentro de un único flujo y deduplicar cada flujo de forma independiente, de modo que la única transformada de llenado del Set —que antes calculaba el hash de cada fila en serie— solo recibe filas únicas. Esto se aplica cuando la expresión de partición es una función determinista de las columnas de salida de la subconsulta. La optimización no se aplica cuando la partición más grande contiene más del doble de filas que la partición promedio; la nueva configuración force_creating_set_partitions_independently (deshabilitada de forma predeterminada) permite omitir esta comprobación. Se controla mediante la nueva configuración allow_creating_set_partitions_independently (habilitada de forma predeterminada). #114645 (nihalzp).
  • Las tablas de registro del sistema MergeTree no replicadas y rotadas que no tienen TTL se marcan ahora como table_readonly para evitar operaciones en segundo plano innecesarias. La configuración table_readonlyMergeTree ahora también suprime todo el trabajo en segundo plano en una tabla MergeTree simple —fusiones regulares, de TTL (DELETE/MOVE/recompresión) y de recompresión, mutaciones en segundo plano y movimientos de partes en segundo plano— y rechaza los comandos de partición que modifican datos (ATTACH/MOVE/DROP/DROP DETACHED/FETCH/REPLACE PARTITION y MOVE PARTITION ... TO TABLE hacia la tabla), además de las inserciones, mutaciones y OPTIMIZE que ya rechazaba. En consecuencia, una tabla table_readonly con TTL deja de recuperar el espacio de sus datos expirados mientras la configuración esté habilitada. #95079 (matt-metivier).

Eficiencia de memoria y recursos

  • Se reduce el uso de memoria de UNLOCK SNAPSHOT al dejar de cargar la metadata de cada parte de datos que la ruta de desbloqueo no utiliza, lo que evita errores por falta de memoria en instantáneas con un número muy elevado de partes. #111849 (jkartseva).
  • Se reducen las asignaciones de memoria al leer la metadata de copias de seguridad: ahora cada entrada de archivo se mueve a los mapas en memoria en lugar de copiarse. #111718 (jkartseva).

Rendimiento de funciones, tipos y formatos

  • Dar formato de texto a valores Decimal es mucho más rápido: hasta 190 veces para un Decimal256 con una escala grande y alrededor de 1,6 veces para un Decimal64. En procesadores con AVX-512 IFMA, convertir enteros de 64 bits a texto es aproximadamente 1,4 veces más rápido. También se corrigió el redondeo de toDecimalString, que descartaba el acarreo procedente de la parte fraccionaria: toDecimalString(toDecimal64('9.995', 3), 2) devolvía 9.00 y ahora devuelve 10.00. #112457 (thevar1able).
  • Se mejoró el rendimiento del algoritmo de unión partial_merge sobre claves FixedString al comparar secuencias de valores de una sola vez, en lugar de realizar una llamada de comparación por cada valor. #105737 (4ertus2).
  • HashJoin ahora admite de forma nativa claves LowCardinality de cadena no anulables de una sola columna. #107264 (nickitat).
  • Se mejoró el rendimiento de replaceAll y replaceRegexpAll cuando tanto el patrón como el reemplazo son un único carácter (por ejemplo, replaceRegexpAll(s, ' ', '_')). Estos reemplazos ya no alteran la disposición de los valores String, por lo que ahora la columna se copia una sola vez y los bytes coincidentes se reescriben in situ, en lugar de ejecutar un bucle de búsqueda por cada coincidencia. #108178 (groeneai).
  • Se aceleró el análisis de la representación canónica de fecha y hora YYYY-MM-DD hh:mm:ss en el modo best-effort (date_time_input_format = 'best_effort', cast_string_to_date_time_mode = 'best_effort'), que es el predeterminado. Con esto se recupera el rendimiento perdido por una regresión en el análisis, introducida al cambiar esos valores predeterminados de basic a best_effort. #108187 (groeneai).
  • Los literales de array y tupla profundamente anidados se analizan ahora en tiempo lineal en lugar de cuadrático. #108892 (alexey-milovidov).
  • La función toStartOfInterval (alias time_bucket, date_bin) es hasta 5 veces más rápida para intervalos SECOND, MINUTE y HOUR. #109729 (raimannma).
  • Las funciones arraySort y arrayReverseSort son varias veces más rápidas con arrays numéricos (incluidos Decimal y DateTime64) cuando se invocan sin una lambda. #109832 (raimannma).
  • Se aceleraron addDays, addWeeks, subtractDays y subtractWeeks con valores DateTime y DateTime64 en zonas horarias de desplazamiento fijo (como UTC) mediante una ruta rápida basada en aritmética. #109836 (raimannma).
  • Se vectorizó la descompresión del códec Delta. La decodificación ahora es entre 1,5 y 5 veces más rápida para tipos de datos de 8/16/32 bits, lo que acelera hasta un 20 % los escaneos de columnas comprimidas con Delta. #110189 (raimannma).
  • Se aceleraron las funciones de búsqueda de cadenas (like, position, match, countSubstrings, hasToken, etc.) sobre columnas Enum con una aguja constante: ahora se buscan solo los nombres distintos del enum y los resultados se asignan de vuelta a cada fila, en lugar de buscar en todas las filas. #110325 (alexey-milovidov).
  • Se ha mejorado hasta 1.5x el rendimiento de las funciones de búsqueda de subcadenas (position, countSubstrings, multiSearch*, replaceAll/replaceOne, y sus variantes que no distinguen entre mayúsculas y minúsculas y UTF-8) con un needle no constante, gracias al uso de buscadores de cadenas basados en SIMD en la ruta por fila en lugar de una alternativa ingenua. #110580 (Algunenano).
  • Se ha mejorado el rendimiento de la combinación de bloques (squashing) y la fusión de columnas Dynamic y Object con muchas variantes dinámicas o rutas JSON. #110583 (cv4g).
  • estimateCompressionRatio es más rápido con el códec NONE #111107 (rienath).
  • Se han acelerado la ordenación y otras operaciones basadas en comparaciones sobre columnas JSON cuyas rutas se almacenan en datos compartidos. Antes, cada comparación de valores materializaba una columna Dynamic temporal y ejecutaba una deserialización binaria completa de ambos operandos, lo que hacía que ORDER BY sobre dichas columnas fuera extremadamente lento. #111894 (groeneai).
  • La división de enteros de 256 bits (Int256, UInt256 y Decimal256) ahora calcula el cociente de 64 en 64 bits (un limb cada vez), mediante un bucle de divisiones 128 / 64 cuando el divisor cabe en 64 bits y el Algoritmo D de Knuth en caso contrario, en lugar de hacerlo bit a bit con división larga por desplazamiento y resta. Esto afecta a intDiv, modulo, la aritmética de Decimal256 y la conversión de estos tipos a texto. #112477 (thevar1able).
  • La lectura de una columna Nested desde un tipo codificado en binario (Native, RowBinary con input_format_binary_decode_types_in_binary_format) ya no convierte el tipo de nuevo en un nombre de tipo para volver a analizarlo. Además, un nombre de tipo Tuple anidado mal formado ahora se notifica como error de sintaxis, en lugar de tardar un tiempo exponencial en función de su profundidad de anidamiento y fallar con TOO_SLOW_PARSING. #112560 (alexey-milovidov).
  • Se han acelerado las consultas PromQL sobre tablas TimeSeries: timeSeriesIdToGroup ahora reutiliza el grupo de la fila anterior cuando filas consecutivas tienen el mismo id de serie, lo que evita la serialización del id y la búsqueda en el hash para cada fila. #113580 (nikitamikhaylov).

Otras mejoras del rendimiento

  • Se implementaron un lector y un escritor nativos para los formatos Arrow y ArrowStream que no utilizan la biblioteca Apache Arrow, lo que evita copias y conversiones de datos adicionales. Ahora son la opción predeterminada (configuraciones input_format_arrow_use_native_reader y output_format_arrow_use_native_writer) y son más rápidos tanto en lectura como en escritura. #106522 (alexey-milovidov).
  • Se optimizan los predicados nullIf(key, sentinel) = const para construir rangos de claves y permitir la poda mediante la clave primaria, las particiones y los índices de omisión. #107308 (adityaksolves).
  • El rendimiento de `INTERSECT ALL` y `EXCEPT ALL` (el modo predeterminado de `INTERSECT` y `EXCEPT`) se multiplica varias veces al indexar el multiconjunto por el valor de la fila en lugar de calcular el hash de cada fila con SipHash. #107649 (Algunenano).
  • Se aceleran las funciones match, extract, extractAll, replaceRegexpOne y replaceRegexpAll con expresiones regulares simples al compilarlas a código nativo con LLVM. Se controla mediante la nueva configuración compile_regular_expressions (habilitada de forma predeterminada); los patrones que quedan fuera del subconjunto admitido recurren de forma transparente al motor RE2. #108004 (alexey-milovidov).
  • Se aceleró la descompresión ZSTD en AArch64 (ARM) para columnas con offsets de coincidencia pequeños, como las columnas de enteros de ancho fijo, mediante la vectorización con NEON de las copias solapadas de offset corto. Por ejemplo, la descompresión de una columna UInt64 es hasta ~2.3 veces más rápida en AWS Graviton 4. #108049 (alexey-milovidov).
  • Se mejoró la velocidad de descompresión LZ4 para columnas de tamaño fijo y baja cardinalidad. #108175 (nickitat).
  • Se mejoró el rendimiento de levenshteinDistance (y editDistance) con cadenas de longitud media en ARM al evitar asignaciones de memoria en el heap por cada fila en la ruta de código de Myers por bloques. #108185 (groeneai).
  • Se acelera el análisis de números de coma flotante a partir de texto con precise_float_parsing = 1, que pasa a ser igual de rápido o más que el analizador predeterminado en casi todas las entradas. Además, se actualiza la biblioteca incluida fast_float a la v8.2.10. #108205 (Algunenano).
  • Las funciones de codificación y decodificación Base64 ahora utilizan simdutf, lo que mejora su rendimiento. #108333 (thevar1able).
  • Se optimiza DISTINCT para claves costosas de alta cardinalidad. #108366 (nihalzp).
  • Se mejoró el rendimiento de las funciones matemáticas al habilitar optimizaciones del compilador que no preservan errno. #108628 (nickitat).
  • Se acelera estimateCompressionRatio para columnas codificadas con T64 al calcular el tamaño comprimido de forma analítica en lugar de comprimir los datos. #109054 (rienath).
  • Los JOIN ahora pueden usar el índice de clave primaria o el índice de omisión de la tabla del lado izquierdo para podar gránulos #109085 (shankar-iyer).
  • Se mejora el rendimiento de las funciones geo de H3 (h3ToGeoBoundary, h3ToGeo, h3CellAreaM2/h3CellAreaRads2, geoToH3) al calcular conjuntamente pares de seno/coseno y eliminar llamadas trigonométricas redundantes en las transformadas de coordenadas. Los resultados no cambian (son idénticos bit a bit). #109399 (alexey-milovidov).
  • Se mejora hasta 7 veces el rendimiento de las comparaciones (<, >, <=, >=) de tipos de enteros anchos (Int128, UInt128, Int256, UInt256 y los tipos basados en ellos, como Decimal128), así como el de la conversión de enteros con signo a Int256 (hasta 7 veces con datos de signo mixto), al eliminar las bifurcaciones del código de comparación y de extensión de signo. #109474 (raimannma).
  • Las funciones con un único argumento Nullable no constante ahora comparten con el resultado el null map del argumento, en lugar de asignar y fusionar uno nuevo. #110151 (raimannma).
  • Se mejora en aproximadamente 1,3-1,5x el rendimiento de las funciones arrayMin y arrayMax sobre arrays numéricos, gracias a una reducción vectorizada en lugar de un bucle de comparación por elemento. #110163 (raimannma).
  • Se mejora el rendimiento de DISTINCT cuando el stream de entrada está ordenado por un prefijo de las columnas de DISTINCT, por ejemplo, SELECT DISTINCT a, b FROM table ORDER BY a. Estas consultas se ejecutan hasta 2,4 veces más rápido. #110170 (nihalzp).
  • Rutas de procesamiento por lotes vectorizadas para groupBitOr/groupBitAnd/groupBitXor y la familia de varianza (varPop, varSamp, stddevPop, stddevSamp, skewPop, skewSamp, kurtPop, kurtSamp, covarPop, covarSamp, corr): hasta 4x más rápidas con el combinador -If en condiciones impredecibles, y hasta 3x más rápidas para la familia de varianza sin él. #110461 (raimannma).
  • Se optimiza el análisis del índice de texto. #110530 (CurtizJ).
  • Se acelera el análisis de valores UUID a partir de texto (p. ej., JSONExtract en LowCardinality(UUID), toUUID, CAST AS UUID) al validar y convertir los dígitos hexadecimales en una sola pasada en lugar de dos. #110625 (groeneai).
  • Se acelera la descompresión ZSTD en x86_64 para columnas con desplazamientos de coincidencia pequeños, como las columnas de enteros de ancho fijo, mediante la vectorización de copias superpuestas de desplazamiento corto con SSSE3 pshufb (el equivalente en x86_64 de la optimización NEON para AArch64 de #108049). #110909 (thevar1able).
  • Se acelera hasta 3x groupUniqArray para tipos numéricos gracias al uso de hashing CRC32 (como en uniqExact) y a la inserción por fila en línea (inlining). #110917 (raimannma).
  • Se mejora la eficiencia de las estadísticas de columna minmax y básicas para columnas de coma flotante. #111221 (cv4g).
  • Devuelve los resultados de las consultas COUNT() directamente a partir de la metadata de cardinalidad del índice de texto. #111494 (ahmadov).
  • Acelera min y max en tipos de 128 y 256 bits (Int128, UInt128, Int256, UInt256, Decimal128, Decimal256): hasta 1,8 veces más rápido con enteros anchos y hasta 3,4 veces más rápido con decimales anchos. #111965 (raimannma).
  • Corrige una regresión de rendimiento en la ingesta de system.query_log. La construcción de las columnas de tipo mapa Settings y asynchronous_read_counters era unas 6 veces más lenta que antes, lo que podía hacer que SYSTEM FLUSH LOGS query_log superara su tiempo de espera de 180 segundos en servidores que registran muchas consultas con numerosas configuraciones modificadas. #112210 (groeneai).
  • Añade una caché opcional para los tokens que no existen en los índices de texto. #112742 (rorylshanks).
  • El registro asíncrono ahora utiliza una cola acotada sin bloqueos: los threads que escriben mensajes de log nunca se bloquean en un mutex ni despiertan a los threads de registro. #112803 (alexey-milovidov).
  • Utiliza el índice de clave primaria para pointInPolygon cuando el argumento de punto es una columna clave completa de tipo Point (u otra Tuple de dos elementos numéricos), p. ej., pointInPolygon(coord, [...]) en una tabla ordenada por coord. Antes solo se analizaba la forma pointInPolygon((x, y), [...]) con dos columnas clave escalares. #112956 (alexey-milovidov).
  • text_index_posting_list_apply_mode ahora tiene lazy como valor predeterminado, de modo que las consultas sobre índice de texto decodifican las listas de postings bajo demanda, con granularidad de bloque empaquetado y mediante un cursor, en lugar de materializarlas por adelantado en mapas de bits en los índices de texto que tienen configurado posting_list_codec. #113521 (CurtizJ).
  • Acelera las transformaciones vectorizadas de etiquetas de TimeSeries al sustituir la reasignación basada en hash por indexación directa cuando los ID de grupos de etiquetas ocupan un rango compacto. #114244 (fallintoplace).
  • Mejora el rendimiento de las fusiones de índices de texto. #114525 (CurtizJ).
  • Utiliza máscaras de presencia compactas para los operadores de conjunto de PromQL. #115224 (fallintoplace).
  • Al adjuntar las tablas del sistema, ya no se copia dos veces la metadata de cada tabla, incluida su descripción completa de columnas, solo para establecer el comentario de la tabla. #115490 (thevar1able).
  • Acelera las comprobaciones de series duplicadas en vectores de condición de PromQL compuestos íntegramente por ceros. #115822 (fallintoplace).
  • Acelera toUTCTimestamp/to_utc_timestamp y fromUTCTimestamp/from_utc_timestamp con argumentos DateTime64 y recupera el caudal que tenían antes de las correcciones previas de desbordamiento. Los resultados no cambian. #115838 (groeneai).
  • Se redujo el coste fijo de inicialización de la generación de datos aleatorios (rand, rand64, randomString, randomFixedString, generateUUIDv4, generateUUIDv7) en x86-64. La mejora es apreciable cuando los bloques son pequeños; los valores generados no cambian. #116158 (Algunenano).
  • Ahora se puede habilitar el plegado temprano con evaluación en cortocircuito para los operadores integrados and y or durante el análisis mediante el ajuste enable_function_early_short_circuit. Esto permite omitir la ejecución de subconsultas escalares count() de una sola fila que son código muerto, sin renunciar a la inferencia de tipos habitual ni a la validación semántica. #83505 (fhw12345).
  • Se utiliza una única llamada de IO al búfer para vectores trivialmente serializables #89842 (Ergus).
  • Se habilita optimize_or_like_chain de forma predeterminada. #94517 (alexey-milovidov).
  • Se mejora el rendimiento al recuperar el registro de un único usuario de system.users cuando el servidor tiene muchos usuarios. #96699 (alistairjevans).

Mejoras

Mejoras en consultas y SQL

  • Las CTE materializadas referenciadas desde varias ramas de una consulta UNION ahora se materializan una sola vez y se comparten entre todas las ramas. Anteriormente, cada rama recibía su propia copia de la CTE, que se expandía en línea y se evaluaba por separado. #102107 (novikd).
  • Se omite el filtro en tiempo de ejecución de JOIN cuando se estima que el lado de sondeo es pequeño. La nueva configuración join_runtime_filter_min_probe_rows (valor predeterminado: 1000) controla el umbral. #104860 (vdimir).
  • EXPLAIN [PLAN] actions=1, compact=1, pretty=1 pasa a ser el comportamiento predeterminado. #105036 (Fgrtue).
  • Se ha reducido la latencia de cancelación en las formas positivas de LIMIT BY (LimitByTransform, LimitBySortedStreamTransform): KILL QUERY y Ctrl+C ahora interrumpen el procesamiento en el transcurso de un único bloque, en lugar de esperar a que finalice todo el paso. #106070 (rvasin).
  • Las consultas JOIN ahora son compatibles con las réplicas paralelas automáticas. #106073 (nickitat).
  • Se añade una nueva métrica asíncrona UntrackedMemory (visible en system.asynchronous_metrics) que informa de la memoria ya asignada por los threads, pero aún no contabilizada en el contador global de seguimiento de memoria. Cada thread acumula localmente pequeñas asignaciones y las notifica en bloque. Esto ayuda a explicar las discrepancias entre MemoryTracking y el uso real de memoria del proceso. Los mensajes de error MEMORY_LIMIT_EXCEEDED ahora también incluyen la cantidad de memoria no contabilizada, lo que facilita entender por qué una consulta o el servidor alcanzó su límite de memoria. #106386 (mstetsyuk).
  • Cuando un INSERT falla porque la tabla de destino TO de una vista materializada rechaza la escritura mientras se construye el pipeline de inserción (por ejemplo, si el destino es una View o no admite transacciones), el mensaje de error ahora indica el nombre de la vista materializada y de su tabla de destino, en lugar de mostrar únicamente el error de almacenamiento sin más contexto. #107234 (groeneai).
  • ALTER TABLE ... MODIFY COLUMN <col> Tuple(...) sobre un Tuple con nombre ahora solo modifica la metadata cuando únicamente se añaden subcampos, por lo que es tan rápido como un ADD COLUMN de nivel superior. Se habilita mediante SET allow_metadata_only_named_tuple_alter = 1. #107305 (amosbird).
  • Se ha añadido la configuración materialized_postgresql_use_extended_date_and_time_types, definible en el momento de la creación, para el motor de base de datos MaterializedPostgreSQL. De forma predeterminada (habilitada), las columnas date/timestamp de PostgreSQL se infieren como Date32/DateTime64; si se establece en 0 al ejecutar CREATE DATABASE, se infieren los tipos de menor rango Date/DateTime. Esta configuración no se aplica al motor de tabla MaterializedPostgreSQL. #107428 (alexey-milovidov).
  • EXPLAIN PLAN ahora marca como aproximadas (~~...) las filas de resultado estimadas de una unión cuando la estimación procede de una sugerencia o de un mecanismo de respaldo aleatorizado en lugar de las estadísticas de la tabla, lo que ayuda a identificar planes que carecen de estadísticas fiables para el reordenamiento de JOIN. #107666 (vdimir).
  • INSERT en una tabla MergeTree ahora respeta la cancelación de la consulta y max_execution_time al escribir muchas partes, en lugar de poder seguir ejecutándose mucho tiempo después de haberse terminado. #107929 (al13n321).
  • arrayFold ahora respeta la cancelación de consultas y max_execution_time. Anteriormente, un fold sobre un array muy largo (por ejemplo, arrayFold(acc, x -> arrayPushFront(acc, x), range(number), emptyArrayUInt64())) ejecutaba todo el fold dentro de una única llamada a función y no podía interrumpirse, por lo que KILL QUERY y los límites de tiempo se ignoraban hasta que el fold terminaba. #108192 (groeneai).
  • Se añaden ProfileEvents para cada fase previa a la ejecución de la consulta: QueryParseMicroseconds, QueryAnalysisMicroseconds, QueryPlanBuildMicroseconds y QueryPipelineBuildMicroseconds. Permiten ver en qué se invierte el tiempo antes de ejecutar la consulta (análisis sintáctico, análisis, construcción del plan de consulta y construcción de la canalización) y están disponibles en system.query_log y system.events. #108282 (jrdi).
  • Las operaciones ALTER TABLE que generarían metadatos de tabla que superan max_query_size ahora se rechazan de antemano, lo que evita que componentes como la distribución de DDL o la recuperación de réplicas no puedan cargar las tablas. #108283 (lockie).
  • Se añadió ConstantJoin para uniones cartesianas y uniones con predicados constantes planificadas por el analizador, de modo que estas consultas ya no fallan por una configuración join_algorithm incompatible cuando se usa el analizador. #108289 (antaljanosbenjamin).
  • Se añadió a system.documentation una columna source con la ruta del archivo fuente donde se define la documentación de cada entidad. La tabla ahora también documenta los códecs de compresión, los eventos de perfil, las métricas actuales, las métricas asíncronas y las propias tablas del sistema (con sus columnas), y la documentación de la configuración incluye ahora su tipo y su valor predeterminado. #108346 (alexey-milovidov).
  • Si se usa WHERE con filtros sobre table y database, system.iceberg_history mostrará solo las bases de datos coincidentes. Esto puede ahorrar tiempo si hay muchas bases de datos remotas no relacionadas en el servidor. #108492 (Diskein).
  • Los parámetros de consulta (sustituciones {name:Type}) ahora pueden usarse como valores de configuración, tanto en la cláusula SETTINGS de una consulta (como SELECT o INSERT) como en consultas SET independientes; p. ej., SELECT ... SETTINGS max_threads = {threads:UInt64} y SET max_threads = {threads:UInt64}. #108760 (alexey-milovidov).
  • Permite calcular el beneficio combinado de los índices de omisión en EXPLAIN WHATIF. Muestra la proporción de datos, que corresponde a la intersección del rendimiento de todos los índices hipotéticos aplicables existentes. #108934 (yariks5s).
  • Una consulta con una única CTE ahora se formatea con los mismos saltos de línea y la misma sangría que una consulta con varias CTE. Anteriormente, WITH a AS (...) mantenía la CTE en la misma línea que WITH, mientras que con dos o más CTE WITH quedaba en su propia línea y cada CTE, sangrada. #109092 (groeneai).
  • Se admite la Query Condition Cache para archivos Parquet locales leídos mediante el motor de tabla File (antes solo se admitía para almacenamiento de objetos y data lakes). #109247 (alexey-milovidov).
  • La Query Condition Cache para archivos Parquet remotos (en almacenamiento de objetos) ahora usa como clave el ETag además de la ruta, de modo que sobrescribir un objeto en el mismo lugar ya no devuelve resultados obsoletos de la caché. #109310 (alexey-milovidov).
  • Una referencia no calificada a una clave de INNER JOIN que se iguala en la condición ON (p. ej., SELECT id FROM a INNER JOIN b ON a.id = b.id) ya no se notifica como identificador ambiguo, ya que se garantiza que ambos lados contienen el mismo valor. #109366 (alexey-milovidov).
  • Las funciones de distancia transpuestas sobre QBit (L2DistanceTransposed, cosineDistanceTransposed, dotProductTransposed y sus equivalentes cuantizadas L2DistanceTransposedQuantized, cosineDistanceTransposedQuantized, dotProductTransposedQuantized) ahora aceptan un vector de referencia más largo que el número de dimensiones en las que se busca e ignoran los elementos finales sobrantes. Esto permite reutilizar un vector de consulta de tamaño completo para una búsqueda de dimensión reducida (Matryoshka) sin tener que recortarlo primero. #109388 (alexey-milovidov).
  • Se añadió una comprobación de coherencia que garantiza que una consulta distribuida siempre incluya una versión de cliente conocida; si no es así, se lanza un error lógico en lugar de reenviar silenciosamente una versión cero a los shards remotos. Las consultas iniciadas por el servidor (vaciados en segundo plano, consumidores de streaming, recargas de diccionarios, vaciados de inserciones asíncronas) ahora informan de la propia versión del servidor como versión del iniciador. #109408 (alexey-milovidov).
  • Este parche corrige el uso de nombres de columna calificados en la cláusula WHERE de las mutaciones sobre los motores de tabla de la familia MergeTree. #109491 (Michicosun).
  • Se admiten funciones de ventana sin particionar (OVER (ORDER BY ...)) en planes de consulta distribuidos (make_distributed_plan). Anteriormente, cualquier consulta con una función de ventana fallaba porque WindowStep no podía serializarse para su ejecución remota; por ahora, las ventanas con PARTITION BY siguen rechazándose. #109802 (VighneshPath).
  • Ahora es posible modificar algunas configuraciones de autenticación del catálogo one-lake con ALTER DATABASE ... MODIFY SETTING = 'xxx'. #110019 (alesapin).
  • Una subconsulta en el lado derecho de IN cuya única columna es un array con un nivel de anidamiento más que el argumento izquierdo ahora se interpreta como el conjunto de los elementos del array (como un literal de array o una función que devuelve un array), en lugar de fallar con un confuso error de incompatibilidad de tipos. Por ejemplo, x IN (SELECT groupArray(x) FROM ...) ahora funciona. #110169 (alexey-milovidov).
  • Las consultas aceleradas mediante el filtrado dinámico TopK (ORDER BY ... LIMIT k) ahora aprovechan mejor la caché de condiciones de consulta: la caché se rellena incluso cuando se aplica la materialización diferida, y estas consultas pueden reutilizar entradas escritas previamente por una consulta ordinaria con el mismo predicado WHERE. #110507 (shankar-iyer).
  • SHOW CREATE TABLE (y SHOW CREATE VIEW / SHOW CREATE DICTIONARY) ahora sugiere una tabla con un nombre similar en el mensaje de error cuando la tabla solicitada no existe, igual que hacen las consultas SELECT. #110633 (alexey-milovidov).
  • Se añade el modificador STREAM BOUNDED, que lee solo la primera instantánea de una consulta de streaming y luego finaliza en lugar de suscribirse a las actualizaciones. #110653 (SmitaRKulkarni).
  • Se corrigió la caché de resultados de consultas para las consultas PromQL. El dialecto promql omitía la comprobación de funciones no deterministas y podía devolver resultados obsoletos anclados en now(); la API HTTP de Prometheus (/api/v1/query, /api/v1/query_range) nunca almacenaba entradas en la caché. #110887 (nikitamikhaylov).
  • EXPLAIN ANALYZE ahora muestra el número de filas de cada lado del join, las tasas de coincidencia, el factor de expansión (fanout) y el estado específico de cada algoritmo, como la memoria de la tabla hash y el volcado a disco. Use matches = 1 para recopilar las métricas de coincidencia que requieren contabilidad adicional. #110892 (Fgrtue).
  • Se corrigió un error de heap-use-after-free en el ejecutor del pipeline que podía provocar la caída del servidor cuando una consulta eliminaba procesadores en tiempo de ejecución (por ejemplo, FINAL con lecturas diferidas u ordenación externa). El error lo detectó el AST fuzzer. #111017 (groeneai).
  • Se corrigió un use-after-free (fallo de segmentación) que se producía cuando una consulta con una instantánea de almacenamiento compartido (configuración enable_shared_storage_snapshot_in_query) eliminaba partes de datos de la instantánea; por ejemplo, una subconsulta en streaming que leía la misma tabla MergeTree que otra parte de la consulta leía de forma concurrente. #111192 (alexey-milovidov).
  • Se admiten planes de consulta distribuidos (make_distributed_plan) para consultas cuyo origen, de forma demostrable, no produce filas en el momento de la planificación, como una lectura de una tabla MergeTree vacía. Anteriormente, estas consultas fallaban con SUPPORT_IS_DISABLED. #111941 (groeneai).
  • Se corrigió un problema por el que la caché de condiciones de consulta no se rellenaba para los gránulos descartados por cualquier conjunción que no fuera la última en una cláusula WHERE con varias condiciones AND. #112083 (shankar-iyer).
  • Se redujo el pico de memoria al escribir columnas JSON con serialización de datos compartidos por buckets (map_with_buckets y advanced), ya que ahora los datos compartidos se dividen en buckets de uno en uno durante la escritura en lugar de materializar todos los buckets simultáneamente. Esto beneficia sobre todo a las columnas Array(JSON): en JSON escalar, los datos compartidos se dividen por gránulo (limitado por index_granularity_bytes), por lo que el ahorro es pequeño; en cambio, un solo gránulo de Array(JSON) puede contener muchas filas anidadas y, por tanto, una gran cantidad de datos compartidos, y en ese caso dividirlos de bucket en bucket reduce considerablemente el pico de memoria #112172 (Avogar).
  • La planificación de reservas de memoria (experimental) ya no desaloja una asignación cuando una liberación de memoria pendiente dejaría libre el espacio necesario para un aumento de reserva que supera el límite: la decisión de desalojo ahora espera a que se apliquen las reducciones en curso, lo que evita terminar consultas innecesariamente en situaciones de presión de memoria. #112299 (serxa).
  • SYSTEM DROP FILESYSTEM CACHE ahora elimina en paralelo las claves de metadatos de la caché, lo que agiliza la limpieza de cachés del sistema de archivos de gran tamaño. La nueva configuración drop_cache_threads de la caché de archivos controla el número de workers de eliminación y su valor predeterminado es 16; con un valor de 1, la eliminación se realiza en el thread de la consulta. #112532 (kssenii).
  • Los modificadores de una declaración de columna (COMMENT, CODEC, STATISTICS, TTL, COLLATE, PRIMARY KEY y SETTINGS por columna) ahora pueden escribirse en cualquier orden en CREATE TABLE, y cada uno de ellos como máximo una vez. Antes solo se aceptaba un orden fijo y, por ejemplo, x UInt64 CODEC(ZSTD) COMMENT 'text' producía un error de sintaxis. En ALTER TABLE ... ADD COLUMN / MODIFY COLUMN, los modificadores compatibles (COMMENT, CODEC, STATISTICS, TTL y SETTINGS por columna) también pueden escribirse en cualquier orden; los SETTINGS por columna en ADD COLUMN y un STATISTICS declarado en ADD COLUMN / MODIFY COLUMN ahora se aplican en lugar de descartarse silenciosamente, y COLLATE y PRIMARY KEY en estos comandos ALTER ahora lanzan una excepción en lugar de ignorarse sin aviso. #112788 (alexey-milovidov).
  • Una consulta sobre una tabla Merge (o la función de tabla merge) que coincide con muchas tablas ahora responde a KILL QUERY y a max_execution_time mientras se construyen los planes de consulta de cada tabla, en lugar de hacerlo solo cuando ha terminado la planificación de todas las tablas hijas. #113415 (alexey-milovidov).
  • Un SELECT sobre una tabla Merge que supera max_execution_time con timeout_overflow_mode = 'break' ahora deja de construir planes de consulta para las tablas coincidentes restantes, en lugar de ejecutar el análisis completo de la consulta para cada tabla coincidente antes de detenerse. La consulta sigue finalizando sin error, tal como establece la documentación de ese modo. #113642 (groeneai).
  • Cuando el tipo declarado de una columna y sus datos no coinciden durante una lectura de MergeTree (procedencia de tipos mixta, p. ej., tras un ALTER TABLE ... MODIFY COLUMN cuya mutación aún no ha finalizado), el servidor ahora devuelve una excepción clara que indica la columna y ambas estructuras, en lugar de realizar una conversión sin comprobar: antes, los builds de depuración y con sanitizadores abortaban con un escueto Bad cast from type A to B sin indicar ninguna columna, y los builds de release recorrían silenciosamente memoria con una estructura distinta. #114087 (alexey-milovidov).
  • Se ha habilitado ie_join de forma predeterminada: el valor predeterminado de join_algorithm es ahora direct,parallel_hash,hash,ie_join. Un JOIN cuya sección ON contiene solo condiciones de desigualdad (dos comparaciones <, <=, >, >= entre expresiones de las tablas unidas) se ejecuta ahora con el algoritmo IEJoin basado en ordenación en lugar de con un CROSS JOIN y un filtro, y se admiten uniones LEFT/RIGHT/FULL/SEMI/ANTI con dichas condiciones. Como ie_join es el último de la lista, solo se utiliza cuando no es posible aplicar los demás algoritmos. #114327 (vdimir).
  • Se propaga el contexto de traza de OpenTelemetry a las fibras utilizadas para el establecimiento asíncrono de conexiones y la ejecución remota de consultas (hedged requests, async_socket_for_remote, async_query_sending_for_remote). Los spans de las consultas remotas en una consulta distribuida ahora cuelgan correctamente del span Connection::sendQuery del iniciador, en lugar de adjuntarse directamente al contexto de traza proporcionado por el cliente, y cada ejecución de tarea asíncrona genera su propio span. #114813 (diegomestre2).
  • DROP DATABASE ahora elimina las tablas en orden topológico inverso según las dependencias tanto de carga como referenciales (antes solo según las de carga), de modo que un fallo a mitad de DROP DATABASE no puede dejar una tabla cuyas dependencias ya se hayan eliminado. #114952 (alexey-milovidov).
  • Se admiten operadores de coincidencia de expresiones regulares al estilo de PostgreSQL: ~ (un alias de la función match), ~* (coincidencia sin distinguir entre mayúsculas y minúsculas), !~ y !~* (negaciones). Los comandos \d, \dt y \dv de psql ahora funcionan al conectarse a ClickHouse mediante el protocolo de compatibilidad con PostgreSQL, y una consulta fallida ya no cierra la conexión. #115066 (alexey-milovidov).
  • EXPLAIN WHATIF ahora indica por qué se omitió la estimación empírica en una nueva línea empirical_reason, que se muestra cuando empirical_status es unsupported. #115140 (yariks5s).
  • Cuando ningún algoritmo de unión habilitado por el ajuste join_algorithm puede ejecutar un JOIN, el mensaje de error ahora indica los algoritmos que se intentaron, así como la rigurosidad y el tipo del JOIN que falló, en lugar de limitarse a informar de que ninguno funcionó. #115226 (elkinal).
  • Las consultas de búsqueda vectorial ahora pueden usar el índice de similitud vectorial cuando el vector de referencia es un literal de array de enteros, p. ej., ORDER BY L2Distance(vec, [1, 2]). Anteriormente, estas consultas recurrían de forma silenciosa a un escaneo por fuerza bruta. #115255 (rschu1ze).
  • BACKUP ya no deja un archivo de bloqueo en su destino cuando el intento que lo creó falla antes de escribir nada, ya sea al reclamar el destino o al abrir un archivo comprimido. Ninguna copia de seguridad posterior podía coincidir con dicho bloqueo, por lo que todos los reintentos hacia el mismo destino fallaban hasta que el archivo se eliminaba manualmente. Las copias de seguridad a destinos S3 y Azure también crean el bloqueo de forma exclusiva, y un bloqueo que pertenece a otra copia de seguridad se notifica como una copia de seguridad concurrente, en lugar de con el error que hubiera devuelto el almacenamiento. #115387 (jkartseva).
  • Una traza iniciada por muestreo (opentelemetry_start_trace_probability) ahora se escribe de vuelta en la información de cliente de la consulta, de modo que las consultas secundarias remotas y distribuidas, así como las entradas DDL, se incorporan a la misma traza en lugar de iniciar trazas independientes. #115619 (diegomestre2).
  • Se corrigió CREATE TABLE para tablas Iceberg respaldadas por Amazon S3 Tables, que gestiona por sí mismo las ubicaciones de las tablas. #115652 (scanhex12).
  • La agregación adaptativa de GROUP BY (enable_adaptive_aggregator) ahora mide si compensa diferir las claves poco frecuentes y vuelve al algoritmo ordinario cuando sus claves o argumentos de agregación son demasiado anchos para que copiarlos resulte rentable, de modo que las agregaciones sobre columnas de cadenas pesadas (p. ej., min(URL) por usuario) se ejecutan con la velocidad y el consumo de memoria del algoritmo ordinario. Se añade adaptive_aggregator_freeze_threshold_bytes para limitar en bytes la tabla congelada de cada hilo (la tabla se congela al alcanzarse el primero de los dos umbrales: este o el de número de claves). #115755 (nihalzp).
  • Se añade el ajuste query_plan_aggregation_bucket_top_k (habilitado por defecto) para activar o desactivar la optimización del plan que materializa solo los n mejores grupos de cada bucket de dos niveles cuando una agregación final alimenta un ORDER BY sobre sus salidas con LIMIT n. La optimización ahora también se muestra en la salida de EXPLAIN. #116124 (nihalzp).
  • Se mejora la compatibilidad de las consultas DESCRIBE con las vistas parametrizadas. Se admiten vistas parametrizadas en expresiones escalares en el nuevo analizador. #68978 (novikd).
  • Las consultas como SELECT * FROM t WHERE id ahora utilizarán la omisión de datos mediante índices en la columna id. #89603 (adityachopra29).
  • Se añadió la configuración query_plan_merge_expression_into_join para permitir la fusión de pasos Expression en pasos JOIN durante la optimización de reordenamiento de JOIN. Esto permite reordenar JOIN a través de subconsultas que encapsulan uniones (p. ej., cuando un JOIN se encuentra dentro de una subconsulta con columnas calculadas), lo que mejora la optimización de árboles de uniones complejos. #98533 (vdimir).
  • Se añadió a la tabla system.grants una columna is_wildcard que indica si un privilegio utiliza coincidencia de prefijo con comodín (p. ej., GRANT SELECT ON db*.*). Anteriormente, en system.grants no era posible distinguir entre los privilegios con comodín y los exactos sobre un mismo nombre. #98577 (il9ue).

Funciones y tipos de datos

  • Se añadió una nueva configuración allow_lossy_numeric_supertype (deshabilitada de forma predeterminada). Cuando está habilitada, if, multiIf, coalesce, ifNull, array y map aplicados a argumentos numéricos que no tienen un tipo común sin pérdida (por ejemplo, un Decimal y un Float64, o un Int64 y un Float64) se resuelven al supertipo numérico Float64 en lugar de a un Variant, de modo que el resultado puede usarse con funciones de agregación como sum, avg, min y max. Ahora, los mensajes de error correspondientes de las funciones de agregación mencionan el nombre de esta configuración. #107236 (groeneai).
  • El cuantificador de array SOME / ALL (expr OP SOME(array) / expr OP ALL(array)) ahora también admite los predicados de comparación con palabra clave IS DISTINCT FROM e IS NOT DISTINCT FROM, así como los predicados de búsqueda de cadenas LIKE, ILIKE, NOT LIKE, NOT ILIKE y REGEXP, que se reescriben como arrayExists / arrayAll. #107454 (alexey-milovidov).
  • Se añadió la configuración input_format_json_max_object_size para limitar el tamaño de los objetos JSON durante el análisis. #107669 (Avogar).
  • Se corrigió una fuga de memoria que se producía al fallar la apertura de una base de datos SQLite (por ejemplo, cuando a la función de tabla sqlite o al motor de base de datos SQLite se les proporciona una ruta que no se puede abrir). #107807 (alexey-milovidov).
  • Se admite la función length para el tipo de datos QBit. Devuelve la dimensión del vector como una constante. #108071 (alexey-milovidov).
  • Se admite CAST de un QBit a un Array, lo que reconstruye el vector original. Es la operación inversa de la conversión ya existente de Array a QBit. #108072 (alexey-milovidov).
  • El motor de base de datos, el motor de tabla y la función de tabla MySQL ahora asignan los tipos de columna espaciales de MySQL (LINESTRING, POLYGON, MULTILINESTRING, MULTIPOLYGON y el genérico GEOMETRY) a los tipos geométricos correspondientes de ClickHouse en lugar de a String. Este comportamiento se controla mediante el nuevo indicador geometry de la configuración mysql_datatypes_support_level, habilitado de forma predeterminada. POINT se sigue convirtiendo siempre a Point. La columna genérica GEOMETRY se asigna al tipo general Geometry; al leer un valor cuyo subtipo no tiene equivalente en ClickHouse (MULTIPOINT, GEOMETRYCOLLECTION), se genera una excepción en el momento de la lectura. #108944 (alexey-milovidov).
  • Ahora se usa de forma predeterminada el algoritmo preciso (el valor representable más cercano) para analizar números de punto flotante, y la configuración precise_float_parsing se aplica a los formatos de entrada (CSV, TSV, JSON, VALUES, …) y a los literales numéricos, no solo a toFloat*/CAST. Establezca precise_float_parsing = 0 para recuperar el comportamiento anterior, más rápido en algunos casos pero menos preciso. #109086 (Algunenano).
  • Se admite reinterpret de un Array de elementos de tamaño fijo como String, la operación inversa del reinterpret ya existente de un String/FixedString como Array. #109383 (alexey-milovidov).
  • Se permite CAST entre tipos QBit que difieren en el tipo de elemento y/o en el stride, siempre que la dimensión se mantenga (por ejemplo, CAST(x AS QBit(Float64, N)) desde un QBit(Float32, N)). Los cambios que solo afectan al stride no implican pérdida; los cambios de tipo de elemento siguen la semántica de conversión de Array correspondiente (por ejemplo, al pasar de Float32 a BFloat16 puede perderse precisión, y accurateCast / accurateCastOrNull rechazan las filas que no se pueden representar con exactitud). #109387 (alexey-milovidov).
  • Las funciones quantizeBFloat16ToInt8 y dequantizeInt8ToBFloat16 ahora también aceptan argumentos Array y QBit, además de las sobrecargas escalares existentes, y aplican el códec Lloyd-Max a todo el vector (devolviendo Array/QBit del tipo de elemento correspondiente). #109398 (alexey-milovidov).
  • El especificador de formato de estilo MySQL %f en parseDateTime / parseDateTime64 (y sus variantes OrZero / OrNull) ahora acepta entre 1 y 6 dígitos fraccionarios, que se interpretan como microsegundos alineados a la izquierda, igual que en STR_TO_DATE de MySQL, en lugar de exigir exactamente 6. También se corrigieron tablas PrettyCompact desalineadas en los ejemplos de la documentación de funciones integradas. #109421 (alexey-milovidov).
  • La subestadística NullCount de las estadísticas basic pasa a llamarse DefaultCount: en lugar de contar las filas NULL de una columna Nullable, build ahora cuenta las filas iguales al valor predeterminado intrínseco del tipo de la columna mediante IColumn::getNumberOfDefaultRows. #109977 (hanfei1991).
  • Se redujo el tamaño del binario en ~10,5 MB al ejecutar las operaciones de comparación y aritméticas sobre pares de tipos mixtos poco usados (Decimal frente a enteros de distinto ancho, y pares que involucran Int128/UInt128/Int256/UInt256) mediante una conversión a un tipo común, en lugar de usar un kernel compilado dedicado para cada combinación de tipos. Los pares del mismo tipo, los pares de uso habitual y las operaciones limitadas por memoria plus/minus/multiply conservan sus kernels dedicados; los resultados, los tipos de resultado y los casos excepcionales no cambian. #110131 (alexey-milovidov).
  • La lectura desde un motor de tabla SQLite o desde la función de tabla sqlite ya no ocupa por completo un núcleo de CPU en espera activa cuando la base de datos SQLite está bloqueada por otra conexión. Ahora la lectura permanece inactiva mientras espera a que se libere el bloqueo y se puede seguir cancelando. #110248 (groeneai).
  • Los valores de tiempo transcurrido, tasa y proporción en los mensajes de log y de excepción se redondean ahora a tres dígitos, de modo que números como 1.345844286 sec. ya no se muestran con precisión completa. #110277 (alexey-milovidov).
  • Se corrigieron las lecturas de MergeTree de columnas String con un stream de tamaños independiente tras omitir filas iniciales, que podían devolver datos erróneos o leer fuera de los límites de la caché de substreams. También se corrigió la posible obtención de datos erróneos cuando lecturas concurrentes o repetidas acceden a un subobjeto JSON almacenado con serialización de datos compartidos de tipo map. #110471 (alexey-milovidov).
  • Se admite la cláusula SETTINGS en el motor de tabla PostgreSQL y en la función de tabla postgresql (por ejemplo, SETTINGS postgresql_connection_pool_size = 50), lo que equipara sus funcionalidades a las del motor MySQL. #110614 (alexey-milovidov).
  • Las funciones bitmaskToArray y bitmaskToList ahora admiten argumentos (U)Int128 y (U)Int256. Con argumentos de enteros grandes, la función bitPositionsToArray ahora se ejecuta en un tiempo proporcional al número de bits activos, en lugar de a la posición del bit activo más alto. #110743 (raimannma).
  • Se corrigió el manejo de valores de ancho fijo con signo que contienen números negativos en el códec GCD. Anteriormente, el divisor se calculaba directamente a partir de los valores con signo, lo que podía impedir encontrar el divisor común y reducir significativamente la eficiencia de compresión en columnas de tipo entero y decimal con signo. Ahora, para los tipos con signo, el divisor se calcula a partir de las magnitudes, y se mantiene el comportamiento existente para los tipos sin signo y para la descompresión. #113798 (kshcherbatov).
  • Las funciones de ventana con PARTITION BY ahora funcionan con make_distributed_plan. Cuando la forma del plan lo permite, la ventana se ejecuta en paralelo en varios buckets, cada uno de los cuales recibe particiones completas. #114111 (VighneshPath).
  • Ahora se utiliza una función hash de 64 bits en los métodos de agregación externa de ancho fijo con valores nullable (lo que evita colisiones masivas en agregaciones de cardinalidad muy alta). #114210 (nickitat).
  • x IN (subquery) sobre una columna LowCardinality ahora devuelve LowCardinality(UInt8), el mismo tipo que x IN (literal list). Anteriormente, ambas formas devolvían tipos distintos, y los planes distribuidos con un IN de este tipo requerían un caso especial en la comprobación de tipos del plan. #114229 (davenger).
  • Ahora se pueden analizar enteros que superan el rango de 64 bits en el tipo de datos JSON, JSONExtract e isValidJSON. Estos valores se leen en tipos de enteros anchos, como Int128/UInt256, en lugar de provocar el rechazo de todo el documento. #114379 (Avogar).
  • Se añadió keyword como alias del tokenizador array del índice de texto para mejorar la compatibilidad con OpenSearch, Elasticsearch, SolR y Lucene. #115507 (rschu1ze).
  • Las funciones toDateOrNull, toDateTimeOrNull y toDateTime64OrNull ahora aceptan argumentos de todos los tipos enteros nativos (que se interpretan igual que en toDate, toDateTime y toDateTime64, con un argumento opcional de zona horaria) y devuelven NULL para valores fuera del rango del tipo de resultado. Por ejemplo, toDateTimeOrNull(1583851242, 'Asia/Shanghai') devuelve 2020-03-10 22:40:42 y toDateTimeOrNull(4294967296) devuelve NULL. #79791 (jitendra1411).

Almacenamiento, lagos de datos y almacenamiento de objetos

  • Se añadieron métricas opcionales de Prometheus para la actividad de desalojo de la caché del sistema de archivos (filesystem_cache_evictions_total, filesystem_cache_evicted_bytes_total, filesystem_cache_evicted_segment_hits, filesystem_cache_evicted_segment_size_bytes y sus variantes por usuario etiquetadas con user_id), expuestas por caché mediante system.dimensional_metrics, system.histogram_metrics y el endpoint de Prometheus. Se controlan con las opciones de configuración de disco de la caché expose_prometheus_eviction_metrics y expose_prometheus_eviction_metrics_per_user (ambas desactivadas de forma predeterminada), que pueden activarse o desactivarse en tiempo de ejecución mediante SYSTEM RELOAD CONFIG. #105020 (sacheendra).
  • El motor Alias ahora admite la lectura con réplicas paralelas cuando la tabla de destino usa un motor de la familia MergeTree. #107830 (nauu).
  • Se limita a max_inflight_parts_for_one_file el número de partes preparadas simultáneamente en la copia de lectura y escritura de Azure Blob Storage (que utilizan las copias de seguridad cuando la copia nativa no está disponible), lo que evita un uso excesivo de memoria al copiar muchos archivos grandes en paralelo. #108232 (SmitaRKulkarni).
  • Se admite la columna virtual _etag para el almacenamiento HDFS #108255 (zhangyifan27).
  • Se añadieron las columnas settings y engine_settings a system.backups y system.backup_log. settings muestra las opciones de configuración específicas de copia de seguridad/restauración solicitadas para una operación (p. ej., allow_s3_native_copy, deduplicate_files, structure_only), y engine_settings muestra las opciones de configuración que realmente utiliza el lector/escritor del motor de copia de seguridad (p. ej., las opciones de solicitudes de S3, como allow_native_copy, que pueden diferir de las solicitadas tras combinarse con la configuración del endpoint). Así es posible ver con qué opciones de configuración se ejecutó realmente una operación BACKUP/RESTORE. #108334 (jkartseva).
  • Se añadieron system.s3_queue_metadata y system.azure_queue_metadata para inspeccionar el estado en Keeper de las tablas S3Queue y AzureQueue registradas, incluidos los recuentos de archivos procesados, en procesamiento y fallidos. #108522 (kssenii).
  • Se redujo entre 2 y 2,5 veces el uso de memoria de la caché de encabezados del índice de texto. Ahora caben más encabezados de partes de datos en la caché (opción text_index_header_cache_size), lo que reduce las lecturas de disco en las consultas de búsqueda de texto. #109332 (CurtizJ).
  • Se añadieron columnas de compatibilidad con MySQL a las vistas de INFORMATION_SCHEMA: SCHEMATA.DEFAULT_COLLATION_NAME y DEFAULT_ENCRYPTION; TABLES.ENGINE y otras columnas de MySQL relacionadas; y COLUMNS.COLUMN_KEY, PRIVILEGES, GENERATION_EXPRESSION, SRS_ID. Esto permite que los clientes compatibles con MySQL ejecuten sus consultas de introspección del catálogo sin toparse con UNKNOWN_IDENTIFIER. #109351 (alexey-milovidov).
  • Se redujo el uso de memoria de las tablas MergeTree con muchas partes de datos al compartir entre las partes de una tabla la metadata por parte derivada del esquema (lista de columnas, descripciones de columnas, serializaciones y subflujos de columnas), en lugar de copiarla en cada parte. El efecto es mayor en tablas anchas con muchas partes pequeñas. #109816 (Algunenano).
  • Se añadió una nueva configuración use_projection_index_in_read_pools (deshabilitada de forma predeterminada). Cuando está habilitada, los rangos de marcas que un índice de proyección filtra por completo se descartan dentro de los grupos de lectura de MergeTree antes de crear tareas de lectura para ellos, en lugar de omitirse gránulo a gránulo durante la lectura. Así se evita crear tareas de lectura y configurar lectores para datos que no se van a leer, y el tamaño de las tareas de lectura se sigue midiendo en marcas restantes. #110291 (KochetovNicolai).
  • Se redujo el nivel de detalle de los diagnósticos de búsqueda binaria en la clave primaria por parte en MergeTree, que pasan del registro de nivel trace al de nivel test. #110324 (alexey-milovidov).
  • Se corrigieron reconexiones espurias de conexiones HTTP keep-alive agrupadas sobre TLS (HTTPS, S3). La comprobación de conexiones obsoletas usaba poll sobre el socket, que informa erróneamente como cerrada una conexión segura activa con un registro TLS posterior al handshake pendiente de leer (un ticket de sesión o KeyUpdate); ahora usa un MSG_PEEK no bloqueante en sockets sin cifrar y SSL_peek/SSL_has_pending en sockets TLS, lo que además detecta correctamente un cierre TLS ordenado y un registro TLS que solo ha llegado en parte. #110402 (alexey-milovidov).
  • Los catálogos de OneLake ahora pueden usar tokens de actualización de OAuth para renovar los tokens de acceso. #110413 (alesapin).
  • Se añadió el ProfileEvent DuplicationDataHashComputations, que cuenta los cálculos de hash de datos por columna realizados al deduplicar bloques insertados con INSERT en tablas *MergeTree. #111173 (valerypetrov).
  • El SST del índice UNIQUE KEY ahora se escribe directamente en la parte a través de la abstracción de almacenamiento, en lugar de almacenarse provisionalmente en un archivo temporal local. #111189 (JingYanchao).
  • Se admiten escrituras concurrentes en tablas Iceberg en un disco local: LocalObjectStorage ahora implementa escrituras condicionales, por lo que la operación compare-and-swap que publica una nueva instantánea mediante version-hint.text funciona también en ese caso y los escritores concurrentes ya no pueden perder las actualizaciones de los demás. #112556 (alexey-milovidov).
  • La caché de regiones de buckets del client de S3 ahora también funciona con los catálogos de data lake; antes, cada solicitud a estos volvía a resolver la región. #113330 (scanhex12).
  • Los fallos de red del lado del cliente de Azure (conexión restablecida/rechazada, errores de DNS y TLS) ahora se reintentan como errores de transporte en lugar de devolverse como un 500 sintético, igual que en el client de S3. #115269 (arsenmuk).

Formatos e ingestión

  • Se permite la compresión snappy en la interfaz HTTP (Accept-Encoding: snappy) y se añade el setting snappy_mode para elegir entre el formato de bloque snappy de Hadoop o el formato de estructura de tramas de snappy para la E/S snappy genérica de file/url. #100752 (alexey-milovidov).
  • Se añadió el setting input_format_csv_missing_nullable_as_empty_string (deshabilitado de forma predeterminada). Cuando está habilitado, un valor ausente de Nullable(String) en la entrada CSV se lee como un String vacío en lugar de NULL, independientemente del valor de input_format_csv_empty_as_default. #107577 (alexey-milovidov).
  • Al procesar mensajes protobuf con input_format_protobuf_oneof_presence, ya no se exige una coincidencia exacta de las etiquetas, lo que permite realizar cambios de esquema. #109174 (ilejn).
  • Se eliminó el lector ORC heredado basado en Apache Arrow. El formato de entrada ORC ahora utiliza siempre el decodificador nativo de ClickHouse (que antes era el predeterminado). El setting input_format_orc_use_fast_decoder queda obsoleto (se sigue aceptando, pero no tiene ningún efecto). #110074 (alexey-milovidov).
  • El motor Hive ahora lee la metadata de los archivos ORC (índices min/max, recuentos de filas) con el lector ORC nativo de ClickHouse en lugar del adaptador ORC de Apache Arrow. #110086 (alexey-milovidov).

Seguridad, acceso y observabilidad

  • Se agregó una nueva columna skipping_indices_types a la tabla system.tables, que contiene los distintos tipos de índices de omisión de datos definidos en cada tabla. #106388 (CurtizJ).
  • El valor automático de max_threads y de configuraciones similares ahora se muestra en system.settings como auto(8) en lugar de 'auto(8)'; las comillas simples que lo rodeaban eran un artefacto heredado que llevaba mucho tiempo incrustado en el valor. Se mantiene la compatibilidad entre versiones: la forma heredada entre comillas se sigue aceptando al analizar las configuraciones recibidas de servidores más antiguos. #108657 (alexey-milovidov).
  • Cuando el valor predeterminado de una configuración está vacío, ahora se muestra como cadena vacía en system.documentation, en lugar de como comillas invertidas vacías. #108708 (alexey-milovidov).
  • La documentación de una configuración en system.documentation (la que muestran la página integrada /docs y el comando help) ahora incluye el historial de cambios de su valor predeterminado: la versión en la que se introdujo la configuración y cada cambio posterior de su valor predeterminado, con el valor anterior, el nuevo valor y el motivo del cambio. #112177 (alexey-milovidov).
  • Ahora es posible consultar la documentación de todas las sentencias SQL (p. ej., nombre, sintaxis, descripción y ejemplos) en la tabla del sistema system.statements. #115341 (rschu1ze).

Configuración

  • Se añadió una nueva configuración de servidor memory_worker_rss_speculative_reserve_ratio (por defecto 1.0, o 0 en builds con sanitizador) que hace que el rastreador de memoria global reserve de forma especulativa ratio * min(resident - previous_resident, resident - tracked) por encima del RSS observado en cada ciclo de MemoryWorker. Esto sesga el rastreador al alza cuando el RSS crece más rápido de lo que el rastreador lo contabiliza entre muestras, de modo que las asignaciones reciben MEMORY_LIMIT_EXCEEDED antes y es menos probable que el OOM-killer del kernel actúe primero. Establezca el ratio en 0 para desactivar la reserva especulativa. Los builds con sanitizador usan 0 por defecto porque en ellos la diferencia resident - tracked se debe principalmente a la memoria sombra del sanitizador. #104976 (alexey-milovidov).
  • El modo de aplicación diferida de listas de publicación del índice de texto deja de ser experimental y puede seleccionarse con text_index_posting_list_apply_mode = 'lazy' sin necesidad de allow_experimental_text_index_lazy_apply. La configuración del umbral de densidad pasa a llamarse text_index_lazy_intersection_density_threshold en lugar de text_index_density_threshold. #108814 (CurtizJ).
  • La configuración merge_selector_enable_heuristic_to_lower_max_parts_to_merge_at_once ahora está habilitada por defecto: el selector de fusiones reduce automáticamente el número máximo de partes que se fusionan a la vez en función del grado de ocupación de la partición. #110726 (Michicosun).
  • Los comandos de limpieza de PostgreSQL RESET, UNLISTEN y DISCARD se aceptan como operaciones sin efecto en el protocolo de comunicación de PostgreSQL, en lugar de rechazarse con un error de sintaxis. Esto mejora la compatibilidad con controladores como Skunk, que envían RESET ALL y UNLISTEN * al establecer y limpiar la conexión. #110780 (alexey-milovidov).
  • Las funciones de texto de IA (aiGenerate, aiClassify, aiExtract, aiTranslate) ahora rechazan las respuestas del proveedor truncadas o incompletas por cualquier otro motivo (p. ej., cuando el modelo alcanza el límite max_tokens) en lugar de devolver silenciosamente una salida parcial. El comportamiento se rige por la configuración ai_function_throw_on_error. #111830 (george-larionov).
  • Se mejoran L2DistanceTransposedQuantized, cosineDistanceTransposedQuantized y dotProductTransposedQuantized con precisión reducida, reconstruyendo los códigos p < 8QBit(Int8) mediante centroides de prefijo de media condicional gaussiana. Con precisión completa (p = 8), los resultados siguen siendo idénticos bit a bit; las distancias aproximadas con precisión reducida pueden cambiar, y las mejoras en recall y latencia dependen de la carga de trabajo. #111867 (skuznetsov).
  • La configuración write_snapshot_version ahora se puede recargar en caliente. #112150 (alesapin).
  • Se añadió observabilidad para las pilas de las fibras, que se usan para la comunicación asíncrona con réplicas remotas: los eventos de perfil FiberStackAllocs, FiberStackAllocBytes, FiberStackAllocNanoseconds y FiberStackFreeNanoseconds, y las métricas FiberStacks y FiberStackBytes. #114541 (alexey-milovidov).
  • El protocolo Prometheus remote-write ahora admite inserciones asíncronas: los datos de varias solicitudes remote-write concurrentes se agrupan en lotes antes de formar partes, según la configuración async_insert (habilitada por defecto; añada async_insert=0 a la URL del handler para mantener el comportamiento síncrono). Una solicitud solo se confirma después de que los datos se hayan volcado en todas las tablas internas de la tabla TimeSeries de destino. #115688 (nikitamikhaylov).

Otras mejoras

  • Se añadieron dos ajustes, shrink_over_allocated_columns_min_waste_ratio y shrink_over_allocated_columns_min_waste_bytes, que hacen que los INSERT reduzcan las columnas sobreasignadas (cuya memoria reservada supera la memoria utilizada debido al crecimiento en potencias de dos de las columnas de longitud variable) para ajustarlas a su tamaño real antes de la materialización y la escritura de partes, lo que reduce el pico de uso de memoria. Deshabilitado de forma predeterminada.. #112161 (Avogar).
  • Se omite por completo el paso de lectura de datos en las fusiones TTLDrop para evitar un uso excesivo de memoria, especialmente en las asignaciones de los búferes de lectura/precarga. #105859 (Avogar).
  • Se añadió compatibilidad con BFloat16 en dotProduct y se mejoró el rendimiento del producto escalar mediante el procesamiento por lotes en la ruta SIMD. #106569 (nickitat).
  • Ahora max_named_collection_num_to_throw, max_table_num_to_throw, max_replicated_table_num_to_throw, max_view_num_to_throw, max_dictionary_num_to_throw y max_database_num_to_throw se pueden modificar sin reiniciar el servidor. #106821 (UberDever).
  • La escritura en tablas DeltaLake, controlada por allow_experimental_delta_lake_writes, pasó a fase Beta. #107034 (kssenii).
  • Se añadió el tipo de estadísticas de columna uniq_v2, una alternativa ligera a uniq basada en el sketch uniqCombined64. #107863 (hanfei1991).
  • Se añadieron los ProfileEvents DistributedPlanRemoteTasks, DistributedPlanLocalExecution y DistributedPlanHostsUsed para supervisar la ejecución de make_distributed_plan. #107985 (shankar-iyer).
  • Las solicitudes a catálogos REST de data lakes, como OneLake, ahora incluyen un encabezado User-Agent de ClickHouse. #108117 (scanhex12).
  • MVTEncodeGeom ahora ajusta la geometría a la cuadrícula de píxeles enteros antes del recorte y recorta los polígonos con wagyu, de modo que la salida recortada es válida (los anillos que se intersecan a sí mismos se reparan) y queda alineada con los bordes, igual que ST_AsMVTGeom de PostGIS. #108248 (saarthak2002).
  • Se habilitaron globalmente las tres cachés del índice de texto; anteriormente, solo estaban habilitadas dentro de las consultas. Además, el tamaño de la caché de listas de postings ahora es cero (lo que, en la práctica, vuelve a deshabilitarla), ya que las listas de postings son grandes y almacenarlas en caché resulta demasiado costoso. #108274 (rschu1ze).
  • El endpoint de Prometheus (para configuraciones solo de métricas) y la recopilación de métricas asíncronas se inician antes de cargar las tablas, para que las métricas puedan observarse durante la fase de carga de metadatos, que puede prolongarse. #108402 (cwurm).
  • Compatibilidad con BFloat16 en las funciones matemáticas binarias #108442 (zhangyifan27).
  • Las funciones de distancia vectorial transpuestas L2DistanceTransposed, cosineDistanceTransposed y dotProductTransposed ahora aplican la optimización de lectura parcial de planos de bits a las columnas Nullable(QBit), de modo que solo leen los planos de bits solicitados en lugar de la columna completa. #109358 (alexey-milovidov).
  • Se admiten arraySum, arrayAvg y arrayProduct para arrays de BFloat16. #109420 (alexey-milovidov).
  • Las funciones L1Normalize, L2Normalize, LinfNormalize y LpNormalize (y sus alias) ahora funcionan con arrays, no solo con tuplas, de forma coherente con L2Norm y las funciones de distancia. #110052 (alexey-milovidov).
  • Ya no se hace ping a las conexiones del grupo antes de cada uso. Esto elimina el viaje de ida y vuelta Ping-Pong que se añadía a cada conexión reutilizada y reduce la latencia de las consultas distribuidas y de clickhouse-benchmark. Las conexiones obsoletas del grupo se detectan mediante un sondeo con tiempo de espera cero (una comprobación no bloqueante que no añade ningún viaje de ida y vuelta) y se recuperan mediante una reconexión. #110068 (alexey-milovidov).
  • Las partes de listas grandes para el análisis distribuido de índices se envían como escalares (lo que evita posibles fallos debidos a max_ast_elements/max_query_size y elimina la sobrecarga de analizar el AST) #110419 (azat).
  • Al hacer clic en el logotipo de la nube en el Playground, ahora se abre el sitio web de ClickHouse en una pestaña nueva para no perder el progreso mientras se ejecutan las consultas. #110422 (williamhatcher).
  • Se cambia el valor predeterminado de auto_statistics_types de basic, uniq a basic, uniq_v2 #110878 (hanfei1991).
  • Cuando salta una aserción de reentrada de RWLockImpl::getLock() (RWLock is already locked in exclusive mode / Cannot acquire exclusive lock while RWLock is already locked), el mensaje de error ahora indica los demás query_id que tienen actualmente el bloqueo y cuántos bloqueos mantiene ya el query_id solicitante, para facilitar el diagnóstico de este tipo de errores de orden de bloqueo. #110971 (groeneai).
  • randomHadamardTransform ahora calcula una transformada exacta que preserva la longitud para cualquier longitud de vector cuyo mayor factor impar sea como máximo 64 (por ejemplo, 3584 = 512 * 7, habitual en modelos de embeddings), lo que amplía las familias anteriores 2^N, 2^k * {12, 20} y 2^k * 9. Una transformada completa de una longitud que no puede representarse de forma exacta ahora genera una excepción en lugar de rellenar silenciosamente con ceros hasta un vector más largo; pase output_dims para calcular una proyección truncada de longitud arbitraria. #111006 (alexey-milovidov).
  • Se devuelve el código HTTP 403 Forbidden (en lugar de 500 Internal Server Error) para las excepciones ACCESS_DENIED a través de la interfaz HTTP. #111043 (Schum-io).
  • UTMToGeo ahora acepta como cuarto argumento la letra de banda de latitud MGRS devuelta por geoToUTM (además del indicador entero de hemisferio), de modo que un resultado de geoToUTM puede convertirse de ida y vuelta directamente con UTMToGeo. #111521 (alexey-milovidov).
  • MaterializedPostgreSQL ahora conserva los valores TOAST de PostgreSQL que no se han modificado durante las actualizaciones, en lugar de reemplazarlos por valores predeterminados. #111552 (OrpheusAgent).
  • Se añadieron las configuraciones text_index_max_processed_tokens_before_flush y text_index_max_memory_usage_before_flush para controlar cuándo los constructores de índices de texto realizan el vaciado de los segmentos temporales. #111573 (rorylshanks).
  • Se añade el modificador STREAM UNORDERED: omite la ordenación por orden de confirmación de cada instantánea #111794 (SmitaRKulkarni).
  • Ahora make_distributed_plan=1 deshabilita las funcionalidades que aún no son compatibles. #112463 (alesapin).
  • Ya no se escriben secuencias de escape ANSI con INTO OUTFILE cuando stdout es un tty #113252 (azat).
  • Se renombró allow_experimental_delta_kernel_rs a allow_delta_kernel_rs. El nombre anterior se mantiene como alias. #113476 (kssenii).
  • Se añaden las configuraciones enable_alp_codec, enable_sz3_codec, enable_zxc_codec y enable_quantized_codec para habilitar por separado cada códec de compresión experimental. #113824 (rienath).
  • Se notifica el desbordamiento de pila en lugar de terminar silenciosamente: los handlers de señales fatales ahora se ejecutan en la pila de señales alternativa, de modo que SIGSEGV, SIGABRT, SIGILL, SIGBUS, SIGSYS, SIGFPE y SIGTRAP generan un stack trace incluso cuando el thread que provocó el fallo ha agotado su pila. #113927 (groeneai).
  • Se admite el parámetro lookback_delta de la Prometheus HTTP API para consultas instantáneas y de rango. #113971 (fallintoplace).
  • Las tablas QueryRunner ahora inician hilos de trabajo bajo demanda y los liberan cuando quedan inactivos, en lugar de ocupar threads durante toda la duración de la tabla. #114522 (mstetsyuk).
  • Con este cambio, al usar índices WHATIF, la línea base servida por proyección devuelve not_applicable para cada candidato en lugar de provocar el fallo de la sentencia. #114846 (yariks5s).
  • Se optimizan las cadenas AND con varias condiciones de comparación sobre la misma expresión: se detectan contradicciones (p. ej., a < 3 AND a > 5 → false) y se eliminan condiciones redundantes (p. ej., a = 3 AND a < 5 → a = 3). #99736 (wudidapaopao).

Correcciones de errores

Correcciones de MergeTree, replicación y almacenamiento

  • Se corrigió una condición de carrera entre ALTER TABLE ... RENAME COLUMN y un OPTIMIZE TABLE ... FINAL concurrente (o cualquier fusión en segundo plano) en MergeTree que podía reemplazar silenciosamente los datos de la columna renombrada por valores predeterminados. La ventana de carrera entre la publicación de los nuevos metadatos en memoria y el registro de la mutación de renombrado en current_mutations_by_version ahora se cierra manteniendo currently_processing_in_background_mutex durante ambas operaciones. #104822 (groeneai).
  • Se corrigieron resultados de consulta incorrectos al usar GROUP BY con ORDER BY y arrayJoin en la proyección. #101775 (Onyx2406).
  • Las configuraciones no válidas del tamaño de carga en Azure (por ejemplo, azure_min_upload_part_size = 0 o azure_max_blocks_in_multipart_upload = 0) ahora se rechazan de forma anticipada con un error claro, en lugar de provocar una excepción interna (second_size > 0) en un punto profundo de la ruta de escritura. Esto se aplica tanto a los ajustes de consulta como a la configuración de disco de Azure. #103394 (statxc).
  • Se lanza BAD_ARGUMENTS en lugar de LOGICAL_ERROR cuando se ejecuta ALTER TABLE ... MOVE/REPLACE/ATTACH PARTITION entre dos tablas MergeTree con configuraciones de granularidad incompatibles (una adaptativa y otra no adaptativa). #103881 (groeneai).
  • Se corrige un LOGICAL_ERROR “Expected one block from input stream” lanzado por KILL QUERY / KILL MUTATION / KILL PART_MOVE_TO_SHARD / KILL TRANSACTION cuando su cláusula WHERE contiene una subconsulta por fila, o cuando max_block_size es tan pequeño que el SELECT interno sobre la tabla system.* correspondiente emite más de un bloque. #104927 (groeneai).
  • Se corrige una fuga en las vistas materializadas actualizables (MATERIALIZED VIEW ... REFRESH ...) por la que la tabla interna temporal que la tarea de actualización retira mediante EXCHANGE TABLES no podía eliminarse si superaba el max_table_size_to_drop del servidor. Cada actualización posterior creaba una nueva tabla interna temporal sin conseguir limpiar las anteriores, de modo que el directorio de datos de la vista crecía hasta agotar el disco. La eliminación interna que realiza la tarea de actualización ahora omite max_table_size_to_drop y max_partition_size_to_drop; estas salvaguardas siguen aplicándose cuando el usuario ejecuta DROP TABLE sobre la propia vista. #105106 (groeneai).
  • Se corrige un error inesperado DATA_TYPE_CANNOT_BE_USED_IN_KEY en consultas ALTER que no pueden modificar la clave de ordenación (configuraciones, comentarios, códecs, adición de una columna que no forma parte de la clave, etc.) en tablas MergeTree que tienen un SimpleAggregateFunction (u otro tipo permitido solo con allow_suspicious_primary_key = 1) en la clave de ordenación. #105111 (groeneai).
  • OPTIMIZE ... DRY RUN interrumpido por un tiempo de espera de consulta (max_execution_time con timeout_overflow_mode = 'break') ahora devuelve TIMEOUT_EXCEEDED en lugar de un error lógico relacionado con rows_sources (que abortaba el servidor en compilaciones de depuración y con sanitizadores). #107114 (groeneai).
  • Se corrigió NOT_FOUND_COLUMN_IN_BLOCK al leer archivos con particionamiento Hive usando use_hive_partitioning=1 y una cláusula WHERE/PREWHERE que filtra una columna real (no virtual) cuando también se selecciona una columna de partición Hive. #107505 (groeneai).
  • Se corrigen resultados de consulta incorrectos debidos a una poda errónea de clave primaria y de partición cuando se aplica toStartOfDay, toStartOfISOYear, toDaysSinceYearZero, toRelativeSecondNum, toRelativeMinuteNum, toRelativeHourNum, toRelativeWeekNum, toRelativeDayNum, toMonthNumSinceEpoch o toYearNumSinceEpoch a una columna clave Date32 que contiene fechas fuera del rango que la función puede representar (en particular, fechas anteriores a 1970-01-01). Estas funciones se declaran monótonas ante el índice primario, pero hasta ahora se desbordaban con dichos argumentos, por lo que el índice podía podar gránulos que en realidad contenían filas coincidentes. Ahora se saturan en los límites de su tipo de resultado y se mantienen monótonas en todo el rango de Date32, de modo que la poda es correcta. #108018 (nihalzp).
  • Se corrige que CREATE TABLE dst AS src SETTINGS ... (y variantes similares con ORDER BY/PARTITION BY pero sin un ENGINE explícito) descartara silenciosamente el motor, las cláusulas de almacenamiento (como el TTL de la tabla y las claves) y la configuración de la tabla de origen. Ahora el motor y las cláusulas de almacenamiento no sobrescritas se heredan de la tabla de origen, y la configuración especificada se combina con la de la tabla de origen, prevaleciendo sobre ella. #108085 (alexey-milovidov).
  • Se corrige que INSERT en tablas MergeTree fallara con filesystem error: in rename: Permission denied en sistemas de archivos respaldados por Windows (WSL, CIFS/SMB, montajes bind de Docker Desktop), debido a que el escritor de partes dejaba descriptores de archivo abiertos durante el renombrado del directorio de la parte. #108089 (alexey-milovidov).
  • Se corrige un bloqueo permanente en una tabla MergeTree adjuntada con un índice de omisión heredado hypothesis (un tipo de índice eliminado que solo se conserva por compatibilidad con ATTACH). Hasta ahora, un DELETE ligero, OPTIMIZE, un INSERT simple o un SELECT filtrado sobre dicha tabla fallaba con ILLEGAL_INDEX (“Index of type ‘hypothesis’ is no longer supported”), y la mutación DELETE se reintentaba indefinidamente. Ahora el índice obsoleto se trata como inerte: se conserva intacto durante la fusión/mutación, se omite en la inserción y en la planificación de consultas, y todavía puede eliminarse con ALTER TABLE ... DROP INDEX. #108217 (groeneai).
  • Se corrige el error NOT_FOUND_COLUMN_IN_BLOCK (p. ej., Column _part not found) al seleccionar columnas virtuales de una tabla MergeTree con réplicas paralelas, incluso mediante SELECT * con asterisk_include_virtual_columns = 1. #108451 (groeneai).
  • Se corrige que ATTACH PARTITION ... FROM rechazara tablas cuyas claves primarias son equivalentes pero están declaradas de forma distinta (una con PRIMARY KEY explícito y la otra implícita a partir de ORDER BY). #108590 (jordiori).
  • join_any_take_last_row ahora se respeta en todas las rutas de unión basadas en hash compatibles, incluidas las uniones que usan volcado automático a disco. #108936 (antaljanosbenjamin).
  • Se corrige el error NOT_FOUND_COLUMN_IN_BLOCK cuando query_plan_optimize_lazy_final está habilitado junto con un filtro WHERE trasladado parcialmente a PREWHERE (mediante optimize_move_to_prewhere_if_final). La optimización de FINAL diferido ya no solicita al almacenamiento las columnas de predicado calculadas en prewhere. #109073 (groeneai).
  • Se corrigió que ALTER TABLE ... ADD PROJECTION sobre una columna ALIAS a nivel de tabla dejara la tabla inutilizable (el INSERT posterior fallaba con UNKNOWN_IDENTIFIER, “Missing columns”) cuando la sesión tenía optimize_respect_aliases = 0. #109091 (groeneai).
  • Se corrigió una aserción de puntero nulo (px != 0 en TreeRewriter::analyzeSelect, que abortaba el servidor en compilaciones de depuración y con sanitizadores) al ejecutar ORDER BY ALL (o GROUP BY ALL) sobre una tabla con motor Merge unida mediante JOIN a otra tabla con el analizador antiguo (allow_experimental_analyzer = 0). #109139 (groeneai).
  • Se corrigió un resultado incorrecto en subconsultas EXISTS correlacionadas y subconsultas escalares cuando la correlación solo aparece en la proyección de la subconsulta junto con una cláusula WHERE no correlacionada (la subconsulta podía evaluarse como falso / NULL para todas las filas). Corrige https://github.com/ClickHouse/ClickHouse/issues/105760. #109186 (novikd).
  • Se corrigió un error por el cual la fusión de una tabla MergeTree con proyecciones, con el ajuste enable_block_number_column o enable_block_offset_column habilitado, generaba partes de proyección con una columna espuria _block_number/_block_offset. Como resultado, la parte de proyección fusionada dejaba de coincidir con la definición de la proyección y con las partes de proyección generadas por inserción, por lo que CHECK TABLE y OPTIMIZE ... DRY RUN la notificaban como corrupta (CORRUPTED_DATA). #109284 (groeneai).
  • Se corrigió el error UNKNOWN_IDENTIFIER al ejecutar ALTER TABLE ... RENAME/ADD/MODIFY COLUMN en una tabla MergeTree que tiene un índice min-max implícito sobre las columnas virtuales persistentes _block_number o _block_offset (habilitado mediante add_minmax_index_for_block_number_column / add_minmax_index_for_block_offset_column). #109428 (groeneai).
  • Se corrigió que se eliminaran índices de omisión de una parte de datos (o que CHECK TABLE fallara con UNEXPECTED_FILE_IN_DATA_PART) tras una mutación que reescribe la parte completa, como ALTER TABLE ... DROP COLUMN de una columna MATERIALIZED, en una parte Wide. #109616 (groeneai).
  • Se corrigieron índices de omisión (text, bloom_filter, etc.) y proyecciones obsoletos tras materializar actualizaciones ligeras con ALTER TABLE ... APPLY PATCHES. Anteriormente, los archivos de índices y proyecciones que dependen de una columna actualizada mediante parche no se modificaban, por lo que las consultas que los utilizaban podían devolver resultados incorrectos (p. ej., hasToken omitía una fila actualizada, o una proyección devolvía agregados obsoletos una vez eliminada la parte de parche ya aplicada). #109709 (groeneai).
  • Se corrigió que una mutación que hace referencia a la columna virtual _sample_factor fallara a mitad de ejecución con Unexpected const virtual column: _sample_factor, dejando la mutación bloqueada. Ahora una mutación la lee como 1, el mismo valor que devuelve una consulta sin SAMPLE. #109813 (groeneai).
  • Se corrigieron dos errores que se producían cuando una consulta con GROUP BY GROUPING SETS (o una subconsulta escalar o de mutación que la contuviera) se ejecutaba con force_aggregation_in_order = 1: Trying to get name of not a column: ExpressionList con el analizador antiguo (enable_analyzer = 0), y Memory bound merging of aggregated results is not supported for grouping sets. en una consulta distribuida con enable_memory_bound_merging_of_aggregation_results = 1 con el analizador. #109862 (groeneai).
  • Se corrigen tres problemas con use_constant_folding_in_index_analysis: un error lógico Invalid partition key size que podía abortar un SELECT que usaba una proyección normal cuando la tabla establece part_minmax_index_columns = 'with_block_number_offset'; resultados incorrectos (filas descartadas de forma silenciosa) al filtrar por una clave de partición basada en módulo, como PARTITION BY id % 200; y un fallo (carrera de datos) al consultar un índice text con un tokenizador sparseGrams mediante un predicado LIKE sobre muchas particiones con max_threads > 1. #109896 (groeneai).
  • Se corrigen resultados incorrectos cuando se construye un índice de omisión minmax sobre una columna LowCardinality(Nullable(...)): los predicados WHERE/PREWHERE/HAVING ... IS NULL delegados al almacenamiento descartaban todos los gránulos y devolvían 0 filas aunque la columna contuviera valores NULL. #110061 (groeneai).
  • Se corrigió la lentitud de las consultas ORDER BY ... LIMIT sobre tablas Distributed cuando prefer_localhost_replica selecciona una réplica local. #110136 (EmeraldShift).
  • Se corrigió una excepción (UNION mode UNION_DEFAULT must be normalized) que se producía cuando una mutación DELETE o ALTER UPDATE usaba una operación de conjuntos (UNION/UNION ALL/UNION DISTINCT/EXCEPT/INTERSECT) dentro de una subconsulta en su condición WHERE o en una asignación UPDATE. #110196 (alexey-milovidov).
  • Se corrigió el apagado lento del servidor y la falta de respuesta de KILL MUTATION cuando una mutación con x IN (subquery) estaba construyendo el conjunto de la subconsulta durante el análisis de la clave primaria; ahora la construcción del conjunto se cancela de inmediato. #110198 (alexey-milovidov).
  • Se corrigió una condición de carrera entre KILL TRANSACTION y ALTER TABLE ... UPDATE/DELETE ejecutado dentro de una transacción: un rollback producido entre el registro de la mutación en la transacción y su registro en la tabla dejaba una entrada de mutación huérfana, lo que provocaba un error lógico (Cannot find transaction ... that has started mutation ...) en los trabajos en segundo plano y bloqueaba todas las mutaciones posteriores de las partes afectadas hasta reiniciar el servidor. #110226 (tiandiwonder).
  • Se corrigió un problema por el que system.tables para una base de datos DataLakeCatalog (Iceberg/Glue) abortaba toda la consulta, o descartaba tablas de forma silenciosa, cuando no se podía resolver el metadata de una sola tabla. Ahora dicha tabla sigue apareciendo por nombre, con valores predeterminados/NULL en las columnas que requieren el objeto de almacenamiento abierto (engine, total_rows, etc.), independientemente de database_datalake_require_metadata_access. El acceso directo a la tabla dañada sigue notificando el error. #110242 (groeneai).
  • La estimación de cardinalidad para el orden de join ahora combina las estadísticas de columnas de las partes que quedan tras la poda por partición/PK, en lugar de las de todas las partes activas. Anteriormente, una consulta podada a una partición pequeña se planificaba con estadísticas de toda la tabla (se observó una sobreestimación de filas de 2500x que invertía el lado de construcción del hash join) y, paradójicamente, desactivar las estadísticas producía un plan mejor. También se corrigió que el FINAL diferido se desactivara de forma silenciosa para relaciones MergeTree bajo un JOIN, porque el resultado memoizado del análisis de índices del optimizador de orden de join se confundía con una proyección aplicada. #110283 (skuznetsov-clickhouse).
  • ALTER TABLE ... MOVE/REPLACE PARTITION entre dos tablas MergeTree con granularidad incompatible (una adaptativa y otra no) ahora lanza BAD_ARGUMENTS en lugar de LOGICAL_ERROR. Es una situación que el usuario puede provocar, por lo que no debe manifestarse como un error interno (que aborta el servidor en builds de depuración/sanitizer). #110535 (groeneai).
  • Se corrige un problema por el que TTL ... DELETE WHERE <cond> nunca eliminaba las filas que empezaban a cumplir <cond> como consecuencia de un ALTER TABLE ... UPDATE sobre una columna referenciada en el WHERE. Ahora la mutación recalcula el TTL de la fila, de modo que las filas expiradas que pasan a cumplir la condición se eliminan en lugar de conservarse sin aviso. #110648 (groeneai).
  • Se corrigió un LOGICAL_ERROR “Invalid partition key size: 0” que podía abortar un INSERT en una tabla MergeTree particionada con non_replicated_deduplication_window habilitado, cuando un lote de inserción asíncrona solo se deduplicaba parcialmente (algunos insert_deduplication_tokens estaban duplicados y otros eran nuevos). #110651 (groeneai).
  • Se corrige un problema por el que el plegado de constantes con el nuevo analizador cambiaba sin aviso el tipo de un valor Geometry constante. Geometry es un Variant con nombre cuyas alternativas pueden compartir la misma disposición de almacenamiento (LineString/Ring, MultiLineString/Polygon y los valores vacíos), por lo que dos constantes plegadas que solo se diferenciaban en su alternativa acababan fusionándose en una sola; por ejemplo, una constante MULTIPOLYGON EMPTY se convertía en LINESTRING(). #110709 (groeneai).
  • Se corrige un resultado incorrecto (fusión mal ordenada) en consultas con lectura en orden en las que distinct-in-order o aggregation-in-order amplían la lectura a un prefijo de clave de ordenación más largo que aquel para el que ORDER BY configuró la fila virtual de lectura en orden. Las columnas de ordenación adicionales de la fila virtual se rellenaban con valores predeterminados, lo que podía alterar el orden en MergingSortedTransform (y provocar un aborto con LOGICAL_ERROR en compilaciones de depuración/sanitizer). #110725 (groeneai).
  • Los roles activos de una consulta (SET ROLE / role=) ahora se propagan a los nodos remotos en lecturas con réplicas paralelas y lecturas distribuidas sobre un clúster con secreto entre servidores; antes se recurría a los roles predeterminados del usuario, por lo que las políticas de filas se evaluaban de forma incoherente con respecto al initiator. #110867 (evillique).
  • Se corrigió una condición de carrera poco frecuente por la que un ALTER que solo modificaba comentarios o configuración de una tabla ReplicatedMergeTree podía descartar sin aviso una columna añadida por un ALTER ... ADD COLUMN concurrente, de modo que una réplica quedaba con una estructura de tabla obsoleta. #111029 (tiandiwonder).
  • Se corrige el error NUMBER_OF_COLUMNS_DOESNT_MATCH en un GROUP BY con una agregación sobre una tabla Merge que envuelve una tabla Distributed, cuando la clave de agrupación es una función de una columna y una agregación lee esa misma columna (p. ej., SELECT toString(g), min(g) FROM merge_over_distributed GROUP BY toString(g)). #111334 (groeneai).
  • Se corrige un resultado incorrecto de un FULL JOIN con USING sobre una tabla con motor Join (StorageJoin) cuando la clave izquierda es Nullable y la clave de almacenamiento no lo es: una fila izquierda sin coincidencia y con clave NULL devolvía 0 en lugar de NULL. #111371 (groeneai).
  • ALTER TABLE ... DETACH PARTITION/PART ahora aplica fsync al clon que crea en detached/ (el subárbol de la parte más la cadena de directorios hasta la raíz del disco) cuando la configuración fsync_part_directory de la tabla está habilitada, tanto para el almacenamiento de partes Full (directorio) como Packed. Anteriormente nunca se aplicaba fsync al clon, pero sí a la parte de cobertura vacía que elimina las filas del conjunto activo, por lo que un corte de energía justo después de la confirmación podía destruir los datos desvinculados en btrfs (las entradas de directorio del clon no sincronizadas se revierten, lo que deja detached/ vacío y nada sobre lo que ejecutar ATTACH). Depende de la configuración existente fsync_part_directory; el comportamiento predeterminado no cambia. #111426 (groeneai).
  • Ahora se rechaza una columna Nullable(Nothing) (o de cualquier otro tipo no permitido en tablas) al ejecutar CREATE TABLE cuando el esquema se infiere del almacenamiento (por ejemplo, una tabla remote()/Remote/Distributed sin columnas sobre una vista que ejecuta SELECT NULL), en lugar de persistir metadata que no se puede cargar en el siguiente reinicio del servidor y que bloquea la carga de tablas no relacionadas. #111487 (groeneai).
  • Se corrige un LOGICAL_ERROR (Got read request from replica N for unknown stream ...) que podía abortar el servidor al leer con réplicas paralelas cuando la consulta se resuelve por completo en el iniciador mediante una optimización de proyección (exact-count, minmax-count o una proyección almacenada de agregación/normal que no selecciona ningún rango). #111689 (groeneai).
  • Se corrige el INSERT particionado de DeltaLake (allow_experimental_delta_lake_writes=1), que corrompía los valores de partición que contenían caracteres de ruta y rechazaba NULL. Un valor como a/b se confirmaba silenciosamente como a, % generaba un archivo de datos que luego no se podía leer y un valor de partición NULL fallaba con NOT_IMPLEMENTED. Ahora los valores de partición se convierten mediante codificación porcentual en un único segmento de ruta, el valor real se almacena en partitionValues en lugar de extraerse de nuevo de la ruta, y un valor de partición NULL (o una cadena vacía) se escribe como __HIVE_DEFAULT_PARTITION__ con una entrada nula en partitionValues. #111793 (groeneai).
  • Se corrigen los errores lógicos Expected UInt64 column for __grouping_set, got BLOB y ColumnBLOB should be converted to a regular column before usage en una consulta distribuida ejecutada en un shard con enable_parallel_blocks_marshalling (habilitado de forma predeterminada), por ejemplo con GROUP BY GROUPING SETS sobre un clúster que tiene una réplica local, o al leer una tabla Merge que abarca una tabla local y una tabla distribuida. BlocksMarshallingStep ya no se añade a los planes cuyos bloques se consumen en el mismo proceso. #111997 (groeneai).
  • Se corrige un LOGICAL_ERROR (Type mismatch when building statistics for column) durante una mutación de MergeTree en una tabla cuyo tipo de columna se había cambiado mediante un ALTER MODIFY COLUMN que solo afecta a la metadata (por ejemplo, de Enum8 a Int8 o de DateTime a UInt32) cuando la columna tiene estadísticas. Ahora la mutación recalcula únicamente las estadísticas de las columnas que realmente reescribe y conserva el resto sin cambios; además, una columna reescrita por MATERIALIZE COLUMN, por un UPDATE de una columna de la que depende una columna MATERIALIZED o por CLEAR COLUMN recalcula ahora sus estadísticas en lugar de conservar contenido obsoleto. #112009 (groeneai).
  • Corrige la omisión silenciosa de filas cuando una consulta filtra por intDiv(constant, key) o divide(constant, key). El análisis de la clave primaria y de la partición indicaba una dirección de monotonicidad incorrecta para una constante dividida por una columna de clave, por lo que los gránulos coincidentes se descartaban y la consulta devolvía menos filas sin ningún error. También corrige intDiv con un dividendo constante sin signo cuyo bit más alto está activado, deja de declarar monotonicidad cuando un operando Decimal hace que la división se calcule con el ancho nativo del decimal, y evita que el análisis de claves genere Cannot compare DB::IPv4 with long para una consulta válida que divide una constante IPv4/IPv6 por una columna de clave. #112156 (groeneai).
  • Corrige que una vista parametrizada cuyo cuerpo SELECT usa INTERSECT/EXCEPT, o una cadena UNION que combina UNION DISTINCT con UNION ALL, se clasificara como una vista ordinaria. La vista se creaba correctamente, pero sus metadata no podían volver a leerse: al cargarla se lanzaba Invalid storage definition in metadata file, lo que impedía cargarla de forma permanente y hacía que un servidor de depuración o con sanitizer abortara durante el arranque. Además, system.tables.parameterized_view_parameters no mostraba ningún parámetro para esas vistas. #112211 (groeneai).
  • Corrige que max_execution_time y KILL QUERY se ignoraran mientras una consulta evalúa geohashesInBox. La consulta expandía todas las filas de un bloque antes de poder interrumpirse, por lo que la cancelación no surtía efecto hasta varios minutos después; ahora la función comprueba el límite de tiempo de la consulta a medida que recorre las filas. Las evaluaciones dentro de una expresión de tabla persistida, como una clave de ordenación, un índice de omisión o un PARTITION BY, no están cubiertas y se abordan por separado. #112273 (groeneai).
  • Corrige un error lógico al usar PREWHERE en una tabla Merge construida sobre otra tabla Merge o sobre una vista materializada cuyo tipo de columna difiere. También corrige que una política de filas se ignorara silenciosamente en tablas que leen de servidores remotos (una tabla Distributed, o una tabla que la envuelve), lo que podía exponer filas que la política debía ocultar; ahora estas consultas se rechazan con un error ILLEGAL_PREWHERE. En su lugar, defina estas políticas en las tablas locales subyacentes de cada servidor remoto; tenga en cuenta que estas políticas siguen sin aplicarse a las lecturas enviadas con serialize_query_plan = 1, lo cual es un bug distinto y preexistente. #112326 (PedroTadim).
  • Corrige la lectura de un índice secundario (de omisión) obsoleto tras un cambio de tipo mediante ALTER TABLE ... MODIFY COLUMN cuya mutación nunca llegó a ejecutarse, por ejemplo porque KILL MUTATION la eliminó: los gránulos en disco se habían escrito con el tipo antiguo, pero se decodificaban con el nuevo, lo que generaba LOGICAL_ERROR, provocaba solicitudes de asignación de varios exabytes o devolvía silenciosamente un resultado incorrecto. También corrige un resultado incorrecto de un índice sobre una expresión cuyo significado cambia aunque todos los bytes almacenados permanezcan idénticos, de modo que no llega a crearse ninguna mutación: un MODIFY COLUMN que solo modifica la zona horaria de un DateTime, o solo un nombre de tipo personalizado, como de UInt8 a Bool. Ahora ese índice se omite para la parte afectada. #112484 (groeneai).
  • Corrige un LOGICAL_ERROR (Cannot add transform Resize to Pipes because it has no outputs) que se producía cuando una consulta de agregación sobre un clúster se ejecutaba con serialize_query_plan = 1 y réplicas paralelas basadas en el plan, debido a que el paso de fusión redimensionaba el pipeline a cero flujos. #112506 (groeneai).
  • Corrige un LOGICAL_ERROR (“Part … contains column … that is absent in table …”) que se producía cuando una réplica ReplicatedMergeTree mutaba una parte obtenida de otra réplica antes de aplicar su propio ALTER ... ADD COLUMN pendiente. Ahora esa mutación se pospone hasta que se aplique el cambio de metadata. #112510 (groeneai).
  • Corrige los contadores de lectura (read_rows, read_bytes, ProfileEvents['SelectedRows'], ProfileEvents['SelectedBytes']) y las cuotas READ_ROWS y READ_BYTES, que se contabilizaban en exceso en consultas cuyo ORDER BY vuelca datos a disco. Las filas que se volvían a leer de los archivos temporales de la ordenación externa se contaban de nuevo como lecturas de origen, por lo que una consulta con volcado a disco notificaba más datos leídos de los reales y podía rechazarse con QUOTA_EXCEEDED aunque no hubiera superado su cuota. #112645 (groeneai).
  • Corrige que ProfileEvents['JoinResultRowCount'] notificara un tamaño de resultado inferior al real en un JOIN que vuelca datos a disco. Las filas emitidas desde los buckets diferidos solo se contaban en JoinDelayedJoinedTransformRowCount y no se incluían en el total. Los resultados de las consultas siempre fueron correctos; solo el evento de perfil era erróneo. #112673 (groeneai).
  • Corrige que max_execution_time y KILL QUERY no tuvieran efecto, sin aviso alguno, en una consulta distribuida que está estableciendo conexiones con las réplicas. Ahora dicha consulta se detiene en el siguiente intento de conexión en lugar de recorrer todas las réplicas y reintentos restantes. #112689 (groeneai).
  • Se corrigió que se aplicara un ALTER en tablas MergeTree mientras todavía estaba en curso una mutación de alteración RENAME COLUMN incompleta. Esto podía actualizar los metadatos de almacenamiento de forma incompatible y bloquear por completo las mutaciones posteriores. #112783 (Michicosun).
  • Corrige resultados incorrectos de ORDER BY al leer de una tabla Merge sobre tablas Distributed: las filas podían devolverse desordenadas y, al usar LIMIT, podían faltar filas que debían formar parte del resultado. #112931 (alexey-milovidov).
  • Se corrigieron resultados incorrectos cuando la precarga de lectura del sistema de archivos está habilitada y se lee una columna Nested junto a una subcolumna que se eliminó y se volvió a añadir, en tablas con share_nested_offsets habilitado (el valor predeterminado). Una consulta de este tipo podía devolver valores predeterminados para una columna físicamente presente que los ALTER nunca habían modificado. En almacenamiento de objetos, donde remote_filesystem_read_prefetch tiene 1 como valor predeterminado, el problema se produce sin cambiar ninguna configuración; en discos locales requiere local_filesystem_read_prefetch = 1. Otro defecto, independiente de la precarga, sigue corrompiendo estas lecturas cuando un rango abarca varios bloques; ese caso no se resuelve aquí. #112997 (groeneai).
  • Se corrigió un error lógico Pipeline stuck en consultas que reparten datos por partición, como una función de ventana con PARTITION BY o una unión con join_algorithm = 'parallel_full_sorting_merge', cuando el procesamiento posterior de un shard finalizaba mientras un bloque solo se había distribuido parcialmente. #113190 (groeneai).
  • Se corrigió un bloqueo de las sentencias ALTER, OPTIMIZE, TRUNCATE y de manipulación de particiones con alter_sync = 2 en ReplicatedMergeTree cuando la tabla comienza a cerrarse mientras la sentencia espera a otra réplica, por ejemplo debido a un DROP DATABASE ... SYNC concurrente. Ahora dicha sentencia falla con UNFINISHED y además respeta max_execution_time y KILL QUERY. #113228 (groeneai).
  • Se corrigió el error Cannot insert element into Set (NOT_IMPLEMENTED) cuando read_in_order_use_virtual_row está habilitado y una consulta de lectura en orden sobre MergeTree combina WITH FILL ... INTERPOLATE con un filtro IN o has. #113264 (groeneai).
  • Se corrige un error lógico (excepción) Chunk info was not set for chunk in MergingAggregatedTransform que se producía cuando el ajuste inject_random_order_for_select_without_order_by estaba habilitado y una consulta de agregación leía de una tabla Merge que contenía una tabla hija Distributed: el envoltorio aleatorio ORDER BY rand() ya no se inyecta en consultas planificadas solo hasta una etapa intermedia. #113266 (alexey-milovidov).
  • Se corrige un problema por el que las filas nunca se eliminaban cuando una tabla MergeTree tenía dos o más reglas TTL ... DELETE WHERE con una expresión de tiempo idéntica que solo se diferenciaban en la condición WHERE. Tras una fusión de eliminación por TTL, el rows_where_ttl_info de la parte se restablecía a cero, por lo que ya no se programaba ninguna otra fusión por TTL para ella y las filas expiradas se conservaban indefinidamente sin ningún error ni mensaje de log. #113384 (groeneai).
  • Se corrige un problema por el que max_execution_time y KILL QUERY se ignoraban mientras una consulta evaluaba geohashesInBox, arrayFold, sleep, base58Decode, h3PolygonToCells o h3PolygonToCellsWithContainment dentro de una expresión almacenada en los metadatos de la tabla, como una clave de ordenación, un índice de omisión o una clave PARTITION BY. #113456 (groeneai).
  • Se corrige un LOGICAL_ERROR (Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan) que se producía cuando una tabla Merge con más de una tabla hija leía una CTE materializada referenciada por la consulta externa. #113558 (alexey-milovidov).
  • Se corrige Logical error: 'Required output position N is out of range for pass-through inputs' en EXPLAIN ANALYZE sobre una tabla Merge con varias tablas hijas, un PREWHERE con una columna simple y un WHERE independiente. #113725 (groeneai).
  • Se corrige un error lógico (Unexpected return type) que se producía al hacer pushdown al almacenamiento de un filtro sobre una vista cuyo tipo de columna difiere del del almacenamiento subyacente (p. ej., information_schema.tables, donde engine es Nullable(String), sobre system.tables, donde es String). #113984 (alexey-milovidov).
  • Se corrige el error Not-ready Set is passed as the second argument for function 'in' que se producía cuando una mutación cuyo predicado contiene IN (subquery) se cancelaba (por ejemplo, mediante KILL MUTATION o DETACH DATABASE) mientras el conjunto de la subconsulta aún se estaba construyendo. #114463 (groeneai).
  • ALTER TABLE ... DROP COLUMN sobre una columna que se usa en la clave de ordenación, primaria o de partición ahora falla con ALTER_OF_COLUMN_IS_FORBIDDEN y una explicación, igual que ALTER TABLE ... CLEAR COLUMN. Anteriormente fallaba con un error confuso, UNKNOWN_IDENTIFIER: Missing columns, procedente del recálculo de las expresiones de clave. Lo mismo ocurre al eliminar o vaciar un grupo Nested completo mediante su prefijo común cuando una columna del grupo se usa en una clave; antes, esto podía destruir silenciosamente los datos del grupo o dejar una mutación que nunca terminaba. Además, al eliminar una columna que solo se usa en una expresión TTL, ahora se indica qué expresión TTL deja de funcionar #114468 (m7kss1).
  • Se corrige un problema por el que una columna renombrada, eliminada y añadida de nuevo en un mismo ALTER devolvía los valores de la columna eliminada en lugar de su propio valor predeterminado mientras la mutación seguía pendiente. #114601 (tiandiwonder).
  • Se corrigió la lectura de una subcolumna (.size0, .null, un elemento de tupla, String.size) a través de una tabla Merge cuando la tabla subyacente declara la columna padre como ALIAS. Esa lectura devolvía el valor predeterminado del tipo y, si la columna padre se seleccionaba en la misma consulta, podía devolver el valor de una columna no relacionada. #114673 (groeneai).
  • Se corrigió la ausencia de filas en el resultado de un SELECT filtrado por pointInPolygon sobre una clave primaria de MergeTree cuando el argumento del polígono es un literal constante no válido y validate_polygons = 0. El análisis de la clave primaria aplicaba la poda de gránulos a partir de un polígono que nunca había validado y descartaba gránulos que contenían filas coincidentes. #114710 (groeneai).
  • Se corrigió el formateo de ALTER TABLE ... MATERIALIZE INDEX, MATERIALIZE STATISTICS y MATERIALIZE PROJECTION, que omitía la cláusula IF EXISTS, de modo que la consulta formateada no coincidía con la consulta analizada. Además, ahora se rechazan cuatro cargas útiles JSON de AST de ALTER ... STATISTICS que el analizador SQL no puede generar y que, al formatearse, daban lugar a un comando distinto. #115099 (groeneai).
  • Se corrigió una lectura fuera de límites de los hashes en caché del diccionario al agregar o hacer un join sobre una clave LowCardinality(String) cuyo diccionario crece durante la agregación, situación que podía darse con TTL ... GROUP BY. Podía producir un hash incorrecto y provocar un heap-buffer-overflow en builds con sanitizador. #115604 (groeneai).
  • CREATE TABLE y ALTER TABLE ahora rechazan códecs con pérdida, como SZ3, en columnas utilizadas en la clave de partición. #115626 (groeneai).
  • La lectura a través de una tabla Merge que coincide con una tabla Alias cuyo destino es una vista parametrizada ya no genera LOGICAL_ERROR: Table has no columns. (que provoca la terminación del servidor en builds de depuración y con sanitizador). Ahora esa tabla devuelve STORAGE_REQUIRES_PARAMETER, el mismo error que devuelve la propia vista parametrizada. Cualquier otra tabla coincidente que no pueda proporcionar columnas devuelve ahora UNSUPPORTED_METHOD en lugar de un error interno. #115896 (groeneai).
  • Se corrigió la vista previa sobre la marcha de una mutación pendiente cuya expresión hace referencia a _sample_factor. Con apply_mutations_on_fly = 1 y una cláusula SAMPLE, la expresión se evaluaba con el factor de muestreo de la consulta de lectura en lugar del valor que persiste la materialización en segundo plano, por lo que las filas previsualizadas no coincidían con el resultado materializado final, y un ALTER TABLE t DELETE WHERE _sample_factor > 1 pendiente podía hacer que una lectura con SAMPLE no devolviera ninguna fila. La columna _sample_factor propia de la consulta no se modifica. #115906 (groeneai).
  • Los archivos de estadísticas con versión de formato V3 ahora se leen en lugar de rechazarse con ILLEGAL_STATISTICS. Estos archivos solo los generaron builds de master durante un breve periodo, pero las partes que los contenían resultaban completamente ilegibles y, en un disco de solo lectura, ALTER TABLE ... MATERIALIZE STATISTICS no puede regenerarlos. #116030 (alexey-milovidov).
  • Se corrigió el error Invalid number of columns in chunk pushed to OutputPort (LOGICAL_ERROR) que se producía cuando una consulta SELECT ... FROM t STREAM ... ORDER BY ... LIMIT n leía una tabla con una PROJECTION. La materialización diferida ya no se aplica a las lecturas STREAM. #116187 (groeneai).
  • ALTER TABLE ATTACH PARTITION FROM ya no se replica en bases de datos replicadas. #94835 (MikhailBurdukov).
  • Se corrigió una interrupción abrupta del servidor (en builds con sanitizador) y una pérdida silenciosa de datos durante el arranque de la tabla cuando una parte transaccional de MergeTree revertida se intersecaba con una parte committed. PartLoadingTree::add ahora identifica correctamente cuál de las dos partes que se intersecan fue revertida, la descarta y reasigna sus partes hijas huérfanas a la parte committed en el orden correcto. #100992 (tuanpach).
  • Se corrigió que indexOfAssumeSorted devolviera resultados incorrectos para columnas Array(LowCardinality(String)) en tablas MergeTree. #101771 (Onyx2406).
  • Se corrigen las excepciones LOGICAL_ERROR al leer tablas de data lake Iceberg o DeltaLake a través de rutas que pueden llegar al pipeline de lectura sin un datalake_table_state fijado, como las actualizaciones concurrentes de metadatos de Iceberg o las lecturas con merge sobre tablas DeltaLake. #102033 (groeneai).
  • Se corrigió el error Logical error: Parsed partition value: ... doesn't match partition value for an existing part with the same partition ID: ... que generaba OPTIMIZE TABLE ... PARTITION ... (y otras consultas que resuelven un valor de partición mediante convertFieldToTypeImpl) en tablas con una clave de partición de tipo Time. #106202 (groeneai).
  • Se corrige que una parte de datos se marcara incorrectamente como si tuviera una proyección dañada cuando una eliminación ligera no dejaba ninguna parte de proyección, ya sea porque la proyección se reconstruye sin filas de salida o porque se elimina (lightweight_mutation_projection_mode = 'rebuild'/'drop'). Anteriormente, este estado dañado deshabilitaba la optimización por proyecciones en las consultas sobre esa parte. #106273 (tiandiwonder).
  • Se corrigió que las advertencias de sobrecarga de memoria/CPU/mutaciones en system.warnings llegaran con un ciclo de métricas asíncronas de retraso (y no aparecieran en el primer ciclo). #108035 (alexey-milovidov).
  • Se corrigió una excepción LOGICAL_ERROR (ScatterExchangeStep should have one source shard, got 8) y la duplicación de filas al consultar una tabla Merge sobre tablas Distributed o vistas con la configuración experimental make_distributed_plan = 1. #108401 (groeneai).
  • Se corrigió una interrupción abrupta del servidor (Sort order of blocks violated) durante una fusión, así como lecturas incorrectas, cuando un elemento LowCardinality no nullable de una columna Nullable(Tuple(...)) se usa como subcolumna (por ejemplo, como clave de ordenación). #108679 (groeneai).
  • Se corrige un fallo en la función Base64Decode del SDK de Azure incluido en el código, accesible mediante azureBlobStorage() (y las funciones de tabla y almacenamiento de Azure relacionados), cuando la clave de la cuenta no es Base64 válido. Un byte >= 0x80 provocaba una lectura fuera de límites de la tabla de decodificación, y cualquier byte no válido causaba un desplazamiento a la izquierda indefinido de un valor negativo (interrupción con sanitizadores). Ahora las claves no válidas se rechazan correctamente. #108716 (groeneai).
  • Se corrigió un LOGICAL_ERROR (“New empty part is about to materialize but the directory already exist”) que podía interrumpir el servidor en builds de depuración y con sanitizador cuando se ejecutaba un DROP/DETACH/MOVE/REPLACE PARTITION sobre una tabla MergeTree después de que una operación similar anterior se interrumpiera (por ejemplo, por una transacción revertida o un fallo) y dejara un directorio tmp_empty_<part> obsoleto. Ahora el directorio obsoleto se reutiliza en lugar de provocar un error. #108879 (groeneai).
  • Se corrige una proyección que devolvía el valor predeterminado del tipo de una columna (p. ej., 0) en lugar de su DEFAULT de DDL (p. ej., -1) después de que expirara el TTL de la columna en una parte ancha. #109013 (tiandiwonder).
  • Se corrige el fallo de las consultas ALTER en tablas MergeTree creadas con una configuración disk personalizada (SETTINGS disk = disk(...)). #109199 (Michicosun).
  • Se corrige la aparición de filas obsoletas y eliminadas al leer tablas de una base de datos MaterializedPostgreSQL a través de una tabla Merge. #109339 (vdimir).
  • Se corrige la lectura de tablas Paimon particionadas por una columna BIGINT cuyo valor no cabe en Int32. Estos valores de partición se truncaban (por ejemplo, 9223372036854775807 se convertía en -1), lo que generaba una ruta de partición incorrecta y provocaba un error del sistema de archivos. #109510 (groeneai).
  • Se corrige un error lógico (“Cannot determine row level filter; 0 columns deleted, 0 columns added”) al leer de una tabla Merge cuya tabla hija tiene una política de filas con un filtro que consiste únicamente en una columna existente (por ejemplo, CREATE ROW POLICY ... USING flag). #109843 (groeneai).
  • IcebergLocal indicaba Azure como tipo de almacenamiento. #109872 (PedroTadim).
  • CHECK TABLE ahora informa de la corrupción real de una parte de proyección cuyos metadatos no se pudieron cargar, en lugar de mostrar el engañoso error Columns doesn't match ... Expected: 0 columns. #110262 (Algunenano).
  • Se corrige un fallo en el inicio del servidor con tablas MergeTree en discos de almacenamiento de objetos cuando un archivo residual txn_version.txt.tmp tiene metadatos a nivel de disco dañados. #110519 (alexey-milovidov).
  • Se corrige un problema por el que una tabla MergeTree con una proyección _part_offset o de orden de commit dejaba de poder adjuntarse de forma permanente tras deshabilitar allow_part_offset_column_in_projections o allow_commit_order_projection y desadjuntar la tabla o reiniciar el servidor. Estas dos configuraciones solo se aplican en el momento de CREATE, por lo que ya no se vuelven a comprobar en ATTACH. #110570 (groeneai).
  • Se corrige un LOGICAL_ERROR poco frecuente (“Unexpected number of parts to remove from parts_queue”) que podía abortar el servidor en una ReplicatedMergeTree cuando dos operaciones de partición (por ejemplo, dos consultas MOVE PARTITION / REPLACE PARTITION, o una en condición de carrera con un DROP_RANGE en segundo plano) cancelaban a la vez la comprobación de partes en segundo plano sobre rangos superpuestos. #110738 (groeneai).
  • Se corrige un error lógico Hash is not set for serialization que podía producirse cuando una columna con un códec Quantized(...) estaba anidada dentro de una serialización reutilizable desde un grupo; por ejemplo, una tabla Merge sobre orígenes cuya columna homónima tiene tipos distintos (fusionados en un Variant). #110776 (groeneai).
  • Se corrige un std::length_error (LOGICAL_ERROR) al leer una tabla MergeTree con un valor anómalo de max_streams_for_merge_tree_reading (cercano al máximo de UInt64) junto con allow_asynchronous_read_from_io_pool_for_merge_tree = 1. Ahora la configuración se limita al mismo tope que max_threads. #110936 (groeneai).
  • Se corrige el error lógico Cannot calculate columns sizes when columns or checksums are not initialized durante la fusión de una tabla MergeTree de una sola columna cuya única columna tiene un TTL de columna que expira por completo (con min_bytes_for_wide_part = 1). #111169 (groeneai).
  • Se aplica fsync a los archivos del índice de texto de una parte fusionada o materializada cuando se configuran min_rows_to_fsync_after_merge / min_compressed_bytes_to_fsync_after_merge / fsync_part_directory. Hasta ahora, estos archivos eran los únicos de la parte que quedaban sin sincronizar, por lo que un corte de energía justo después de una fusión podía dejar una parte committed pero dañada y provocar pérdida de datos. #111335 (groeneai).
  • Se corrige OPTIMIZE TABLE ... MANIFEST para tablas Iceberg cuando las tuplas de partición del manifiesto no coinciden con su especificación de partición #111368 (SmitaRKulkarni).
  • Se corrige una lectura fuera de límites (release) / error lógico (depuración) en la optimización de materialización diferida, así como un error lógico en Pipe::unitePipes para tablas Merge, cuando la optimización de lectura directa desde el índice de texto deja una columna virtual de índice sin usar en el encabezado de lectura de una tabla MergeTree con varios índices text. #111467 (groeneai).
  • Se corrige un LOGICAL_ERROR (“Part level Min-Max index was constructed from unexpected columns set”) que podía abortar una fusión en segundo plano en builds de depuración/sanitizador tras reducir part_minmax_index_columns (por ejemplo, de with_block_number_offset de vuelta a partition_key_only). #111511 (groeneai).
  • Se corrigió un fallo al ejecutar una lectura STREAM (enable_streaming_queries = 1) sobre una tabla con más de una partición y una política de filas definida. En builds de depuración y con sanitizador fallaba con el error lógico Filter column ... not found in DAG outputs; en builds release podía producirse un fallo de segmentación. #111572 (groeneai).
  • Se corrigió un LOGICAL_ERROR (Cannot create part with type Compact and storage type Full because table does not support polymorphic parts) que se producía cuando una tabla MergeTree cargaba una parte Compact preexistente mientras su configuración actual deshabilitaba las partes polimórficas (granularidad no adaptativa). Esto podía ocurrir, por ejemplo, cuando una tabla de solo lectura comparte una ruta en disco con otra tabla y recarga sus partes mediante SYSTEM RESTART DISK o durante el inicio del servidor. En builds de depuración y con sanitizador, la excepción aborta el servidor. #111626 (groeneai).
  • Con fsync_part_directory = 1, el cambio de nombre de un directorio de parte de su nombre temporal a su nombre final ahora también se hace duradero aplicando fsync al directorio padre (y, cuando se mueve entre directorios padre distintos, también al padre de origen). Hasta ahora solo se aplicaba fsync al directorio movido, por lo que un corte de energía justo después de hacer commit de una parte podía hacer que la parte no existiera en disco aunque sus archivos ya estuvieran escritos, con la consiguiente pérdida de filas pese a tener habilitada la configuración. #111861 (groeneai).
  • Se corrigieron resultados incorrectos y un LOGICAL_ERROR al seleccionar de una tabla MergeTree una columna Nullable(Tuple(...)) junto con una de sus subcolumnas de elementos que admiten valores nulos (Variant, Dynamic o LowCardinality). Al leer la subcolumna, las filas que son NULL en la tupla padre se marcaban como NULL en una columna que ya se había compartido a través de la caché de subflujos, por lo que la lectura de la columna completa obtenía valores desplazados. #111949 (groeneai).
  • Se corrigió la pérdida de las optimizaciones posteriores a la fase de build en los hash joins (conversión a una tabla hash fija, el runtime filter compartido, la reasignación de rangos de la tabla derecha) siempre que se configuraba un umbral automático de volcado a disco, que es el comportamiento predeterminado desde la versión 26.5. #111972 (alexey-milovidov).
  • Corrige resultados incorrectos (filas que faltan de forma silenciosa) en hasAllTokens y otras búsquedas multitoken en índices text en builds que no usan simdcomp (todos los destinos excepto x86_64 Linux, p. ej., aarch64) cuando text_index_posting_list_apply_mode = 'lazy'. El decodificador portable de empaquetado de bits no escribía los ceros decodificados para un bloque con un ancho de bits de cero, por lo que se descartaba una entrada ubicada en un segmento de una sola entrada. El formato en disco no cambia y los datos existentes se leen correctamente tras la corrección. #112178 (groeneai).
  • Ahora las operaciones fallan cuando se cargan estadísticas de MergeTree corruptas, en lugar de ignorar el error. #112201 (skuznetsov-clickhouse).
  • Corrige la pérdida silenciosa de escrituras de Iceberg confirmadas en HDFS: un commit de Iceberg publica cada nuevo archivo de metadatos mediante una escritura condicional, pero HDFSObjectStorage descartaba la condición y realizaba una sobrescritura simple, por lo que todos los escritores concurrentes recibían confirmación mientras la instantánea de uno de ellos quedaba inaccesible. Ahora HDFS rechaza las escrituras condicionales, de modo que fallan las escrituras de Iceberg gestionadas por el almacenamiento en HDFS, incluido CREATE TABLE ... ENGINE = IcebergHDFS(...) con una lista de columnas explícita. Las lecturas no se ven afectadas. #112437 (groeneai).
  • Corrige que DELETE en tablas KeeperMap eliminara solo las primeras max_block_size filas coincidentes y, aun así, informara de que la mutación se había completado correctamente. También corrige que DELETE con keeper_map_strict_mode = 1 no fuera atómico: podía recurrir a eliminaciones sin versión y borrar filas actualizadas de forma concurrente, y aplicaba las filas coincidentes bloque a bloque, de modo que un conflicto podía dejar la eliminación aplicada parcialmente. #112777 (alexey-milovidov).
  • Se corrigió que un error transitorio de Azure Blob Storage en la ruta de lectura o de fusión —un 403 Forbidden por propagación de permisos RBAC, un fallo de autenticación de credenciales o un tiempo de espera de conexión notificado como 408— se clasificara erróneamente como no reintentable y se notificara como POTENTIALLY_BROKEN_DATA_PART (Code 740), lo que generaba una falsa alerta crítica para una parte en buen estado. Ahora estos fallos transitorios se tratan como reintentables, y uno realmente persistente se notifica como un error simple de Azure en lugar de como una parte de datos dañada inexistente. #112871 (arsenmuk).
  • Se corrigió que listObjects en un disco de Azure Blob Storage con endpoint con prefijo devolviera nombres de blob incorrectos en todas las páginas posteriores a la primera, porque la paginación omitía el envoltorio del cliente que elimina el prefijo del endpoint. Ahora la paginación vuelve a pasar por el envoltorio mediante el token de continuación, de modo que los nombres de blob de cada página son correctos. #112872 (arsenmuk).
  • Corrige la pérdida del índice minmax por parte sobre _block_number y _block_offset tras recargar una tabla cuando la parte se generó mediante una mutación que no reescribe la parte completa. #112878 (alexey-milovidov).
  • Se corrigió una excepción (en builds de release, un error que impide que el servidor se inicie) cuando un predicado de mutación usa la función de tabla merge sin un nombre de base de datos explícito. Ahora se usa la base de datos de la tabla mutada, igual que se hace con los nombres de tabla. #113185 (alexey-milovidov).
  • Se corrigen resultados incorrectos y un LOGICAL_ERROR al leer una subcolumna de un miembro Nested eliminado y vuelto a añadir junto con un miembro presente del mismo grupo, en una tabla MergeTree con share_nested_offsets = 1. Los miembros presentes devolvían valores de un bloque posterior siempre que la lectura abarcaba más de un bloque. #113225 (groeneai).
  • Se corrige una excepción aritmética en compilaciones de depuración y con sanitizadores al leer de una tabla Merge con un valor muy grande de max_streams_to_max_threads_ratio: el número de flujos se truncaba a 32 bits, por lo que los múltiplos de 2^32 se convertían en cero. Además, ahora se lanza PARAMETER_OUT_OF_BOUND en lugar de provocar un comportamiento indefinido cuando el producto del número de flujos de una tabla Merge excede size_t, se evita un desbordamiento al limitar los flujos de MergeTree en función de la cantidad de datos y se rechaza cualquier lectura de una tabla Merge cuyo número total de fuentes supere 65536. #113382 (alexey-milovidov).
  • Se corrigen las escrituras en el disco hdfs: fallaban con Parent directory doesn't exist porque las claves de objeto generadas contienen un prefijo de directorio anidado, pero, a diferencia de los almacenamientos de blobs, HDFS tiene directorios reales y no crea el directorio padre que falta al crear un archivo.. #113396 (alexey-milovidov).
  • Se corrige el error que se notificaba cuando las funciones de tabla remote/remoteSecure o los motores de tabla Remote/RemoteSecure recibían una colección con nombre inexistente junto con una sobrescritura key = value. Dicha llamada se reinterpretaba silenciosamente como una llamada posicional, por lo que la sobrescritura se analizaba como una expresión de datos y el error notificado hacía referencia a algo que no tenía relación (por ejemplo, Function with name merge does not exist para remote(collection, database = merge(...))). Ahora se notifica que la colección con nombre no existe. #113510 (groeneai).
  • Se corrige un bucle infinito en las fusiones en segundo plano y en OPTIMIZE cuando merge_max_block_size_bytes se establecía por debajo del byteSize() de una columna vacía. Una columna LowCardinality vacía sigue conteniendo su diccionario, por lo que el límite de bytes podía alcanzarse antes de fusionar una sola fila; la fusión producía entonces bloques vacíos indefinidamente, consumía el 100 % de un núcleo de CPU y nunca liberaba su ranura del pool en segundo plano. #113585 (groeneai).
  • Se corrige que una mutación de una parte Compact produjera un resultado distinto según si la información de serialización de la parte seguía en memoria o se había recargado desde serialization.json, cuando la tabla usa serialization_info_version = 'basic'. En ReplicatedMergeTree, esto hacía que dos réplicas con una parte de origen idéntica byte a byte escribieran partes mutadas diferentes, y la mutación fallaba con CHECKSUM_DOESNT_MATCH. #113588 (groeneai).
  • Las copias de seguridad ahora notifican el error subyacente de acceso al archivo de bloqueo, en lugar de indicar erróneamente que hay una copia de seguridad concurrente, cuando el almacenamiento de destino no puede leer el archivo .lock. #113637 (kirillshokhin).
  • Se corrige una condición de carrera de datos entre las tareas en segundo plano de una tabla MergeTree (actualización de estadísticas, actualización de partes, carga de partes obsoletas/inesperadas) y la destrucción de la tabla. #113722 (alexey-milovidov).
  • Se corrige que UPDATE y la eliminación ligera DELETE leyeran tablas incorrectas cuando la base de datos de la tabla actualizada difiere de la base de datos de la sesión. La expresión de la mutación ahora se canonicaliza respecto a la base de datos de la tabla actualizada, tanto para la función de tabla merge, que usa implícitamente la base de datos actual, como para los identificadores de tabla no cualificados. Anteriormente, dichos nombres se resolvían respecto a la base de datos de la sesión, por lo que la sentencia actualizaba o eliminaba silenciosamente filas seleccionadas de otra tabla. #113748 (groeneai).
  • Se corrigió una excepción al leer una tabla MergeTree por capas de rango de clave primaria cuando una capa produce un pipe vacío. #114177 (alexey-milovidov).
  • BACKUP, RESTORE y ENGINE = Backup ahora autorizan la ubicación de la copia de seguridad según los permisos SOURCES del usuario, del mismo modo que lo hacen s3(), file() y azureBlobStorage(). Anteriormente, un usuario con BACKUP pero sin SOURCES podía escribir y leer copias de seguridad en cualquier ubicación accesible para el servidor. Ahora, escribir una copia de seguridad requiere la dirección WRITE sobre la fuente del destino (WRITE ON S3, WRITE ON AZURE, WRITE ON FILE) y leerla requiere READ; los destinos Disk(...) siguen restringidos únicamente por backups.allowed_disk. #114405 (groeneai).
  • Se corrigió la lectura de una tabla mientras hay una mutación en curso: una columna MATERIALIZED podía devolver un valor obsoleto y, si se seleccionaba junto con una columna actualizada, la consulta podía fallar con un error. #114561 (tiandiwonder).
  • Se corrigió un error lógico (Block structure mismatch) al leer una tabla Merge con make_distributed_plan habilitado sobre tablas hijas con operaciones de conjuntos internas. #114753 (alexey-milovidov).
  • OPTIMIZE TABLE sobre una tabla de almacenamiento de objetos cuyo motor no implementa la compactación indicaba que se había ejecutado correctamente sin hacer nada. Ahora genera un error, como cualquier otro motor que no admite la sentencia. Esto afecta a DeltaLake, Paimon, Hudi y a los motores de almacenamiento de objetos simples (S3, GCS, COSN, OSS, AzureBlobStorage, HDFS y URL respaldado por almacenamiento de objetos); Iceberg, que sí implementa la compactación, no se ve afectado. #114805 (groeneai).
  • Se corrigió BAD_DATA_PART_NAME (“Trying to get part name in new format for old format version”) en una tabla ReplicatedMergeTree creada con la sintaxis posicional obsoleta mediante allow_deprecated_syntax_for_merge_tree. Una mutación podía notificarse como completada en una réplica que no la había aplicado, y la tabla podía quedar en modo de solo lectura tras un reinicio. #114980 (groeneai).
  • Se corrigió Found patch part ... that intersects mutation with version ... (LOGICAL_ERROR) en tablas con actualizaciones ligeras. Una fusión de partes de parche podía producir un parche cuyo rango de versiones de datos abarcara la versión de datos de una parte existente; ese parche no podía aplicarse ni omitirse, por lo que todas las operaciones posteriores sobre la partición fallaban y la cola de replicación se bloqueaba. Este tipo de fusiones ya no se asigna. #115064 (alexey-milovidov).
  • Se corrigió el fallo de arranque del servidor cuando un motor de base de datos Backup hace referencia a una copia de seguridad que ha dejado de estar disponible (por ejemplo, porque se eliminaron sus archivos o el almacenamiento subyacente no es accesible). Ahora la base de datos se carga sin tablas en lugar de impedir que arranque todo el servidor. #83188 (orloffv).
  • Se corrigió la recuperación del registro tras un error de disco lleno. Anteriormente, cuando el disco de logs se llenaba, ClickHouse entraba en un estado de fallo e inundaba syslog con mensajes de error (llegando a escribir más de 100 GB/hora), sin recuperarse nunca, ni siquiera después de liberar espacio en disco. Ahora el sistema de registro se recupera automáticamente en cuanto vuelve a haber espacio en disco disponible, sin necesidad de reiniciar el servidor. #93127 (jaehanbyun).
  • Se corrigió un fallo en el visitante de esquemas del almacenamiento DeltaLake. #97112 (kssenii).

Correcciones en lagos de datos y almacenamiento externo

  • Se corrigió un fallo transitorio Code: 499 ... InvalidPart (S3_ERROR) en las cargas multiparte de S3 (por ejemplo, INSERT INTO ... hits_s3). MinIO puede indicar brevemente que una parte recién cargada no existe en CompleteMultipartUpload; ahora este error se reintenta del mismo modo que NoSuchKey, que ya se gestionaba, con el límite establecido por s3_max_unexpected_write_error_retries. #109364 (groeneai).
  • Ahora se rechazan ALTER TABLE ... DELETE y ALTER TABLE ... UPDATE en tablas Iceberg cuyo formato de archivo de datos no es Parquet, con un error NOT_IMPLEMENTED claro, en lugar de provocar la caída del servidor o corromper la tabla de forma silenciosa. #105893 (groeneai).
  • Se corrigió el error Cannot add column ...: column with this name already exists en INSERT SELECT desde una función de tabla como file, s3 o input cuando la misma columna de origen se selecciona más de una vez. #105982 (crakjie).
  • Los valores sensibles pasados como parámetros de la cadena de consulta HTTP (por ejemplo, la vinculación de parámetros de consulta param_*, como param_secret_key/param_aws_secret_access_key, el parámetro password o los parámetros signature de estilo S3) ya no se escriben literalmente en system.text_log ni en los spans de OpenTelemetry. La línea de log Request URI ahora oculta los valores de los parámetros cuyos nombres parecen sensibles y los sustituye por [HIDDEN]. #108475 (groeneai).
  • Se corrigió la columna virtual _etag de los motores de tabla S3Queue y AzureQueue: estaba declarada pero nunca se rellenaba, por lo que SELECT _etag siempre devolvía una cadena vacía. Ahora devuelve el ETag del objeto, igual que el motor S3 y la función de tabla s3(). #108625 (groeneai).
  • Una consulta que lee o escribe en S3 y se cancela (por ejemplo, mediante KILL QUERY) mientras hay una solicitud a S3 en curso ahora se notifica como cancelada, en lugar de con un error engañoso de red o de S3. En concreto, una copia de seguridad o restauración en S3 cancelada ahora notifica BACKUP_CANCELLED/RESTORE_CANCELLED en system.backups. #108673 (jkartseva).
  • Se corrigió la columna virtual _tags del motor de tabla S3Queue: estaba declarada pero nunca se rellenaba, por lo que SELECT _tags siempre devolvía un mapa vacío. Ahora devuelve las etiquetas del objeto, igual que el motor S3 y la función de tabla s3(). #108676 (groeneai).
  • Se corrigió un problema por el que SHOW TABLES y SELECT … FROM system.tables devolvían resultados distintos para bases de datos de catálogos de data lake: ahora las tablas que ClickHouse no puede leer se ocultan de forma coherente en ambos casos. #109273 (SmitaRKulkarni).
  • Se corrigió una terminación abrupta del servidor (o, en las builds de release, un archivo de datos que quedaba sin finalizar de forma silenciosa) cuando un INSERT en una tabla de Delta Lake (DeltaLakeLocal / deltaLake) falla después de que el sink haya empezado a escribir; por ejemplo, cuando la consulta de origen lanza una excepción a mitad de la inserción o se cancela la consulta. #109328 (groeneai).
  • Se corrigió el error Not found column or subcolumn c.null in block (y Bad cast from ColumnConst to ColumnNullable en builds de depuración/sanitizer) al ejecutar WHERE col IS NULL / IS NOT NULL sobre una columna Iceberg añadida mediante evolución del esquema después de que se escribieran archivos de datos más antiguos, con optimize_functions_to_subcolumns=1 (el valor predeterminado). #109515 (groeneai).
  • Se corrige el error Host is empty in S3 URI cuando se usa una subconsulta escalar como argumento de URL de la función de tabla s3 (o como argumento de cualquier otra función de tabla) en consultas CREATE TABLE ... AS SELECT: las subconsultas escalares en los argumentos de funciones de tabla ahora se evalúan durante el análisis de la consulta. #110254 (CheSema).
  • Se corrige un error lógico (aborto del servidor en compilaciones de depuración/sanitizer) que se producía al ejecutar un ALTER con varios comandos, como UPDATE ..., DELETE ..., sobre una tabla Iceberg. Ahora estas mutaciones se rechazan con un error NOT_IMPLEMENTED claro. #110347 (groeneai).
  • Se corrige un problema por el que las tablas Iceberg generaban IDs de campo duplicados tras ALTER TABLE ... ADD COLUMN cuando el esquema inicial contenía campos anidados (Tuple/Array/Map). last-column-id ahora registra el ID de campo máximo asignado, incluidos los hijos anidados, de modo que una columna añadida posteriormente ya no reutiliza un ID de campo anidado y las lecturas ya no fallan con ICEBERG_SPECIFICATION_VIOLATION (Duplicate field id). #110884 (groeneai).
  • Se corrige un problema por el que DELETE/UPDATE sobre una tabla Iceberg eliminaba silenciosamente filas incorrectas (o lanzaba NOT_FOUND_COLUMN_IN_BLOCK) cuando la tabla contenía archivos de datos escritos tanto antes como después de ALTER TABLE ... ADD COLUMN y optimize_move_to_prewhere estaba habilitado. #111693 (groeneai).
  • Se corrige un problema por el que made_current_at en system.iceberg_history pasaba a ser 1970-01-01 para una instantánea conservada tras ejecutar ALTER TABLE ... EXECUTE expire_snapshots sobre una tabla Iceberg. También se corrige que system.iceberg_history no devolviera filas para una tabla cuyos metadata no incluyen snapshot-log. #111781 (groeneai).
  • Se corrige la corrupción de datos al insertar en una tabla Iceberg a través de una MATERIALIZED VIEW. El archivo de datos se escribía con los tipos de columna que tenía el destino en el momento del CREATE, en lugar de con su esquema Iceberg actual, por lo que un valor DateTime se almacenaba como un simple int de Avro y se leía como microsegundos, y con DateTime64(0) o DateTime64(9) el archivo directamente no podía leerse. En consecuencia, INSERT INTO <materialized view> sobre un destino cuyo esquema Iceberg es más amplio que las columnas declaradas de la vista ahora genera TYPE_MISMATCH en lugar de escribir una fila corrupta. #112359 (groeneai).
  • Se corrige la escritura de tablas Iceberg cuyo esquema contiene una tupla anidada dentro de otra tupla. Los metadata publicados de la tabla sustituían los nombres de campo de la tupla interna por nombres posicionales 1, 2, …, por lo que con el formato predeterminado Parquet el INSERT fallaba con INCORRECT_DATA y con Avro la columna no podía volver a leerse. #112480 (groeneai).
  • Se corrige un interbloqueo que dejaba bloqueada de forma permanente una base de datos Filesystem o HDFS cuando dos consultas resolvían el mismo nombre de tabla simultáneamente. Todas las consultas posteriores sobre esa base de datos quedaban bloqueadas indefinidamente sin posibilidad de interrumpirlas, por lo que era necesario reiniciar el servidor para recuperarla. #112495 (groeneai).
  • Se corrige un problema por el que las tablas DeltaLake devolvían menos filas de las debidas cuando el predicado WHERE contenía, bajo un NOT, una subexpresión que el traductor de predicados de delta-kernel no puede manejar. Ahora dicha subexpresión se notifica a delta-kernel como un predicado desconocido explícito en lugar de como el final del iterador hijo, lo que antes truncaba silenciosamente la conjunción que la contenía. #112652 (groeneai).
  • Se corrigió que ALTER TABLE ... EXECUTE remove_orphan_files eliminara un metadata/version-hint.text activo de una tabla Iceberg. Su entrada en el conjunto de archivos alcanzables se construía mediante concatenación de cadenas suponiendo una barra final en un valor que nunca la tiene, por lo que el archivo de pista real nunca se reconocía como alcanzable y se eliminaba en cuanto superaba el umbral older_than. Con iceberg_use_version_hint = 1, la tabla dejaba de poder leerse por completo. #113548 (groeneai).
  • Se corrigió un LOGICAL_ERROR al filtrar una columna Iceberg que ALTER TABLE ... MODIFY COLUMN había convertido en Nullable. #114521 (groeneai).
  • Se corrigió un caso en el que ATTACH TABLE con una definición ENGINE = URL(...) no comprobaba el permiso TABLE ENGINE del motor al que redirige el esquema de la URL. Un usuario que solo tuviera TABLE ENGINE ON URL podía adjuntar y luego leer una tabla respaldada por File, S3, AzureBlobStorage o HDFS, algo que CREATE TABLE rechaza correctamente. #115914 (groeneai).
  • Se corrigió que las solicitudes HTTP salientes (p. ej., `aiGenerate`, la función de tabla `url`, S3) fallaran con `No route to host` en hosts que anuncian tanto IPv4 como IPv6 cuando solo una de las familias de direcciones es enrutable. El pool de conexiones HTTP ahora recurre a la siguiente dirección resuelta cuando la primera falla con un error de red, en lugar de propagar el error ya en la primera solicitud. #103786 (alexey-milovidov).
  • Ahora se puede leer un array de Avro compuesto por registros {key, value} de dos campos en una columna Map de ClickHouse. Esta es la codificación que generan Iceberg y Spark para un MAP<K, V> cuya clave no es de tipo cadena (los mapas nativos de Avro solo admiten claves de tipo cadena). Antes, un archivo así podía leerse como Array(Tuple(key, value)), pero no como Map(K, V), que fallaba con Type Map(...) is not compatible with Avro array. #109289 (groeneai).
  • Se corrigió la lectura de una tabla Iceberg con un archivo de metadata cuyo número de versión está compuesto solo por dígitos, pero excede el rango de los enteros de 32 bits (por ejemplo, v99999999999999999999.metadata.json). Antes, un nombre así producía un error poco descriptivo std::out_of_range (STD_EXCEPTION) en lugar de un error BAD_ARGUMENTS claro. #109619 (groeneai).
  • Se corrigió el nombre de los archivos de metadata de Iceberg comprimidos con gzip. ClickHouse los escribía como v{N}.gzip.metadata.json (el token Content-Encoding de HTTP), mientras que la especificación de Iceberg espera la extensión gz: v{N}.gz.metadata.json. Por ello, Spark y otros lectores de catálogos Hadoop no encontraban la metadata escrita por ClickHouse. ClickHouse ahora escribe v{N}.gz.metadata.json y sigue leyendo el nombre heredado gzip por compatibilidad con versiones anteriores. #109812 (groeneai).
  • Se corrigió que una tabla Iceberg con formato de escritura Avro serializara como obligatorio un campo declarado "required": false cuyo tipo es list, map o struct, sin una unión ["null", T], de modo que el propio esquema del archivo de datos no coincidía con la metadata de la tabla y otros lectores de Iceberg veían un campo obligatorio. Ahora, dicho campo se escribe como la unión ["null", T] que la especificación de Iceberg utiliza para los campos opcionales. #112648 (groeneai).
  • Se corrigió que made_current_at en system.iceberg_history indicara el primer momento en que una instantánea pasó a ser la actual, en lugar del más reciente, cuando el mismo snapshot-id aparece más de una vez en el snapshot-log de Iceberg (como ocurre tras un rollback). #113598 (groeneai).
  • Se corrigió un bloqueo de hasta una hora en BACKUP/RESTORE ... TO S3, en los discos GCS y en la función de tabla s3 cuando la colección con nombre establece http_client = 'gcp_oauth' y el endpoint de tokens OAuth2 de Google acepta la conexión pero nunca responde. La solicitud del token Bearer ya no hereda el tiempo de espera de solicitud de transferencia de datos del llamador; la espera de su respuesta está limitada a 10 segundos, igual que el límite de la solicitud STS AssumeRole. #115531 (groeneai).
  • Se corrigió un error lógico en la caché del sistema de archivos (Expected file ... not to exist) que podía producirse cuando una descarga de caché en segundo plano fallaba con una excepción distinta de ErrnoException (por ejemplo, al ejecutar OPTIMIZE sobre una tabla Iceberg) y dejaba un archivo de caché huérfano vacío. #110549 (groeneai).
  • Se corrigió que las cachés configuradas con un número máximo de entradas (política SLRU) dejaran de admitir nuevas entradas sin previo aviso una vez que ese mismo número de entradas se hubiera accedido al menos dos veces. Entre las cachés afectadas figuran las cachés de archivos de metadatos de Iceberg y Paimon, la caché de metadatos de Parquet, las cachés de índices de texto, la caché de índices de similitud vectorial, la caché de expresiones compiladas y la caché de estado de archivos de ObjectStorageQueue. #115517 (groeneai).
  • Se corrigieron las lecturas de tablas Paimon que podían fallar mientras la pista mutable snapshot/LATEST se reemplazaba de forma concurrente. Ahora, ante pistas no válidas u obsoletas, se recurre de forma segura al listado de instantáneas. #112010 (JiaQiTang98).
  • Ahora se muestra la excepción subyacente real cuando no se puede descomprimir un archivo zip porque el búfer de entrada (p. ej., un búfer de lectura de S3 con restricted_seek = true) rechaza un reposicionamiento o una lectura solicitados por minizip. Antes, el error real quedaba oculto tras el mensaje genérico Couldn't unpack zip archive: Code = -100 / Couldn't open zip archive. #105103 (groeneai).
  • Se corrigió la escritura en Iceberg para metadatos sin refs #106896 (AVMusorin).
  • Se corrigió una excepción al insertar en una tabla Iceberg cuyos metadatos fueron creados por un motor externo y omiten los arrays opcionales snapshots, metadata-log o snapshot-log. Estas inserciones ahora se completan correctamente en lugar de fallar. #107473 (tiandiwonder).
  • Se corrigió un error ReadBuffer is canceled. Can't read from it. que podía producirse al reintentar una subida a S3 (por ejemplo, una copia de seguridad) tras un error de lectura transitorio. #108573 (groeneai).
  • Se corrigió un std::future_error (“The associated promise has been destructed prior to the associated state becoming ready”) que podía producirse, y abortar el servidor en compilaciones de depuración o con sanitizador, cuando fallaba la planificación de la tarea asíncrona final que completa la subida multiparte a S3/Azure (por ejemplo, al agotarse el pool de hilos). Ahora se notifica el error de planificación real. #108730 (groeneai).
  • Se corrigió la lectura de marcas de tiempo ORC posteriores aproximadamente al año 2262 en una columna DateTime64 con una escala menos precisa que 9. El lector ORC nativo convertía cada marca de tiempo mediante un valor intermedio fijo DateTime64(9), que desborda Int64 a escala de nanosegundos, y rechazaba dichos valores con VALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, incluso cuando la escala DateTime64 solicitada (por ejemplo, DateTime64(6), como la que genera Iceberg) podía representar el valor. Ahora las marcas de tiempo se leen directamente en la escala solicitada y se respeta date_time_overflow_behavior cuando ni siquiera la escala de destino puede contener el valor. #109302 (groeneai).
  • Al leer una tabla Paimon cuyo esquema contiene un tipo anidado no compatible (por ejemplo, un campo ROW), ahora se notifica un error BAD_ARGUMENTS claro que indica el tipo no compatible, en lugar de un simple DB::Exception. (OK) con código de error 0 y sin mensaje. #109762 (groeneai).
  • Se corrigió la lectura de tablas Iceberg particionadas más de una vez por la misma columna de origen (por ejemplo, PARTITIONED BY (hours(ts), ts)). Anteriormente, estas tablas fallaban con Cannot add column ...: column with this name already exists (ILLEGAL_COLUMN). #109895 (groeneai).
  • Los archivos de datos que ClickHouse escribe en tablas Iceberg ahora incorporan los ID de campo de Iceberg para los formatos Avro (field-id) y ORC (atributos de tipo iceberg.id/iceberg.required), y las columnas String de ORC se escriben como string de ORC en lugar de binario. Anteriormente solo Parquet incorporaba los ID de campo, por lo que los lectores que cumplen la especificación (p. ej., Spark/iceberg-java) devolvían NULL sin avisar en las filas Avro escritas por ClickHouse tras renombrar una columna, y no podían leer en absoluto los archivos ORC escritos por ClickHouse. #109994 (groeneai).
  • Se corrigió un error lógico ChunkInfoRowNumbers does not exist al ejecutar OPTIMIZE TABLE sobre una tabla Iceberg que contenía un archivo de datos en un formato distinto de Parquet (p. ej., ORC) más reciente que todos los archivos de eliminación por posición. #110107 (alexey-milovidov).
  • Se corrigió la lectura de archivos Parquet grandes desde entradas zip STORED sin comprimir mediante s3 y file. #110495 (Gudauu).
  • Un fallo al iniciar un pool de programación en segundo plano (por ejemplo, el pool iceberg, cuando se agota el pool global de hilos) ya no aborta el servidor: ahora el error es una excepción recuperable. Además, leer system.background_schedule_pool ya no crea esos pools como efecto secundario. #111209 (groeneai).
  • Se corrigió la autenticación DLF en el catálogo REST de Paimon: la firma de la solicitud se calculaba una sola vez y se reutilizaba, por lo que todas las solicitudes al catálogo posteriores a la primera fallaban con HTTP 401 y SHOW TABLES devolvía una lista vacía. También se corrigió la detección de HTTP 404 en las comprobaciones de existencia de tablas. #112015 (JiaQiTang98).
  • Se corrigió un LOGICAL_ERROR (partitions_count > 0) al particionar fragmentos de datos de Iceberg que habían quedado vacíos tras eliminaciones por posición, p. ej., durante la compactación de una tabla Iceberg particionada con archivos de datos completamente eliminados. #112432 (PedroTadim).
  • Se corrigió un problema por el que la eliminación de objetos por batch en Azure no registraba eventos Delete en system.blob_storage_log cuando fallaba la propia solicitud del batch, con lo que todo el batch quedaba sin registrar. Ahora se registra un evento Delete para cada objeto cuando se produce un fallo a nivel de batch. #112873 (arsenmuk).
  • Se corrigió la lectura de tablas Paimon particionadas por una columna TIMESTAMP con una precisión superior a milisegundos, que fallaba con scale 6 is not supported, only support scale <= 3. #113401 (JiaQiTang98).
  • Se corrige un fallo al leer una tabla de lago de datos cuyo esquema declara una columna con un nombre vacío. Los metadatos de Iceberg mal formados se rechazan con ICEBERG_SPECIFICATION_VIOLATION; un esquema proporcionado por un catálogo, Delta Lake o Paimon se rechaza con AMBIGUOUS_COLUMN_NAME. La comprobación es incondicional, por lo que una tabla Iceberg que simplemente conserve un esquema histórico sin usar con un nombre de campo vacío también pasa a ser ilegible, en lugar de provocar un aborto en el momento en que se lee dicho esquema. #114394 (groeneai).
  • La lectura de una tabla Iceberg cuyos metadatos describen una evolución de esquema prohibida por la especificación de Iceberg ya no provoca el aborto del servidor. Cuatro infracciones de la especificación en IcebergSchemaProcessor se notificaban como LOGICAL_ERROR, que se trata como una aserción fallida, o llegaban sin comprobar a una aserción fatal; ahora generan ICEBERG_SPECIFICATION_VIOLATION. #114518 (groeneai).
  • Se corrigió que la columna virtual _time de las funciones de tabla url/urlCluster fuera siempre NULL en compilaciones basadas en musl, debido a un análisis no portable del encabezado HTTP Last-Modified. #111619 (thevar1able).
  • Se corrigió un problema por el que el servidor no arrancaba tras crear una tabla con CREATE TABLE ... AS url('http://host/**/', ...) con allow_experimental_url_wildcard_from_index_pages habilitado. Al cargar los metadatos de dicha tabla se volvía a evaluar la comprobación experimental, que fallaba con SUPPORT_IS_DISABLED e interrumpía el arranque. #115095 (groeneai).
  • Una tabla del motor de base de datos URL ya no revela si existe un archivo local a un usuario que carece del permiso de lectura de origen: ni EXISTS TABLE, que solo requiere el privilegio SHOW TABLES, ni la resolución de una tabla consultan ya el sistema de archivos antes de confirmar el permiso. #113029 (alexey-milovidov).
  • Se aplica query_masking_rules a los mensajes añadidos mediante Exception::addMessage, de modo que las credenciales codificadas en URL de los sufijos (in file/uri ...) de los errores de jdbc()/odbc() no se filtren cuando hay reglas de enmascaramiento configuradas. #106916 (gaurav0107).

Correcciones de formatos e ingestión

  • Las lecturas sin esquema de time32/time64 de Arrow (p. ej., SELECT * FROM file(..., 'Arrow')) ahora infieren Time64 en lugar de DateTime64. Anteriormente se infería DateTime64. Cualquier proceso posterior que dependa del tipo inferido anterior dejará de funcionar tras la actualización. También se añade compatibilidad para exportar Time/Time64 a Arrow, seleccionando el tipo de tiempo de Apache Arrow adecuado según la precisión. #104316 (Maoyao233).
  • Se corrigieron posibles resultados incorrectos o lecturas fuera de límites cuando un INSERT se revierte tras un error a mitad de lote (por ejemplo, en tablas Buffer, inserciones asíncronas o los motores Kafka/RabbitMQ/FileLog) mientras está activa la replicación diferida de columnas (enable_lazy_columns_replication). #108935 (groeneai).
  • Se corrigió una incoherencia del analizador por la cual una lista de columnas de INSERT aceptaba un selector de columnas calificado escrito como t.* LIKE '<pattern>' / t.* ILIKE '<pattern>', pero rechazaba su forma canónica t.COLUMNS('<regexp>'), lo que impedía el formateo de ida y vuelta de la consulta (y abortaba el servidor en compilaciones de depuración/sanitizador). #109176 (groeneai).
  • Se corrigió el fallo de INSERT con IncorrectEndpointError (HTTP 400) en una tabla DataLakeCatalog de Microsoft Fabric / OneLake: ahora las escrituras de ADLS Gen2 (DFS) se dirigen al host del endpoint .dfs en lugar del host .blob. Nota: con remote_url_allow_hosts, tanto el host .blob (lectura) como el .dfs (escritura) de Fabric deben incluirse en la lista de permitidos para INSERT. #110290 (zlareb1).
  • Se corrigieron las escrituras mediante funciones de tabla de data lake (p. ej., INSERT INTO FUNCTION icebergS3(...)) que generaban archivos Parquet cuyas columnas de cadena perdían la anotación de tipo String, lo que hacía que los datos escritos fueran ilegibles para lectores externos como Spark. Estas escrituras ahora usan la misma configuración de formato que las realizadas mediante el motor de tabla. #110465 (tiandiwonder).
  • Se corrigió que system.session_log quedara ilegible tras un inicio de sesión mediante Arrow Flight: la columna interface es un Enum8, pero faltaba el valor ArrowFlight en su enumeración, por lo que un inicio de sesión mediante el protocolo Arrow Flight escribía el valor bruto 10 y cualquier SELECT que leyera esa fila lanzaba la excepción Unexpected value 10 in enum. #110758 (alexey-milovidov).
  • Se corrige la inferencia de esquema de la familia de formatos TSV, que infería String para un valor decimal escrito con un cero inicial, como 0.0 o 0.5, mientras que CSV infiere correctamente Float64. Además, la detección automática de encabezados de TSV consumía como encabezado una primera fila con dichos valores, que desaparecía del resultado. También se corrige que TSKV infiriera un tipo numérico para un valor escrito con una secuencia de escape, como x=1\x2E5, que después no se podía analizar. Los valores cuyo cero inicial es relleno de un entero, como 007, se siguen infiriendo como String, ya que el analizador de valores de TSV no puede volver a leerlos. #112226 (groeneai).
  • Se corrigió que la inferencia de esquema propusiera un tipo numérico para valores de texto que el analizador de valores no puede volver a leer. La inferencia aceptaba un exponente incompleto (1e+), una mantisa ausente (.) o un signo repetido (++inf), que readFloatTextPrecise rechazaba después con CANNOT_PARSE_NUMBER al leer el esquema inferido; en una columna Dynamic, esto provocaba un error en el momento del INSERT. Ahora la inferencia valida el número con el mismo analizador que utiliza el lector. Esto también elimina un caso en el que el tipo inferido dependía de max_read_buffer_size y permite que las formas válidas de exponente con ceros a la izquierda, como 0e5, se infieran como Float64 en TSV, tal como ya ocurre en CSV. Además, corrige las formas de exponente mal formadas. #112453 (groeneai).
  • Se corrige que KILL QUERY y max_execution_time se ignoraran durante minutos mientras un formato de entrada basado en filas analizaba un bloque. Ahora los formatos de entrada basados en filas comprueban si la consulta se ha cancelado cada 8192 filas, de modo que una inserción terminada (en particular, un vaciado de inserción asíncrona en segundo plano, que analiza hasta max_insert_block_size filas por bloque) se detiene de inmediato en lugar de continuar hasta el final del bloque. #112646 (groeneai).
  • Se corrigió que el tipo de columna inferido dependiera del orden de las consultas anteriores en un origen cuyo esquema está en caché. Las configuraciones que modifican un tipo inferido no formaban parte de la clave de la caché de inferencia de esquema, por lo que el valor de la primera consulta determinaba el tipo que veían todas las consultas posteriores: input_format_try_infer_exponent_floats, max_parser_depth, input_format_json_infer_array_of_dynamic_from_array_of_different_types y, para Parquet, también input_format_parquet_local_time_as_utc, input_format_parquet_allow_geoparquet_parser, input_format_parquet_skip_columns_with_unsupported_types_in_schema_inference y schema_inference_make_json_columns_nullable. Asimismo, registra el getter de clave de caché que faltaba para Form y hace que el getter de Template utilice la regla de escape de su propio formato de fila. #113533 (groeneai).
  • Se corrigió el formateo de un argumento de subconsulta de las funciones de tabla view y viewIfPermitted cuando la consulta que las contiene termina con una cláusula SETTINGS. Dicha consulta se formateaba como view((SELECT ...)), que no puede volver a analizarse, por lo que no superaba la comprobación interna de formateo-análisis-formateo y generaba Inconsistent AST formatting. #114658 (groeneai).
  • Se corrige que los datos JSON se detectaran erróneamente como TSKV durante la detección automática del formato. #106009 (Avogar).
  • La exportación al formato Arrow de valores Time/Time64 fuera de una hora del día válida (negativos o >= 24h) ahora se rechaza con un error claro en lugar de escribir datos Arrow time32/time64 no válidos. #107179 (tiandiwonder).
  • Se corrigió la lectura de archivos Arrow, ArrowStream y ORC basados en Arrow cuya columna de marca de tiempo usa como zona horaria un desfase UTC numérico fijo (p. ej., +05:30, -08:00, 00:00) o el marcador no IANA fixed, que antes fallaba con Cannot load time zone ... (BAD_ARGUMENTS). #108633 (groeneai).
  • Ahora una columna Nullable(Tuple(...)) se serializa como un único campo CSV en lugar de aplanarse en columnas separadas. Antes, un valor no nulo se escribía como varios campos CSV, mientras que un NULL era un único \N, lo que daba lugar a un número de columnas variable según la fila que rompía los encabezados de CSVWithNames/CSVWithNamesAndTypes y las conversiones de ida y vuelta. #108959 (groeneai).
  • Se corrigió una asignación de memoria excesiva durante la inferencia de esquema del formato MsgPack: una entrada corrupta o generada mediante fuzzing cuyo encabezado de array/mapa/string/binario declara un número enorme de elementos ya no provoca una única asignación de varios gigabytes (ahora se rechaza como entrada mal formada). Esto corrige una interrupción allocation-size-too-big con sanitizadores y una condición de falta de memoria en las builds de release. #109019 (groeneai).
  • Se corrigió un LOGICAL_ERROR al escribir una columna LowCardinality(Time) en el formato Arrow con output_format_arrow_low_cardinality_as_dictionary = 1. #109730 (groeneai).
  • Se corrigió la lectura de un stream corrupto en formato Native cuyo número de tipos Dynamic o de rutas JSON/Object se aproxima a SIZE_MAX: este tipo de entrada mal formada ahora se rechaza con un error INCORRECT_DATA claro, en lugar de producir un std::length_error no capturado. #110590 (alexey-milovidov).
  • Se corrigió un LOGICAL_ERROR: Cannot sum Bools (interrupción del servidor en builds de depuración o con sanitizadores) al combinar estados de agregación de sumMap/sumMapWithOverflow/sumMapFiltered con valores Bool serializados en el formato de estado antiguo (versión 0). La misma corrección resuelve además dos casos en los que se devolvían resultados incorrectos de forma silenciosa con estados Bool de versión 0: las claves de mapa de tipo Bool no se deduplicaban entre estados y la compactación de valores cero eliminaba entradas equivocadas. #110922 (groeneai).
  • Se corrigió que la función de tabla format lanzara NOT_FOUND_COLUMN_IN_BLOCK cuando el análisis de los datos de entrada no produce ninguna fila (por ejemplo, un JSON vacío o un FeatureCollection de GeoJSON sin features). Ahora devuelve un resultado vacío con las columnas correctas. #111428 (groeneai).
  • Ahora es posible leer archivos GeoParquet, Arrow y ArrowStream cuya columna de geometría codificada en WKT usa una palabra clave de tipo que no está en mayúsculas (point(1 2)) o un contenedor vacío (LINESTRING EMPTY, POLYGON(), POLYGON(())). Hasta ahora, la importación de estos archivos fallaba con BAD_ARGUMENTS o CANNOT_PARSE_NUMBER, aunque la función readWKT analizaba correctamente esas mismas cadenas. También se corrige la lectura de un archivo que almacena la salida de wkt para una geometría vacía, que se escribe como LINESTRING(). #112020 (groeneai).
  • Se corrigió el error Unknown compression method que se lanzaba con las pistas de compresión auto y none cuando no estaban escritas completamente en minúsculas, por ejemplo file('data.csv.gz', 'CSV', 'x String', 'AUTO'). Los nombres de códecs como GZIP ya se aceptaban sin distinguir entre mayúsculas y minúsculas; ahora estas dos pistas especiales se comportan igual. #113631 (groeneai).
  • Se corrigió la lectura de una columna Tuple cuyo primer elemento es NULL en los formatos CustomSeparated, Regexp y Template con la regla de escape CSV. En estos formatos, un Tuple simple ocupa un campo por elemento, por lo que el campo \N inicial corresponde a ese elemento y no a toda la columna. Antes se interpretaba como la columna completa, lo que desplazaba los campos de los elementos restantes a las columnas siguientes e impedía que CustomSeparated pudiera volver a leer su propia salida. #114471 (groeneai).
  • Se corrigió que el formato de entrada Regexp descartara silenciosamente el resto no analizado de un campo coincidente, lo que almacenaba un valor truncado o inventado en lugar de notificar un error: con la regla JSON, v=-1 en UInt64 se leía como 0, y v=2020-01-01junk en Date se leía como 1975-07-14. Ahora los campos mal formados se rechazan con las reglas Escaped, CSV y JSON, en consonancia con los formatos a los que, según la documentación, se asemeja el comportamiento de dichas reglas. Con Raw, un campo coincidente que contiene un tabulador ahora se lee completo en lugar de truncarse en el tabulador. #114520 (groeneai).
  • Se corrigió un error lógico Inconsistent AST formatting (que provocaba la terminación abrupta del servidor en builds de depuración y con sanitizador) en expresiones CREATE INDEX / CREATE HYPOTHETICAL INDEX que no superaban un ciclo completo de formateo-análisis-formateo, por ejemplo CREATE HYPOTHETICAL INDEX i0 ON t0 ((a())) TYPE a y CREATE INDEX i0 ON t0 ((a, b).1) TYPE minmax. #109175 (groeneai).
  • Se corrige un error lógico (Logical error: 'KeyCondition uses PREWHERE output') en el lector de Parquet v3 que se producía cuando una condición de clave a nivel de formato hacía referencia a una columna que no se lee del archivo Parquet. #109267 (groeneai).
  • Se corrige una excepción en el HTTP handler predefinido cuando falta un encabezado #108324 (vitlibar).
  • Se corrigió un posible Logical error: 'ReadBuffer is canceled. Can't read from it.' cuando un formato de entrada basado en filas (p. ej., TSV/CSV) no lograba analizar la entrada y la lectura subyacente ya se había cancelado (por ejemplo, por un fragmento HTTP mal formado o un cuerpo truncado). La generación de los diagnósticos detallados de análisis ya no lee de un búfer cancelado. #109708 (groeneai).
  • El formato Values ya no registra errores de análisis en system.errors ni en system.error_log cuando el análisis en streaming recurre correctamente al análisis de expresiones SQL. #111141 (pamarcos).
  • Se corrige que SYSTEM REFRESH sobre una tabla RabbitMQ detenida a veces no consumiera los mensajes pendientes en cola. Un REFRESH concede exactamente un ciclo de streaming fuera de orden, pero ese ciclo podía finalizar de inmediato con cero filas porque el bucle de entrega AMQP acababa de iniciarse de forma asíncrona, con lo que se desperdiciaba el único permiso y los mensajes quedaban sin consumir hasta el siguiente SYSTEM START. #111480 (groeneai).
  • Se corrige que una tabla NATS con nats_stream configurado dejara de consumir mensajes silenciosamente tras reiniciarse el servidor NATS. La suscripción de JetStream ahora se restablece automáticamente, sin necesidad de ejecutar DETACH TABLE y ATTACH TABLE. #112828 (groeneai).
  • Se rechaza un valor desmesuradamente grande de kafka_num_consumers con un error claro, en lugar de que falle una asignación dentro del motor de tabla Kafka. Anteriormente, con kafka_disable_num_consumers_limit habilitado, dicho valor producía una excepción std::length_error. #114764 (alexey-milovidov).
  • Servidor Arrow Flight: se aceptan credenciales de autenticación Basic codificadas en Base64 sin relleno, tal como las envían los clientes de Flight basados en Go (por ejemplo, el controlador ADBC Flight SQL), y se devuelve un error de autenticación adecuado en lugar del genérico Unexpected error in RPC handling cuando el encabezado authorization está mal formado. #115085 (alexey-milovidov).
  • Servidor Arrow Flight: ahora rechaza las credenciales de autenticación Basic mal formadas que omiten el separador entre el nombre de usuario y la contraseña. #115347 (alexey-milovidov).

Correcciones de tipos de datos, funciones y serialización

  • Se corrigió un error lógico Stream <col>.variant_discr ... is not found (aborto del servidor en compilaciones de depuración y con sanitizers) que se producía cuando ALTER TABLE ... MODIFY COLUMN convertía una columna a un tipo con subcolumnas dinámicas (por ejemplo, de Variant a Dynamic) en una tabla con partes Wide, y la parte se leía o fusionaba posteriormente. #110204 (groeneai).
  • Se corrigió la lectura de una subcolumna de una columna Nullable(Tuple(...)) cuyo elemento es un LowCardinality(T) no nullable cuando la misma consulta también lee la subcolumna padre. En una parte Compact, la subcolumna padre devolvía valores incorrectos, la consulta fallaba con Unexpected return type from assumeNotNull o el servidor terminaba abruptamente por una aserción de refuerzo de string_view, porque la subcolumna extraída se deserializaba en un búfer LowCardinality(Nullable(T)) cuyos subflujos se compartían luego con la lectura de la subcolumna padre. #112232 (groeneai).
  • Se corrigió un LOGICAL_ERROR “Not-ready Set is passed as the second argument for function globalNullIn” y la pérdida del mensaje de error real de la consulta, que podían producirse cuando la poda de partes basada en estadísticas ejecutaba de forma especulativa una subconsulta IN/GLOBAL IN durante el análisis de índices y dicha subconsulta fallaba. #114121 (groeneai).
  • Se corrigió el error Cannot read all data of type FixedString al leer la subcolumna product_quantization_codebook de una columna con un códec Quantized('product', ...). El codebook de cada parte se escribe después de los datos de todos los gránulos, por lo que no está delimitado por marcas, y una lectura cuyo rango de marcas terminara antes de la marca final de la parte podía leerlo de forma incompleta. #112818 (alexey-milovidov).
  • Ya no se escriben partes cuya disposición de Map contradice sus propios metadata, en el caso de un valor Map dentro de una columna Dynamic. Las tablas que solo diferían en map_serialization_version compartían un mismo objeto de serialización en caché, de modo que una parte podía recibir la disposición de Map basic mientras sus metadata declaraban with_buckets, y su lectura posterior fallaba con LOGICAL_ERROR: Stream ...buckets_info ... is not found. Las partes que una versión anterior ya haya escrito de esta forma siguen siendo ilegibles y deben eliminarse. #113514 (groeneai).
  • Se corrigió que ALP, FPC y GCD omitieran en el hash del códec su parámetro derivado del tipo. En una parte Compact, el escritor comparte un flujo comprimido por cada hash de códec distinto, por lo que dos columnas con distinto ancho de valor y el mismo códec colisionaban y compartían un único objeto de códec con el ancho incorrecto. Como consecuencia, se rechazaban inserciones válidas con CANNOT_COMPRESS cuando los anchos no coincidían y, en otros casos, una de las columnas se comprimía peor de lo debido. #114189 (groeneai).
  • Se corrigió una poda de índice incorrecta cuando la clave de ordenación de una tabla envuelve una columna Date en toDateTime (por ejemplo, ORDER BY toDateTime(date_column)) y una consulta filtra por la columna original con una comparación como WHERE date_column >= '...'. toDateTime(Date) se desborda con valores Date fuera del rango de DateTime (posteriores a 2106-02-07), por lo que la clave almacenada no es monótona; ClickHouse ya no utilizará la poda por clave primaria para esta combinación de clave y predicado, ya que hacerlo podría descartar gránulos que contienen filas coincidentes. #101814 (nihalzp).
  • Se corrigió el fallo de ALTER MODIFY COLUMN al convertir una columna Nullable con un DEFAULT a un tipo diferente (p. ej., Nullable(UInt8) → String,LowCardinality(String) o Array(UInt8)). #102156 (il9ue).
  • Se corrigió el escapado incorrecto de literales SQL en StorageSQLite y en la función de tabla sqlite() al enviar predicados WHERE a SQLite: las comillas simples y los caracteres de control (\n, \r, \t, \) se escapaban con barras invertidas, que SQLite no interpreta, lo que provocaba errores de sintaxis o resultados de consulta incorrectos. También se corrigió el escapado de los literales de cadena a los que se hace pushdown hacia PostgreSQL: las cadenas anidadas dentro de listas IN conservaban el escapado de ClickHouse, y los caracteres de control se enviaban como secuencias con barra invertida que PostgreSQL interpreta como bytes distintos. #104217 (tiandiwonder).
  • Se corrige la excepción NOT_FOUND_COLUMN_IN_BLOCK en consultas INNER JOIN ... ON arrayJoin(...) = ... cuando query_plan_convert_join_to_in está habilitado y el SELECT hace referencia a la columna del array de origen. #104809 (tiandiwonder).
  • Se corrigen las expresiones IN y NOT IN cuyos operandos del lado derecho no son constantes y hacen referencia a columnas de la fila actual, y se alinea el tratamiento de tuplas en el lado derecho del nuevo analizador con la semántica actual de IN en ClickHouse. Con el analizador antiguo, una columna de origen aislada en el lado derecho (x IN (arr)) se sigue resolviendo como nombre de tabla y queda fuera del ámbito. #104993 (niyue).
  • Se corrigió un problema por el que un JOIN contra tablas EmbeddedRocksDB, Redis y KeeperMap podía devolver cero filas sin avisar al usar DirectKeyValueJoin con claves String o Nullable(String). #105253 (vdimir).
  • Se corrige un LOGICAL_ERROR (“Unexpected expression in JOIN ON section. Expected boolean (UInt8), got ‘Nothing’”) que se producía cuando un predicado JOIN ... ON sin igualdad hacía referencia a una columna de tipo Nothing, como la generada por ARRAY JOIN []. #106981 (groeneai).
  • Se corrigió un error lógico Inconsistent AST formatting que podía abortar el servidor en compilaciones de depuración y con sanitizadores al usar una lambda con alias como operando de un operador de acceso (elemento de tupla .N o elemento de array []) en cualquier posición salvo la primera de una lista de expresiones, p. ej., SELECT 1, ((p0, p1) -> p0 AS a7).4[3] FROM t. #107092 (groeneai).
  • Una función de tabla de cluster (urlCluster, fileCluster, s3Cluster, …) anidada dentro de otra consulta distribuida, como clusterAllReplicas(..., urlCluster(...)), ahora se rechaza con un error BAD_ARGUMENTS en lugar de fallar con un error lógico (Distributed task iterator is not initialized). #107107 (groeneai).
  • Se corrigió el fallo de la función de tabla values con ARGUMENT_OUT_OF_BOUND al usar un literal decimal que no puede representarse exactamente en una columna de coma flotante de menor precisión (como 0.1 en una columna Float32), p. ej., SELECT * FROM values('x Float32', 0.1). Ahora estos valores se aceptan y se convierten al valor representable más cercano, en coherencia con CAST e INSERT ... VALUES. #108055 (alexey-milovidov).
  • Se corrigió un problema por el que mapFilter, mapSort (y sus variantes) y mapConcat eliminaban LowCardinality de los tipos de clave y valor de un Map. Anteriormente, mapFilter sobre una columna Map(LowCardinality(String), String) devolvía Map(String, String), lo que podía corromper los metadatos de una tabla creada mediante CREATE TABLE ... AS SELECT y hacer que CHECK TABLE fallara. #108057 (alexey-milovidov).
  • Se corrigió que un INSERT cancelado o finalizado con KILL siguiera ejecutándose durante mucho tiempo mientras construía un índice de omisión (por ejemplo, un índice set(0) sin límite sobre una columna de alta cardinalidad). Ahora la construcción del índice se detiene de inmediato al cancelarse la consulta. #108351 (tiandiwonder).
  • Se corrigió que un SELECT sobre la función de tabla primes no respondiera a la cancelación: con un step (o limit) grande, la consulta podía seguir ejecutándose durante mucho tiempo después de KILL QUERY o de agotarse el tiempo de espera. Ahora se detiene de inmediato. #108353 (tiandiwonder).
  • Se corrigió el análisis de nombres de tipos de datos que contienen la subcadena INT (por ejemplo, un nombre similar a una función, como quantileInterpolatedWeighted, usado en la posición de un tipo de datos). Estos nombres se confundían con tipos enteros de MySQL y su primer grupo de argumentos (...) se consumía silenciosamente como modificador de ancho de visualización, lo que podía romper el ciclo de ida y vuelta del formateo de la consulta. #108354 (groeneai).
  • Se corrigió una inconsistencia por la que un ARRAY JOIN mal formado seguido de una coma y una lista de tablas entre paréntesis se interpretaba erróneamente como una unión cruzada en lugar de rechazarse. #108365 (Algunenano).
  • Se corrigió una excepción LOGICAL_ERROR (“Invalid action query tree node …”) que se producía cuando una consulta distribuida deduplicaba columnas ALIAS duplicadas y estructuralmente idénticas y, a la vez, hacía referencia a una función de tabla con un argumento de colección con nombre key = value (por ejemplo, oss(s3_conn, filename = '...')). #108435 (groeneai).
  • Se corrigió un error lógico (una excepción en las builds de release y una interrupción del servidor en las builds de depuración y con sanitizadores) que podía producirse en una llamada a función con más de un argumento LowCardinality sobre una tabla distribuida, por ejemplo, concatAssumeInjective((SELECT toLowCardinality('p')), s) usado como clave de GROUP BY con remote(). Los mensajes eran Default functions implementation for LowCardinality is supported only with a single LowCardinality argument o Expected the argument ... to have N rows, but it has M. #108871 (groeneai).
  • Se corrigió que use_client_time_zone se ignorara en los literales de cadena DateTime/DateTime64 interpretados en el servidor (INSERT asíncrono, literales en SELECT). Ahora el cliente propaga su zona horaria local como session_timezone cuando use_client_time_zone está habilitado, de modo que el análisis en el servidor coincide con el de la ruta síncrona de INSERT. #109051 (groeneai).
  • Se corrigió que max_execution_time (con timeout_overflow_mode = 'throw') a veces no llegara a cancelar nunca una consulta: cuando el vigilante interno de tiempos de espera ya estaba esperando una consulta con un plazo posterior, una consulta registrada después con un plazo anterior podía pasarse por alto por completo, lo que le permitía ejecutarse mucho más allá de su límite de tiempo. #109792 (tiandiwonder).
  • Se corrigió el error NOT_FOUND_COLUMN_IN_BLOCK que se producía cuando una consulta sobre una tabla Distributed usaba _shard_num (o shardNum()) convertido en Nullable (por ejemplo, con FULL JOIN y join_use_nulls = 1) junto con ORDER BY, con el analizador habilitado. #109798 (groeneai).
  • Se corrigió el error NOT_IMPLEMENTED (“Method getDataAt is not supported for Nullable(String)”) que podía producirse en una unión con enable_join_runtime_filters = 1 (activado de forma predeterminada desde 26.2) cuando la clave de unión del lado de construcción era LowCardinality(Nullable(...)) con valores NULL y el filtro en tiempo de ejecución recurría a su filtro Bloom. #109824 (groeneai).
  • Se corrigió un fallo del servidor que se producía al pasar una expresión lambda donde una función de orden superior espera un valor concreto (por ejemplo, el acumulador de arrayFold, como en arrayFold(lambda, arr, another_lambda)). Ahora, cuando enable_analyzer = 0, estas consultas se rechazan con ILLEGAL_TYPE_OF_ARGUMENT en lugar de provocar un fallo. #109840 (groeneai).
  • Se rechaza el alias unnest de arrayJoin en los filtros de row policy, lo que cierra un resquicio por el que dicha política podía generar un error lógico column->size() == num_rows durante la lectura. #109973 (Algunenano).
  • Se corrigió un problema por el que los índices de omisión definidos sobre subcolumnas de Tuple no se utilizaban cuando se accedía al campo mediante tupleElement(t, 'name'), tupleElement(t, N) o t.N y, a la vez, se leía la tupla completa en la misma consulta (p. ej., SELECT *). Ahora todas estas formas descartan gránulos del mismo modo que el acceso a la subcolumna por nombre t.name. #110056 (groeneai).
  • Se corrigió el error BAD_GET al comparar una columna Array(String) con un literal de array (arr = ['x']) cuando la columna tiene un índice de omisión text, tokenbf_v1 o ngrambf_v1. Ahora el índice trata dicha comparación como un escaneo completo en lugar de hacer fallar toda la consulta. #110057 (groeneai).
  • Se corrigió un error espurio ILLEGAL_COLUMN en ALTER TABLE ... ADD COLUMN IF NOT EXISTS cuando la columna ya existe en el momento de aplicar el cambio. Esto ocurría cuando la misma columna se añadía dos veces con IF NOT EXISTS en una sola sentencia, o cuando un ALTER concurrente añadía la columna entre las fases de preparación y aplicación. #110080 (groeneai).
  • Se corrigió un LOGICAL_ERROR (Bad cast from type ColumnLowCardinality to ColumnString) que se producía cuando identity() (o el resultado de una subconsulta escalar) envuelve un valor que contiene un LowCardinality anidado y la consulta usa WITH TOTALS/WITH ROLLUP. #110138 (groeneai).
  • Se corrigió un error NOT_FOUND_COLUMN_IN_BLOCK al usar GROUP BY ALL sobre una expresión de tupla junto con ORDER BY. #110206 (alexey-milovidov).
  • Se corrigió un error NOT_FOUND_COLUMN_IN_BLOCK al ejecutar INSERT en una tabla con una restricción CHECK que hace referencia a una subcolumna (como x.null de una columna Nullable o arr.size0 de un Array). #110208 (alexey-milovidov).
  • Se corrigieron resultados de consulta incorrectos de la optimización optimize_and_compare_chain (habilitada de forma predeterminada): una condición derivada por transitividad a partir de a < b AND b < c podía usar una semántica de comparación distinta de la de las condiciones originales cuando la cadena mezclaba tipos con reglas de conversión específicas de cada par (p. ej., Enum frente a String, Decimal frente a Float64 o FixedString de distintos anchos). Ahora las condiciones transitivas solo se derivan dentro de grupos de tipos que comparten un único orden de comparación. #110621 (yariks5s).
  • Se corrigió que optimize_injective_functions_in_group_by alterara los resultados de las consultas con GROUP BY GROUPING SETS y GROUP BY ... WITH TOTALS. La configuración está documentada como una que preserva los resultados, pero al eliminar una función inyectiva de una clave de agrupación se producía un valor incorrecto (o se descartaba una fila) en las filas en las que esa clave no forma parte del conjunto agregado (un conjunto de GROUPING SETS al que no pertenece) o en la fila de WITH TOTALS. El valor incorrecto podía coincidir con un valor de clave real, de modo que una fila de superagregación resultaba indistinguible de un grupo real dentro del mismo conjunto de resultados. #110721 (groeneai).
  • Se corrige un bloqueo del servidor al multiplicar un estado de función de agregación median/quantile (basada en ReservoirSampler) por una constante entera enorme (p. ej., medianState(x) * 18446744073709551615). La consulta dejaba de responder a la cancelación y podía ejecutarse indefinidamente. #110779 (groeneai).
  • Se corrige un fallo (desreferencia de puntero nulo durante el análisis de la consulta) al llamar a getSubcolumn sobre un argumento JSON con un nombre interno de subcolumna de indicación de tipo, es decir, uno que empieza por un marcador de tipo con acento grave. #110940 (groeneai).
  • Se corrigió que map[key] devolviera el valor de una clave duplicada posterior en lugar del de la primera. Cuando una columna Map contenía claves duplicadas, el resultado de map[key] podía depender de las filas anteriores del mismo bloque y de la configuración optimize_functions_to_subcolumns, por lo que un SELECT y un WHERE sobre la misma fila podían dar resultados distintos. #111246 (groeneai).
  • Se corrige un error lógico !rhs_literal->getValue().isNull() en el optimizador de expresiones lógicas cuando una cadena AND compara una columna con una constante de valor NULL de un tipo no Nullable (por ejemplo, un Variant con valor NULL) con use_variant_default_implementation_for_comparisons = 0. #111292 (groeneai).
  • Se corrigieron resultados incorrectos cuando una consulta tiene un índice de omisión set y un predicado de la forma (x AND <null-value>) OR y, donde el NULL lo genera una función (p. ej., toInt64OrNull('x'), nullIf(1, 1), CAST(NULL AS Nullable(Int64))). Dicho valor se envolvía con __bitWrapperFunc y propagaba NULL en lugar de la máscara “desconocido”, por lo que el índice set podía descartar gránulos que sí coincidían y la consulta devolvía menos filas de las debidas. #111604 (groeneai).
  • Se corrige que CREATE TABLE/ALTER TABLE con el analizador aceptara una expresión de columna DEFAULT/MATERIALIZED que hiciera referencia a una columna virtual como _table o _database. Las inserciones en dicha tabla fallaban con NOT_FOUND_COLUMN_IN_BLOCK, y una columna MATERIALIZED (que no puede proporcionarse explícitamente) impedía de forma permanente insertar datos en la tabla. Ahora estas expresiones se rechazan en el momento de la definición, igual que ocurre sin el analizador. Las columnas ALIAS (evaluadas en tiempo de lectura) y las columnas EPHEMERAL (entradas de inserción no almacenadas) basadas en columnas virtuales siguen funcionando. #111776 (groeneai).
  • Se corrigió el error UNKNOWN_QUERY_PARAMETER al llamar a una vista parametrizada con un argumento cuyo valor es una subconsulta de tipo Array, Tuple o LowCardinality, p. ej., SELECT * FROM v(param = (SELECT groupArray(x) FROM t)). #111790 (groeneai).
  • Se corrigieron tres errores en las reescrituras del analizador que convierten una cadena de comparaciones en IN/NOT IN (x = c1 OR x = c2 OR ..., x != c1 AND x != c2 AND ... y has(const_array, x)). Para una expresión Variant con use_variant_default_implementation_for_comparisons = 0, la reescritura cambiaba el tipo de resultado de la expresión de UInt8 a Nullable(UInt8), lo que provocaba un LOGICAL_ERROR en la comprobación de validación del árbol de consulta en las compilaciones de depuración y con sanitizadores. Para una expresión con estructura dinámica (Dynamic, Array(Dynamic), JSON), la reescritura hacía que una consulta que antes funcionaba fallara con Illegal type ... of argument of function in, porque IN rechaza ese tipo de argumentos. Además, en ambos sentidos se devolvían resultados incorrectos cuando una constante no se convierte sin pérdida al tipo de la expresión, por ejemplo, una constante DateTime con hora del día comparada con una columna Date. #111924 (groeneai).
  • Se corrige que quantileDeterministic, quantilesDeterministic y medianDeterministic devolvieran resultados distintos para los mismos datos en cada ejecución cuando la consulta usa réplicas paralelas, una tabla distribuida o agregación externa, o cuando los estados se almacenan en una tabla (incluso dentro de un valor Dynamic). Los estados escritos antes de esta versión con la notación de tipo sin versión conservan el comportamiento anterior, ya que su estructura no puede cambiar. #112052 (alexey-milovidov).
  • Se corrigen resultados incorrectos causados por consultas de búsqueda vectorial que contaminaban la caché de condiciones de consulta. Una consulta SELECT ... WHERE <condition> ORDER BY <distance function> LIMIT n sobre una tabla con un índice vector_similarity podía registrar gránulos como no coincidentes con <condition>, de modo que una consulta SELECT ... WHERE <condition> ordinaria posterior sobre la misma tabla devolvía, sin avisar, menos filas. Las lecturas de búsqueda vectorial ya no escriben en la caché de condiciones de consulta. #112086 (groeneai).
  • Se corrige que serialize_string_in_memory_with_zero_byte se omitiera del plan de consulta serializado. Con serialize_query_plan = 1, en un clúster con este ajuste deshabilitado, la representación en cadena en memoria podía diferir entre el iniciador y el nodo que ejecutaba el plan deserializado, porque el ajuste se leía al deserializar pero nunca se escribía al serializar y, por tanto, en el nodo de ejecución siempre tomaba su valor predeterminado. #112131 (groeneai).
  • Se corrigió un resultado incorrecto en un JOIN cuya expresión ON contiene una conjunción constante, por ejemplo ON l.id = r.id AND CAST(NULL AS Nullable(UInt8)). La optimización del plan de consulta descartaba silenciosamente la constante, por lo que la unión se ejecutaba como si no existiera: las uniones INNER, LEFT SEMI y RIGHT SEMI devolvían filas coincidentes cuando una condición que nunca es verdadera no debe devolver ninguna, y RIGHT ANTI no devolvía ninguna fila en lugar de devolverlas todas. #112155 (vdimir).
  • Se corrigen resultados incorrectos al llamar a una vista parametrizada con un argumento que no es una asignación parameter = value. Con enable_analyzer = 0, y en EXPLAIN SYNTAX con la configuración predeterminada, llamadas como pv(concat(name, '!')), pv(name, 'a'), pv(name != 'a') y pv(tuple(name = 'a')) vinculaban silenciosamente un parámetro de la vista a una expresión sin relación en lugar de devolver UNKNOWN_QUERY_PARAMETER, como hace el analizador. Ahora estas llamadas se rechazan de la misma forma en ambas rutas de ejecución. #112194 (groeneai).
  • Corrige un error por el cual se aceptaba un CREATE VIEW o CREATE FUNCTION cuya definición llama a substr, mid o byteSlice de una forma que la gramática de substring no puede volver a analizar, aunque la metadata que ClickHouse escribe para ello no es SQL válido. Al leer esa definición posteriormente, se produce el error SYNTAX_ERROR y, durante el inicio del servidor, se interrumpe la carga de metadata, por lo que el servidor no llega a iniciarse. Ahora estas definiciones se conservan correctamente en un ciclo de ida y vuelta, y los archivos de metadata existentes con la forma substring(x, a, b, c) vuelven a ser legibles, de modo que un servidor afectado se inicia sin intervención manual. #112195 (groeneai).
  • Se corrigieron resultados incorrectos, una salida de ORDER BY mal ordenada y una excepción BAD_TYPE_OF_FIELD cuando la clave primaria es un Array o Tuple y la consulta le aplica plus, minus, multiply, divide o intDiv. La aritmética sobre un valor compuesto se evalúa elemento a elemento, mientras que la comparación de valores compuestos es lexicográfica, por lo que el análisis de la clave primaria ya no considera monótona dicha expresión. #112339 (groeneai).
  • Se corrigió el error Code: 62 ... You must not specify ANY or ALL for PASTE JOIN. (SYNTAX_ERROR) que generaba un servidor remoto ante una consulta con PASTE JOIN enviada a otro servidor, por ejemplo, cuando la tabla izquierda es una tabla Distributed o una función de tabla *Cluster. El formateador generaba ALL PASTE JOIN, una sintaxis que el analizador rechaza, por lo que el servidor receptor no podía analizar la consulta recibida. #112404 (groeneai).
  • Corrige que una lista de alias de columna como (SELECT 1) AS t(x) o WITH t(x) AS (SELECT 1) no fuera visible dentro de la función de tabla view, donde una referencia a t.x fallaba con UNKNOWN_IDENTIFIER pese a que la misma construcción funciona fuera de view. #112690 (groeneai).
  • Corrige un error lógico en el formateo de consultas cuando una cláusula ARRAY JOIN no contiene expresiones. Ahora dicha cláusula se rechaza durante el análisis con SYNTAX_ERROR, de forma coherente con un USING vacío, en lugar de aceptarse y formatearse como un texto que no puede volver a analizarse. #112699 (groeneai).
  • Se corrigió que connectionId lanzara Context has expired cuando las acciones de expresión preparadas para una subconsulta se ejecutaban después de haberse liberado su contexto de construcción. #112870 (clickgapai).
  • Corrige un error lógico y resultados incorrectos cuando una condición JOIN ON que no es de igualdad y que se evalúa durante la unión contiene arrayJoin. Las uniones hash, parallel_hash y grace_hash ahora rechazan dicha condición con INVALID_JOIN_ON_EXPRESSION. Si la expansión depende de un solo lado, muévala a un ARRAY JOIN dentro de una subconsulta previa a la unión; si el argumento de arrayJoin lee columnas de ambos lados, será necesario reestructurar la condición. #112889 (groeneai).
  • Se corrigió que geohashesInBox dedicara un tiempo ilimitado a un recuadro de área cero, como geohashesInBox(0., 0., 180., 0., 12). Dicha consulta devolvía el único geohash correcto, pero desperdiciaba aproximadamente 5e8 iteraciones de bucle vacías por fila e ignoraba tanto max_execution_time como KILL QUERY. #112976 (groeneai).
  • Se rechaza un cambio de SETTINGS marcado como escrito sin valor cuando contiene un valor distinto de true, y ya nunca se omite el valor de dicho cambio al formatear una consulta. Anteriormente, una carga útil JSON de AST manipulada podía ejecutar un ajuste Bool con false mientras system.query_log y formatQueryFromJSON mostraban la forma sin valor. #113025 (alexey-milovidov).
  • Se corrigió el error UNKNOWN_IDENTIFIER al seleccionar desde una VIEW cuyos tipos de columna declarados difieren de los que produce su consulta interna, por ejemplo SELECT sum(length(arr)) FROM v, donde v declara arr Array(UInt8) sobre una columna String. Con el valor predeterminado optimize_functions_to_subcolumns = 1, el optimizador reescribía length(arr) como una lectura de la subcolumna arr.size0 y propagaba ese nombre a la consulta interna, que no tiene dicha subcolumna. #113057 (groeneai).
  • Se corrigió la cancelación de las lecturas con la función de tabla postgresql y el motor PostgreSQL. Cancelar mientras la lectura aún se estaba iniciando podía provocar una condición de carrera sobre el puntero de la transacción, y la cancelación podía perderse por completo, de modo que la consulta seguía ejecutándose hasta que PostgreSQL la terminaba. Una cancelación que llegue a PostgreSQL antes de que la sentencia COPY haya empezado a ejecutarse todavía puede descartarse. #113150 (groeneai).
  • Se corrigió un LOGICAL_ERROR (Next task callback is not set for query) que se producía cuando una vista SQL SECURITY DEFINER o SQL SECURITY NONE sobre una función de tabla de cluster (s3Cluster, urlCluster, fileCluster) se leía como consulta secundaria, por ejemplo a través de remote o clusterAllReplicas. Este anidamiento no compatible ahora se rechaza con un error de consulta normal, en lugar de abortar el servidor en builds de depuración y con sanitizador. #113371 (groeneai).
  • Se corrige un error lógico IDENTIFIER is not a table expression que se producía cuando una función de tabla de la familia remote con un argumento view(...) se usaba en el lado izquierdo de un JOIN ... USING cuya clave es un alias de la lista SELECT, con analyzer_compatibility_join_using_top_level_identifier = 1. #113400 (groeneai).
  • Se corrigió el error Not-ready Set is passed as the second argument for function 'in' cuando una consulta filtra system.databases por la columna name con una subconsulta dentro de indexHint, por ejemplo SELECT count() FROM system.databases WHERE indexHint(name IN (SELECT 'foo')). Dicha consulta se rechazaba con un LOGICAL_ERROR en builds de release y abortaba el servidor en builds de depuración y con sanitizador. #113556 (groeneai).
  • Se corrigió que una consulta sobre una columna Variant ignorara max_execution_time y KILL QUERY. Al llamar a una función con varios argumentos Variant, la función se resolvía una vez por cada alternativa de cada argumento, y ninguno de los dos bucles que realizaban ese trabajo comprobaba la cancelación, por lo que la consulta no podía detenerse hasta que terminaba. #113612 (groeneai).
  • Se corrige que ALTER TABLE ... MODIFY COLUMN fallara con Cannot specify codec for column type ALIAS cuando una misma sentencia convierte una columna ALIAS en física (DEFAULT o MATERIALIZED) y además especifica un CODEC. #113853 (groeneai).
  • Se corrigió un fallo del servidor al realizar una unión con una expresión ON constante sobre un lado derecho que contiene un ARRAY JOIN. La lectura de una columna del lado derecho replicada de forma diferida usaba un ColumnReplicated ya liberado. #113901 (groeneai).
  • Corrige una fuga de memoria con optimize_aggregation_in_order = 1 cuando la clave de ordenación de la tabla es un prefijo estricto de la clave de GROUP BY y se utiliza una función de agregación cuyo estado reserva memoria en el heap, como quantileDD. La memoria del servidor crecía con cada consulta de este tipo hasta que se reiniciaba. #114010 (groeneai).
  • Se corrigió que isProbablePrime sobre UInt128/UInt256 ignorara max_execution_time y KILL QUERY. Un bloque de valores anchos se procesaba por completo dentro de una única llamada a la función, sin ningún punto de cancelación, por lo que una consulta podía seguir ejecutándose durante minutos después de agotar su tiempo límite. #114032 (groeneai).
  • Se corrigió el error Code: 46. DB::Exception: Unknown function exists. (UNKNOWN_FUNCTION) que se producía cuando una cláusula PREWHERE contenía un predicado IN (subquery) y se había establecido rewrite_in_to_join = 1 (o make_distributed_plan = 1, que lo habilita de forma forzosa). La misma consulta escrita con WHERE funcionaba correctamente. #114067 (RohithPariki).
  • Se corrigió un LOGICAL_ERROR en arrayAutocorrelation cuando el argumento es un array no vacío cuyo tipo de elemento es Nothing, por ejemplo, SELECT arrayAutocorrelation([arrayMax([])]). Ahora dicho argumento se rechaza con ILLEGAL_COLUMN. El literal de array vacío [] sigue devolviendo []. #114249 (groeneai).
  • CREATE TABLE y ALTER TABLE ahora rechazan códecs con pérdida, como SZ3, en columnas utilizadas en la clave de ordenación. #114531 (groeneai).
  • Se corrigió un bucle infinito y no cancelable en las funciones hop y windowID cuando la duración de un argumento de intervalo en segundos es múltiplo de 2^32 (por ejemplo, toIntervalDay(2147483648)): la resta desbordada eludía la comprobación de desbordamiento temporal y, con argumentos constantes, el bucle se ejecutaba durante el análisis, donde ni siquiera era posible terminar la consulta. El mismo intervalo también podía dejar un hilo en segundo plano de una WINDOW VIEW girando indefinidamente; ahora una window view de este tipo se rechaza al crearla. #114607 (alexey-milovidov).
  • Corrige el error lógico Not-ready Set is passed as the second argument for function 'in' en consultas con una subconsulta IN que lee de un clúster remoto: ahora la consulta falla con el error real de la subconsulta, como un fallo de conexión. #114983 (alexey-milovidov).
  • Se corrigió un INSERT en una tabla Log, TinyLog o StripeLog que fallaba al confirmar los tamaños de archivo registrados. Dicha inserción podía conservar sus filas en la tabla aunque informara de un error, o dejar los archivos de datos de una columna de tipo array inconsistentes entre sí. Al leer una tabla Log o TinyLog cuya columna de tipo array no contiene elementos pero cuyos offsets indican que sí los hay, ahora se genera un error que indica el nombre de la columna, en lugar de leer más allá del final de los elementos. Las columnas de elementos escritas parcialmente ya se rechazaban. #115027 (groeneai).
  • Corrige TYPE_MISMATCH (“CAST AS Array can only be performed between same-dimensional array types”) en consultas con una constante de tipo Array(Map(...)), como has([map('k', 'v')], m), ejecutadas sobre una tabla Distributed o con réplicas paralelas. #115883 (alexey-milovidov).
  • Se corrigieron resultados incorrectos al realizar una unión con una vista o view() cuya columna proyectada tiene el mismo nombre que una columna de una de sus propias relaciones internas, por ejemplo SELECT expr(x.c0) AS c0 FROM a AS x, b AS y. El optimizador del orden de join fusionaba dicha expresión en el grafo de uniones aplanado y después la aplicaba dos veces, por lo que la consulta devolvía valores sesgados sin ningún aviso. Si la expresión además cambiaba el tipo de la columna, la misma causa producía en su lugar el error AMBIGUOUS_COLUMN_NAME durante la planificación. #116152 (groeneai).
  • Se corrigió una excepción en subconsultas correlacionadas cuando las columnas externas pasan a ser Nullable con group_by_use_nulls y ROLLUP/CUBE. #100365 (alexey-milovidov).
  • Ahora se rechaza max_replication_lag_to_enqueue = 0 en bases de datos Replicated. Este valor hacía que la comprobación de falta de sincronización posterior a la recuperación fuera trivialmente verdadera y provocaba que el servidor abortara con LOGICAL_ERROR en compilaciones de depuración y con sanitizador. Ahora 0 se rechaza durante el análisis con BAD_ARGUMENTS, independientemente del origen (CREATE DATABASE ... SETTINGS, el bloque <database_replicated> de la configuración del servidor, la reproducción de ATTACH y la reproducción de los metadatos existentes durante una actualización). El valor mínimo válido es 1. #106006 (groeneai).
  • Se prohíbe crear índices de omisión minmax en columnas JSON (Object) para evitar la excepción NO_COMMON_TYPE al insertar arrays de tipos mixtos. En su lugar, utilice subcolumnas tipadas (p. ej., INDEX idx json.field TYPE minmax). #106094 (linhaojie).
  • Se corrigió que JSON_QUERY/JSON_VALUE/JSON_EXISTS devolvieran Dynamic en lugar de String/UInt8 al recibir argumentos Dynamic. #106877 (Avogar).
  • Se corrigió un desbordamiento de entero con signo cuando una configuración de tiempo de espera, como interactive_delay, se establecía en un valor muy grande: la espera podía agotarse de inmediato en lugar de esperar, y el servidor podía abortar con el Undefined Behavior Sanitizer. #106961 (groeneai).
  • Se corrigió un LOGICAL_ERROR (“Unsupported argument types”) en la función geohashesInBox cuando sus argumentos de coordenadas combinaban valores constantes y no constantes, o cuando una coordenada era de tipo BFloat16. Ahora funcionan los argumentos Float32 que combinan valores constantes y no constantes, y los argumentos BFloat16 se rechazan con un mensaje de error claro. #107063 (groeneai).
  • Se corrigió que el encabezado de CSVWithNames y CSVWithNamesAndTypes tuviera menos columnas que los datos cuando output_format_csv_serialize_tuple_into_separate_columns está habilitado (valor predeterminado). Ahora el encabezado (y la fila de tipos) descompone las columnas Tuple en sus campos hoja con nombres separados por puntos (p. ej., t.a, t.b), de modo que el número de columnas del encabezado coincide con el de los datos. Una nueva configuración, output_format_csv_header_serialize_tuple_into_separate_columns (predeterminado 1), controla este comportamiento y puede establecerse en 0 para recuperar el encabezado anterior con un único nombre. #107371 (groeneai).
  • Se corrigió una fuga de memoria en el mongo-c-driver integrado que podía producirse al leer desde MongoDB (por ejemplo, mediante un diccionario de MongoDB o la función de tabla mongodb) cuando a un error de lectura reintentable le seguía un fallo en la selección del servidor para el reintento. #107448 (groeneai).
  • Se corrige un error lógico (WhichDataType(const_type).isArray()) y la terminación abrupta del servidor durante el análisis de la clave primaria cuando se llama a pointInPolygon con un argumento de polígono constante de un tipo contenedor como Variant o Dynamic (por ejemplo, pointInPolygon((x, y), if(c, [(0, 0), ...], NULL))). #107589 (groeneai).
  • Se corrigieron errores lógicos (Bad cast) causados por la eliminación inconsistente de LowCardinality anidado dentro de columnas Variant y Dynamic, por ejemplo, en concat, format y en el análisis de la clave primaria. #107773 (Avogar).
  • Se corrigió el análisis de los parámetros de comando de las funciones definidas por el usuario de tipo executable, de modo que ya no se aceptan como parámetros los marcadores de posición con nombres vacíos o no válidos. #107983 (goutamadwant).
  • Se corrige accurateCastOrNull de un Tuple cuyo elemento es Dynamic/Variant: un NULL real en el origen se trataba como un fallo de conversión. Si el elemento de destino es Nullable, un NULL en el origen ahora se mantiene como NULL en el elemento (igual que con un origen Tuple(Nullable(...)) simple); si el elemento de destino no es Nullable, un NULL en el origen ahora convierte en nula toda la tupla (igual que en la referencia sin Dynamic), en lugar de generar el valor predeterminado del elemento. Los fallos de análisis o de desbordamiento siguen convirtiendo en nula toda la tupla. #108023 (groeneai).
  • La función de tabla mongodb ahora acepta oid_columns como argumento con nombre (p. ej., oid_columns='_id'), en lugar de rechazarlo con BAD_ARGUMENTS. #108039 (alexey-milovidov).
  • Ahora es posible consultar un diccionario range_hashed o complex_key_range_hashed que utilice un rango DateTime64, Decimal o de coma flotante pasando a dictGet/dictHas un argumento del tipo correspondiente. Anteriormente, estas consultas fallaban con must be convertible to Int64, y los intervalos abiertos de rangos Decimal/DateTime64 devolvían incorrectamente el valor predeterminado. #108052 (alexey-milovidov).
  • Se corrige una terminación abrupta del servidor (Logical error en IColumn::insertFrom) al convertir un Array(Dynamic) o Array(Variant) a QBit con accurateCastOrNull, p. ej., accurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)'). #108288 (groeneai).
  • Se corrigió un fallo del servidor (Received signal 4, instrucción ilegal) que podía provocarse mediante un flujo del protocolo TCP nativo malformado o desincronizado. Ahora se valida que el campo initial_address de ClientInfo sea un host:port numérico antes de analizarlo, en lugar de permitir que un puerto no numérico llegue a la función de libc getservbyname, que está bloqueada mediante una trampa. #108410 (groeneai).
  • Se corrigió la asignación excesiva de memoria al deserializar estados de funciones de agregación manipulados para mannWhitneyUTest, rankCorr, largestTriangleThreeBuckets, quantileGK, sequenceMatch/sequenceCount y groupArrayIntersect. Un estado malformado podía declarar un número enorme de elementos y hacer que el servidor intentara asignar decenas de gigabytes a partir de unos pocos bytes de entrada; ahora estos estados se rechazan con TOO_LARGE_ARRAY_SIZE. #108465 (groeneai).
  • Se corrigió un error lógico (Bad cast from type DB::ColumnNullable to DB::ColumnString) y posibles resultados incorrectos al usar group_by_use_nulls con una clave de agrupación constante LowCardinality en GROUPING SETS/ROLLUP/CUBE. #108771 (alexey-milovidov).
  • Se corrigió TYPE_MISMATCH en mapFilter, mapSort, mapReverseSort, mapPartialSort y mapConcat cuando un valor Map contiene un Map anidado con LowCardinality, p. ej., mapFilter((k, v) -> 1, map('a'::LowCardinality(String), map('x'::LowCardinality(String), 'y'))). #108798 (groeneai).
  • Se corrigió un LOGICAL_ERROR (“Inconsistent AST formatting”) que provocaba la terminación abrupta del servidor en builds de depuración y con sanitizador al formatear un tipo de datos Tuple que combina elementos con nombre y sin nombre (por ejemplo, Tuple(a UInt8, UInt16)). #108915 (groeneai).
  • JSONExtract ahora respeta cast_string_to_date_time_mode al convertir valores JSON de tipo cadena a DateTime/DateTime64, de forma coherente con CAST. #109252 (Utkal059).
  • Se corrigió un problema por el que IN con una columna de array simple como argumento derecho devolvía silenciosamente un resultado incorrecto (siempre falso) o lanzaba una excepción; ahora x IN arr se comporta como has(arr, x). #109416 (alexey-milovidov).
  • Se corrigió un LOGICAL_ERROR en arrayFold sobre un argumento Array(LowCardinality(T)) no constante (por ejemplo, arrayFold((acc, x) -> acc + x, materialize([1, 2, 3]::Array(LowCardinality(Int64))), toInt64(0))), que fallaba con “Arguments of ‘plus’ have incorrect data types” (lo que provocaba la terminación abrupta del servidor en builds de depuración y con sanitizador). #109462 (groeneai).
  • Se corrigió una excepción ILLEGAL_COLUMN en conv al convertir correctamente los argumentos FixedString a String. #109771 (hp77-creator).
  • Se corrigieron resultados incorrectos en lecturas de funciones de tabla con FINAL / SAMPLE con serialize_query_plan = 1, así como la clave de caché de estadísticas de la tabla hash de agregación para funciones de tabla (antes, todas las funciones de tabla compartían una única entrada de preasignación). #109847 (azat).
  • Se corrigió el análisis de los valores numéricos 1/0 como valores Bool dentro de tipos contenedores (p. ej., Array(Bool), Tuple(Bool, ...)). Antes, [1,0] fallaba con CANNOT_READ_ARRAY_FROM_TEXT, mientras que [true,false] funcionaba. #109976 (groeneai).
  • Se corrigió el error NOT_IMPLEMENTED (Method getDataAt is not supported for Nullable(String) in case if value is NULL) que se producía al construir un índice text sobre Array(LowCardinality(Nullable(String))) (incluidos los campos Nested almacenados de esa forma) cuando un array indexado contenía un elemento NULL. Ahora los elementos NULL del array se omiten durante la construcción del índice, igual que con Array(Nullable(String)). #110055 (groeneai).
  • Se corrigieron resultados incorrectos de subBitmap, bitmapSubsetInRange y bitmapSubsetLimit en bitmaps que aún se encontraban en la representación pequeña, incluidos valores de elementos UInt64 e Int64 superiores a 2^32, que se truncaban a 32 bits. Las comparaciones en las funciones de bitmap sobre tipos de elemento con signo ahora usan de forma coherente el valor sin signo del tipo de elemento, de modo que en un bitmap Int8 el elemento -1 se compara como 255 y no como el valor con extensión de signo 4294967295; esto también corrige bitmapMin, bitmapMax, bitmapContains y bitmapTransform en bitmaps que ya han superado la representación pequeña. Las consultas que pasaban umbrales con extensión de signo deben ajustarse: sobre un bitmap Int8, bitmapSubsetInRange(bm, 4294967168, 4294967296) pasa a ser bitmapSubsetInRange(bm, 128, 256). También se corrigió que groupNumericIndexedVector devolviera resultados distintos para columnas del índice Int8 e Int16 que para tipos de índice más anchos, así como que numericIndexedVectorGetValue devolviera 0 para índices negativos. Se corrigió la documentación de las funciones de bitmap, incluidas las funciones de subconjunto, que se describían como basadas en indexación desde 1, y la compatibilidad de bitmapBuild / bitmapToArray con valores con signo. #110072 (RamiDarwiche).
  • Se corrigieron rutas con desbordamiento con signo de comportamiento no definido en la aritmética de intervalos para WITH FILL STEP de tipo intervalo y para las funciones de intervalo de fecha/hora add* / subtract* con deltas extremos, de modo que los valores de intervalo extremos ahora son deterministas en lugar de depender del desbordamiento con signo. También se corrigió un bloqueo de WITH FILL de tipo intervalo con un paso YEAR enorme, que hacía retroceder el calendario. #110158 (groeneai).
  • Se corrigió un aumento cuadrático del tiempo de ejecución (y la falta de respuesta a max_execution_time) en la agregación en orden al agrupar por varias claves cuyo orden de clasificación es solo un prefijo de las grouping keys. #110159 (alexey-milovidov).
  • Se corrigieron comparaciones que antes lanzaban ILLEGAL_TYPE_OF_ARGUMENT cuando los operandos no tienen un supertipo común mínimo. Los arrays como Array(Int64) frente a Array(UInt64) y Array(Int256) frente a Array(UInt256) ahora pueden compararse lexicográficamente con =, !=, <, <=, >, >=, IS DISTINCT FROM e IS NOT DISTINCT FROM. Las comparaciones seguras frente a NULL, como isDistinctFrom / isNotDistinctFrom, ahora también comparan por valor los pares numéricos o decimales compatibles que no son arrays, en lugar de lanzar una excepción. Las comparaciones de igualdad también funcionan con arrays cuyos elementos son Tuple(Nullable(...)) anidados. #110245 (diegomestre2).
  • Se corrigió un desbordamiento de entero con signo (UBSan) al convertir un valor DateTime64 extremo (p. ej., INT64_MIN) a Time/Time64 en una zona horaria con desfase negativo. #110451 (groeneai).
  • La conversión de valores de coma flotante fuera de rango (BFloat16, Float32, Float64) y de valores UInt64 superiores a Int64::max() a DateTime y Time ahora se satura de forma fiable en los límites del rango en todas las arquitecturas (anteriormente, el resultado de una conversión fuera de rango dependía de la arquitectura y podía dar la vuelta en x86-64), y los valores no finitos (NaN, inf) ahora lanzan una excepción en lugar de producir un resultado arbitrario. La misma corrección se aplica a la ruta de conversión de coma flotante a Date de toDate y a las conversiones de UInt64 y de enteros anchos ((U)Int128, (U)Int256) a Date y Date32, que podían devolver un día anterior a la época en lugar de saturarse. La conversión de un número a Time ahora se satura al rango del tipo para todos los tipos numéricos de origen (anteriormente, los valores procedentes de enteros sin signo estrechos o de enteros anchos se almacenaban sin acotar y solo se acotaban al imprimirse), y la conversión precisa a Time ya no rechaza los valores negativos que Time admite, ni satura silenciosamente los valores que no caben en él. La conversión precisa de un número a Date32 (accurateCast, accurateCastOrNull) ya no satura silenciosamente un valor fuera de rango o no finito, sino que lanza una excepción o devuelve NULL, como ya ocurría con Date y DateTime, y las variantes OrDefault devuelven el valor predeterminado de Date32 para dicha entrada. La conversión precisa de un número de coma flotante no entero a Date, Date32, DateTime o Time ahora se rechaza en lugar de truncarse silenciosamente. También se corrigió la documentación de la función toDateTime32, que mostraba por error ejemplos de toDateTime64 y describía el rango de valores de DateTime64. #110459 (alexey-milovidov).
  • Se corrige el fallo de la inferencia de esquema con Map cannot have a key of type LowCardinality(Nullable(String)) al leer archivos ORC cuyas claves de mapa están codificadas mediante diccionario, incluidos los archivos ORC escritos por Spark y los escritos por el propio ClickHouse con output_format_orc_dictionary_key_size_threshold habilitado. #110492 (tiandiwonder).
  • Se corrige un error lógico (Function node with name '...' is not resolved as ordinary function) que podía producirse con optimize_or_like_chain habilitado cuando una función de agregación o de ventana aparecía en el lado izquierdo de un LIKE/ILIKE/match dentro de una cadena OR. #110641 (groeneai).
  • Se corrigió un desbordamiento de entero con signo en toStartOfInterval con un número extremo de intervalos MONTH, WEEK o DAY sobre valores Date/Date32/DateTime64. #110688 (groeneai).
  • Se corrigió que readWKT y readWKTPoint devolvieran coordenadas sin inicializar (escalar) u obsoletas de la fila anterior (vectorizado) para POINT EMPTY. POINT EMPTY ahora se rechaza con CANNOT_PARSE_TEXT, ya que un Point de ClickHouse es un Tuple(Float64, Float64) fijo sin representación vacía. #110692 (groeneai).
  • Se corrigió que flipCoordinates perdiera el tipo Geometry: para un argumento Geometry, el resultado vuelve a ser de tipo Geometry en lugar del Variant(...) subyacente, por lo que puede pasarse directamente a funciones como areaCartesian. #110694 (groeneai).
  • Se corrigió la serialización WKB no canónica de un polígono vacío: wkb(POLYGON EMPTY) ahora emite numRings = 0 en lugar de un anillo espurio de cero puntos, de modo que una conversión de ida y vuelta WKB de un polígono vacío estándar preserva la identidad. #110796 (groeneai).
  • El análisis de los valores numéricos 1/0 en Bool de JSON ahora respeta el ajuste allow_special_bool_values. Antes, una entrada JSON como {"v":1} para Variant(Bool, UInt32) se leía como Bool incluso con allow_special_bool_values_inside_variant = 0, porque los analizadores de Bool de JSON ignoraban el ajuste y Bool tiene mayor prioridad de deserialización en Variant que los tipos enteros. #110835 (groeneai).
  • Se corrigió que throwIf(notLike(col, pattern)) (y cualquier otro throwIf aplicado sobre una función) lanzara una excepción de forma incondicional cuando col es LowCardinality. La implementación predeterminada de LowCardinality ejecutaba throwIf sobre todo el diccionario, que siempre contiene el valor predeterminado reservado aunque ninguna fila haga referencia a él, de modo que un valor distinto de cero en esa posición sin usar provocaba que throwIf lanzara una excepción con datos que no cumplen la condición. #110864 (groeneai).
  • Se corrigió un fallo que se producía cuando una función de agregación con el combinador -Tuple se usaba con RESPECT NULLS y generaba un estado intermedio (-State, agregación distribuida, WITH ROLLUP/WITH CUBE). La función combinada tomaba el nombre de una variante de estado incorrecta, por lo que, al serializarse y deserializarse, su tipo AggregateFunction se volvía a resolver a una disposición en memoria incompatible. #110930 (groeneai).
  • Se corrigió el error Nested type LineString cannot be inside Nullable type (ILLEGAL_TYPE_OF_ARGUMENT) al leer una columna espacial de MySQL que admite NULL (LINESTRING, POLYGON, MULTILINESTRING, MULTIPOLYGON, MULTIPOINT o el genérico GEOMETRY) mediante la función de tabla mysql o los motores de tabla/base de datos MySQL. Ahora estas columnas se leen como Nullable(String), con el valor tal como lo devuelve MySQL (un prefijo SRID de 4 bytes seguido de la carga útil WKB). POINT sigue asignándose a Nullable(Point). #110943 (groeneai).
  • Se corrigió la serialización Native de los contenedores SimpleAggregateFunction que incluyen estados de agregación versionados cuando se comunican con pares de versiones anteriores. #110997 (groeneai).
  • Se corrigió el error CANNOT_CONVERT_TYPE con constantes de tipo Variant (incluido Geometry) en consultas distribuidas y en consultas con réplicas paralelas. #111136 (fm4v).
  • Se corrigió un LOGICAL_ERROR (“Lambda resolved type … is not equal to type from actions DAG …”) que se producía cuando el cuerpo de la lambda de una función de orden superior es un if/multiIf con condición constante que combina una rama con un literal Bool y una rama de comparación UInt8, p. ej., arrayFilter(p -> multiIf(false, true, p = 'ALL'), ['ALL']). #111245 (groeneai).
  • Se corrigió un desbordamiento de entero con signo en toStartOfInterval con intervalos inferiores a un segundo: para valores DateTime64 situados a menos de un intervalo del límite inferior de Int64, el resultado redondeado se desbordaba silenciosamente y daba un valor positivo sin sentido; ahora la función lanza una excepción DECIMAL_OVERFLOW. #111370 (alexey-milovidov).
  • Se corrigió una excepción (CANNOT_CONVERT_TYPE o un error lógico) en consultas distribuidas que usan el combinador -Tuple con un modificador RESPECT NULLS / IGNORE NULLS dentro de combinadores anidados, p. ej., anyRespectNullsStateTuple(...) IGNORE NULLS. #111570 (alexey-milovidov).
  • Corrige un intento de análisis de texto de FixedString que dejaba bytes añadidos parcialmente en la columna cuando fallaba el análisis, lo que podía provocar un error lógico Sizes of nested column and null map of Nullable column are not equal durante la serialización de columnas Variant/Array/Nullable, o bien bytes desplazados en el resultado sin ningún aviso. #111908 (groeneai).
  • Corrige una excepción y la omisión silenciosa de datos al leer una subcolumna dinámica (una ruta dentro de una columna JSON o Dynamic) a través de una tabla Buffer. #111948 (alexey-milovidov).
  • Se corrigió la complejidad cuadrática de countSubstringsCaseInsensitiveUTF8, que hacía que la función tardara minutos en procesar un texto de unos pocos megabytes con muchas coincidencias. Ahora el desplazamiento en caracteres de cada coincidencia se calcula de forma incremental en lugar de volver a contarse desde el inicio de la fila. #112003 (groeneai).
  • Se corrigió un desbordamiento de entero con signo en la sobrecarga de tres argumentos de toStartOfInterval: con un argumento origin cercano al límite inferior de Int64, la función devolvía un valor desbordado en lugar de notificar un error. #112045 (alexey-milovidov).
  • Se prohíben los estados de agregación en los parámetros de funciones de tabla, ya que no son compatibles en absoluto. #112087 (PedroTadim).
  • Se corrigió que la función de tabla values representara como 1/0, en lugar de true/false, una constante Bool no literal (p. ej., CAST(true, 'Nullable(Bool)')) insertada en una columna String/textual. #112308 (yakov-olkhovskiy).
  • Corrige un error lógico (que provoca la interrupción en compilaciones de depuración y con sanitizador) al aplicar finalizeAggregation a una columna cuyos estados de agregación provienen de funciones distintas que comparten la representación del estado, pero cuyo resultado final es de tipos diferentes; por ejemplo, quantileState y quantilesState(0.9) combinados mediante un UNION o generados con arrayReduce. Ahora estas consultas generan un error normal en lugar de provocar un fallo. #112662 (zainulabidin302).
  • Se corrigió el análisis de enteros que no caben en el tipo de destino en Poco::NumberParser, que se utiliza para leer números JSON. Estos números se analizaban silenciosamente con un valor incorrecto (por ejemplo, 18446744073709551617 se convertía en 1) en lugar de rechazarse, y un número UInt64 superior al máximo de Int64 no se conservaba tras convertir el AST a JSON y viceversa. #112904 (alexey-milovidov).
  • Se corrigió que una constante Bool en el lado derecho de IN se convirtiera a '1'/'0' frente a un lado izquierdo de tipo String, en lugar de a los valores canónicos 'true'/'false' (ahora es coherente con CAST y con la función de tabla values). #113051 (yakov-olkhovskiy).
  • Corrige el formato inconsistente del AST de viewIfPermitted: afectaba a las funciones que normalmente se escriben como operador (p. ej., not) en la rama ELSE de la forma de función de tabla, y a la forma de expresión viewIfPermitted(...), que se formateaba incorrectamente con ELSE. #113652 (alexey-milovidov).
  • Se corrigen el comportamiento no definido y los resultados incorrectos de avg sobre Date/DateTime/DateTime64/Time/Time64: ahora el promedio se calcula de forma exacta en el espacio de enteros, lo que corrige tanto el desbordamiento en el límite de Int64 (UB, resultado incorrecto en x86) como la pérdida de precisión de Float64 por encima de 2^53 (visible a escala de nanosegundos). #113912 (alexey-milovidov).
  • Se corrige una fuga de memoria en el códec de compresión experimental SZ3: cuando la compresión de datos poco comprimibles o corruptos fallaba con una excepción, los búferes temporales de trabajo no se liberaban. #113916 (alexey-milovidov).
  • Se corrige que hasAny, hasAll, has, indexOf, mapContainsKey, mapContainsValue y mapContains devolvieran menos filas de las esperadas, o fallaran con TOO_LARGE_STRING_SIZE, al consultar un índice bloom_filter con una constante FixedString. El índice calculaba el hash de la forma rellenada de la constante, mientras que la función compara la forma sin relleno, por lo que se omitía un gránulo coincidente. #114089 (alexey-milovidov).
  • Se corrige que min y max sobre columnas DateTime64 devolvieran resultados incorrectos cuando la agregación se compila con JIT y los datos contienen marcas de tiempo anteriores a 1970. is_signed no estaba especializado para DateTime64 y Time64, que derivan de Decimal64, por lo que el código generado comparaba los recuentos de ticks como enteros sin signo, y una marca de tiempo anterior a 1970 ganaba en max y perdía en min. #114168 (groeneai).
  • Se corrige que arrayExists(x -> x = needle, arr) devolviera un resultado incorrecto, o fallara con TOO_LARGE_STRING_SIZE, cuando el elemento del array y el needle son de tipos de cadena distintos (por ejemplo, un needle String frente a un elemento Array(FixedString(N))). La optimización optimize_rewrite_array_exists_to_has, habilitada de forma predeterminada, reescribía dicha llamada como has, que, a diferencia de =, no compara con relleno de ceros. #114496 (groeneai).
  • Se corrige la evaluación del índice de texto del operador LIKE/ILIKE aplicado sobre contenedores Map o JSON. #114544 (ahmadov).
  • Se corrigieron el comportamiento no definido y los resultados incorrectos en los límites de quantile y quantiles para valores DateTime64 y Decimal anchos. #114919 (alexey-milovidov).
  • Se corrigió que if y multiIf devolvieran un valor positivo grande en lugar de uno negativo cuando una rama Time se combina con Time64, DateTime o DateTime64 y la expresión se compila con JIT. #115146 (groeneai).
  • Se corrigió que timezoneOffset (alias timeZoneOffset) devolviera un desplazamiento erróneo en exactamente un día para zonas horarias cuyo desplazamiento respecto a UTC difiere en un día completo del que tenían el 1970-01-01, como Pacific/Kiritimati y Pacific/Apia tras cruzar la línea internacional de cambio de fecha, y para la mayoría de las zonas antes de 1970. Esto también corrige parseDateTime, parseDateTimeOrNull, parseDateTime64, parseDateTimeInJodaSyntax, EXTRACT(TIMEZONE_HOUR / TIMEZONE_MINUTE ...), el %z de formatDateTime, toUTCTimestamp y fromUTCTimestamp, que utilizan dicho desplazamiento. #115332 (groeneai).
  • Se corrigió el error Code: 349. Cannot convert NULL value to non-Nullable type que se producía cuando un predicado has o notHas contenía un elemento de array NULL y la clave primaria era String, Array(String) o Map(String, String). También se corrigieron los resultados incorrectos que se obtenían cuando ese elemento era un Dynamic o Variant que contenía NULL. Ahora el NULL se descarta del conjunto durante el análisis de claves, como ya ocurría con otros tipos de clave. #115647 (groeneai).
  • Se corrigió un problema por el que cast_keep_nullable no conservaba la nulabilidad cuando el tipo de destino era LowCardinality. Al convertir un valor que admite NULL a LowCardinality(T), se lanzaba CANNOT_INSERT_NULL_IN_ORDINARY_COLUMN en lugar de obtenerse LowCardinality(Nullable(T)). #115851 (groeneai).

Correcciones de índices y de la caché de consultas

  • Se corrige la lectura de subcolumnas de una columna que tiene una expresión DEFAULT y no está materializada en una parte (p. ej., después de ALTER TABLE ADD COLUMN o durante ALTER TABLE MATERIALIZE COLUMN): la subcolumna se rellenaba con los valores predeterminados del tipo en lugar de con el resultado de evaluar la expresión DEFAULT, y las funciones de distancia vectorial transpuestas (cosineDistanceTransposed y otras) sobre dichas columnas QBit fallaban con el error SIZES_OF_ARRAYS_DONT_MATCH. #110636 (alexey-milovidov).
  • Se corrige la excepción Not-ready Set is passed as the second argument, que podía producirse cuando la construcción del conjunto de una subconsulta IN durante el análisis de la clave primaria fallaba de forma silenciosa (por ejemplo, por un tiempo de espera agotado de la subconsulta con overflow_mode = 'break'), lo que dejaba el conjunto sin construir de forma permanente para la canalización de la consulta. #107924 (alexey-milovidov).
  • Se corrige un SELECT que fallaba con NOT_FOUND_COLUMN_IN_BLOCK en una tabla con un índice de omisión de datos set cuando una política de filas la filtraba mediante una condición siempre verdadera combinada con una comprobación sobre una columna no indexada. #107971 (tiandiwonder).
  • getClientHTTPHeader ahora se trata correctamente como no determinista, por lo que la caché de resultados de consultas ya no reutiliza su resultado de forma indebida. #108029 (alexey-milovidov).
  • Se corrigen resultados erróneos que se producían cuando la caché de condiciones de consulta (use_query_condition_cache = 1) reutilizaba una exclusión de marcas derivada de índices de omisión para una consulta que ejecutaba un conjunto distinto de índices de omisión, por ejemplo con use_skip_indexes = 0, ignore_data_skipping_indices o un modo distinto de use_skip_indexes_for_disjunctions. Ahora, las entradas de caché derivadas de índices de omisión usan como clave el conjunto efectivo de índices de omisión ejecutados, mientras que las entradas a nivel de fila de la caché de condiciones de consulta siguen pudiendo reutilizarse en todos estos casos. #108548 (groeneai).
  • Se corrige un bloqueo por el que una consulta que leía a través de la caché del sistema de archivos podía seguir esperando una descarga en curso tras cancelarse con KILL QUERY, y por el que eliminar una vista materializada actualizable, o aplicarle SYSTEM STOP VIEW, se quedaba bloqueado si su actualización estaba atascada en dicha espera. #109116 (murphy-4o).
  • Se corrigen resultados de consulta erróneos causados por el índice de clave primaria al descartar incorrectamente gránulos en tablas con una columna de clave en orden inverso (DESC) cuando las partes no tienen marca final (granularidad no adaptativa, index_granularity_bytes = 0). #109901 (nihalzp).
  • Se corrigen el error lógico Expected CommonSubplanReferenceStep to reference CommonSubplanStep, el error Subplan cannot be used to build pipeline y el error lógico Trying to extract chunk from ChunkBuffer before all inputs are finished en IN (subquery) cuando la subconsulta contiene una subconsulta correlacionada y el conjunto se construye durante el análisis de índices. #110491 (alexey-milovidov).
  • Se corrige el error NOT_FOUND_COLUMN_IN_BLOCK en las funciones de distancia transpuestas sobre columnas QBit (como cosineDistanceTransposed) cuando se invocaban con un vector de referencia constante o procedente de una subconsulta escalar con las réplicas paralelas habilitadas. #110729 (alexey-milovidov).
  • Se corrige que el índice de texto no se utilizara cuando su expresión contenía una comparación con una cadena vacía, como arrayFilter(s -> s != '', ...), ya que el ajuste optimize_empty_string_comparisons reescribe la comparación como notEmpty solo en el lado de la consulta. #112115 (Ergus).
  • Ya no se eliminan columnas referenciadas tanto en las condiciones de filtro de PREWHERE como en las de WHERE, aunque se reescriban como una columna virtual de índice de texto. #114460 (ahmadov).
  • Se corrigió el error lógico Multi-block postings must be compressed en consultas sobre tablas con un índice de texto en el modo de aplicación diferida de posting-lists, cuando la consulta se cancelaba durante la lectura. #114636 (CurtizJ).
  • Se corrigieron resultados incorrectos cuando una cláusula WHERE contenía una expresión NULL dentro de un NOT, por ejemplo SELECT count() FROM t WHERE NOT (id >= 20 AND NULL). El análisis de índices consideraba que dicha condición era demostrablemente verdadera para todo el rango, por lo que se omitía el filtro: count() devolvía filas que la consulta rechaza, y ALTER TABLE ... DELETE con esa condición eliminaba filas que debería haber conservado. #115152 (groeneai).
  • Se corrigió un LOGICAL_ERROR (Join is supported only for pipelines with one output port) en un JOIN full_sorting_merge con query_plan_join_shard_by_pk_ranges habilitado cuando la poda deja sin ninguna parte a uno de los dos lados, ya sea por la clave primaria, por las estadísticas de columna o porque la tabla está vacía. #115352 (alexey-milovidov).
  • Se deshabilita la caché de condiciones de consulta para filtros sobre _part_starting_offset #115358 (azat).
  • Se corrigió LOGICAL_ERROR: Index with name auto_minmax_index_<column> already exists cuando una única sentencia ALTER TABLE combinaba RENAME COLUMN con otro comando, como MODIFY SETTING, en una tabla con índices minmax implícitos (add_minmax_index_for_numeric_columns y similares). Además, renombrar una columna simple ya no provoca que un DROP COLUMN posterior falle con UNKNOWN_IDENTIFIER, ni que un ADD COLUMN posterior quede sin su índice implícito. #116063 (groeneai).
  • Un patrón LIKE/NOT LIKE sin comodines (%, _) ahora utiliza un rango exacto de la clave primaria, por lo que lee el mismo número de gránulos que el predicado equivalente =/!=, en lugar de un rango de prefijo más amplio. #107077 (groeneai).
  • Se corrigieron un LOGICAL_ERROR (Invalid binary search result in MergeTreeSetIndex) y la falta de poda de índices en builds de release cuando una condición IN/NOT IN sobre la clave primaria envuelve la clave en intDiv por una constante y la clave es un entero sin signo cuyos valores cruzan el límite del tipo con signo resultante de intDiv (por ejemplo, intDiv(uint64_column, -9223372036854775807)). #107586 (groeneai).
  • Se corrigió que numericIndexedVectorPointwiseMultiply devolviera un resultado vacío al multiplicar por un vector de unos con una configuración de bits BSI diferente. #108027 (alexey-milovidov).
  • Se corrigió un desbordamiento de búfer en el heap al construir un índice de texto con positions = 1 sobre muchos tokens cortos distintos. #108659 (groeneai).
  • Se permite que las expresiones preprocessor y postprocessor de un índice de texto hagan referencia a columnas ALIAS. #110014 (Ergus).
  • Se omite la optimización de búsqueda vectorial cuando se usa LIMIT ... WITH TIES, ya que la optimización limita la búsqueda ANN a exactamente n candidatos y se descartan las filas empatadas con la n-ésima fila. #110453 (tamish560).
  • Se corrigió un problema por el que el índice de texto no se utilizaba para ILIKE cuando el índice se define sobre una expresión en lugar de una columna simple (por ejemplo, assumeNotNull(col) con un preprocesador lower(...)). Ahora estas consultas usan el índice en lugar de leer todos los gránulos. #110595 (ahmadov).
  • Se corrige un LOGICAL_ERROR (LazyMaterializingTransform: Number of rows in lazy chunk N does not match number of offsets M) que podía producirse en consultas de búsqueda vectorial con vector_search_with_rescoring = 1 combinadas con materialización diferida cuando había empates entre varias distancias. #111003 (groeneai).
  • Se rechazan los vectores cuya magnitud al cuadrado se desborda a infinito al usar un índice vector_similarity con cuantización i8 (anteriormente, estos vectores provocaban un comportamiento no definido en usearch y generaban datos basura sin ningún aviso). #111085 (groeneai).
  • Se corrigieron lecturas obsoletas en discos plain_rewritable con la caché de páginas habilitada. #111105 (Michicosun).
  • Se corrigieron resultados incorrectos de count() y filas descartadas cuando una clave String (o FixedString de menor longitud) o un índice de omisión minmax se filtraba mediante una comparación con una constante FixedString de mayor longitud, p. ej., toFixedString('abc', 257) = string_col. La poda por clave primaria y por minmax construía el rango a partir de la constante rellenada con NUL y omitía erróneamente gránulos que sí coincidían. #111106 (groeneai).
  • Se corrigió la lectura de archivos Parquet cuyo índice de offsets no comienza en la fila 0. Un archivo de este tipo podía hacer que el lector nativo de Parquet devolviera filas incorrectas o notificara LOGICAL_ERROR en lugar de INCORRECT_DATA. Ahora el índice de offsets se valida al leerse. #114530 (groeneai).

Correcciones de seguridad, acceso, copias de seguridad y restauración

  • RESTORE ahora ejecuta fsync sobre los archivos de las partes restauradas cuando la tabla de destino tiene fsync_after_insert habilitado, de modo que una parte restaurada resiste un corte de energía igual que una insertada. Anteriormente, los archivos restaurados solo se escribían y cerraban (nunca se ejecutaba fsync sobre ellos), por lo que un corte de energía justo después de que RESTORE devolviera RESTORED podía dejar las partes dañadas y la tabla vacía. #111378 (groeneai).
  • Se corrige un problema de seguridad por el cual un cliente TCP no autenticado podía sondear la existencia de tablas y el estado de replicación a través del puerto entre servidores. #99854 (tiandiwonder).
  • Se corrigió que DELETE FROM (eliminación ligera) requiriera el privilegio ALTER UPDATE además de ALTER DELETE. Un usuario al que solo se le haya concedido ALTER DELETE ahora puede ejecutar DELETE FROM, tal como indica la documentación. #107491 (tiandiwonder).
  • Se corrigió que CREATE TABLE ... AS SELECT en bases de datos Atomic dejara una tabla vacía cuando la consulta fallaba, por ejemplo, cuando el usuario no tiene acceso a una tabla referenciada desde una subconsulta. Anteriormente, al reintentar se informaba de que la tabla ya existía en lugar de mostrar el error original. Ahora la tabla se crea mediante una tabla temporal y solo se vuelve visible una vez que se ha llenado por completo. #108048 (alexey-milovidov).
  • Se corrigió un LOGICAL_ERROR (No available columns) al ejecutar SELECT count() (u otras consultas triviales) sobre una tabla en la que al usuario solo se le ha concedido acceso SELECT a una columna ALIAS. #108056 (alexey-milovidov).
  • Se corrige un problema por el cual solicitudes no autenticadas podían hacer que ClickHouse resolviera nombres de host proporcionados en encabezados de dirección de cliente redirigida. Ahora ClickHouse solo acepta direcciones IP numéricas en estos encabezados. Los valores no válidos se ignoran, sin resolución DNS, a efectos de atribuir cuotas por dirección redirigida. Cuando auth_use_forwarded_address está habilitado, las direcciones redirigidas no válidas se rechazan durante la autenticación. Los rechazos se registran en el log con nivel de depuración. #111060 (otselnik).
  • Se corrige que SQL SECURITY DEFINER (y SQL SECURITY NONE) no se respetaran en las vistas parametrizadas cuando el analizador está deshabilitado (enable_analyzer = 0). Anteriormente, consultar una vista de este tipo como usuario sin privilegios sobre la tabla subyacente fallaba con ACCESS_DENIED, aunque la misma vista funciona con el analizador habilitado. #111458 (groeneai).
  • Se corrigió un defecto en las integraciones de MySQL por el cual se aceptaba sobrescribir una credencial TLS de una colección con nombre con un valor vacío de ssl_ca_pem/ssl_cert_pem/ssl_key_pem cuando la colección almacenaba la credencial como contenido, lo que descartaba silenciosamente la CA o el certificado de cliente configurados en lugar de rechazar la sobrescritura. #113947 (alexey-milovidov).
  • Se corrigió que EXPLAIN ANALYZE perdiera las estadísticas de unión de una vista declarada con SQL SECURITY DEFINER o SQL SECURITY NONE cuyo cuerpo contiene un JOIN. En las compilaciones de depuración y con sanitizers, la consulta se abortaba con el error lógico JoinStep analyzed without the analyze mode. #115156 (groeneai).
  • Se corrige que RESTORE ... AS <new name> dejara la lista REFRESH ... DEPENDS ON de una vista materializada actualizable apuntando a la base de datos original. La vista restaurada se actualizaba en respuesta a una tabla que ya no leía, ignoraba las actualizaciones de su propia tabla padre y dejaba de actualizarse por completo en cuanto se eliminaba la base de datos original. #115689 (groeneai).
  • Se corrigió una excepción LOGICAL_ERROR durante la copia de seguridad de una base de datos Replicated que se estaba eliminando y recreando de forma concurrente; ahora estas copias de seguridad fallan de forma controlada con CANNOT_GET_REPLICATED_DATABASE_SNAPSHOT. #100651 (alexey-milovidov).
  • GRANT role TO role sobre el mismo rol ahora se rechaza con BAD_ARGUMENTS, en lugar de crear silenciosamente una entrada autorreferencial en system.role_grants. #103315 (zxuhan).
  • BACKUP de una base de datos MaterializedPostgreSQL ya no se queda bloqueado indefinidamente con “Table … were created or changed its definition during scanning” y ahora sí realiza la copia de seguridad de los datos de la tabla (delegándola en el ReplacingMergeTree subyacente), que puede restaurarse como un ReplacingMergeTree independiente. #107433 (alexey-milovidov).
  • Se permite EXISTS <dictionary> a un usuario que solo tiene el privilegio SHOW DICTIONARIES sobre el diccionario (antes se requería SHOW TABLES). #108084 (alexey-milovidov).
  • Se corrigió la limpieza de un BACKUP ... TO Memory(...) que falla antes de finalizar: la copia de seguridad fallida permanecía registrada, por lo que su nombre no podía reutilizarse. #109947 (jkartseva).
  • Se corrigió un error lógico ReadBuffer is canceled. Can't read from it. (que abortaba el servidor en builds de depuración o con sanitizador) que podía producirse al leer un archivo zip (p. ej., durante un RESTORE desde una copia de seguridad en zip) después de que una lectura previa del mismo archivo fallara a mitad del flujo. #110197 (groeneai).
  • Se corrigió una corrupción del heap, que podía provocar el fallo del servidor durante el apagado, causada por que el método const AccessRights::getFilters modificaba un árbol de derechos de acceso compartido por consultas concurrentes. #112692 (groeneai).

Ejecución distribuida, tablas, vistas y diccionarios

  • Se corrigió un error espurio Inconsistent AST formatting en ALTER TABLE ... MOVE PART ... TO SHARD '<path>'. El formateador de consultas omitía la palabra clave SHARD, por lo que la consulta reformateada no podía volver a analizarse y se producía un LOGICAL_ERROR (una excepción gestionada en las builds de release y una interrupción en las builds de depuración y con sanitizadores). #109060 (groeneai).
  • Se corrigió un error lógico (!part.empty()) que se producía al usar en un JOIN con distributed_product_mode = 'local' una tabla Distributed definida con un nombre de base de datos remota vacío. #110677 (groeneai).
  • Se corrigió que DISTINCT con un LIMIT/OFFSET ordenado devolviera filas incorrectas cuando la pista de límite de detención anticipada de DISTINCT no podía acotar el inicio del resultado: un LIMIT negativo (devolvía el inicio en lugar del final), un LIMIT/OFFSET fraccionario (la fracción solo se resuelve tras una lectura completa) y un OFFSET sin LIMIT (se descartaba el final posterior al offset). Por ejemplo, SELECT DISTINCT intDiv(x, 100) FROM t ORDER BY intDiv(x, 100) LIMIT -1 sobre una tabla con varias partes devolvía el valor distinto más pequeño en lugar del más grande. #111326 (groeneai).
  • Corrige el caso en que el analizador no aceptaba un alias después de una subconsulta en DESCRIBE TABLE, lo que provocaba un error de sintaxis. Corrige https://github.com/ClickHouse/ClickHouse/issues/100031. #100205 (yariks5s).
  • Se corrigió una interrupción del servidor (Logical error: 'Block structure mismatch') que podía producirse durante un INSERT concurrente mientras se ejecutaba un ALTER RENAME COLUMN en una base de datos Atomic con lazy_load_tables = 1 después de DETACH DATABASE / ATTACH DATABASE. #104852 (groeneai).
  • Corrige la corrupción de nombres de columnas y la excepción BAD_ARGUMENTS causadas por el ajuste inject_random_order_for_select_without_order_by. Con el ajuste habilitado, los SELECT de varias columnas ya no fallan y los nombres de las columnas de salida (p. ej., en CREATE TABLE AS SELECT, CREATE VIEW AS SELECT o JSONEachRow) se conservan en lugar de sustituirse por alias internos __subquery_column_<UUID>. #105896 (groeneai).
  • Corrige la confusa pista “Maybe you meant X?” que aparecía tras reiniciar el servidor (o tras DETACH/ATTACH DATABASE): al intentar eliminar una tabla ya eliminada, se sugería como alternativa el mismo nombre recién eliminado. Ahora, las tareas de carga asíncrona se eliminan de DatabaseOrdinary::startup_table y load_table al desconectar la base de datos. #106238 (groeneai).
  • Corrige los motores de tabla y de base de datos MaterializedPostgreSQL para que una sola tabla o base de datos pueda replicarse desde un esquema de PostgreSQL distinto del predeterminado (materialized_postgresql_schema), incluido el caso en que existen tablas con el mismo nombre en varios esquemas de la misma base de datos (antes compartían una publicación y un slot de replicación, e interferían entre sí). #107425 (alexey-milovidov).
  • Se corrigieron los errores NO_SUCH_COLUMN_IN_TABLE cuando una consulta con réplicas paralelas selecciona una columna ALIAS de una tabla enviada como tabla temporal de GLOBAL JOIN; MULTIPLE_EXPRESSIONS_FOR_ALIAS cuando ambos lados de un JOIN distribuido declaran una columna ALIAS con el mismo nombre; y UNKNOWN_IDENTIFIER cuando una tabla Distributed declara una columna ALIAS basada en otra columna ALIAS, también cuando se usa como clave de JOIN USING. #107700 (yakov-olkhovskiy).
  • Se corrigió un desbordamiento de entero con signo cuando una vista materializada actualizable reintenta una actualización fallida con refresh_retries establecido en un valor muy grande (cercano al máximo de Int64). El desbordamiento podía provocar la terminación abrupta del servidor en builds con el sanitizador de comportamiento indefinido. #108005 (groeneai).
  • Se corrigió una excepción (CANNOT_PARSE_TEXT) al cargar un diccionario con una clave compuesta cuyas columnas de clave no son las primeras de la definición del diccionario, con una fuente local ClickHouse que usa una consulta explícita. Ahora las columnas de origen se asocian a la estructura del diccionario por nombre en lugar de por posición. #108053 (alexey-milovidov).
  • Se corrigió un fallo (desreferencia de puntero nulo) al consultar una tabla Hive sin cláusula WHERE, p. ej., SELECT * FROM hive_table. #108094 (alexey-milovidov).
  • Se corrigió un fallo del servidor (violación de segmento) que podía producirse cuando una consulta distribuida hacía referencia a un CTE MATERIALIZED aún no materializado como tabla externa y la fuente remota se creaba de forma diferida (fuente retrasada). El fallo se debía a la desreferencia de un Logger nulo dentro de RemoteQueryExecutor::sendExternalTables(). #108547 (groeneai).
  • Se corrigió un error lógico (Equal values are not contiguous within the range assumed to be sorted) al ejecutar DISTINCT sobre una lectura STREAM (SELECT DISTINCT ... FROM table STREAM). Las optimizaciones de lectura en orden ya no se aplican a las lecturas STREAM, que devuelven las filas en orden de confirmación y no según la clave de ordenación. #108568 (groeneai).
  • Se corrigió una excepción (Cannot find sharding key column y, en builds de depuración/sanitizador, la terminación abrupta del servidor) cuando la clave de sharding de una tabla Distributed es una expresión que el analizador pliega como constante, por ejemplo if(1, toInt32(id), toInt32(id) + 1), con optimize_skip_unused_shards = 1. #108737 (groeneai).
  • Se corrigió una terminación abrupta del servidor (LOGICAL_ERROR / aserción en builds de depuración y sanitizador) cuando un INSERT ... SELECT a través de una tabla Alias se cancela sin lanzar una excepción, por ejemplo con timeout_overflow_mode = 'break'. #108783 (groeneai).
  • Se corrigió una terminación abrupta del servidor (LOGICAL_ERROR / aserción en builds de depuración y sanitizador) cuando un INSERT ... SELECT en una tabla TimeSeries se cancela sin lanzar una excepción, por ejemplo con timeout_overflow_mode = 'break'. #108796 (tiandiwonder).
  • Se corrigió un problema por el que las consultas distribuidas fallaban ocasionalmente con UNEXPECTED_PACKET_FROM_SERVER (“expected TablesStatusResponse, got ProfileInfo”) al reutilizarse desde el pool una conexión que una consulta cancelada previamente había dejado desincronizada. #108854 (alexey-milovidov).
  • Se corrigió un LOGICAL_ERROR (CTE '...' does not have query tree, but was not planned yet) cuando se hace referencia a un CTE MATERIALIZED desde más de una posición del árbol de uniones (por ejemplo, dos subconsultas unidas, o una subconsulta unida más una subconsulta escalar en WHERE) en una consulta sobre una tabla Distributed. Ahora la consulta se ejecuta en lugar de lanzar la excepción (que provocaba la terminación abrupta del servidor en builds de depuración/sanitizador). #108924 (groeneai).
  • Corrige un problema de seguridad de memoria por el que el trabajo asíncrono programado desde el procesamiento de una vista materializada podía seguir usando la contabilidad a nivel de consulta después de que esta hubiera finalizado. #108988 (filimonov).
  • Corrige un LOGICAL_ERROR (“Cannot find __grouping_set column in header of MergingAggregatedTransform with grouping sets”, o “Chunk info was not set for chunk in MergingAggregatedTransform”) que podía producirse, sin el analizador, en un UNION ALL/INTERSECT/EXCEPT en el que una rama usa GROUP BY GROUPING SETS con réplicas paralelas y otra usa FINAL. #109003 (groeneai).
  • Corrige el fallo de CREATE TABLE ... AS SELECT FROM s3Cluster(...) (y de otras funciones de tabla de cluster como fileCluster/urlCluster) con NOT_FOUND_COLUMN_IN_BLOCK dentro de una base de datos Replicated. #109266 (groeneai).
  • Se corrigió un error (NOT_FOUND_COLUMN_IN_BLOCK, o std::bad_function_call en versiones anteriores) al ejecutar CREATE TABLE ... ON CLUSTER ... AS SELECT para leer una tabla Distributed en un cluster con dos o más shards. #109407 (alexey-milovidov).
  • Se corrigió un error interno confuso (Method getResultType is not supported for TABLE query tree node) que se producía al usar una expresión de tabla como argumento izquierdo del operador IN; ahora estas consultas devuelven un mensaje de error claro. #109412 (alexey-milovidov).
  • Corrige un error lógico Bad cast from type DB::FunctionNode to DB::ConstantNode (cierre abrupto del servidor en builds de depuración/sanitizador) al ejecutar SELECT ... ORDER BY ... WITH FILL sobre una tabla Distributed con un valor bajo de optimize_const_name_size. #109938 (groeneai).
  • Corrige un LOGICAL_ERROR (Left and right columns have same names) en el optimizador del orden de join que podía desencadenarse con una unión mediante coma sobre una vista de varias tablas cuando query_plan_merge_expression_into_join está habilitado. #110227 (groeneai).
  • Corrige un Logical error: 'No more packets are available.' poco frecuente que se generaba en una consulta distribuida válida con LIMIT y que provocaba el cierre abrupto del servidor en builds de depuración y con sanitizador. #110334 (groeneai).
  • Se corrigió un error del analizador sintáctico por el que COMMENT se interpretaba incorrectamente como alias implícito cuando una consulta SELECT terminaba justo después de un identificador de tabla sin más (p. ej., ... FROM t COMMENT 'x'), lo que provocaba un error de sintaxis engañoso en lugar de aplicar el comentario a la vista/tabla. #110372 (adityaksolves).
  • Se corrigió un resultado incorrecto por el que length() (y la dimensión de QBit) sobre una columna FixedString devolvía 0 en lugar del tamaño fijo N con réplicas paralelas cuando la consulta tenía un filtro selectivo. #110427 (groeneai).
  • Corrige el error NOT_FOUND_COLUMN_IN_BLOCK en consultas con una subconsulta en FROM cuando las réplicas paralelas se ejecutan en modo custom_key_sampling / custom_key_range. Hasta ahora, estas consultas (p. ej., SELECT * FROM (SELECT id, k, v FROM t WHERE id < 20) ORDER BY k) fallaban con Not found column __table2.id in block .... #110690 (groeneai).
  • Se corrige Logical error: 'clock' (en builds de depuración/sanitizer el servidor se cae; en builds de release se queda colgado indefinidamente) al ejecutar EXPLAIN ANALYZE sobre una consulta con una lectura en streaming (FROM ... STREAM) que no es una expresión de tabla simple de nivel superior: anidada en una subconsulta (por ejemplo, dentro de WHERE ... IN (...) o de una CTE), u oculta tras una vista ordinaria o parametrizada. EXPLAIN ANALYZE ahora rechaza estas consultas con NOT_IMPLEMENTED, igual que ya rechazaba una lectura en streaming de nivel superior. #110935 (groeneai).
  • Se corrige la resolución de nombres de columna completamente calificados, como db.table.column, en el analizador para tablas que tienen el mismo nombre que su base de datos. #110976 (alexey-milovidov).
  • Se corrigieron los errores NOT_FOUND_COLUMN_IN_BLOCK / THERE_IS_NO_COLUMN (y, en algunas versiones, resultados incorrectos sin ningún aviso) en un RIGHT JOIN cuando se establece parallel_replicas_min_number_of_rows_per_replica y se proyecta una columna de la tabla izquierda. #111332 (groeneai).
  • Se corrige una condición de carrera en las UDF ejecutables, el motor de tabla executable y los diccionarios ejecutables, en la que un fcntl sobre un descriptor de archivo ya cerrado podía corromper un descriptor ajeno perteneciente a una consulta concurrente (eliminando O_NONBLOCK), lo que podía dejar las consultas colgadas indefinidamente. #111779 (Algunenano).
  • Se corrigió un LOGICAL_ERROR (“Invalid number of rows in Chunk”) —y, en builds reforzados, una interrupción relacionada por acceso fuera de límites— en ORDER BY ... WITH FILL ... INTERPOLATE sobre una tabla Distributed con dos o más segmentos, sobre clusterAllReplicas o sobre réplicas paralelas con clave personalizada, incluso con resultados vacíos. WITH FILL ahora se aplica solo en el nodo que produce el resultado final, lo que además corrige la duplicación de las filas de relleno generadas entre segmentos/réplicas. #111919 (yakov-olkhovskiy).
  • Se corrigió que DROP TABLE ... SYNC se quedara colgado indefinidamente cuando una consulta sobre system.replicas se había terminado antes de que se procesaran sus solicitudes de estado. #112164 (evillique).
  • Se corrige una excepción LOGICAL_ERROR (Block structure mismatch in joined block stream) en una unión de varias tablas cuyas dos subuniones no producen ninguna columna de salida, por ejemplo SELECT count() FROM t1, t2, t3, t4 WHERE (t1.b = t2.b) AND (t3.a = t4.a) con query_plan_optimize_join_order_limit establecido en 0 o 1. #112205 (groeneai).
  • Se corrige un error lógico Cannot add step Expression to QueryPlan because it has incompatible header with root step JoinLazyColumnsStep en una consulta con FINAL, un filtro PREWHERE, un LIMIT pequeño y make_distributed_plan = 1, cuando las columnas seleccionadas se enumeran en un orden distinto al de las columnas de la tabla. La materialización diferida reemplazaba un nodo del plan sin conservar su encabezado de salida, lo que volvía inconsistente el plan de consulta. #112303 (groeneai).
  • Se corrigen resultados incorrectos y un error lógico cuando un argumento que debe ser constante, como la escala de toDecimal32 o la zona horaria de toDateTime, proviene de una subconsulta escalar y se utiliza el analizador antiguo. Dicho argumento se analizaba como si su valor fuera cero o vacío, por lo que el tipo de resultado declarado no coincidía con el valor calculado, y CREATE VIEW y CREATE MATERIALIZED VIEW guardaban un tipo de columna incorrecto. #112492 (groeneai).
  • Corrige un error lógico y un registro de dependencia incorrecto cuando el cuerpo de una VIEW ordinaria hace referencia a una tabla o diccionario mediante un parámetro de consulta, como en CREATE VIEW v AS SELECT x FROM {db:Identifier}.t. Este tipo de vista ya no registra una dependencia referencial con una tabla homónima de la base de datos actual, por lo que vuelve a ser posible eliminar tablas no relacionadas. #112704 (groeneai).
  • Corrige un error lógico cuando se usa una tabla con motor Join en el lado derecho de un JOIN cuya sección ON contiene una condición que hace referencia a columnas de ambas tablas, por ejemplo ON (t.key = j.key) AND (t.a < j.a). Ahora este tipo de consulta se rechaza con una excepción clara en lugar de generar required columns: ... but not found any in left table o std::bad_variant_access. #112815 (groeneai).
  • Se corrigió un comportamiento indefinido y un error silencioso de planificación cuando una tarea en segundo plano se programa con un retraso muy grande, por ejemplo, desde una vista materializada actualizable con un período REFRESH AFTER enorme. Ahora los retrasos se limitan al mayor valor representable en lugar de desbordarse. #113041 (groeneai).
  • Se corrigió el error que se notificaba cuando un INSERT asíncrono en una tabla Distributed necesita un directorio de cola cuyo nombre supera el límite de 255 bytes del sistema de archivos (algo que puede ocurrir con use_compact_format_in_distributed_parts_names = 0). Se producía un LOGICAL_ERROR en un shard con internal_replication y, en los demás casos, un Code: 1001. std::exception sin contexto; ahora ambos casos notifican ARGUMENT_OUT_OF_BOUND e indican la tabla, el clúster y el límite. #113083 (groeneai).
  • Ahora UNDROP TABLE puede interrumpirse con KILL QUERY mientras espera a que las consultas en ejecución liberen la tabla eliminada. #113263 (alexey-milovidov).
  • Se corrigió un bloqueo permanente de DROP TABLE y una fuga de memoria tras el fallo de una consulta que usaba un CTE materializado. La tabla quedaba atascada en la cola de eliminación hasta que se reiniciaba el servidor. #113397 (tiandiwonder).
  • Corrige un fallo de segmentación y un LOGICAL_ERROR (No host found for exchange stream final_result__0_0) cuando una subconsulta establece distributed_plan_execute_locally en su propia cláusula SETTINGS con make_distributed_plan. El plan distribuido y el código que lo ejecuta leían la configuración desde dos contextos distintos y podían no coincidir, de modo que el iniciador construía un pipeline contradictorio. #113422 (groeneai).
  • Se corrigió que un CREATE TABLE ... AS SELECT cuyo SELECT de llenado fallaba no pudiera terminarse cuando database_atomic_wait_for_drop_and_detach_synchronously está habilitado: el DROP interno de limpieza de la tabla temporal esperaba a la cola de eliminación en segundo plano e ignoraba tanto KILL QUERY como max_execution_time. #113504 (groeneai).
  • Corrige resultados incorrectos y, en compilaciones con aserciones habilitadas, un aborto por aserción en un JOIN con un diccionario cuya cláusula ON incluye una condición de no igualdad sobre ambas tablas, como ON (t.key = d.key) AND (t.a * 10 < d.a), cuando join_use_nulls está habilitado. La condición se evaluaba sobre una columna leída con un tipo que no correspondía, por lo que las filas podían coincidir de forma arbitraria. #113534 (alexey-milovidov).
  • Se corrigió un problema por el que una vista parametrizada perdía su base de datos cuando una consulta que la referenciaba sin calificar se enviaba a un segmento, de modo que el segmento resolvía el nombre en su propia base de datos predeterminada. Según lo que contuviera esa base de datos, la consulta fallaba con UNKNOWN_FUNCTION o devolvía silenciosamente filas de otra vista. Afecta a IN, JOIN y remote() a través de una tabla Distributed. #113550 (groeneai).
  • Se corrigió Unsupported JOIN keys of type keys256 in StorageJoin al leer una tabla con motor Join cuya clave es compuesta (varias columnas) o un único valor de 16/32 bytes, como UUID, Int256 o FixedString(4). Una tabla así podía crearse, recibir escrituras y usarse en uniones, pero nunca podía leerse con SELECT. #113578 (groeneai).
  • Se corrigió un error lógico Sending a distributed query with unknown (zero) client version que se producía al adjuntar una tabla Distributed sin estructura sobre un segmento remoto, o al cargarla a partir de metadatos escritos por una versión anterior del servidor. #113675 (alexey-milovidov).
  • Se corrigió un LOGICAL_ERROR que se producía cuando un SELECT usaba el modificador STREAM sobre una tabla con nombre junto con réplicas paralelas en el modo de tareas de lectura. Con un CTE materializado usado como conjunto IN en PREWHERE, el servidor generaba Reading from materialized CTE ... DelayedPortsProcessor gate is missing in the query plan (lo que provocaba un aborto del servidor en builds de depuración y con sanitizador). Ahora se rechaza una tabla con STREAM cuando se solicitan réplicas paralelas: con enable_parallel_replicas = 2, la consulta falla con SUPPORT_IS_DISABLED, y con 1 se ejecuta sin ellas, tal como ya ocurre con FINAL. #113754 (groeneai).
  • Se corrigió la complejidad cuadrática del análisis del argumento de dirección de las funciones de tabla remote, mysql y similares: una dirección muy larga (p. ej., un FixedString de un megabyte rellenado con ceros) hacía que la consulta se quedara bloqueada durante el análisis, fase en la que no podía cancelarse. #113918 (alexey-milovidov).
  • Se corrigió un error espurio Failed to drop temporary table after refresh. Table ... is left behind and requires manual cleanup. que se registraba cuando se cancelaba la actualización de una vista materializada actualizable (por ejemplo, por un apagado del servidor) con database_atomic_wait_for_drop_and_detach_synchronously habilitado. En realidad, la tabla temporal sí se eliminaba, por lo que nunca fue necesaria una limpieza manual. #113957 (groeneai).
  • Se corrigió la ausencia de una fila en system.query_views_log para una vista materializada que falla mientras se recopilan sus dependencias con materialized_views_ignore_errors habilitado. En builds de depuración y con sanitizador, esto además abortaba el servidor con std::out_of_range en lugar de registrar la vista. #114064 (groeneai).
  • Se corrigieron resultados inconsistentes cuando un filtro sobre una columna no clave de la tabla derecha se desplazaba por debajo de un ANY INNER JOIN. #114313 (kirillshokhin).
  • Se corrigió que CREATE OR REPLACE dejara huérfana una tabla interna _tmp_replace_* y que CREATE OR REPLACE VIEW fallara con NOT_IMPLEMENTED cuando se establecía ignore_drop_queries_probability. Los DROP que emite internamente forman parte de una única sentencia del usuario, por lo que la inyección de fallos en DROP ya no se les aplica. #114420 (groeneai).
  • Se corrigió un LOGICAL_ERROR al leer una tabla de Delta Lake cuyo metaData.partitionColumns hace referencia a una columna que metaData.schemaString no declara. Ahora estos metadata se rechazan con BAD_ARGUMENTS en el lector delta-kernel y con INCORRECT_DATA en el lector heredado siempre que la tabla o su esquema se lean desde una instantánea, y no solo cuando la consulta incluye un predicado. #114538 (groeneai).
  • Se corrigió un problema por el que las estadísticas de tablas hash —y, con ellas, la preasignación de tablas hash de agregación— quedaban deshabilitadas de forma silenciosa y permanente para todo el servidor cuando una consulta que usaba la optimización diferida de FINAL (query_plan_optimize_lazy_final) era la primera agregación ejecutada tras el inicio del servidor. #114597 (alexey-milovidov).
  • Se corrigió un problema por el que una vista materializada actualizable dejaba huérfana su tabla de destino rotada cuando ignore_drop_queries_probability estaba habilitado. El DROP que emite una actualización para limpiar el destino anterior forma parte de la propia actualización, no es un DROP solicitado por el usuario, por lo que la inyección de fallos ya no se le aplica. #114622 (groeneai).
  • Se corrigió un problema por el que ANY RIGHT JOIN y SEMI RIGHT JOIN con varias condiciones combinadas con OR en la sección ON devolvían algunas filas de la tabla derecha por duplicado y perdían las coincidencias de otras. Un ANY LEFT JOIN escrito explícitamente también se veía afectado, ya que el planificador puede intercambiar las tablas y ejecutarlo como ANY RIGHT JOIN. #114676 (vdimir).
  • Se corrige un LOGICAL_ERROR (Cannot find input column ... on its position in inputs of expression actions DAG) cuando una consulta tiene un JOIN sobre una tabla cuya columna con índice de texto se usa tanto en un predicado de búsqueda de texto de PREWHERE como en uno de WHERE. #114771 (groeneai).
  • Se corrige el error NOT_FOUND_COLUMN_IN_BLOCK que se producía en cada INSERT en una tabla que declara STATISTICS(...) sobre una columna ALIAS o EPHEMERAL, lo que dejaba dichas tablas en modo de solo lectura. #115231 (groeneai).
  • Se corrige dictGet y sus variantes en consultas distribuidas: ahora un nombre de diccionario no calificado se vincula a la base de datos actual del initiator, en lugar de resolverse con la base de datos actual de cada shard, donde o bien no se encontraba o bien se resolvía a otro diccionario con el mismo nombre. #115541 (alexey-milovidov).
  • Se corrigió un error por el que, al restaurar una base de datos o tabla con un nuevo nombre, se eliminaban los alias de tabla de los cuerpos de las vistas almacenadas, por lo que la lectura de una vista restaurada fallaba con UNKNOWN_IDENTIFIER. #115645 (groeneai).
  • Se corrige el LOGICAL_ERROR “Reading from materialized CTE ‘X’ before its materialization completed - DelayedPortsProcessor gate is missing in the query plan” cuando se lee una CTE MATERIALIZED desde una subconsulta IN sobre una tabla Distributed. #115740 (groeneai).
  • Se corrige el error BAD_ARGUMENTS “Dictionary not found” en dictGet tras un DETACH DICTIONARY … PERMANENTLY rechazado por la comprobación de dependencias (HAVE_DEPENDENT_OBJECTS). Ahora el diccionario sigue siendo plenamente utilizable cuando se rechaza el detach. #105259 (groeneai).
  • Se corrigió un Logical error: 'removed' (aborto del servidor en compilaciones de depuración) en la cola en segundo plano de eliminación de tablas. Podía producirse al reutilizar el mismo UUID explícito en varias consultas CREATE OR REPLACE TABLE, lo que añadía a la cola más de una tabla eliminada con ese mismo UUID. #107031 (groeneai).
  • Se corrigió que MaterializedPostgreSQL detuviera la replicación de toda una base de datos (con LOGICAL_ERROR: Columns number mismatch) cuando la estructura de una sola tabla replicada cambiaba mientras el servidor estaba detenido. Ahora solo se omite la tabla afectada, que puede recuperarse con DETACH/ATTACH. #107427 (alexey-milovidov).
  • Se corrigió un desequilibrio grave en el reparto del trabajo con réplicas paralelas cuando el cluster contiene réplicas inactivas (por ejemplo, entradas obsoletas que quedan tras el escalado automático). El coordinador de lectura ya no tiene en cuenta dichas réplicas, por lo que el trabajo se reparte entre las réplicas en línea en lugar de acumularse en una sola. #107805 (alexey-milovidov).
  • Se corrigió un bloqueo de SYSTEM RELOAD DICTIONARIES (y RELOAD DICTIONARY) cuando muchos diccionarios de MySQL definidos en XML compartían un único grupo de conexiones mediante share_connection. Ahora dichos grupos respetan los valores de connection_pool_size y connection_wait_timeout (5 segundos por defecto) de la configuración, igual que los diccionarios definidos mediante colecciones con nombre. #108083 (alexey-milovidov).
  • Se evita que, al agotarse los reintentos de un DDL distribuido replicado ejecutado por el líder, se bloqueen de forma permanente las consultas DDL ON CLUSTER posteriores. #108505 (ahaanlimaye).
  • Se corrigió un posible fallo (use-after-free) cuando SYSTEM FLUSH DISTRIBUTED se ejecuta simultáneamente con DROP TABLE sobre la misma tabla Distributed. #108684 (groeneai).
  • Se corrigió un LOGICAL_ERROR (local_replica_plan_reading_step->getAnalyzedResult() == nullptr) en el planificador automático de réplicas paralelas que podía producirse al habilitar automatic_parallel_replicas_mode junto con un valor de parallel_replicas_min_number_of_rows_per_replica mayor que 0. #109011 (groeneai).
  • Se corrigió un LOGICAL_ERROR (creation_csn is not set while removal_csn is set to 1) que podía producirse cuando un TRUNCATE no transaccional se ejecutaba simultáneamente con una transacción sin commit que había insertado datos en la misma tabla. Dicho TRUNCATE ya no elimina las partes creadas por transacciones que aún no han hecho commit. #109598 (tuanpach).
  • Los motores de base de datos externos (p. ej., PostgreSQL) ya no delegan las comparaciones de rango (>=, >, <=, <) sobre columnas UUID. ClickHouse y las bases de datos externas ordenan los UUID de forma distinta, por lo que delegar estas comparaciones descartaba silenciosamente filas del resultado; ahora es ClickHouse quien evalúa dichos predicados. #109833 (vismaytiwari).
  • Se corrigió un fallo del servidor en el motor de base de datos MaterializedPostgreSQL que podía producirse al desvincular una tabla (o cambiar su estructura) mientras aún estaba en cola para sincronizarse. #110596 (alexey-milovidov).
  • Se corrigió que las query_masking_rules del servidor reescribieran el tipo de una columna EPHEMERAL. Una regla que coincidía dentro del tipo hacía que CREATE TABLE almacenara un tipo incorrecto o fallara. #112048 (alexey-milovidov).
  • Corrige un desbordamiento por debajo (underflow) sin signo en la comprobación de la longitud del nombre de tabla que permitía crear una tabla que luego era imposible eliminar. Cuando el nombre escapado de la base de datos alcanzaba los 214 bytes, el límite calculado para el nombre de archivo metadata_dropped se desbordaba, por lo que CREATE TABLE se aceptaba y el posterior DROP TABLE o DROP DATABASE fallaba con File name too long. Ahora ese nombre se rechaza con ARGUMENT_OUT_OF_BOUND, el mismo error que ya se devolvía justo por debajo de ese límite. #112527 (groeneai).
  • Se corrigió que RENAME TABLE comprobara la longitud máxima del nombre de tabla con respecto a la base de datos de origen en lugar de la de destino. Al renombrar una tabla para moverla a una base de datos con un nombre largo, se podía obtener una tabla que DROP TABLE no podía eliminar, y al moverla fuera de dicha base de datos, la operación se rechazaba erróneamente. #113019 (groeneai).
  • Corrige la columna views de query_log, que siempre quedaba vacía en las inserciones en una tabla Alias cuyo destino dispara vistas materializadas. #113076 (eclbg).
  • Las expresiones parallel_replicas_custom_key no válidas, como tuple() o (x, y), ahora se rechazan con ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER en lugar de leer más allá de la lista de tipos de la clave personalizada. #113359 (nickitat).
  • Se corrigió que RENAME DATABASE aceptara un nombre de destino lo bastante largo como para que las tablas de la base de datos ya no pudieran eliminarse. La comprobación de la longitud del nombre de tabla ahora se ejecuta independientemente de check_table_dependencies y abarca también las tablas desacopladas (detached), que nunca se comprobaban y, por tanto, se veían afectadas incluso con la configuración predeterminada. #113557 (groeneai).
  • Al usar inserciones en segundo plano en tablas con el motor Distributed, los retrasos causados por errores repetidos al enviar datos a shards remotos ahora disminuyen una vez que los errores se resuelven. Antes, el retraso solo aumentaba y nunca se restablecía. #87378 (Blackmorse).
  • Se rechazan los handshakes del protocolo nativo que usan USER_INTERSERVER_MARKER para un cluster desconocido o para un cluster configurado sin <secret>. Antes, un handshake de este tipo permitía que un cliente no autenticado entrara en modo entre servidores y utilizara paquetes del protocolo previos a la autenticación (p. ej., TablesStatusRequest) respaldados por un fake_interserver_context, con lo que podía obtener información sobre las tablas locales sin demostrar que conocía el secreto del cluster. #99675 (MillaFleurs).

Correcciones de SQL, del analizador y de JOIN

  • Se corrige la sustitución de parámetros de consulta dentro de las definiciones de una cláusula WINDOW con nombre. Anteriormente, esos parámetros se quedaban sin sustituir sin ningún aviso, y un parámetro Identifier sin asignar podía provocar la excepción Logical error: '!part.empty()' durante EXPLAIN SYNTAX. #110506 (alexey-milovidov).
  • Se corrige un fallo poco frecuente del servidor al eliminar o reemplazar de forma concurrente vistas materializadas actualizables. Se desreferenciaba un puntero nulo en RefreshTask::doScheduling cuando otro hilo establecía la view de la tarea en nullptr mientras el código de planificación había liberado temporalmente su mutex. #105588 (groeneai).
  • Se corrige un resultado incorrecto de una vista definida con EXCEPT o INTERSECT cuyo operando es una cadena UNION tras DETACH/ATTACH o un reinicio del servidor. El formateador omitía los paréntesis alrededor de los hijos UNION de INTERSECT/EXCEPT, por lo que el SQL almacenado se volvía a analizar con la precedencia invertida. #105935 (groeneai).
  • Se corrigen resultados incorrectos (filas duplicadas) en SELECT DISTINCT sobre un GROUP BY con WITH CUBE, WITH ROLLUP o GROUPING SETS sobre las mismas claves. La optimización query_plan_remove_redundant_distinct ya no elimina el DISTINCT en estos casos, ya que los modificadores de agrupación emiten filas adicionales con las columnas clave en sus valores predeterminados, que pueden coincidir con valores reales de grupo. #107072 (groeneai).
  • Se corrige un resultado incorrecto en un OUTER JOIN cuando el filtro WHERE es una conjunción que contiene un término constante (por ejemplo, p AND 1, o WHERE p QUALIFY NULL, donde QUALIFY NULL se fusiona en WHERE). El término constante de la conjunción podía trasladarse al lado no preservado de la unión y eliminarse del filtro posterior a la unión, de modo que la unión producía filas sin coincidencia con las columnas de ese lado en sus valores predeterminados, y dichas filas superaban el filtro de forma incorrecta. #107084 (groeneai).
  • Se corrige un LOGICAL_ERROR (“Cannot find input column … on its position in inputs of expression actions DAG”) que abortaba el servidor en una subconsulta escalar correlacionada sobre un origen que proyectaba dos veces el mismo identificador de columna (p. ej., SELECT number, *) cuando correlated_subqueries_default_join_kind = 'left'. #107112 (groeneai).
  • Se corrige un LOGICAL_ERROR (aborto del servidor en compilaciones de depuración/sanitizer) cuando un JOIN utiliza el operador de comparación segura frente a NULL (<=> / IS NOT DISTINCT FROM) y una de las claves es una subconsulta escalar, p. ej., ... JOIN t2 ON (SELECT x FROM t1) <=> t2.k, con el analizador antiguo (enable_analyzer = 0). Ahora, una consulta de este tipo devuelve un error NOT_FOUND_COLUMN_IN_BLOCK normal en lugar de un error lógico. #108123 (groeneai).
  • Se corrigen las excepciones LOGICAL_ERROR (Join is supported only for pipelines with one output port) y NOT_IMPLEMENTED (MergeJoinAlgorithm is not implemented for strictness Semi) que se producían al usar join_algorithm = 'full_sorting_merge' en una unión SEMI/ANTI, incluidas las uniones generadas al descorrelacionar una subconsulta correlacionada EXISTS. Ahora, full_sorting_merge rechaza las combinaciones de estrictez/tipo que no puede ejecutar, de modo que el planificador recurre a otro algoritmo habilitado o informa de que la unión no puede ejecutarse. #108658 (groeneai).
  • Se corrigió un error por el cual la fila WITH TOTALS de un JOIN podía contener valores predeterminados (como 0) en lugar de los valores constantes procedentes de una subconsulta constante en uno de los lados de la unión. El resultado incorrecto solo aparecía con determinados órdenes de unión o con el ajuste query_plan_join_swap_table. #108807 (vdimir).
  • Se corrigió una interrupción durante el arranque (Cannot allocate ThreadStack, EINVAL) en builds con glibc ejecutadas en CPU con un tamaño de pila de señales grande (por ejemplo, Intel Sapphire Rapids / Granite Rapids con un kernel compatible con AMX), en las que el tamaño de la pila alternativa de señales no se redondeaba al alza a un múltiplo del tamaño de página antes de llamar a aligned_alloc. #108813 (groeneai).
  • Se corrigió un error lógico Block structure mismatch in JoinStep (interrupción del servidor en builds de depuración/sanitizador) cuando una subconsulta correlacionada se descorrelaciona en una unión y la relación de origen contiene un mismo nombre de columna más de una vez, p. ej., WITH t AS (SELECT number, * FROM numbers(3)) SELECT *, (SELECT t.number WHERE t.number >= 0) FROM t con correlated_subqueries_default_join_kind = 'right'. #109114 (groeneai).
  • Se corrigió un problema por el que CREATE USER ... HOST LIKE 'a', 'b' (y el ALTER USER equivalente) conservaba silenciosamente solo el primer patrón. Ahora todos los patrones HOST LIKE especificados se almacenan en la lista de hosts permitidos del usuario. #109187 (groeneai).
  • Se corrigió un resultado inesperado de ANY JOIN con una condición ON constante (p. ej., t1 ANY INNER JOIN t2 ON 1): la consulta devolvía el producto cartesiano completo en lugar del resultado de la unión ANY #109207 (vdimir).
  • Se corrigió un problema por el que el límite global max_rows_in_join / max_bytes_in_join no se aplicaba en el algoritmo de unión parallel_hash, de modo que una consulta con join_overflow_mode = 'throw' podía finalizar sin errores en lugar de generar SET_SIZE_LIMIT_EXCEEDED. #109488 (m-selmi).
  • Se corrigió una pérdida silenciosa de datos cuando un INSERT ... VALUES dentro de un flujo de varias consultas va seguido de un comentario SQL final (por ejemplo, VALUES (1) -- comment) en la ruta de análisis de inserciones con datos en línea del lado del servidor (send_table_structure_on_insert_with_inline_data = 0). El comentario final se interpretaba como datos de fila más allá del ; de terminación, lo que provocaba que las consultas siguientes del flujo se omitieran silenciosamente. #109643 (groeneai).
  • Se corrigió el PREWHERE diferido con optimize_move_to_prewhere = 1 cuando PREWHERE se ejecuta después de FINAL: las condiciones WHERE ya no se adelantan a una ROW POLICY diferida, lo que podía alterar los resultados de las consultas. #109703 (yariks5s).
  • Se corrigió un LOGICAL_ERROR (query tree node does not have valid source node) que se producía cuando un CTE recursivo resolvía un identificador de un ámbito externo como columna correlacionada (con allow_experimental_correlated_subqueries = 1). Ahora estas consultas devuelven un error UNSUPPORTED_METHOD claro. #109863 (groeneai).
  • Se corrigió un desbordamiento de entero con signo cuando ORDER BY ... WITH FILL salta un hueco muy grande en una columna Int64/UInt64 (p. ej., un paso de 2 a través de un hueco cercano a 2^63). El desbordamiento provocaba un comportamiento indefinido con sanitizadores y se truncaba silenciosamente en las builds de release. #109937 (groeneai).
  • Se corrigió un error lógico Invalid number of rows in Chunk que se producía cuando el destino de INTERPOLATE es un alias de una columna WITH FILL con el analizador antiguo (enable_analyzer = 0). Ahora estas consultas se rechazan con un error claro INVALID_WITH_FILL_EXPRESSION. #110103 (groeneai).
  • Se corrige un error lógico (Unexpected number of columns in result sample block) que se producía cuando un filtro que contiene una subconsulta correlacionada (por ejemplo, exists((SELECT ...))) se optimiza con convert_query_to_cnf u optimize_and_compare_chain. #110187 (alexey-milovidov).
  • Una subconsulta EXISTS correlacionada anidada que hace referencia a una columna de un ámbito situado más allá de su consulta externa inmediata (saltándose un ámbito intermedio) ahora falla con un error claro NOT_IMPLEMENTED en lugar de un error interno NOT_FOUND_COLUMN_IN_BLOCK. #110310 (groeneai).
  • Se corrigieron resultados incorrectos de subconsultas escalares correlacionadas cuando la consulta externa tiene valores duplicados en la columna correlacionada y la subconsulta se descorrelaciona mediante la ruta de CROSS JOIN. Anteriormente, funciones de agregación como count() y sum() se multiplicaban por el número de duplicados. Esto afecta a la funcionalidad experimental allow_experimental_correlated_subqueries. #110311 (groeneai).
  • Se corrigió un problema por el que ORDER BY ... WITH FILL no respetaba max_execution_time y tardaba en cancelarse al generar un rango de relleno grande (especialmente con INTERPOLATE). #110332 (alexey-milovidov).
  • La optimización diferida de FINAL (query_plan_optimize_lazy_final, deshabilitada de forma predeterminada) ya no se aplica cuando la consulta lee en el orden de la clave de ordenación, ya que su plan de reemplazo no genera las filas en ese orden, mientras que el plan superior puede depender ya de él tras la optimización de lectura en orden, lo que podría dar lugar a resultados mal ordenados. Tampoco se aplica ya cuando unLIMIT menor que el número de filas a leer se aplica directamente al paso de lectura, en cuyo caso la pasada obligatoria de construcción del conjunto impediría la terminación anticipada. #110576 (KochetovNicolai).
  • El vaciado en segundo plano de una inserción asíncrona ahora se detiene de inmediato al terminarse con KILL QUERY; antes, el vaciado de una carga grande almacenada temporalmente en el búfer seguía analizándose hasta el final e ignoraba la cancelación. #110652 (tiandiwonder).
  • Se corrigieron resultados incorrectos de GROUP BY ... optimize_aggregation_in_order y DISTINCT ... optimize_distinct_in_order situados sobre una unión partial_merge. La optimización de lectura en orden se propagaba a través de PartialMergeJoin, que reordena su entrada izquierda por la join key y, por tanto, no conserva el orden original del flujo izquierdo, por lo que las filas se agrupaban incorrectamente. #110671 (groeneai).
  • Se corrige un caso en el que, al usar alias de columna de CTE con consultas INTERSECT o EXCEPT (p. ej., WITH t (a, b) AS (SELECT 1, 2 INTERSECT SELECT 1, 2) SELECT a, b FROM t), la consulta fallaba con el error UNKNOWN_IDENTIFIER. #110885 (yariks5s).
  • Se corrigió un LOGICAL_ERROR: ReadBuffer is canceled. Can't read from it. que podía producirse en una unión grace_hash cuando la lectura de bloques volcados a disco fallaba a mitad de proceso mientras varios hilos compartían el lector. #111056 (groeneai).
  • Corrige un error por el que la materialización de las columnas del lado derecho durante las *_hash JOINs utilizaba la zona horaria incorrecta. #111074 (yariks5s).
  • Corrige las sentencias CREATE con una cláusula COMMENT para que generen un error de sintaxis cuando falta el literal de cadena del comentario, en lugar de aceptar sin avisar una consulta mal analizada (p. ej., CREATE VIEW v COMMENT AS SELECT 1 ya no crea una vista sin comentario). #111159 (tiandiwonder).
  • Corrige un LOGICAL_ERROR (Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan) que se producía cuando una CTE materializada reutilizada (enable_materialized_cte) se leía en una rama cuya salida WITH TOTALS o extremes se descarta, incluidas la agregación externa, INSERT ... SELECT, las operaciones de conjuntos y EXPLAIN ANALYZE. #111194 (groeneai).
  • Corrige que join_algorithm = 'full_sorting_merge' rellenara las filas no unidas de un LEFT/RIGHT/FULL/ASOFJOIN con un cero literal en lugar del valor predeterminado del tipo de columna. En una columna Enum (cuyo valor predeterminado es su primer elemento, no 0), esto producía resultados incorrectos (un filtro sobre el valor de relleno descartaba las filas sin coincidencia, de modo que una unión externa se comportaba, sin avisar, como una interna) y un error UNKNOWN_ELEMENT_OF_ENUM al seleccionar la columna. #111197 (groeneai).
  • Corrige resultados incorrectos de SummingMergeTree (y CoalescingMergeTree) con FINAL cuando optimize_move_to_prewhere_if_final = 1 y la cláusula WHERE es una condición booleana implícita sobre una columna de la clave de ordenación (p. ej., WHERE k). La columna clave se devolvía sumada entre las partes no fusionadas en lugar de conservarse intacta. #111342 (groeneai).
  • Corrige un error lógico (Unexpected number of columns in result sample block) que podía producirse en un RIGHT/FULL JOIN cuando el lado izquierdo contiene una columna duplicada con el mismo nombre (por ejemplo, 1 AS b, 1 AS b) que persiste tras un UNION ALL. #111554 (groeneai).
  • Corrige un fallo del client al formatear una consulta EXECUTE AS cuyo AST tiene un hijo reemplazado (como hace el AST fuzzer). ASTExecuteAsQuery ahora es propietario de sus hijos target_user y subquery, en lugar de mantener punteros no propietarios a elementos de children. #111725 (groeneai).
  • Corrige resultados incorrectos cuando query_plan_join_swap_table intercambia un ANY JOIN con join_any_take_last_row = 1: ClickHouse ahora conserva el orden original de los lados de la unión para que ANY JOIN siga devolviendo la última fila coincidente. #112458 (vdimir).
  • Corrige la excepción Context has expired al usar getClientHTTPHeader dentro de una subconsulta. #112533 (alexey-milovidov).
  • Corrige resultados incorrectos en un JOIN cuya cláusula ON contiene una condición mixta, es decir, una condición residual de no igualdad entre ambos lados, como ON (t1.key = t2.key) AND (t1.a * 10 < t2.a). Solo la familia de algoritmos hash evalúa este tipo de condición, pero full_sorting_merge, partial_merge y la unión directa clave-valor declaraban poder ejecutar estas uniones y luego ignoraban sin avisar la condición residual, con lo que devolvían filas de más. Ahora las rechazan y, en su lugar, se utiliza un algoritmo hash. #112831 (groeneai).
  • Se corrigieron resultados incorrectos en una unión por coma o CROSS cuyo WHERE compara columnas de dos tablas mediante una expresión no determinista como rand. Una consulta de este tipo podía devolver filas que contradecían su propia cláusula WHERE, ya que, al reescribir la unión como una unión INNER, la expresión se trasladaba a la join key, donde se vuelve a evaluar para cada fila de cada lado. #112938 (groeneai).
  • Se corrigió una ralentización cuadrática al analizar una consulta PromQL con una larga secuencia final de caracteres no reconocidos (p. ej., un valor FixedString rellenado con bytes NUL): el análisis de una entrada no válida de un megabyte mantenía ocupado un hilo durante decenas de minutos y no se podía cancelar, porque se produce durante el análisis de la consulta. Ahora el analizador se detiene en el primer error. #112944 (alexey-milovidov).
  • Se corrigió que intDiv sobre una columna no constante con el divisor constante -1 desbordara silenciosamente la división del número con signo mínimo (p. ej., intDiv(-9223372036854775808, -1)) en lugar de lanzar la excepción ILLEGAL_DIVISION, como hacen las demás rutas de ejecución. Este desbordamiento silencioso también podía producir resultados incorrectos en ORDER BY/DISTINCT, porque la optimización de lectura en orden trata correctamente intDiv por una constante negativa como monótona, y el valor desbordado rompía el orden resultante. #113048 (alexey-milovidov).
  • Se corrigió el error UNKNOWN_IDENTIFIER con enable_analyzer = 0 cuando un WHERE hace referencia a una columna generada por untuple dentro de una subconsulta, por ejemplo SELECT t.keys FROM (SELECT untuple(arrayJoin(m)) AS t FROM ...) WHERE t.values > 0. La reescritura de enable_optimize_predicate_expression trasladaba dicho predicado a la subconsulta como un HAVING, donde el nombre todavía no existe. #113760 (groeneai).
  • Se corrigieron resultados incorrectos en JOIN con join_algorithm = 'partial_merge' cuando el lado derecho incluye totales: el lado derecho podía quedar sin fusionar, de modo que las uniones LEFT sustituían coincidencias reales por valores predeterminados y las uniones INNER/RIGHT no devolvían ninguna fila. En la ruta de filas no unidas de RIGHT/FULL, ese mismo estado desreferenciaba un puntero nulo, lo que provocaba la caída del servidor. #113936 (groeneai).
  • Se corrigieron resultados incorrectos en SELECT DISTINCT con un LIMIT que debe leer toda su entrada: LIMIT n WITH TIES descartaba filas empatadas, exact_rows_before_limit = 1 devolvía un rows_before_limit_at_least truncado y GROUP BY ... WITH TOTALS calculaba la fila de totales a partir de solo una parte inicial del flujo. #114025 (groeneai).
  • Se corrigió un LOGICAL_ERROR («Unexpected number of kept output positions after removing unused columns from ReadFromMergeTree») que generaba un SELECT ... FINAL cuyo PREWHERE usa una columna que FINAL necesita para la fusión (ver, is_deleted, sign) sin seleccionar dicha columna. #114746 (groeneai).
  • Se corrigió un problema de duración de vida en el vaciado de INSERT asíncronos, el procesamiento de vistas materializadas y EXPLAIN ANALYZE que podía provocar el acceso a un estado de seguimiento de consultas ya expirado. #114940 (azat).
  • Se corrigió que CREATE QUOTA y ALTER QUOTA descartaran silenciosamente todos los bloques FOR INTERVAL salvo el último cuando se omitía la coma que separa los intervalos. La sentencia se ejecutaba sin errores, pero no aplicaba ninguno de los límites anteriores. Ahora los intervalos vuelven a acumularse, como ocurría antes de 2020. #115320 (groeneai).
  • Se corrigió que randConstant devolviera dos valores distintos en una misma consulta cuando sus llamadas tenían alias diferentes. Según la documentación, randConstant mantiene un único valor durante toda la consulta, y SELECT randConstant() = randConstant() ya devolvía 1, pero al añadir alias, como en SELECT randConstant() AS a, randConstant() AS b, se obtenían dos valores sin relación entre sí. #115384 (alexey-milovidov).
  • Se corrigió que SELECT count() no terminara nunca, o devolviera un número de filas inventado, al leer un archivo MsgPack o ProtobufList corrupto. La ruta optimizada de optimize_count_from_files contaba filas sin exigir que la posición de lectura avanzara, de modo que un archivo ProtobufList de dos bytes generaba miles de millones de filas y la consulta nunca terminaba. Ahora este tipo de entrada se rechaza con el mismo error que produce la ruta de lectura ordinaria. #115884 (groeneai).
  • Se corrigió que broken_data_files en system.distribution_queue y la métrica BrokenDistributedFilesToInsert indicaran siempre 0: al escanear la cola de inserción asíncrona durante el inicio, DistributedAsyncInsertDirectoryQueue::initializeFilesFromDisk contabilizaba los bytes dañados, pero nunca incrementaba el contador de archivos dañados. #92124 (squalfof).

Otras correcciones de errores

  • Las consultas secundarias ejecutadas como parte de consultas internas ahora se registran como consultas internas. #108506 (mstetsyuk).
  • Se corrige que una columna DEFAULT ausente en una parte se rellenara con el valor predeterminado del tipo en lugar de con la expresión DEFAULT cuando la condición PREWHERE se dividía en varios pasos de lectura. #111795 (yariks5s).
  • Las cuotas con clave normalized_query_hash ahora contabilizan todos los recursos (read_rows, read_bytes, result_rows, result_bytes, execution_time, written_bytes, errors) por patrón de consulta, igual que los contadores de número de consultas, en lugar de imputarlos a un único bucket compartido por usuario. #107681 (alexey-milovidov).
  • Se corrige que connect_timeout y los tiempos de espera de lectura y escritura de MySQL no surtieran efecto: un intento de conexión a un servidor MySQL que no respondía podía quedarse bloqueado más de dos minutos incluso con connect_timeout = 1, porque las señales periódicas del perfilador de consultas por muestreo reiniciaban una y otra vez el plazo interno de sondeo del cliente de MySQL. #109592 (tiandiwonder).
  • Se corrige que el tiempo de espera de bloque de las inserciones en streaming (input_format_max_block_wait_ms) pudiera no expirar nunca mientras el perfilador de consultas estaba activo: el sondeo del descriptor de archivo se reiniciaba con el tiempo de espera completo tras cada señal del perfilador, por lo que una fuente de entrada bloqueada podía retrasar indefinidamente el vaciado del bloque parcial en lugar de vaciarlo al alcanzar el límite de espera. #109602 (tiandiwonder).
  • Se corrige un LOGICAL_ERROR (std::length_error) cuando una consulta con la configuración experimental make_distributed_plan = 1 usaba un valor muy grande de distributed_plan_default_reader_bucket_count o distributed_plan_default_shuffle_join_bucket_count. Ahora estos valores se rechazan con INVALID_SETTING_VALUE. #109770 (groeneai).
  • Se corrige distinct_overflow_mode = 'break': DISTINCT ahora devuelve el resultado parcial acumulado hasta el límite y deja de leer la fuente, tal como indica la documentación. Antes, el fragmento que superaba max_rows_in_distinct / max_bytes_in_distinct se descartaba (lo que producía resultados truncados o vacíos) y la consulta seguía leyendo e insertando en el conjunto hash hasta el final de la entrada, lo que podía acabar en MEMORY_LIMIT_EXCEEDED. #110075 (skuznetsov-clickhouse).
  • Se corrige que optimize_aggregation_in_order ignorara la cancelación de consultas. AggregatingInOrderTransform ahora comprueba si se ha cancelado la consulta mientras agrega un fragmento, de modo que una consulta detenida mediante KILL QUERY o por max_execution_time (con el valor predeterminado timeout_overflow_mode = 'throw') se detiene de inmediato en lugar de procesar el fragmento entero hasta el final. #110104 (groeneai).
  • Se corrige una terminación abrupta del servidor (en compilaciones de depuración y con sanitizador) cuando un valor de una fuente PostgreSQL de la familia mysql/postgresql/sqlite se leía en un tipo declarado al que no se puede convertir (por ejemplo, una columna text declarada como Int32). Ahora esta discrepancia de tipos se notifica como un error de consulta en lugar de detener el servidor. #110264 (groeneai).
  • Se corrige una terminación abrupta del servidor al analizar determinadas consultas PRQL (SET dialect = 'prql'). Un pánico dentro del compilador prqlc abortaba el proceso en lugar de notificarse como un error de consulta. #110316 (groeneai).
  • Se corrige NOT_FOUND_COLUMN_IN_BLOCK cuando una política de filas y additional_table_filters hacen referencia a una misma columna que la consulta no selecciona por ningún otro motivo. #111099 (groeneai).
  • Se corrigió un bloqueo en randChiSquared, randStudentT, randFisherF y randBinomial con parámetros extremos. La consulta no podía interrumpirse mediante max_execution_time ni KILL QUERY. Ahora estos parámetros se rechazan incluso cuando max_rand_distribution_parameter o max_rand_distribution_trials se establece en 0, y max_rand_distribution_trials ya no puede aumentarse por encima de su valor predeterminado de 10^9 para randBinomial. #111909 (alexey-milovidov).
  • Se corrige connection_pool_max_wait_ms para que su valor documentado y predeterminado, 0, signifique un tiempo de espera infinito. Una consulta que encontraba lleno el grupo de conexiones reintentaba en un bucle continuo, lo que consumía CPU y registraba No free connections in pool. Waiting 0 ms. en cada iteración. Ahora espera hasta que se devuelva una conexión al grupo. #112380 (groeneai).
  • Se corrige que replaceOne, replaceAll, replaceRegexpOne y replaceRegexpAll ignoraran max_execution_time y KILL QUERY. Ahora cada llamada comprueba si se ha solicitado la cancelación mientras se ejecuta, de modo que un reemplazo de larga duración sobre un valor grande o un gran número de filas se detiene en lugar de ocupar un hilo del servidor hasta finalizar. Una llamada de este tipo no tiene un resultado parcial que devolver, por lo que con timeout_overflow_mode = 'break' notifica el vencimiento del plazo como un error: siempre que se evalúa como constante y, en la canalización, cuando este punto de control se alcanza antes de la comprobación entre bloques del ejecutor, que sigue deteniendo la consulta de forma silenciosa. #112483 (groeneai).
  • Se corrigió que countSubstrings, countSubstringsCaseInsensitive y countSubstringsCaseInsensitiveUTF8 ignoraran KILL QUERY y max_execution_time: una llamada sobre muchas filas o con muchas coincidencias podía seguir ejecutándose durante minutos después de cancelar la consulta. #113369 (groeneai).
  • Se corrige un posible bloqueo de la consulta (durante receive_timeout segundos) cuando esta finaliza muy rápidamente en el initiator. #113551 (nickitat).
  • Se corrige que countMatches y countMatchesCaseInsensitive ignoraran max_execution_time y KILL QUERY al contar las coincidencias de un único valor grande, lo que mantenía en ejecución durante minutos una consulta ya cancelada. Con un argumento constante, la llamada se produce durante el análisis de la consulta, por lo que no existe ninguna canalización que pueda cancelarla. #113886 (groeneai).
  • Una consulta podía cancelarse hasta 1 ms antes de que transcurriera su max_execution_time y fallaba con el mensaje contradictorio Timeout exceeded: elapsed 999.672 ms, maximum: 1000 ms. #114559 (alexey-milovidov).
  • Se corrigió una lectura fuera de límites en pointInPolygon con un polígono constante cuyo cuadro delimitador no está acotado, por ejemplo, cuando una coordenada alcanza +-DBL_MAX. Ahora estos polígonos se rechazan con BAD_ARGUMENTS, y un polígono con un anillo vacío se trata como si no tuviera interior. Anteriormente, la consulta podía devolver un resultado incorrecto o provocar la terminación abrupta del servidor en compilaciones con hardening o sanitizadores habilitados. #115035 (groeneai).
  • Se corrige una condición de carrera que podía hacer que una consulta STREAM BOUNDED devolviera menos filas de las que se habían confirmado (committed) antes de su inicio; normalmente, ninguna. #115543 (alexey-milovidov).
  • Se corrige el error Unknown identifier que se producía durante la optimización del plan de consulta con make_distributed_plan = 1 cuando la columna de ordenación de una consulta con funciones de ventana pasa por un paso Expression que no la menciona. #115890 (groeneai).
  • Se corrigió que h3kRing, h3HexRing, h3Line y h3ToChildren ignoraran max_execution_time y KILL QUERY al expandir un bloque de filas. #115893 (alexey-milovidov).
  • Se corrige NOT_FOUND_COLUMN_IN_BLOCK en el lector nativo de Parquet V3 (tras una regresión previa) cuando un PREWHERE tenía conjunciones que compartían una expresión intermedia común. #107059 (groeneai).
  • Se corrige un bloqueo indefinido al escribir Parquet con output_format_parquet_parallel_encoding habilitado (el valor predeterminado) y max_threads mayor que 1. Si el codificador no lograba programar un thread adicional, su contador de threads activos sufría un subdesbordamiento y la escritura podía quedarse detenida de forma permanente en lugar de finalizar o informar de un error. #112959 (groeneai).
  • Se corrigió una asignación de memoria ilimitada al leer un archivo Parquet cuya metadata Thrift declara una longitud de contenedor o de cadena mayor que la propia metadata. Ahora dicha longitud se rechaza en lugar de reservar memoria para ella. #113212 (groeneai).
  • Se corrige una excepción std::out_of_range (Logical error: 'std::exception. Code: 1001, type: std::out_of_range', que además aborta el servidor en compilaciones de depuración y con sanitizador) en el lector de Parquet v3 cuando una columna necesaria solo para evaluar el filtro se programaba para decodificarse después de que su slot de salida ya se hubiera eliminado. #113956 (groeneai).
  • Se corrigen carreras de datos en los profile events y en el rastreador de memoria. #112466 (mstetsyuk).
  • Se corrige una posible carrera de datos en los profile events al usar la configuración trace_profile_events_list para escribir stack traces de determinados profile events en system.trace_log. #113553 (mstetsyuk).
  • Se corrigió que intDivOrNull, moduloOrNull y positiveModuloOrNull devolvieran 0 en lugar de NULL, y que intDivOrNull e intDivOrZero lanzaran una excepción en lugar de devolver NULL / 0, cuando la división provoca una excepción de coma flotante (división por cero o INT_MIN / -1), también con argumentos mixtos con signo/sin signo. #101976 (yariks5s).
  • Se corrigió IS DISTINCT FROM para valores Array y Map comparados con NULL. #103162 (ylw510).
  • Se corrigió groupConcat cuando se combinan las sintaxis paramétrica y de dos argumentos, por ejemplo groupConcat(',', 2)(x, '/'): el parámetro de límite de filas se descartaba silenciosamente, por lo que se devolvían todas las filas en lugar del número solicitado; ahora el delimitador del segundo argumento sobrescribe correctamente el parámetro. #104882 (yariks5s).
  • Se corrigen errores al usar CAST de unidades de intervalo menores a mayores. #105058 (yariks5s).
  • Se corrigió un error lógico (Assertion 'row < chunk.getNumRows()' failed) en consultas LIMIT ... WITH TIES que se ejecutan con la canalización de lectura en orden (optimize_read_in_order = 1 y read_in_order_use_virtual_row_per_block = 1). #105102 (groeneai).
  • Se corrigió Logical error: 'Pipeline stuck' en consultas que usan enable_sharding_aggregator = 1 junto con un UNION ALL y un max_streams_for_union_step menor que el ancho de la canalización. BufferedShardByHashTransform ahora finaliza los puertos de salida con la cola vacía en cuanto se agota su entrada, y sigue extrayendo datos de entrada cuando un puerto vacío solicitado no tiene nada que drenar, aunque una cola hermana haya alcanzado el límite de contrapresión. #106251 (groeneai).
  • Se corrigió que removeDirectory en discos de almacenamiento de objetos plain (como s3_plain) eliminara todos los archivos de un directorio no vacío como si se tratara de una eliminación recursiva. Ahora, intentar eliminar un directorio no vacío falla con CANNOT_RMDIR, y la eliminación recursiva gestiona el contenido de forma explícita. #106281 (RinChanNOWWW).
  • Se corrigió que las funciones definidas por el usuario executable_pool configuradas con <lifetime> no detectaran los cambios en el script subyacente. Anteriormente, solo SYSTEM RELOAD FUNCTIONS volvía a leer un script modificado; las recargas periódicas de <lifetime> seguían ejecutando la versión anterior. #107087 (groeneai).
  • Se corrigió una carrera de datos en el colector de trazas global del servidor entre un hilo de trabajo que iniciaba su profiler y el apagado del servidor. #107307 (groeneai).
  • Se corrigió una interrupción poco frecuente del servidor durante el apagado (std::future_error, “The associated promise has been destructed prior to the associated state becoming ready”) que se producía cuando una tarea programada mediante threadPoolCallbackRunnerUnsafe se descartaba de la cola del pool de hilos antes de ejecutarse. #107383 (groeneai).
  • Se corrigió un error lógico de FileLog (Last stored last_written_position in meta file ... is bigger than current last_written_pos) que podía producirse cuando un archivo supervisado se eliminaba y se volvía a crear reutilizando el mismo inodo. #107617 (groeneai).
  • Se corrigió que toTime64 y CAST(... AS Time64) no ajustaran los valores fuera de rango al rango de Time64 en los modos de desbordamiento saturate e ignore, lo que podía dar lugar a valores que se mostraban igual pero que, al compararse, resultaban distintos. #108028 (alexey-milovidov).
  • Se corrigió el tratamiento incorrecto de las aserciones de ancho cero (\b, ^, $) en las funciones de expresión regular de tipo “match all” extractAll, extractAllGroupsVertical, extractAllGroupsHorizontal, countMatches y splitByRegexp. Por ejemplo, extractAll('new york is the greatest', '\b(\w)') ahora devuelve correctamente la primera letra de cada palabra en lugar de todas las letras. #108047 (alexey-milovidov).
  • Se corrigieron resultados incorrectos al usar hasToken en índices de texto con un tokenizador distinto de splitByNonAlpha. #108066 (rschu1ze).
  • Se corrigió que toStartOfInterval y dateTrunc devolvieran un valor redondeado en lugar del inicio del intervalo que lo contiene cuando la entrada tiene una precisión mayor que la unidad del intervalo; por ejemplo, toStartOfInterval(toDateTime64('2023-10-09 10:11:12.000999', 6), INTERVAL 1 millisecond) devolvía 10:11:12.001 en lugar de 10:11:12.000. La sobrecarga con un origen explícito también se veía afectada. #108186 (yariks5s).
  • Se corrigieron replaceRegexpOne y replaceRegexpAll para que . coincida con caracteres de nueva línea de forma predeterminada, en coherencia con otras funciones de expresiones regulares. #108265 (linjiayu1025-collab).
  • Se corrige que las condiciones de las operaciones ligeras UPDATE/DELETE se evaluaran dos veces. #108323 (ofeliacode).
  • Se corrige arrayPartialSort() con un argumento de límite no constante. #108327 (vitlibar).
  • Se corrigió que las funciones de expresiones regulares (match, extract, extractAll, replaceRegexpOne, replaceRegexpAll, etc.) devolvieran resultados incorrectos sin avisar cuando el patrón contenía un byte NUL (\0). Ahora el NUL se trata como un byte literal ordinario, en coherencia con RE2. #108427 (alexey-milovidov).
  • Se corrige que changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecond sobre un argumento DateTime64(N) crearan la columna de resultado con la escala predeterminada fija (3) en lugar de N. Los valores se calculaban con escala N, pero el objeto de columna declaraba escala 3, lo que lo dejaba estructuralmente incoherente con su tipo. #108551 (groeneai).
  • Se corrige un LOGICAL_ERROR (“Trying to extract chunk from ChunkBuffer before all inputs are finished”) cuando una operación de conjuntos (INTERSECT / UNION ALL / EXCEPT) combina ramas que usan subconsultas correlacionadas y correlated_subqueries_default_join_kind = 'left'. #108554 (groeneai).
  • Se corrigieron errores de DateTime64 en changeYear, changeMonth, changeDay, changeHour, changeMinute y changeSecond: las entradas con precisión de nanosegundos (escala 9) ya no lanzan DECIMAL_OVERFLOW, y las entradas con fracciones de segundo anteriores a la época Unix ahora devuelven el segundo de calendario correcto. #108681 (takumihara).
  • Se evita una salida excesiva en el log del servidor y un mensaje de error desmesurado al compilar una expresión regular muy grande (por ejemplo, un patrón LIKE o match con cientos de miles de comodines); ahora estos patrones fallan con un error CANNOT_COMPILE_REGEXP claro. #108821 (Algunenano).
  • Se corrige que reinterpret(x, 'Decimal128(scale)') (y los tipos de destino Decimal32/Decimal64/Decimal256/DateTime64) produjera una columna de resultado cuya escala interna era la de origen en lugar de la escala de destino solicitada cuando el origen y el destino tenían el mismo tipo físico. Los valores eran correctos, pero el objeto de columna era estructuralmente incoherente con su tipo declarado. #108878 (groeneai).
  • Se corrigió un comportamiento no definido al convertir a cadena un tipo de paquete de protocolo fuera de rango (p. ej., en los mensajes de error “Unexpected packet from server” / “Received … packet”) en una conexión desincronizada o sometida a fuzzing. #108885 (groeneai).
  • Se corrige que changeYear/changeMonth/changeDay/changeHour/changeMinute/changeSecond sobre DateTime64(N) construyeran la columna de resultado con la escala predeterminada fija de 3 en lugar de N, y que timeSlots sobre DateTime64 ignorara la escala del argumento opcional Size en su tipo de retorno declarado. En ambos casos se producía una columna cuya escala física no coincidía con su tipo declarado, lo que provocaba un LOGICAL_ERROR (writeSlice expects same column types) cuando el resultado se pasaba a arrayPushBack/arrayPushFront/arrayConcat; además, timeSlots con la escala máxima en Size devolvía marcas de tiempo incorrectas. #108994 (groeneai).
  • Se corrigen los incrementos no monótonos de ProfileEvents #109180 (azat).
  • Se corrige que las proporciones de SAMPLE con un exponente cuya magnitud desborda Int32 (p. ej., SAMPLE 1e-3000000000) se trataran silenciosamente como SAMPLE 1. #109197 (Algunenano).
  • Se corrigieron dos errores en la ruta DateTime64 de toUTCTimestamp/fromUTCTimestamp (y sus alias to_utc_timestamp/from_utc_timestamp) y de toTime64. El primero, un desbordamiento de entero con signo cerca del límite de Int64 (ahora se calcula en Int128 y se acota al rango representable). El segundo, un resultado incorrecto para valores fraccionarios negativos cerca de un límite de desplazamiento de zona horaria: la separación de los segundos truncaba hacia cero, por lo que timezoneOffset() examinaba el segundo siguiente y podía situarse en el lado equivocado de un cambio de horario de verano o de desplazamiento. #109738 (groeneai).
  • Se corrigió un error lógico (column->size() == num_rows) cuando la expresión de filtro de una política de filas usa arrayJoin; ahora estos filtros se rechazan. #109753 (Algunenano).
  • Se corrigió que generateRandomStructure() generara ocasionalmente una cadena de estructura no válida con dos tipos de datos concatenados (por ejemplo, Decimal32(7)IPv4) cuando el anidamiento de tipos superaba el límite interno de profundidad, lo que impedía analizar el resultado. #109928 (groeneai).
  • Se corrigió la propagación de la configuración de la consulta en accurateCastOrDefault y la conservación de los NULL de origen codificados por Dynamic y Variant. #109946 (Avogar). #114912 (alexey-milovidov).
  • Se corrigen max_bytes_in_distinct y max_bytes_in_set: las claves de tipo cadena se almacenan en un arena que no se contabilizaba en las comprobaciones de límites, por lo que DISTINCT / IN sobre claves de tipo cadena podía retener memoria que superaba el límite de bytes en todo el volumen de las claves (sin cota en función de la longitud de la clave). Ahora los límites tienen en cuenta el arena, tal como indica su documentación; las consultas con claves de tipo cadena cercanas a un límite de bytes pueden alcanzarlo antes (como corresponde). #110120 (skuznetsov-clickhouse).
  • Se corrigió la lectura de archivos Npy con dimensiones internas de tamaño cero para que las filas materializadas y los resultados de count() optimizados y no optimizados coincidan. #110146 (qiuyanjun888).
  • Se corrige un error lógico (aborto del servidor en builds de depuración/sanitizer) cuando las funciones indexHint/ignore/isZeroOrNull reciben un argumento cuyo tipo se resuelve como Nothing, p. ej., dentro de expresiones como indexHint(assumeNotNull(materialize(NULL))). #110192 (groeneai).
  • Se corrige la lectura de archivos en discos plain_rewritable después de que una ruta existente se reescribiera con contenido de distinto tamaño: los metadatos en memoria conservaban el tamaño de archivo obsoleto, lo que podía hacer fallar las lecturas con UNEXPECTED_END_OF_FILE. #110304 (thevar1able).
  • Se rechazan los valores de vector_search_index_fetch_multiplier inferiores a 1.0 para evitar resultados vacíos en búsquedas ANN cuando el número calculado de elementos a recuperar se trunca a cero. #110452 (tamish560).
  • Se corrige un error esporádico Cannot parse string ... as UInt64 ... While executing ValuesBlockInputFormat que podía producirse al insertar valores cuyas expresiones contienen una conversión numérica como initializeAggregation('sumState', 0::UInt64). #110637 (groeneai).
  • Se corrige que readWKT rechazara cadenas WKT con espacios en blanco iniciales (p. ej., readWKT(' POINT(1 2)')), que sí aceptan los lectores tipados readWKTPoint/readWKTPolygon/… y la gramática WKT. #110706 (groeneai).
  • Se corrige un fallo del servidor (división entera por cero) al consumir una cuota con un intervalo de duración cero (por ejemplo, CREATE QUOTA q FOR INTERVAL 0 SECOND MAX queries = 1000). Ahora, al crear la cuota, se rechazan las duraciones de intervalo no positivas. #110846 (PedroTadim).
  • Se corrige un fallo en builds FIPS al usar una clave SSH Ed25519 (CREATE USER ... IDENTIFIED WITH ssh_key ... TYPE 'ssh-ed25519', o una clave de este tipo en users.xml). Ed25519 no está aprobado por FIPS, por lo que ahora estas claves se rechazan con un error LIBSSH_ERROR explícito. #110891 (thevar1able).
  • Las funciones de distancia transpuestas sobre QBit (cosineDistanceTransposed, L2DistanceTransposed, dotProductTransposed) ahora usan una reconstrucción acotada de baja precisión de un valor truncado a precision planos de bits, en lugar de reconstruirlo en la arista inferior de la celda gruesa (con los bits descartados rellenados con ceros). El relleno con ceros sesgaba todos los valores reconstruidos hacia cero y resultaba degenerado con baja precisión: para QBit(BFloat16) con precisión 1 solo se conserva el bit de signo, por lo que todos los valores se reconstruían como ±0.0 y la distancia era la misma constante para todas las filas, sin aportar ninguna información de ordenación. Ahora la reconstrucción depende de qué bits se descartan: los códigos Int8 sin procesar se reconstruyen en el centro de su celda (en línea con la reconstrucción Lloyd-Max que ya usaba la ruta ...TransposedQuantized); un valor de coma flotante con precisión 1 se convierte en una cuantización de signo propiamente dicha; un valor de coma flotante que conserva todo su exponente y descarta solo bits de la mantisa se reconstruye en el punto medio acotado dentro de su propia binada (mientras que un cero real o ±0.0 se mantiene exactamente en cero y la celda no finita se trata aparte para que ±inf siga siendo exactamente infinito; véase la nota siguiente sobre la celda ambigua de NaN); y mientras aún se truncan bits del exponente se mantiene la arista inferior acotada, de modo que una precision menor sacrifica exactitud a cambio de velocidad sin inflar una magnitud en varios órdenes. Los resultados de precisión completa no cambian. #110911 (alexey-milovidov).
  • Se corrige una lectura fuera de rango en el lector ORC nativo durante la inferencia de esquema de un archivo ORC corrupto cuyo árbol de tipos declara más columnas que codificaciones de columna hay en el pie de la franja. Ahora se rechaza con CANNOT_EXTRACT_TABLE_STRUCTURE en lugar de abortar el servidor en builds de depuración o con sanitizador. #110967 (groeneai).
  • Ahora cada clave SSH cuenta de forma individual para el límite max_authentication_methods_per_user, de modo que el límite se aplica de forma coherente independientemente de la sintaxis. Anteriormente, varias claves en un único método ssh_key contaban como una sola. #111181 (TheMC47).
  • Los catálogos REST de Iceberg ahora notifican las credenciales caducadas junto con el error subyacente, en lugar de devolver silenciosamente UNKNOWN_TABLE. #111379 (alesapin).
  • Se corrige que readWKTPoint/readWKT devolvieran coordenadas sin inicializar (escalar) o de la fila anterior (vectorizado) para un punto vacío con etiqueta de dimensión, como POINT M EMPTY. Estas entradas ahora se rechazan con CANNOT_PARSE_TEXT, de forma coherente con POINT EMPTY. #111517 (groeneai).
  • La creación de estadísticas minmax ahora emite una advertencia en lugar de lanzar una excepción. #111785 (hanfei1991).
  • randBinomial sigue pudiendo usarse con las probabilidades degeneradas 0 y 1 para cualquier número de ensayos. #112021 (alexey-milovidov).
  • Se corrige que system.s3_queue_settings mostrara valores incorrectos para bucketing_mode, partitioning_mode, partition_regex y partition_component. #112300 (bharatnc).
  • Ahora se indica la posición correcta de los errores en las consultas PromQL. #112494 (fallintoplace).
  • SYSTEM DISABLE FAILPOINT ahora rechaza los nombres de fail point inexistentes y genera BAD_ARGUMENTS, como ya hacía SYSTEM ENABLE FAILPOINT. Anteriormente, un nombre mal escrito devolvía un resultado correcto pero dejaba habilitado el fail point en cuestión, sin ninguna indicación de que no se había deshabilitado nada. #112680 (groeneai).
  • Se corrige una lectura con tipo incorrecto de una subcolumna de elemento Nested cuya columna se había eliminado y vuelto a añadir. Al seleccionar dicha subcolumna junto con su propia columna principal, se devolvía el elemento completo en la posición de la subcolumna mientras el bloque seguía declarando el tipo del elemento, lo que producía valores arbitrarios en las builds de release y un error lógico en las builds de depuración y con sanitizador. #112769 (groeneai).
  • Se rechazan las duraciones de PromQL cuyas unidades están repetidas o no están ordenadas de mayor a menor. #112954 (fallintoplace).
  • Se corrige un comportamiento no definido (puntero nulo pasado a memcpy) en replaceRegexpOne/replaceRegexpAll cuando la cadena de reemplazo sustituye un grupo de captura que no participó en la coincidencia, p. ej., replaceRegexpAll('abc', '(a)|(b)', '\\2'). #113012 (alexey-milovidov).
  • Se corrige una incompatibilidad por la que los índices de texto creados en ClickHouse 26.3 con el tokenizador unicode_word no podían cargarse en versiones posteriores #113061 (rschu1ze).
  • Se rechazan los puntos de código sustitutos de Unicode no válidos en las secuencias de escape de cadenas de PromQL. #113203 (fallintoplace).
  • Se rechazan las secuencias de escape entre delimitadores no válidas en las cadenas de PromQL. #113587 (fallintoplace).
  • Se corrige theilsU sobre una trama de ventana, que devolvía un valor arbitrario en lugar de 0 cuando el primer argumento era constante dentro de la trama. #113691 (alexey-milovidov).
  • Se corrigió el código de error notificado para algunas columnas mal formadas serializadas con Replicated y recibidas a través del protocolo nativo: ahora se rechazan con INCORRECT_DATA en lugar de LOGICAL_ERROR (que abortaba el servidor en compilaciones de depuración y con sanitizador). #114186 (Avogar).
  • Se corrigen los literales Time64 y las constantes de listas IN incorrectos, a menudo con el signo invertido, que se generaban cuando el reescalado de un Decimal64 de menor escala desbordaba Int64. Ahora dicha conversión notifica DECIMAL_OVERFLOW, en consonancia con la rama de DateTime64 y con CAST explícito. #114546 (groeneai).
  • Se admiten nombres de métricas y etiquetas entre comillas en los selectores de PromQL. #114551 (fallintoplace).
  • Se corrigió un problema por el que las tablas ReplicatedMergeTree permanecían indefinidamente en modo de solo lectura tras un intento fallido de inicio ejecutado a través del hilo de adjunción. El reintento de reinicio ahora se programa correctamente, lo que restablece la recuperación automática y sus comprobaciones de sesión. #114802 (azat).
  • timeSeriesRange y timeSeriesFromGrid lanzaban un falso DECIMAL_OVERFLOW para marcas de tiempo anteriores a 1970 porque las marcas de tiempo de inicio y fin se leían como valores sin signo. Además, para marcas de tiempo DateTime/UInt32, el paso se truncaba silenciosamente a sus 32 bits inferiores. Ahora todos los cálculos se realizan en Int64. #114815 (vitlibar).
  • Se corrigió una posible excepción en las inserciones asíncronas después de que una consulta fallara con MEMORY_LIMIT_EXCEEDED, y se corrigió async_insert_queue_flush_on_shutdown para que las inserciones en cola se vacíen durante el apagado del servidor. #114839 (azat).
  • Se corrigió una excepción out_of_range lanzada como error interno Code: 1001 cuando un patrón de sequenceMatch, sequenceCount o sequenceMatchEvents contenía el número de evento 0, por ejemplo sequenceMatch('(?0)'). Ahora dicho patrón se rechaza con BAD_ARGUMENTS. Una condición temporal que contenía únicamente un signo, como sequenceMatch('(?1)(?t>+)(?2)'), se trataba silenciosamente como (?t>0) y ahora se rechaza con SYNTAX_ERROR. #115056 (groeneai).
  • Se corrigió el mensaje de error de geoToH3, que indicaba una posición de argumento y un tipo incorrectos cuando una coordenada no era Float64. Con el valor predeterminado geotoh3_argument_order = 'lat_lon', el mensaje hacía referencia al otro argumento y mostraba el tipo de este. #115503 (groeneai).
  • Se corrigen caracteres de escape con barra invertida no válidos en los índices text, tokenbf_v1 y ngrambf_v1. #115634 (ahmadov).
  • Se corrige un problema por el que el servidor no podía iniciarse cuando la variable de entorno TZ estaba vacía. #68921 (ardenwick).
Última modificación el 14 de octubre de 2026