Backward Incompatible Changes
Data type changes
icebergHashandicebergBucketnow rejectInt128,UInt128,Int256,UInt256, andDecimal256arguments with an explicit error. Previously they silently truncated wider values and produced colliding hashes. The Iceberg spec only defines hashing for 32/64-bit integers and decimals with precision up to 38; cast toInt64orDecimal128to keep the previous behaviour for values that fit. #105866 (Algunenano).
Storage and index changes
- Reject nested Dynamic/Variant in min/max aggregates and minmax indexes. Previously only top-level Dynamic/Variant were checked. #105468 (Avogar).
- The default of the server setting
insert_deduplication_versionchanges fromcompatible_double_hashestonew_unified_hash. Insert deduplication now works on the whole inserted block (per insert) rather than per part/partition: a retry of the same insert is still deduplicated, but two different inserts that produce an identical part are no longer cross-deduplicated, and reordered inserts of the same rows are no longer deduplicated. Setinsert_deduplication_version = compatible_double_hashesto restore the previous behavior. Async-insert deduplication is also governed by the sync window undernew_unified_hash: both whether it is enabled (replicated_deduplication_window) and its retention (replicated_deduplication_window_seconds, default 1 hour) follow the sync settings, so*_for_async_insertsis legacy and applies only toold_separate_hashes/compatible_double_hashes. Instances upgrading directly from a release that defaulted toold_separate_hashesshould first run withcompatible_double_hashesuntil the longest relevant deduplication window has elapsed (includingreplicated_deduplication_window_for_async_inserts, default one week, if async inserts are used) before relying onnew_unified_hash. Async workloads switching fromcompatible_double_hashesshould first raisereplicated_deduplication_window[_seconds]to the async window (and run a full async window), quiesce async inserts, or stay oncompatible_double_hashes, becausenew_unified_hashno longer checks the longer-livedasync_blocksids. #107886 (CheSema). - Fix
hasTokenwith a separator-containing needle silently returning results via a text index instead of raisingBAD_ARGUMENTS. #108189 (Ergus).
Removed features
- Removed the obsolete
allow_experimental_query_deduplicationsetting and its unsupported experimental query-deduplication behavior. #99398 (devcrafter). ALTER TABLE ... REPLACE PARTITION ... FROM ...no longer silently drops the destination partition’s data when the source table has no parts in the requested partition. Previously such a request removed the destination partition and wrote nothing in its place. It is now rejected withBAD_ARGUMENTSby default. This is a backward incompatible change: aREPLACE PARTITIONfrom an empty source that used to succeed (clearing the destination) will now throw after upgrade. To restore the previous silent-clear behavior, set the new settingallow_replace_partition_from_empty_source = 1(per query or in the profile), or setcompatibilityto26.5or lower. To explicitly drop destination data, useALTER TABLE ... DROP PARTITION .... #104939 (groeneai).- Removed the experimental KQL (Kusto) functions
array_sort_ascandarray_sort_desc, and their SQL backendskql_array_sort_ascandkql_array_sort_desc. These functions were experimental, implemented with low quality, and the source of correctness and parser bugs. Queries using these names now returnUNKNOWN_FUNCTION. #108101 (groeneai).
New Features
Functions
- Added support for the PromQL
histogram_quantilefunction inprometheusQueryandprometheusQueryRangetable functions. This enables computing quantiles over classic Prometheus histogram buckets identified by thelelabel. #103477 (Yasumoto). - Added the
h3PolygonToCellsWithContainmentfunction, which supports center-based, fully-contained, and overlapping containment modes. #104455 (yousefQadry). - User can now specify an optional precision argument to the
formatReadableSize,formatReadableDecimalSizeandformatReadableQuantityfunctions, controlling the number of digits after the decimal point. Default is 2, preserving the prior behavior. #104648 (antoniofilipovic). - Added
min_byandmax_byaggregate aliases forargMinandargMax. #105712 (itsjoeoui).
SQL and query features
formatReadableTimeDeltanow accepts anINTERVALexpression of type other thanMonthandYearas input. #64315 (Beetelbrox).- Added the PNG output format support, allowing query output results to be directly rendered as PNG images. #74691 (m7kss1).
- Introduced a memory reservation feature for workloads. See the workload scheduling documentation. #82414 (serxa).
- Added
IPV4_PREFIX_BITSandIPV6_PREFIX_BITSoptions for quotas keyed byIP_ADDRESSorFORWARDED_IP_ADDRESS, allowing quota limits to be shared by IP subnet instead of applied to each full address separately. #89270 (adityachopra29). - Implement
ADD ENUM VALUESinALTER TABLEqueries to simplify appending new values to an existing Enum type without the need to specify all current Enum values again. #93830 (ilejn). - Add the
GeoJSONinput format for reading. #98124 (mneedham). - Added a postprocessor to the text index which transforms the tokens after tokenization. #98939 (Ergus).
- Added opt-in support for TTL nodes in ClickHouse Keeper. TTL nodes expire automatically after their configured lifetime and cannot have children. #100397 (scanhex12).
- Added token-position storage for text indexes to support exact
hasPhrasesearches. Enable thesupport_phrase_searchindex argument and theallow_experimental_text_index_phrase_searchMergeTreesetting. #103172 (ahmadov). - Add functions arrayTopK and arrayBottomK: -
arrayTopK(k, array)returns the K largest elements in descending order -arrayBottomK(k, array)returns the K smallest elements in ascending order. #104563 (vitlibar). - Add support for selecting columns by name pattern with
* LIKE '<pattern>'and* ILIKE '<pattern>', including qualified forms such astable.* LIKE '<pattern>'andtable.* ILIKE '<pattern>'.LIKEmatches column names case-sensitively,ILIKEcase-insensitively. #104569 (niyue). - Added continuous queries for
MergeTreetables using a sequence of snapshot reads. #105114 (Michicosun). - Added the
RowBinaryWithNamesAndTypesAndDefaultsformat to improve schema evolution support. #105736 (mzitnik). - Added functions for serving Mapbox Vector Tiles directly from SQL:
MVTEncodeGeomprojects a geometry into the pixel space of a slippy-map tile and clips it,MVTEncodeaggregates the projected geometries of a group into the binary bytes of a single-layer tile, andMVTBoundingBox/MVTBoundingBoxMercatorreturn the bounding box of a tile for restricting rows to it. Point, line and polygon geometry is supported. Also available under the PostGIS aliasesST_AsMVTGeomandST_AsMVT. #106107 (saarthak2002). - Added
LOCALTIMEandLOCALTIMESTAMP(SQL-standard / PostgreSQL syntax).LOCALTIMESTAMPis an alias fornow()(returnsDateTime);LOCALTIMEreturns the current time of day as aTimevalue. #106139 (thomas-cabral). - Added two new
load_balancingstrategies,hostname_longest_common_prefixandhostname_longest_common_suffix, which prefer the replica whose hostname shares the longest common prefix (respectively, suffix) with the initiator’s hostname. They are useful when the data center is encoded as a prefix or suffix of hostnames whose numeric segments have variable length, where the existingnearest_hostnameandhostname_levenshtein_distancestrategies pick the wrong replica. #107360 (den-crane). - New functions
quantizeBFloat16ToInt8anddequantizeInt8ToBFloat16: a scalar codec that compresses embedding components to 8-bit using a 256-level Gaussian Lloyd-Max quantizer, from which Int4/Int2/binary codes can be extracted by bit-truncation. #108102 (alexey-milovidov).
Table engines and storage
Settings and configuration
- Added a setting
output_format_always_write_decimal_point_in_float_and_decimalto always print a decimal point for floating-point andDecimalnumbers in text formats, even when the value is a whole number. For example, output1.instead of1. Disabled by default. #62614 (qoega). - Add a new immutable
MergeTreesettingallow_tuple_element_aggregation, disabled by default. When enabled,SummingMergeTree,AggregatingMergeTreeandCoalescingMergeTreerecursively flattenTuplecolumns and aggregate each leaf element independently during merges, exactly as if it were a top-level column —SummingMergeTreesums it,AggregatingMergeTreemerges its aggregate-function state, andCoalescingMergeTreekeeps its last non-NULL value. The setting must be specified at table creation time and is silently ignored by engines that do not support it. #98039 (JingYanchao). - Add output_format_float_precision setting to control the number of decimal digits in floating-point text output. #99721 (phulv94).
- Add
materialize_projections_on_insertandmaterialize_projections_on_mergeMergeTree table settings. Whenmaterialize_projections_on_insert = 0, INSERTs skip building projection parts, which improves insert throughput for tables with many projections. Whenmaterialize_projections_on_merge = 1, a merge rebuilds a projection that is missing from all of its source parts, so projections can be built during merges instead of on insert. Merges still combine only parts that share the same set of projections. #100993 (cwurm). - Added a new S3Queue setting after_processing_move_preserve_path. When enabled together with after_processing=‘move’ and after_processing_move_prefix, processed objects are moved while preserving their full source path under the destination prefix instead of being flattened to just the file name. #105354 (asya-ch).
- Added the
url_prefixandfull_url_prefixHTTP-handler configuration elements for matching all paths with a given prefix, plus expliciturl_regexp,full_url_regexp, andheaders_regexpelements. The legacy<url>regex:...</url>form remains supported. #107492 (vitlibar).
Authentication
- Add an optional
external_idcredential for S3 role-based access. #106941 (eliangidoni). - Added TLS client certificate information (subjects, serial number, issuer, and validity period) to the
system.session_logtable to improve observability of certificate-based authentication. #107679 (alexey-milovidov).
System tables
- Added the
system.iceberg_filestable, which exposes per-file metadata for Iceberg tables with one row per data or delete file in each table’s current snapshot. #104415 (asya-ch). - Added hypothetical (what-if) skip indexes. Use
CREATE HYPOTHETICAL INDEX ... ON t (expr) TYPE ...to define a session-scoped virtual skip index, thenEXPLAIN WHATIF SELECT ...to estimate its skip ratio and cost without materializing it. Defined indexes are visible in the newsystem.hypothetical_indexestable. #104608 (yariks5s). - Added system.constraints table that provides information about all CHECK and ASSUME constraints across all tables, including constraint name, type, and expression. #105337 (PedroTadim).
- Added a new system table
system.documentationthat collects the embedded reference documentation of the uniform components of the system (functions, table engines, data types, settings, formats, and others) into a single table, with the documentation rendered as Markdown. #107463 (alexey-milovidov).
Experimental Features
- Added the experimental
dphypjoin reordering algorithm for inner joins as an option for thequery_plan_optimize_join_order_algorithmsetting, and thequery_plan_optimize_join_order_max_searched_planssetting, which bounds the join-order search and falls back to the next algorithm in the chain when the bound is exceeded; set it to0to keep the previous unbounded search behavior. #98798 (davenger). - Added lazy posting list apply mode for the text index. When enabled via
SET allow_experimental_text_index_lazy_apply = 1andSET text_index_posting_list_apply_mode = 'lazy', posting lists are decoded on demand at packed-block granularity using a cursor-based approach instead of being fully materialized into Roaring Bitmaps, reducing memory usage and CPU time for selective text index queries. #100035 (fastio). - Allow for attaching prometheus handlers on the main http port with an optional prefix. #104975 (JTCunning).
- Added an experimental MergeTree setting
packed_skip_index_max_bytesthat bundles small skip-index substreams into a singleskp_idx.packedarchive per part, reducing inode pressure when many skip indices are defined on a table. The decision is per substream at write time: substreams whose serialized size stays under the threshold go into the archive, anything larger keeps the standaloneskp_idx_<name>.idx2/.mrk2layout. A single part can mix layouts. Full-text indices are not supported and are always per-file. Default is 0 (packing disabled). #105321 (Algunenano). - Support
Buffersserialization for WebAssembly UDFs usingABI BUFFERED_V1, and addwebassembly_udf_enable_fuelas a persisted WASM UDF function setting. #105574 (antonio2368). - Multi-stage distributed query execution: the planner splits the query plan into stages connected by scatter / broadcast / gather / shuffle exchanges and dispatches the plan fragments to worker nodes. The data between stages is streamed via TCP or passed via temporary files in shared object storage, the path supports distributed shuffle and broadcast hash joins, shuffle aggregation, and distributed sort. The feature is experimental and is disabled by default. #106020 (davenger).
- The experimental distributed query plan engine (
make_distributed_plan) can now use a different task-dispatch and streaming-exchange port per worker, configured per replica in<remote_servers>withstateless_worker_portandstreaming_exchange_port. When unset, the previous server-level ports (stateless_worker_client.portanddistributed_query.streaming_exchange_port) are used. This makes it possible to run several workers on one host. #107885 (davenger).
Performance Improvements
JOIN performance
- Implement lazy application of selector and replication indexes in case of JOIN followed by a selective LIMIT or TopN or another JOIN. To control the number of payload columns for enabling lazy selector indexes use the setting
query_plan_min_columns_for_join_lazy_indexing(0 means the optimization is disabled). To control the LIMIT for which the optimization is applied use the settingquery_plan_max_limit_for_join_lazy_indexing. #98883 (m-selmi). - Allow
ASOF JOINto use theparallel_hashjoin algorithm, parallelizing the build across distinct equality-key values. Previously ASOF was unconditionally opted out ofparallel_hash. #105375 (gregakinman). - Share the hash join’s FixedHashMap as the join runtime filter on the probe side. When the build-side hash table is (or can be converted to) a FixedHashMap, it is published as the runtime filter and replaces the
Set/BloomFilterthatBuildRuntimeFilterStepwould otherwise install. Controlled by the new settingenable_join_runtime_filter_shared_fixed_hash_table(defaulttrue). #105640 (wudidapaopao). - DP JOIN reordering is now allowed with parallel replicas. #105889 (nickitat).
- Improved query plan when JOIN uses runtime filters (default-on
enable_join_runtime_filters): the join-reorder cost model now sees throughWindowTransform(and other row-preserving plan steps) on the right subtree and uses the underlying row count and per-column NDV instead of falling back to no statistics. #107229 (UnamedRus).
Query optimization
- Improved performance of text index analysis in multi-token searches by optimizing handling of rare tokens. #98226 (CurtizJ).
- Improve performance of the
encrypt,decrypt, andhalfMD5functions by avoiding implicit per-row OpenSSL provider lookups in OpenSSL 3.x. #99105 (thevar1able). - Squash source blocks before
projection.calculate()duringMATERIALIZE PROJECTIONto reduce the number of temporary projection parts and merge overhead. ~3.4x speedup on a 50M-row table. #100047 (amosbird). - Users now profit from an improved performance of Approximate Runtime Filters and Bloom Filter Indices. #100201 (cv4g).
- Speed up
ORDER BY ... LIMIT BYqueries by runningLIMIT BYinside each parallel sorted stream duringSortwhenLIMIT BY’s columns are a prefix of theORDER BY. This reduces the number of rows flowing through the final sort merge and any downstream pipeline steps. This optimization is controlled by the new settingquery_plan_push_limit_by_into_sort(enabled by default). #104000 (nihalzp). - Reduce per-query overhead for simple SELECT queries (parsing, analysis and planning). For example,
SELECT count() FROM hitsfrom a single connection is roughly 50% faster. #104513 (Algunenano). - Improve performance of
bitmapContainsfor non-UInt64groupBitmapstates by avoiding repeatedrb_maxcalls during range checks. #105960 (niyue). - Improved insertion performance for
LowCardinalitycolumns withbloom_filterindexes. #106410 (EmeraldShift). - Improved performance of the
L2DistanceTransposedandcosineDistanceTransposedfunctions for theQBitdata type. #106701 (rienath). - Improve performance of query analysis for queries over tables with many columns: avoid computing column node hashes (which include the whole source table expression) when not needed. Analyzing nested
SELECT *subqueries over a table with ~1200 columns is now about 50 times faster. #106957 (novikd). - Improve performance of the
encrypt,decrypt,tryDecrypt,aes_encrypt_mysql, andaes_decrypt_mysqlfunctions by up to an order of magnitude, recovering the performance lost in the BoringSSL to OpenSSL 3.x migration (24.4). #107339 (thevar1able). - Improve execution of
arrayElementonArray(LowCardinality(String))and map LIKE functions on maps withLowCardinality(String)keys or values by avoiding unnecessary string materialization. #107450 (EmeraldShift). - Reduced CPU usage and improved skip-index evaluation performance for queries filtering
DateTime64columns. #107707 (shankar-iyer). - Improved the performance of case-insensitive substring searches, including
positionCaseInsensitiveUTF8,ILIKE, andmultiSearchAnyCaseInsensitiveUTF8. #107882 (Algunenano). - Fix a ~16% throughput regression of the
FPCfloating-point codec on ARM that was introduced when its predictor tables started usingVectorWithMemoryTracking. #108182 (groeneai). - Fixed a performance regression where a single lightweight
DELETEdisabled the query condition cache for the whole table. Repeated selective queries over a table that had ever been touched by a lightweight delete stopped pruning granules and fell back to reading every mark. #112947 (fm4v). - Bounded the cost of estimating the selectivity of
col IN (...)from column statistics, which could add hundreds of milliseconds to the planning of a single query. The estimator no longer runs the subquery behindcol IN (subquery)to fill a set it only needs one selectivity number from — an unbuilt set is skipped instead. For a set larger than the newstatistics_max_set_size_for_exact_selectivity_estimationsetting (default 10000), the selectivity is now derived from the size of the set and its bounding range. #114389 (nickitat).
Function and aggregation performance
- Optimize primary key index analysis for long and high-cardinality primary keys. For a long primary key, the run time of index analysis now mainly depends on the complexity of the query’s filter (the key columns it actually uses), not on the length of the primary key — so extending the sorting key has negligible extra overhead on index analysis for queries that filter on only a few of its columns. For a high-cardinality primary key, where ClickHouse keeps only a selective prefix of the key columns in memory and does not load the trailing ones, index analysis now works on just that in-memory prefix instead of the whole key. The optimization is enabled by default and can be turned off with the new setting
use_lightweight_primary_key_index_analysis. #91836 (nihalzp). - Reduced peak memory usage when merging partial two-level aggregation results with large aggregate states (e.g.
groupArray), by freeing each bucket’s source states incrementally during the merge instead of keeping them all alive until the merge completes. #102330 (yurifedoseev). - New
GROUP BYoptimization for high cardinality evenly distributed keys that scatters rows across threads by hashing the grouping key, so each thread aggregates a disjoint subset of keys without a merge phase. Setenable_sharding_aggregator = 1to enable it. #104233 (nihalzp). - Speed up
LIMIT BYqueries on partitionedMergeTreetables by runningLIMIT BYinside each partition’s stream in parallel, instead of merging all streams into one before applying the limit. This applies when the partition expression is a deterministic function of theLIMIT BYcolumns, so noLIMIT BYgroup can span two partitions. Controlled by the new settingallow_limit_by_partitions_independently(enabled by default). #105126 (nihalzp). - Speed up
SELECT ... LIMIT N BY <cols>queries when<cols>are a prefix of the table’s sorting key, or become one afterWHERE col = constfixes leading columns. With this enabled theMergeTreereads data in primary-key order andLIMIT BYfirst filters in streaming mode with O(1) memory per sorted stream which filters out most of the data, then finally running normalLIMIT BYon reduced data to get the final result. Controlled by the new settingoptimize_limit_by_in_order(enabled by default). #105135 (nihalzp). - Speed up
LIMIT BYqueries by removing redundant key expressions: a key that is a deterministic function of the other keys is dropped (e.g.LIMIT 5 BY x, f(x)becomesLIMIT 5 BY x), and an injective function of a key is replaced by its argument (e.g.LIMIT 5 BY toString(x)becomesLIMIT 5 BY x). This evaluates fewer and cheaper expressions per row. Controlled by the new settingsoptimize_limit_by_function_keysandoptimize_injective_functions_in_limit_by, both enabled by default. #106818 (nihalzp). - Sped up query analysis for queries with many or deeply nested function calls by removing a redundant query-tree hash from the function resolution cache. #107516 (novikd).
- Parallelize the processing of a recursive CTE’s result: a
GROUP BYor other operation over a largeWITH RECURSIVEresult is no longer limited to a single thread. #107694 (alexey-milovidov).
Storage and I/O performance
- S3 clients with the same endpoint and bucket share a cache, avoiding duplicate region discovery. #96802 (zvonand).
- Improved object-storage copy performance by copying blobs in parallel. #105089 (asya-ch).
- Avoid reading file contents when using the One input format with file-like table functions such as file and s3. #105157 (niyue).
- The
MergeTreeprimary key and skip indexes can now prune granules for filters whereifNullorcoalescewraps a condition, such asifNull(key = 0, 0)orcoalesce(key = 0, 0). Such predicates — often emitted by query generators to turn a possibly-NULLcomparison into a definite boolean — were previously opaque to index analysis and could not skip granules. This extends the existingallow_key_condition_coalesce_rewritesetting (enabled by default). #106272 (andyzzhao). - Improved decoding performance for
BYTE_STREAM_SPLIT-encoded ParquetFLOATandDOUBLEcolumns. #106376 (Algunenano). - Fixed long login and query-startup stalls with replicated access storage when many access entities (row policies, roles, quotas, settings profiles) change at once. Each per-entity cache now recomputes once per notification batch instead of once per changed entity, removing quadratic work that could hold the access lock for minutes. #107672 (azat).
- Fixed a performance regression where reading many small files from object storage via the
s3and other table functions stopped prefetching and fell back to synchronous reads, significantly slowing single-threaded or low-concurrency reads of many small files. #108872 (fm4v). - Enabled the initial small-object prefetch when object storage reads go through the filesystem cache (
filesystem_cache_name). Previously, reads of many small files, such asS3Queueingestion, remained synchronous and latency-bound when the filesystem cache was enabled. #109478 (fm4v). - Improved
PREWHEREoptimization forMapsubcolumns by accounting for their on-disk size. #110623 (Avogar). - Lazy materialization is now applied to queries with
FINAL, a filter, and a smallLIMIT, even withoutORDER BY(forReplacingMergeTree). #110722 (KochetovNicolai). - Reduced deduplication CPU time for asynchronous insert flushes that span many partitions. #111150 (valerypetrov).
- Fixed a CPU regression for queries that issue many independent small reads against the same
MergeTreepart when the table hasLowCardinalitycolumns. The check deciding whether a part has a single shared dictionary scanned every mark of the whole part on each read task; it now finds each run of equal marks by binary search instead. Queries of this shape on tables with a smallindex_granularitywere up to several times slower since 26.6. #116134 (groeneai).
Memory optimization
- Reduced the memory used by
Enumtype metadata by up to 10 times for tables withEnumcolumns. Value-to-name lookups remain similar or faster, while name-to-value lookups during parsing and deserialization can be slower. #95668 (qoega). - Reduced peak memory usage of
BACKUPby no longer copying the internal list of file infos when writing backup entries (significant for backups containing millions of files). #111162 (jkartseva).
Improvements
Query and SQL
- Identify columns by position (instead of by name) when removing unused columns in the query plan. This enables unused-column removal when duplicated column names are present. #100586 (antaljanosbenjamin).
- Added
SESSION_USERas a case-insensitive alias ofcurrentUser()for PostgreSQL / SQL-standard compatibility. #106081 (takumihara). - Reduced cancellation latency for queries running over the PostgreSQL wire protocol: KILL QUERY now interrupts output serialization within a single chunk instead of waiting for the entire chunk to be sent to the client. #106535 (rvasin).
- Fix an
ILLEGAL_TYPE_OF_ARGUMENTerror for distributed queries withserialize_query_plan = 1that contain a lambda with a constant argument (e.g.arrayMap(t -> t.2, ...)). Constant columns ofActionsDAGINPUTnodes are now preserved during query plan serialization. #107124 (alexey-milovidov). - Reduced cancellation latency for queries running over the MySQL wire protocol: KILL QUERY now interrupts output serialization within a single chunk instead of waiting for the entire chunk to be sent to the client. #107228 (rvasin).
Functions
EXPLAIN SYNTAXnow formats operators as function calls consistently in explain output (for exampleplus(1, 2)instead of1 + 2). #94681 (1abdelhalim).- PostgreSQL-style
expr OP SOME(array)/expr OP ALL(array)(non-subquery right-hand side) is now supported and rewritten tohas/NOT hasfor=/<>, or toarrayExists/arrayAlllambdas for other comparison operators.ANYis not accepted for the array form becauseanyis also an aggregate function; useSOMEinstead. The subquery form ofANY/SOME/ALLcontinues to be lowered toIN/NOT IN. #105129 (alexey-milovidov). - Added support for functions
multiSearchAny,multiSearchAnyUTF8, andmultiMatchAnyin text indexes. Also improved text index analysis for the functionmatch: now patterns with alternative groups can skip more granules. #106279 (CurtizJ). - Function
h3PolygonToCellsnow enforces the maximum array size across all polygons of aMultiPolygon, validates the underlying H3 library return codes, and rejectsMultiLineStringarguments instead of silently returning an empty result. #106399 (Algunenano). - Deserialization of the states of the
contingency,cramersV,cramersVBiasCorrected, andtheilsUaggregate functions now validates that the stored counts form a consistent contingency table and throws aCORRUPTED_DATAexception otherwise. #107185 (nihalzp). - Improve cardinality estimation in the query plan optimizer: a column produced by a deterministic single-argument function (e.g.
toYear(date)) now inherits its argument’s number of distinct values as an upper bound instead of being left without statistics, leading to more accurate join reordering. #107757 (davenger).
Table engines and storage
- Fixes Kafka table engine consumers that kept using a short poll interval after partition assignment, so they return to the configured
kafka_poll_timeout_msand avoid excessive empty polls, smaller inserted parts, and extra merge overhead after rebalances. #100431 (sugaf1204). - Data lake table engines, including
IcebergandDeltaLake, can now use cache-wrapped S3 and Azure disks, allowing repeated reads to use the filesystem cache. #102017 (RinChanNOWWW). - Allow filters introduced after the initial PREWHERE selection (predicate pushdown, runtime filters, or explicit PREWHERE plus a WHERE set by the planner) to be merged into the existing PREWHERE on a second optimizer pass instead of staying as a separate Filter step above the MergeTree read. #105445 (yariks5s).
- Added the
wait_for_part_commit_in_dependent_materialized_viewssetting. When enabled, a cascading materialized view that joins back to its source can see the row currently being inserted. #105943 (ahmadov). - PostgreSQL-compatible
EXTRACT(TIMEZONE_HOUR FROM dt)andEXTRACT(TIMEZONE_MINUTE FROM dt)for the hour and minute parts of a timezone offset, andEXTRACT(<unit> FROM INTERVAL n <unit>)/date_part('<unit>', INTERVAL n <unit>)for extracting the value out of an interval. #106227 (vinayakj592). - Implemented
SYSTEM RESTART DISK <name>: it now reloads a disk’s in-memory metadata and re-scans the data parts of readonly-replica tables located on it. This lets a readonly replica of a table on sharedplain_rewritablestorage observe data written by another server on demand, without waiting forrefresh_parts_intervalor restarting the server. #106645 (jrdi). - Skip unnecessary mark file loads for JSON advanced shared data. #107051 (Avogar).
- Added the create-time
materialized_postgresql_use_extended_date_and_time_typessetting for theMaterializedPostgreSQLdatabase engine. By default (enabled), PostgreSQLdate/timestampcolumns are inferred asDate32/DateTime64; setting it to0atCREATE DATABASEtime infers the narrowerDate/DateTimetypes. The setting is not applicable to theMaterializedPostgreSQLtable engine. #107428 (alexey-milovidov). - MergeTree can now read a compressed stream whose blocks use different codecs. This is the read-side prerequisite for adaptive codec selection. #108592 (rienath).
- Use the
bloom_filterskip index forINpredicates on a directly indexed column whentransform_null_in = 1and theIN-set contains noNULLvalue. Previously the index was skipped for such queries, forcing a full scan. #111329 (groeneai).
S3 and object storage
- Record privileges in
system.query_log.used_privilegesfor all granted access checks, including those that go through the non-throwingisGrantedpath (checkAccessWithFilter). Previously only privileges checked via throwing entry points (checkAccess/checkGrantOption) were recorded, which madeREAD ON FILE/READ ON S3/READ ON AZURE/READ ON URLinvisible in the audit log forDESCRIBE,CREATE TABLE AS, and similar queries that usefile/s3/azure/urltable functions. Access enforcement is unchanged. #104693 (alexbakharew). - Complete the final S3 multipart upload request asynchronously via the task tracker, so it can overlap with the last part upload instead of running serially in finalize. #105487 (asya-ch).
- Increased the default
persistent_processing_node_ttl_secondssetting forS3QueueandAzureQueuefrom one hour to six hours, preventing long-running or restarted processing from losing its bucket lock too early. #106838 (kssenii). - Support the
REDUCED_REDUNDANCY,STANDARD_IA,ONEZONE_IA,GLACIER_IR, andEXPRESS_ONEZONEvalues (in addition toSTANDARDandINTELLIGENT_TIERING) for thes3_storage_class_namesetting. #107251 (adityaksolves). - The hive partitioning sample path for object storage tables (e.g.
S3) is resolved on the first use of the table instead ofCREATE/ATTACH, so an unreachable endpoint no longer blocks table creation and server startup. #111842 (evillique).
Settings and configuration
- Make hive partition strategy a default under compatibility setting
file_like_engine_default_partition_strategy. #86746 (kssenii). - Added four new MergeTree table settings to control default parameters of text indexes:
text_index_dictionary_block_size,text_index_dictionary_block_frontcoding_compression,text_index_posting_list_block_size, andtext_index_posting_list_codec. These settings allow tuning text index behavior at the table level without specifying parameters in every index definition. Explicit per-index arguments still take precedence. #100626 (CurtizJ). - Add setting
output_format_pretty_use_nbsp_for_paddingto render table-layout padding in table-stylePrettyformats asU+00A0NO-BREAK SPACE whenoutput_format_pretty_grid_charsetisUTF-8. This helps copiedPrettyoutput keep table alignment in tools that collapse regular spaces. The setting is disabled by default, andASCIIcharset output keeps regular spaces. #103559 (ashrithb). - Support compatibility with the old analyzer under the
analyzer_compatibility_allow_non_aggregate_in_havingsetting. If enabled, non-aggregate conjunctions will be moved from HAVING to WHERE. #104232 (novikd). OPTIMIZE TABLE ... ON CLUSTERand other DDL no longer hang when the target table hastable_readonly = 1. The setting now throws a new dedicated error codeTABLE_IS_PERMANENTLY_READ_ONLY, whichDDLWorkertreats as non-retriable (distinct from the transientTABLE_IS_READ_ONLYthat arises during temporaryReplicatedMergeTreeZooKeeper disconnects). Thetable_readonlysetting is also now explicitly rejected forReplicatedMergeTree, both at creation and viaALTER MODIFY SETTING. #105109 (alexey-milovidov).- Descending sort order in
MergeTreesorting keys (e.g.ORDER BY (time DESC, key)) is now always supported and no longer requires the experimental settingallow_experimental_reverse_key, which became obsolete. #106440 (nikitamikhaylov). - Support
keyed_by_normalized_query_hashfor quotas defined in the static server configuration (users.xml), matching the existingCREATE QUOTA ... KEYED BY normalized_query_hashDDL syntax. #107654 (alexey-milovidov). - The compatibility setting no longer applies obsolete settings, so it does not mark them as changed or produce obsolete-setting warnings. #107737 (UberDever).
- Added the setting
analyzer_compatibility_multiple_joins_qualify_column_names(defaultfalse). When enabled and theFROMclause of a query contains two or moreJOINs, result column names produced by the analyzer mimic the old analyzer’s multiple-joins rewrite: columns expanded from*are named<alias-or-table>.<column>, and an unaliased column reference in theSELECTlist keeps its name exactly as written. This makes outer queries that reference such qualified names, likeSELECT ll.Date FROM (SELECT * FROM t AS ll JOIN t1 ON ... JOIN t2 ON ...), work as they did with the old analyzer. Also fixed the analyzer losing qualified result column names for columns expanded from*whengroup_by_use_nullsis combined withROLLUP,CUBEorGROUPING SETS, which produced duplicate result column names and broke outer references to those columns. #110746 (novikd). - Added setting
analyzer_compatibility_apply_final_to_all_joined_tablesthat restores the old behavior, where theFINALmodifier on the left-most table of a JOIN was also applied to the other joined tables. The setting is registered in the settings changes history, socompatibilitywith versions before 26.6 restores the old semantics automatically. #111589 (fm4v). - Added a new MergeTree setting
text_index_versionthat controls the on-disk format version of text indexes:v0_initial,v1_with_codec, orv2_with_positions. During a rolling upgrade or before a downgrade, set it to an older version so that newer servers keep writing text index parts in a format older servers can still read; the compatibility setting automatically adjusts it. #111803 (CurtizJ).
System tables and monitoring
- Populate
used_storagesinsystem.query_logwith the storage engine name when querying tables via DataLakeCatalog. #100706 (melvynator). - Add
current_projection,current_projection_progress,projections_completed, andprojections_remainingcolumns tosystem.mergesto expose projection merge progress. #102611 (amosbird). - Table engines now carry embedded documentation, introspectable via the new
description,syntax,examples,introduced_in, andrelatedcolumns of thesystem.table_enginestable. #106177 (alexey-milovidov). - Database engines now carry embedded documentation, introspectable via the new
description,syntax,examples,introduced_in, andrelatedcolumns of thesystem.database_enginestable. #106178 (alexey-milovidov). - Data types now carry embedded documentation, introspectable via the new
description,syntax,examples,introduced_in, andrelatedcolumns of thesystem.data_type_familiestable. #106180 (alexey-milovidov). - Input/output formats now carry embedded documentation, introspectable via the new
description,examples,introduced_in, andrelatedcolumns of thesystem.formatstable. #106181 (alexey-milovidov). - Aggregate function combinators now carry embedded documentation, introspectable via the new
description,syntax,examples,introduced_in, andrelatedcolumns of thesystem.aggregate_function_combinatorstable. #106185 (alexey-milovidov). - Added a new
system.data_skipping_index_typestable that lists the available data skipping index types together with embedded documentation (description,syntax,examples,introduced_in,related). #106186 (alexey-milovidov). - Added a new
system.disk_typestable that lists the available disk types together with embedded documentation (description,syntax,examples,introduced_in,related). #106187 (alexey-milovidov). - Added asynchronous metrics
TotalUncompressedBytesOfMergeTreeTablesandTotalUncompressedBytesOfMergeTreeTablesSystem, reporting the total uncompressed size of data stored in MergeTree-family tables. #106364 (alexey-milovidov). - Adds the
GlobalMemoryLimitExceededprofile event so operators can monitor when the server-wide memory limit is hit. #106466 (sacheendra). - Added asynchronous metrics
ExecutableUserDefinedFunctionMemoryResidentBytesandExecutableUserDefinedFunctionProcesses, reporting the resident memory (VmRSS) and number of live processes ofexecutableandexecutable_pooluser-defined functions, including descendant processes and idle pool workers. #107300 (HanziJiang). - Added
show_remote_databases_in_system_tables, enabled by default, to let users hideMySQLandPostgreSQLdatabases fromsystem.tables,system.columns, andsystem.completions.show_data_lake_catalogs_in_system_tablescontinues to control onlyDataLakeCatalogvisibility. #104416 (pamarcos). #109082 (pamarcos).
ClickHouse Keeper
- Various changes to Keeper that make it around 2x faster overall (better batching, pipelining messages to leader, pipelining log appends). #101757 (al13n321).
- Add more keeper profile (server-side + client-side) events for watches. #105336 (scanhex12).
- Add a new keeper-only
system.keeper_snapshotstable with information about local ClickHouse Keeper snapshots. #105571 (mstetsyuk). - Add a new keeper-only
system.keeper_changelogstable with information about local ClickHouse Keeper changelog (Raft log) files. #105617 (mstetsyuk). - Add a keeper-only
system.keeper_clustertable. Contains one row per Raft cluster member as seen by the current Keeper. #105646 (mstetsyuk). - Reduce peak memory usage when applying received snapshots in ClickHouse Keeper with
KeeperMemoryStorage. #105851 (antonio2368). - Added Keeper
coordination_settingsforNuRaftuncommitted log entry admission limiting and append-entries backward-probe throttling. #106108 (antonio2368).
Memory management
- Fixed syntax-error messages potentially including bytes from adjacent memory after the parser backtracked past the end of a statement. #105086 (groeneai).
- Reduced memory usage when opening a backup (for
RESTORE, or as the base of an incrementalBACKUP). The.backupmetadata is now parsed as a stream instead of being loaded into an in-memory XML document tree, which for large (especially incremental) backups avoids allocating a multi-gigabyte DOM tree. #109107 (jkartseva). - Reduced peak memory usage when finalizing a
BACKUP. Writing the backup metadata no longer copies the file infos of all files into a temporary vector (which, for backups of millions of files, transiently cost several gigabytes); the infos are now iterated in place. #109861 (jkartseva).
Data formats
- Users can now insert Avro Fixed fields for 8-bit/16-bit/32-bit/64-bit integer variants. #98139 (patrickpichler).
- The
AvroConfluentformat now retries the Confluent Schema Registry HTTP client on transient failures (transport timeouts, connection refused, DNS errors, HTTP5xx/408/429) with exponential backoff, instead of aborting the INSERT on the first network glitch. New settingsformat_avro_schema_registry_max_retries(default5) andformat_avro_schema_registry_retry_initial_backoff_ms(default100) control the policy. Schema-validation errors (HTTP409, malformed Avro JSON) remain fatal. #106661 (groeneai). - Preserved the original ClickHouse error codes for errors returned through Apache Arrow. #107267 (azat).
Named collections and dictionaries
- Add
enable_compressionsetting for themysqltable function, theMySQLtable engine, theMySQLdatabase engine, dictionarySOURCE(MYSQL), and named collections. When enabled, ClickHouse negotiates MySQL protocol-level compression for all data transferred over the connection. #103229 (bernardlim). - Added a new
system.dictionary_layoutstable that lists the available dictionary layouts together with embedded documentation (description,syntax,examples,introduced_in,related). #106182 (alexey-milovidov). - Added a new
system.dictionary_sourcestable that lists the available dictionary sources together with embedded documentation (description,syntax,examples,introduced_in,related). #106184 (alexey-milovidov). - The effective named collections storage type is now available as
named_collections_storage.typeinsystem.server_settingsand throughgetServerSetting('named_collections_storage_type'). #111806 (pamarcos).
Other improvements
- Improved table name hints in error messages: no longer suggests the exact same name, and includes the database name in the suggestion (e.g., “Maybe you meant other_db.my_table?”). #95116 (matt-metivier).
- Improved error message for unresolved identifiers in queries without a FROM clause to suggest adding one. #101769 (Onyx2406).
- Fixed
PREWHEREwithINsubquery on primary key columns not using primary key index for granule pruning, causing full table scans instead of reading only relevant granules. #102570 (nikitamikhaylov). - Refreshable materialized views now continue refreshing after their target table is replaced using
EXCHANGE TABLESand the old table is dropped. Previously, refreshes could fail with anUNKNOWN_TABLEexception because they retained the old table’s UUID. #102724 (seva-potapov). - Turn on
enable_join_transitive_predicatesby default. #103724 (davenger). - Refreshable materialized view now supports
REFRESH DEPENDS ONto trigger refreshes on another RMV’s refreshes instead of time-based schedule. (REFRESH EVERY ... DEPENDS ONalready existed, but couldn’t be used reliably for this use case.) See CREATE MATERIALIZED VIEW documentation. #104440 (al13n321). - Add
EXPLAIN PIPELINEoption to compact repeated processor chains. #104662 (niyue). - Added
REGEXP_SUBSTRas a case-insensitive alias ofregexpExtractfor Oracle/MySQL/Snowflake compatibility. #105122 (alexey-milovidov). - Added
date_part('unit', expr)as syntactic sugar forEXTRACT(unit FROM expr). Standard interval kinds and the PostgreSQL extras (epoch,dow,doy,isodow,isoyear,century,decade,millennium) are all supported. #105127 (alexey-milovidov). - The
QueryConditionCachenow records individually filtered-out granules even within read batches that partially pass PREWHERE, reducing the number of marks re-read by subsequent queries with the same condition. #105335 (hanfei1991). - Add BFloat16 support for numeric predicate functions. #105391 (mohhddhassan).
- Support basic statistics, a compact per-column statistic that stores numeric min/max, average string length, and NULL counts where applicable. #106048 (hanfei1991).
- Support a trailing
NULL/NOT NULLmodifier inALTER TABLE ... ADD/MODIFY COLUMN, mirroringCREATE TABLE. #106150 (takumihara). - The PREWHERE optimizer now groups conjuncts that reference the same column set before estimating selectivity, so that conditions like
a > 2500 AND a < 2502are evaluated together as a combined range (~0.02% selectivity) rather than as two independent predicates (~50% each). This produces a more accurate ordering of PREWHERE conditions when column statistics are available. #106337 (hanfei1991). - Do not print the “Stack trace (when copying this message, always include the lines below):” preamble in exception messages when the stack trace is actually empty. #106524 (alexey-milovidov).
- Fixed
CREATE TABLE ... CLONE AS (and REPLACE / ATTACH PARTITION ... FROM)on encrypted disks copying data instead of hardlinking it. #106731 (nikitamikhaylov). - Fix
DataLakeCatalogdatabases withcatalog_type = 'onelake'reading table data by using the OneLake Blob endpoint (.blob.fabric.microsoft.com) by default. Setonelake_use_blob_endpoint = falseto keep the previous DFS endpoint (.dfs.fabric.microsoft.com) behavior. #106843 (scanhex12). - Reduced CPU overhead of asynchronous logging under high log rates by notifying the log consumer only on the empty-to-non-empty queue transition instead of on every message. #107352 (nikitamikhaylov).
- Fixed reading of the
auth_responselength in the MySQL handshake, where a length byte>= 128was interpreted as a multi-gigabyte value because it was read as a signedchar. #107384 (uwezkhan). MaterializedPostgreSQLnow maps PostgreSQLnumeric(p, 0)columns with precision greater than 76 (e.g.numeric(78, 0)used for 256-bit integers) to ClickHouseInt256instead of failing with “Precision too big”. Values that do not fit intoInt256are rejected with a clear error. #107431 (alexey-milovidov).Nullable(Tuple(...))is now Beta. Disabled by default, setenable_nullable_tuple_type = 1to use it. #107754 (nihalzp).- Async inserts no longer log the full list of
query_ids attrace/debuglevel, which since 26.2 could blow uptext_logon services with heavy async insert traffic. Detailed lines are now attestlevel. #107852 (CheSema). - Reduced filesystem-cache metadata usage by releasing invalidated priority entries promptly. #107903 (kssenii).
- A
bloom_filterskip index on anArraycolumn is now used forarrayJoin(column) IN (set),arrayJoin(column) GLOBAL IN (set)andarrayJoin(column) = const, the same way it was already used forhasAny(column, set)andhas(column, const). Previously thesearrayJoin ...forms fell back to a full scan. #109536 (groeneai). IS NOT DISTINCT FROMandIS TRUEnow use primary-key and minmax indexes to prune granules, the same as=. Previouslyk IS NOT DISTINCT FROM 42and(k = 42) IS TRUEscanned all granules. #110006 (groeneai).
Bug Fixes
JOIN fixes
- Fixed
nestedfunction (used internally byARRAY JOIN) strippingLowCardinalityfrom column types, causingArray(LowCardinality(String))to becomeArray(String)in output. #98974 (Onyx2406). - Fix join reordering silently dropping unmatched rows of a
RIGHT/LEFT JOINwhen it is comma-joined (cross) with another table, e.g.t1 RIGHT JOIN t2 ON t1.c = t2.c, t3. The query previously returned the inner-join result instead of the outer-join one. #101684 (groeneai). - Fix a
LOGICAL_ERROR(“Port is not connected”, code 49) that could occur when executing queries involving a VIEW with aggregation inside a JOIN.. #102574 (Ergus). - Fix
max_rows_to_transferandmax_bytes_to_transferbeing silently ignored forGLOBAL INandGLOBAL JOINqueries under the new analyzer. The settings now raiseSET_SIZE_LIMIT_EXCEEDED(or break, depending ontransfer_overflow_mode) when the materialised external table exceeds the configured limit, matching the behavior of the old analyzer. #104119 (groeneai). - Fixed wrong results or query failures for
JOINqueries usingjoin_algorithm = 'direct'with aMergeTreetable on the right side when optimization reordered the lookup columns. #104174 (groeneai). - Fixed a bug where queries combining
arrayJoinwithORDER BY ... LIMITafter aJOINcould silently return zero rows. The query plan optimization that lifts function evaluation above theSortingStepno longer applies when the lifted expression containsarrayJoin, sincearrayJoincan change the number of rows. #104558 (groeneai). - Fix logical error in negative
LIMIT BYin some cases when used withARRAY JOIN. #105403 (nihalzp). - Add a new compatibility setting
analyzer_compatibility_prefer_alias_over_subcolumn(disabled by default). When enabled, the new analyzer prefers the alias-prefix interpretation over Tuple-subcolumn / dotted-column matches for multi-part identifiers, restoring the previous interpreter’s behavior. This avoidsAMBIGUOUS_IDENTIFIER(and related) errors when a query joins a table whose name matches an inner table of a CTE/subquery that usesSELECT *over a join, where asterisk-renamed columns (e.g.b.id) would otherwise leak the inner table identifiers into the outer scope. #105491 (vdimir). - Fix possibly wrong results for queries that combine an outer join with a subsequent inner join referencing the outer join’s null-supplying side. Join reordering could pick a plan that pulled inner-join conditions into the outer join’s ON clause. #105992 (vdimir).
- Better compatibility with the old analyzer. If the table has columns like
x.a Array, x.b Array, x String, prefer arrays forARRAY JOIN x. #106069 (KochetovNicolai). - Fixed an exception for
INNER JOINqueries with an empty leftMergeTreetable whenenable_parallel_replicas,query_plan_use_new_logical_join_step, andquery_plan_optimize_join_order_algorithm = 'greedy'are enabled. #106338 (KochetovNicolai). - Fix a logical error (
Left and right columns have same names) in the join order optimizer that could occur for joins executed with parallel replicas when two relations in the join graph share column names. #106418 (alexey-milovidov). - Fix a
LOGICAL_ERROR(Invalid number of rows in Chunk) inJoiningTransformfor aLEFT JOINwith unique right keys, a mixedONcondition, and a smallmax_joined_block_size_rows. #106928 (groeneai). - Fix an exception (
LOGICAL_ERROR) in the join runtime filter when the join key contains aVariantorDynamictype nested inside aTuple,Array, orMapand the right side of the join has a single distinct value. #106931 (groeneai). - Fix a
LOGICAL_ERROR(Expected the argument N to have X rows, but it has Y) when executing a function over aDynamiccolumn built by a JOIN overDynamic(for example the non-joined rows of aRIGHT/FULL JOIN, or a correlatedEXISTSsubquery decorrelated into a join). #107095 (groeneai). - Fix a
Bad cast from type DB::IColumn const* to DB::ColumnNullable const*logical error exception when a qualified asterisk (t.*) over aJOIN ... USINGkey is passed to an aggregate function and the other side of an outer JOIN has aNullablekey (withjoin_use_nulls = 0). #107129 (groeneai). - Fix a logical error (
Unexpected return type from equals. Expected Nullable(UInt8). Got UInt8) when the disjunction (partial predicate) push-down optimization pushes a condition over aUSINGkey whose type is widened by the JOIN. Also fix a server crash (segmentation fault) in the analyzer when resolving identifiers inJOIN ... USINGqueries that contain constant-foldableif/multiIfbranches referencing unknown identifiers. #107407 (groeneai). - Fix runtime join filter producing wrong results for JSON columns. #107663 (Avogar).
- Fix a
Bad cast from type DB::ColumnNullable to DB::ColumnVector<...>logical error exception when a qualified asterisk (t.*) selects aJOIN USINGkey and that join is nested below aPASTE/CROSS/comma join or an outerONjoin, withjoin_use_nulls = 0. #108043 (groeneai). - Fixed a bug in the new analyzer where FINAL on one table of a JOIN (e.g.
FROM t1 FINAL JOIN t2) was incorrectly applied to the other joined tables as well, what could made such queries slower. #108979 (vdimir). - With
analyzer_compatibility_join_using_top_level_identifier = 1, an identifier inJOIN ... USINGcan now be resolved from an alias defined on a subexpression inside the SELECT list (for example,SELECT uniqExact(lower(x) AS id) FROM t1 JOIN t2 USING (id)), matching the old analyzer behavior. Previously only top-level projection aliases were considered, and such queries failed with anUNKNOWN_IDENTIFIERexception even with the setting enabled. The error hint suggesting the setting is now also produced when the matching alias is nested. #110739 (novikd). - Fixed
INCOMPATIBLE_TYPE_OF_JOINerror for anANYjoin on aJoinengine table when aWHEREfilter on a right-side column allowed the query planner to rewrite the join toSEMIorANTI. AJoinengine table has a fixed declared strictness that cannot be changed, so the conversion is now declined for such tables. #111362 (groeneai). - Fix
TYPE_MISMATCH(“Key type for complex key … does not match”) when aJOINonto a dictionary uses aNullable,LowCardinality, orLowCardinality(Nullable)join key while the dictionary key is not wrapped. The direct-join dictionary lookup now normalizes the key to the dictionary’s declared key type (asdictGet/dictHasalready do), and aNULLkey never matches. #111857 (groeneai). - Fixes
AMBIGUOUS_COLUMN_NAME(Block structure mismatch in (columns with identical name must have identical structure)) for a query that repeats aJOIN ONcondition inWHEREwithjoin_use_nulls = 1. Such a query now returns its result instead of failing. #112007 (groeneai). - Fixed wrong results or server termination for direct dictionary
JOINs whose key uses sparse serialization. #112327 (groeneai). - Fixed wrong results when a hash join has a single
LowCardinalitykey of a type wider than 8 bytes (UInt128,Int128,UInt256,Int256, and theirNullablevariants). Such a join silently returned rows whose key values are not equal. #113230 (groeneai). - Fix part and granule pruning for a
JOIN ONcondition involving constant columns of the other side. #113484 (vdimir). - Fix a wrong value returned for a virtual column such as
_tableor_databaseselected from the right side of a JOIN served byDirectKeyValueJoin(a key-value storage such asEmbeddedRocksDB,KeeperMap,Redis, or a dictionary). The query returned the contents of a data column instead, or failed withLOGICAL_ERROR. #113698 (groeneai).
Query and analyzer fixes
- Fix a bug with splitMultipartQuery throwing an “Empty query” error for queries that ends with comment after semicolon. #85491 (yariks5s).
- Fixes the case where an alias after a subquery in DESCRIBE TABLE is not accepted by the parser and results in a syntax error. #100205 (yariks5s).
- Fixed
FORMATclause being consumed byINSERTinstead of applying toEXPLAINoutput inEXPLAIN INSERT INTO ... SELECT ... FORMAT .... #101772 (Onyx2406). - Fix SELECT queries being significantly slower when concurrent INSERTs are running. Previously an INSERT pipeline reserved CPU slots up to
max_threadsat query start even when most slots were never used, starving concurrent SELECTs. CPU slot allocation is now demand-driven: the pipeline only requests slots as it actually pushes parallelizable work. Applies both to concurrency control and to the preemptive CPU scheduler for workloads. New server settingconcurrent_threads_lazy_allocation(defaulttrue) acts as a rollback lever. #102928 (seva-potapov). - Fix a bug where
ALTER TABLE ... MODIFY SETTINGon anEmbeddedRocksDBtable could persist an invalid setting value to the table metadata file even when the server rejected the query. On the next server restart the table would fail to attach withCANNOT_PARSE_BOOL(or a similar parsing error), and in databases where load failures are fatal the server would refuse to start. Invalid setting values are now rejected before any metadata is written. #103417 (groeneai). - Fixed streaming
INSERTwithinput_format_max_block_wait_msfor theHTTPinterface and forINSERT SELECT FROM input, so partial input blocks are flushed before the request finishes. #104534 (alexey-milovidov). - Fix
CASEexpression returning theELSEbranch instead of the matchingTHENwhen both the expression and aWHENvalue wereNULL. #105556 (Algunenano). - Fix support for using
WASMSQL UDFs inMATERIALIZED VIEWdefinitions. #106161 (niyue). - Fix
INTERPOLATE ()throwingINVALID_WITH_FILL_EXPRESSIONwhen ORDER BY columns are aliased in the SELECT list with the old analyzer. #106252 (yakov-olkhovskiy). - Functions
base58Encode,base58DecodeandtryBase58Decodenow respectmax_execution_timeand query cancellation on large inputs, and reject inputs larger than 10 KB instead of running for a very long time. The limit is configurable via the new settingfunction_base58_max_input_size(0disables it). #106428 (alexey-milovidov). - Fix wrong-results bug where
WHERE c0 = constreturned no rows for tables withORDER BY f(c0)whenf(const)evaluates to NaN, e.g.ORDER BY sqrt(c0)with a negative constant. The primary-key analysis incorrectly pruned every granule and poisoned the query condition cache for subsequent queries. #106507 (groeneai). - Fixed wrong results for
SELECT c, count() FROM t WHERE c GROUP BY cagainst tables with the implicit_minmax_count_projection, an explicit aggregate projection, or a normal projection: every group used to collapse into one row with a constant key and the total row count. #106590 (groeneai). - Make
FORMATapply to theEXPLAINoutput ofEXPLAIN ... INSERT ... SELECT ... FORMAT ...also whenSETTINGSprecede theFORMATor the output format isValues. #106686 (alexey-milovidov). - Fixed a rare spurious
RESOURCE_ACCESS_DENIEDerror (“Scheduler queue with resource request is about to be destructed”) for a query that was actually granted access to a workload resource, caused by a reused thread-local request object retaining a previous request’s failure. #106690 (alexey-milovidov). - Fixed
match,extract,extractAllandcountMatchesreturning wrong results for regular expressions containing hex or octal escapes. #106709 (ofeliacode). - Fix an integer underflow in the PostgreSQL wire protocol parser where a message with a length field smaller than 4 caused a
size - 4wraparound and an oversizedresize/ignore. #107485 (uwezkhan). - With
enable_analyzer = 1(the default), querying a table by its bare name when it only exists in another database now suggests the right table, e.g.SELECT * FROM functionsreportsMaybe you meant system.functions?. Previously the new analyzer gave a hint-lessUnknown table expression identifiererror, while the old analyzer already produced the helpful suggestion. #107550 (groeneai). - Fixed a server abort (
std::terminate, signal 6) during teardown of a distributed-plan query (make_distributed_plan = 1) when a worker status-check failed to re-schedule the next check (for exampleCANNOT_SCHEDULE_TASKon shutdown orMEMORY_LIMIT_EXCEEDED). The query now fails cleanly and the server keeps running. #107575 (groeneai). - Fixed incorrect results from distributed queries selecting
ALIAScolumns that share a common subexpression: columns could be misaligned and values returned under the wrong column. #107675 (vdimir). - Fixed an
Inconsistent AST formattinglogical error for a no-argument window function inside aCODECor engine declaration (e.g.CODEC(cume_dist() OVER (...))); such a function now keeps its parentheses so the query survives a format/parse round-trip. #107806 (alexey-milovidov). getClientHTTPHeaderis now correctly treated as non-deterministic, so its result is no longer incorrectly reused by the query result cache. #108029 (alexey-milovidov).- Fixed wrong results when using
SELECT [...] SAMPLE [...]together with the query condition cache (settinguse_query_condition_cache = 1which is also the default). #108488 (groeneai). - Fix
NOT_FOUND_COLUMN_IN_BLOCKwhen a compound predicate is aliased inGROUP BYand referenced again, withenable_identifier_resolve_cacheenabled (the default). Theoptimize_and_compare_chainoptimization was not idempotent and a shared resolved node accumulated a duplicate transitive conjunct. #108553 (groeneai). - Fix
NUMBER_OF_COLUMNS_DOESNT_MATCHerror when a subquery on aDistributedtable reads two or moreALIAScolumns that expand to the same expression (for examplea1 String ALIAS toString(x), a2 String ALIAS toString(x)) and the subquery feeds an outer query, e.g.SELECT count() FROM (SELECT a1, a2 FROM dist GROUP BY a1, a2). #108725 (groeneai). - Fix
UNKNOWN_IDENTIFIERerror onALTER TABLE ... DROP COLUMNwhen another column has aDEFAULTorMATERIALIZEDexpression that defines and references an inline alias. #109374 (alexey-milovidov). - Fix
system.tablessilently skipping databases for users with per-database grants when the query reads only thename/databasecolumns. Introduced in 26.2. #109723 (samay-sharma). - Fix
UNKNOWN_IDENTIFIERerror for columns qualified by CTE name (cte_name.column) in queries stored in views when the analyzer is enabled. #111386 (novikd). - Fixes
NOT_FOUND_COLUMN_IN_BLOCKwhen aFINALquery filters on a sorting-key column that is not in theSELECTlist and the filter is moved toPREWHERE(for exampleSELECT s FROM t FINAL WHERE k GROUP BY swithoptimize_move_to_prewhere_if_final = 1). #111721 (groeneai). - Fixed server startup and
ATTACHfailing withWITH RECURSIVE is not supported with the old analyzerfor a view with a recursive CTE whenenable_analyzer = 0is the server default. #112784 (evillique). - Fix propagation of query settings and NULL handling in
accurateCastOrDefault. #114912 (alexey-milovidov). - Fix
read_rows,read_bytes,written_rowsandwritten_bytesinsystem.query_thread_logreporting a thread lifetime running total instead of the values for the logged query. Rows of long-lived pooled threads, in particular the query’s initiatingHTTPHandlerthread, were affected. #115596 (groeneai).
MergeTree and storage fixes
- Detached parts with a
tryNsuffix can now be dropped. #58957 (antaljanosbenjamin). - Fix a
MULTIPLE_EXPRESSIONS_FOR_ALIASexception for queries with duplicate projection aliases (for exampleSELECT *, day + 365 AS day) inside nested subqueries when running with parallel replicas. #80310 (alexey-milovidov). - Fixed incorrect compression codec selection for
MergeTreeparts when the table-leveldefault_compression_codecsetting was explicitly configured. Parts written on insert, during merges, and for projections used the server-wide default codec instead of the table-level setting (the empty part produced by a fully-deleting mutation is now covered as well). #101784 (Onyx2406). - Fix
MULTIPLE_EXPRESSIONS_FOR_ALIASerrors thrown by remote replicas when running queries that reference projection aliases insidePREWHERE/WHERE/HAVING/QUALIFY(e.g.SELECT x AS a, y AS b, (a AND b) AS c FROM t PREWHERE c) orSELECT *over self-joins with overlapping column names, with parallel replicas andparallel_replicas_local_plan = 0. #103806 (groeneai). - Fix a broken patch part after
ALTER TABLE ... DROP PARTITION ID 'patch-...'followed byDETACH/ATTACH TABLE. Previously the empty covering part was written withoutpartition.datandsource_parts.dat, leading to abroken-on-start_patch-...entry insystem.detached_partsafter the next attach or server restart. #104353 (groeneai). - Fixed silent data replacement with default values when
ALTER TABLE ... RENAME COLUMNran concurrently withOPTIMIZE TABLE ... FINALor another background merge. #104822 (groeneai). - Fixed two
LOGICAL_ERROR: Reading from materialized CTE 'X' before it has been materializedshapes thrown by queries withenable_materialized_cte: (1) a reused materialized CTE filtered byIN (subquery)over another materialized CTE, and (2) a materialized CTE referenced both directly and inside aWHERE ... IN (...)filter that hits a MergeTree primary key through a nested IN-subquery.EXPLAINon the same queries was affected too because the bugs fired during plan optimization. #105041 (novikd). - With
skip_cache_on_disk_failure = 1, queries now continue whenFileCachecannot create an on-disk cache directory. The failure is logged instead of failing the query. #105250 (Diskein). - Fixed the logical error exception
Mutation of Memory table produced incomplete outputraised byALTER TABLE <memory_table> APPLY PATCHESandALTER TABLE <memory_table> APPLY DELETED MASK.Memorytables do not own patch parts or deletion masks, so both commands are now correctly treated as no-ops. #105286 (groeneai). - Fix
CANNOT_CONVERT_TYPEforMergeoverMergeoverDistributedwithdistributed_group_by_no_merge=1#105330 (azat). - Fixed
singleValueOrNullMergereturning a concrete value instead ofNULLwhen merging a state that had already observed multiple distinct values. #105734 (fallintoplace). - Fix a crash in the
mongodbtable function, MongoDB storage and MongoDB dictionary source when the collection name is empty or contains NUL bytes. #105776 (Algunenano). - Fix
ALTER TABLE ... CLEAR COLUMNbeing rejected for explicitSummingMergeTreeandCoalescingMergeTreecolumns_to_sumcolumns. #105785 (antonio2368). - Fixed
UNKNOWN_DATABASEerrors when creating a parameterized view whose database name is supplied through a query parameter. #105799 (groeneai). - Restored read-in-order optimization for
Mergetables when using the analyzer. #105867 (KochetovNicolai). - Fixed
UPDATEandDELETEmutations on Iceberg tables accessed through a catalog, including repeated updates and deletes that match no rows. #106111 (scanhex12). - Fix
optimize_skip_unused_shardsdid not apply (and force_optimize_skip_unused_shards falsely failing) when aDistributedtable is queried through aMergetable or themergetable function, with the predicate applied above it. #106250 (KochetovNicolai). - Fix a logical error
Column identifier ... is already registeredwhen a mutation (DELETE/UPDATE) predicate contains anIN/EXISTSsubquery that reads from a default table expression nested in another subquery. #106414 (alexey-milovidov). - Fix sporadic incorrect results for
ORDER BY ... DESCqueries when reading wide parts in reverse order withread_in_order_use_virtual_row_per_block = 1and a smallmax_block_size. #106429 (vdimir). - Fixed a
Bad cast exceptionfor Redis dictionaries that useSTORAGE_TYPE 'simple'with acache/directlayout and a single string (complex) key; such dictionaries now work, and composite keys oversimplestorage report a clear error. #106501 (vdimir). - Fixed the exception
Mutation of Memory table produced incomplete outputraised byALTER TABLE <memory_table>commands that have no per-row data effect on aMemoryengine, includingAPPLY PATCHES,APPLY DELETED MASK,MATERIALIZE STATISTICS,MATERIALIZE INDEX,MATERIALIZE PROJECTION, andREWRITE PARTS.Memorytables do not own those structures, so these commands are now treated as no-ops. #106621 (groeneai). - Fix server failing to start with
Too many marks in file ...skp_idx_idx.cmrk4, marks expected 0 (bytes size 0)when aMergeTreetable has a skip-index part with zero granules and a non-empty marks file on disk. #106675 (groeneai). - Fixes the case when parallel replicas wasn’t applied for view with UNION due to empty table in the UNION. #106900 (devcrafter).
- Fix a logical error exception
conflicted_part_name.has_value()that could occur during a synchronous insert into aReplicatedMergeTreetable when the inserted block was fully deduplicated and the conflicting part’s deduplication node had already been removed (for example by a concurrentDROP PARTITION). #107026 (groeneai). - Fix a rare
LOGICAL_ERROR“Attempt to release query context that does not exist” and the accompanying server crash when readingMergeTreetables through a filesystem cache disk created withenable_filesystem_query_cache_limit = 1. #107028 (groeneai). - Fix a server crash when moving an empty part to a
plain_rewritabledisk (for example withALTER TABLE ... MOVE PARTITION ... TO DISKfor an empty part kept byremove_empty_parts = 0). #107040 (groeneai). - Fix a
Logical error: Too large size passed to allocatorexception onINSERTinto aMergeTreetable whenadaptive_write_buffer_initial_sizeis set to an extremely large value. The adaptive write buffer initial size is now clamped to the buffer maximum. #107104 (groeneai). - Fix
ALTER TABLE ... ON CLUSTERbatches that mixMODIFY SETTING/RESET SETTINGwith a comment change (for exampleMODIFY COMMENT 'x', MODIFY SETTING old_parts_lifetime = 123) being applied only on the leader replica, leaving the other replicas diverged. Also fix a positional or per-column-SETTINGSMODIFY COLUMN ... COMMENTbeing misclassified as a local comment-only metadata change, which left the column reorder out of the replicated metadata and could causeINCOMPATIBLE_COLUMNSon replica restart. #107142 (groeneai). - Fix the
Argument ... of GROUPING function is not a part of GROUP BY clauseerror for queries that use thegroupingfunction with thegroup_by_use_nullssetting enabled. #107206 (KochetovNicolai). - Fix lightweight
UPDATEqueries with legacy parallel replicas enabled for non-replicatedMergeTreetables. #107246 (groeneai). - Fix a possible logical error exception in SYSTEM SYNC DATABASE REPLICA … STRICT and make the STRICT modifier actually take effect for database replicas. #107344 (PedroTadim).
- Fix
Logical error: 'Duplicate announcement received for replica number N'that could occur with parallel replicas when a scalar subquery contained nested subqueries reading the same table. #107381 (groeneai). - Fix silent data loss on plain (non-replicated)
MergeTreewhenREPLACE PARTITION,MOVE PARTITION,DETACH PARTITION, orDETACH PARTis run on a partition that still has unapplied lightweightUPDATEpatches. These operations now reject the command (asReplicatedMergeTreealready does), pointing toALTER TABLE ... APPLY PATCHES, instead of silently reverting the committed update. #107386 (groeneai). - Fix
MaterializedPostgreSQLsilently stopping replication of changes when the PostgreSQL database or table name contains upper-case letters (thepgoutputconsumer requested an unquoted, lower-cased publication name that did not match the case-preserving publication). #107423 (alexey-milovidov). - Fix
THERE_IS_NO_COLUMNerror whenoptimize_if_transform_strings_to_enum = 1and the optimizedif/transform-over-string-literals expression is aGROUP BYorORDER BYkey over a Distributed table or parallel replicas. #107455 (groeneai). - Fixed
SELECT ... FINALandOPTIMIZE TABLE ... FINALreturning duplicate rows afterCREATE TABLE ... CLONE AS,ATTACH PARTITION ... FROMorMOVE PARTITION ... TO TABLEadopted parts from a plainMergeTreeinto aReplacingMergeTree,SummingMergeTreeorAggregatingMergeTree. The adopted part’s merge level is now reset to 0 when the source and destination engines differ, so the destination deduplicates it on the next merge. #107481 (groeneai). - Query cancellation is now better tracked while waiting for the quorum in ReplicatedMergeTree. #107513 (nickitat).
- Account memory used by the rapidjson library (in
prettyPrintJSON,JSONMergePatchand the rapidjson JSON parser) against the memory tracker, so pathological inputs are rejected withMEMORY_LIMIT_EXCEEDEDinstead of allocating without bound. #107555 (Algunenano). - Fix a
Logical error: Stream ... variant_discr ... is not foundthat could occur when merging or reading aMergeTreepart produced by a mutation of a table with aDynamiccolumn. #107562 (alexey-milovidov). - Fix a
LOGICAL_ERROR(updateFormatPrewhereInfo called more than once) raised when querying afile(),url(), or object-storage source with both an explicitPREWHEREand aWHEREwhileoptimize_prewhere_after_pushdownwas enabled. #107568 (groeneai). - Fixed a server exception (
Digest does not matchlogical error) that could happen onRENAME TABLE,RENAME DATABASE, orCREATE OR REPLACE TABLEinvolving aTimeSeriestable inside aReplicateddatabase. Renaming aTimeSeriestable is now supported. #107583 (groeneai). - Fix
DROP TABLEof aTimeSeriestable in aReplicateddatabase, which previously leaked the inner tables and left the background drop task retrying forever (DROP TABLE ... SYNCwould hang). #107604 (groeneai). - Fixed two path-traversal issues in the replicated part fetch protocol that could let a malicious replica write files outside the part directory. #107606 (antonio2368).
- Fixed
ALTER TABLE ... REPLACE PARTITIONon a plainMergeTreetable resurrecting the replaced-out parts after a server restart, which made the table return both the replacement rows and the stale replaced rows. #107623 (groeneai). - Fixed a
LOGICAL_ERROR(“Block structure mismatch … betweenConvertingTransformandRemovingReplicatedColumnsTransform”) when inserting into a materialized view whoseTOtarget table declares a column with a widerEnumthan the view’sSELECTproduces. The validEnumwidening is now applied on the materialized-view insert path, like a directINSERT ... SELECT. #107648 (groeneai). - Fix
NUMBER_OF_COLUMNS_DOESNT_MATCHerror when querying aDistributedtable (or using parallel replicas) that has severalALIAScolumns expanding to the same expression and referencing them together withORDER BY/GROUP BY/HAVING. #107913 (yakov-olkhovskiy). - A transient error while refreshing data parts of a read-only table no longer permanently stops the background refresh task. #108034 (alexey-milovidov).
index_granularity_bytesis now honored forAggregateFunctionstate columns. Previously the granule byte cap was ignored for such columns (for exampleuniqExactstates inAggregatingMergeTreetables and aggregating projections), producing granules far larger than the configured limit and increasing read amplification and query-time memory. #108297 (groeneai).- Fixed
insert_quorum = 'auto'not rejecting inserts up front when fewer than a majority of replicas were alive. Such inserts now fail immediately withTOO_FEW_LIVE_REPLICASinstead of writing a local part and later timing out withUNKNOWN_STATUS_OF_INSERT. #108800 (gagandhakrey). - Fixed a server crash on asynchronous insert with deduplication when
optimize_on_insertmakes the inserted block empty (for example, rows summing to zero inSummingMergeTree). #109229 (Diskein). - Fix data loss of a column with no default expression when a merge runs concurrently with
ALTER TABLE ... RENAME COLUMN, or when the column’s only values come from a lightweightUPDATE. The column could be dropped from the merged part, so all of its values read back as NULL. #109356 (groeneai). - Fixed a rare server termination when merging
uniqExactaggregate states in parallel withGROUPING SETS,ROLLUP, orCUBE. #109389 (groeneai). - Fixed rollup merges being rescheduled indefinitely. #109410 (Michicosun).
- Fixed
GROUP BYmutations for tables with materialized or persistent virtual columns. #109532 (Michicosun). - Fixed
UNKNOWN_IDENTIFIER: Missing columns: '_block_offset'error when runningALTER TABLE ... MATERIALIZE INDEXon the implicit minmax index created byadd_minmax_index_for_block_number_column/add_minmax_index_for_block_offset_columnon a table that has freshly inserted (0-level) parts. The index is now built for those parts instead of failing. #110236 (groeneai). - Fixed a read-only object-storage replica (a disk configured with
read_only = true) not discovering new parts viarefresh_parts_interval, andtable_disk = truebeing rejected on such a disk with “table_disk is not supported for non-ObjectStorage disks”. #110460 (jkartseva). - Fix a LOGICAL_ERROR (“No set is registered for key”) in ALTER TABLE … DROP COLUMN, ALTER TABLE … DELETE/UPDATE mutations, and lightweight DELETE, on tables that have an ALIAS column whose expression uses an IN operator (including through another ALIAS column). #111039 (PedroTadim).
- Fixes cases where row policy was not used for MergeTree Projections during query execution. #112329 (yariks5s).
- Fix
ReadBufferFromEncryptedFile: Wrong file positionlogical error when reading aCompactpart from anencrypteddisk with direct I/O, which made merges get stuck insystem.replication_queue. #112943 (alexey-milovidov). - Fixed reading the internal
_temporary_and_external_tablesdatabase through themergetable function and theMergetable engine, which allowed one session to read the temporary tables of other sessions and other users, and caused an exception on the old analyzer path. A database regexp now skips that database, and naming it explicitly is denied, the same way as direct access to it is. #113224 (alexey-milovidov). - Fixed a row policy containing a scalar subquery being evaluated only once and then reused forever after the table had been read through a
Mergetable. The parsed policy condition is cached and shared by all queries, and reading it throughMergerewrote the cached expression in place, which also caused a data race between concurrent queries using the same policy. #113563 (alexey-milovidov). - Fixed
CANNOT_CONVERT_TYPEerrors when reading aMergetable containing aDistributedtable with custom-key parallel replicas. #113742 (alexey-milovidov). - Fix
Logical error: No set is registered for key ...when reading through aMergetable whose child declares anALIAScolumn containingIN, and the children disagree about that column’s default. #113757 (groeneai). - Fixed a row policy bypass where the mergeTreeIndex table function exposed primary key and minmax index values of the rows hidden by a SELECT row policy on the source table; reading mergeTreeIndex for a table with a row policy is now denied. #115304 (yariks5s).
Data type and serialization fixes
- Fixed an exception in
ARRAY JOINwhenLowCardinalitynumeric types are used. #91784 (Ergus). - Fix
NOT NULLcolumns being silently created asNullablewhendata_type_default_nullable = 1and the table is created in aReplicateddatabase or viaON CLUSTER. #97572 (xiaohuanlin). - Fixed wrong row count returned by a
MaterializedViewquery withquery_plan_enable_optimizations = 0when the view maps anintegercolumn to aBoolcolumn. #100692 (Maximus5). - Fix inconsistent part metadata after mutations of columns with non-default serializations. #102817 (korowa).
- Fix
NULLpropagation when reading subcolumns extracted fromNullable(Tuple(...))columns. For example, fortup Nullable(Tuple(s Nullable(String))),SELECT tup.snow correctly returnsNULLin rows where the outer tuple isNULLinstead of garbage values. This covers all element types that can representNULL:Nullable,Dynamic,VariantandLowCardinality(Nullable(...)). #102942 (nihalzp). - Fixed
recursiveRemoveLowCardinalityerasing custom geometry type names (e.g.LineStringvsRing,MultiLineStringvsPolygon), which caused misinterpretation of the geometry type. #103041 (jh0x). - Fix
dictGetOrNullsilently overwriting other columns in theSELECTprojection withNULLwhen called with aNullablekey column whose values are missing in the dictionary. The function was mutating an input-aliased null map in place; it now deep-clones the result column before mutation. #104327 (groeneai). - Fixed an exception for distributed queries containing an empty
INtuple on the sharding key whenoptimize_skip_unused_shards_rewrite_inis enabled. #104966 (alexey-milovidov). - Fixed count-min statistics
PREWHEREselectivity estimation forFloat32columns, including comparisons withFloat64literals. #105047 (hanfei1991). - Fixed
ILLEGAL_TYPE_OF_ARGUMENTwhen mergingquantileExactWeightedInterpolated,quantileDD, orquantilePrometheusHistogramaggregate states with their pluralquantilesXxxMergecounterparts (and vice versa). The singular and plural variants of these three quantile families share the same internal aggregate state but were not listed in the internal name-mapping table, so cross-function state merge — and the function-fusion optimization for these families — were rejected. #105189 (groeneai). - Fix incorrect results of
toStartOfWeek,toLastDayOfWeek,toMonday,toStartOfMonth,toLastDayOfMonth,toStartOfQuarterandtoStartOfYearforDate32andDateTime64arguments whose result falls outside theDaterange: instead of overflowing into arbitrary dates, results before1970-01-01are now clamped to1970-01-01and results after2149-06-06are clamped to2149-06-06. This also fixes wrong query results (incorrectly pruned parts and granules) when such functions were used inWHEREover aDate32orDateTime64key containing out-of-range values. #105244 (yariks5s). - Fix a logical error in
arrayRemovewhen the first argument is an array ofVariantwhose alternatives are all incompatible with the type of the second argument andvariant_throw_on_type_mismatchis disabled. The function now treats the comparison as “never equal” and returns the array unchanged instead of triggering a server-sideassertTypeEqualityfailure. #105248 (groeneai). - Fix
toFloat64/toUInt32/toString/etc. on Dynamic ignoringcast_keep_nullable. #105467 (Avogar). - Fix a server segfault in
uniqStateOrNull/uniqStateOrDefault/uniqOrNullState(and similar combinator chains overuniq) when used withGROUP BY ... WITH ROLLUP,WITH CUBE, orWITH TOTALSand a Nullable argument. #105470 (groeneai). - Fix
toStartOfMillisecondandtoStartOfMicrosecondreturning a result off by nearly a second for negative (pre-epoch)DateTime64values, and fixUndefinedBehaviorSanitizersigned-integer-overflow intoStartOfSecond,toStartOfMillisecond, andtoStartOfMicrosecondforDateTime64inputs nearINT64_MIN. #105482 (groeneai). - Fixed a server termination when deserializing
singleValueOrNullstates forJSON. #105535 (Avogar). - Fix ignoring
input_format_try_infer_datetimesduring insertion into shared data in JSON. #105544 (Avogar). - Fix
DateTimewrapping around for out-of-range values inJSONExtractand text deserializations. #105551 (Avogar). - Fix crash when inserting tuples of different sizes in the same VALUES clause into a String column. #105582 (Avogar).
- Fixes NOT_IMPLEMENTED error on toString from DateTime with Timezone containing NULL value. #105587 (yariks5s).
- Added validation for malformed flattened
Dynamiccolumns in Native input. #105666 (Avogar). - Fix a
LOGICAL_ERROR(Unexpected return type from if) raised during query planning forifexpressions whose result type isVariantand whose second-or-third branch is a constant-conditionifover aUInt64literal that fits intoInt64. #105680 (groeneai). - Fix
Bad get: has Decimal32, requested Decimal128fromsumMapandsumMapWithOverflowover aNested(... Nullable(Decimal(P, S)))column when the aggregate state is serialised (e.g. parallel replicas,sumMapStatevia a binary-state formatter, external aggregation). #105816 (groeneai). - Fix
Expected ColumnLowCardinality, got String/Bad cast from type DB::ColumnString to DB::ColumnLowCardinalityerrors whenapply_mutations_on_fly = 1is used on a table with pending on-flyUPDATE/DELETEmutations queued before anALTER MODIFY COLUMN ... LowCardinality(...)mutation. #105847 (Algunenano). - Fix
Cannot find columnerror for distributed queries withIN Array(...)filter for the new analyzer. #105894 (KochetovNicolai). - Fixed a server termination when a column with
STATISTICSwas modified toNullablewhile anotherALTERconcurrently dropped it. #105917 (groeneai). - Reject out-of-range
IntervalKindbytes duringRowBinaryWithNamesAndTypestype decoding (input_format_binary_decode_types_in_binary_format = 1) with a clearINCORRECT_DATAerror instead of constructing aDataTypeIntervalwith an invalid kind that could subsequently trip undefined behavior in hash paths. #106261 (groeneai). - Read ‘null’ subcolumn as JSON path in Nullable(JSON) instead of null-map. #106295 (Avogar).
- Fixed an out-of-bounds read in
sipHash64Keyed,sipHash128KeyedandsipHash128ReferenceKeyedwhen hashing a column whose arrays are all empty and the key is not constant. #106355 (Algunenano). - Fixes a bug where users could not use scalar subqueries in the first argument of
INwhere the second argument is a non-constant tuple. #106610 (yariks5s). - Fix
session_timezonebeing ignored when serializingLowCardinality(DateTime)columns to text formats (CSV, TSV, JSONEachRow, etc.). Previously, after the first write of aLowCardinality(DateTime)column on a server, every subsequent query that wrote such a column rendered the wall-clock string in whichever timezone was first seen, regardless ofsession_timezone. #106634 (groeneai). - Fixed a server termination in
ifandmultiIfwhen the condition is a constantNullable(Nothing)value. #106678 (groeneai). - Revert a change that made
sumMap/ the-Mapcombinator reject custom-named numeric value types (such asSimpleAggregateFunction(sum, T)andBool) withILLEGAL_TYPE_OF_ARGUMENT: Values for -Map cannot be summed, breaking previously-working aggregations. #106729 (fm4v). - Fixed a
Bad castexception while pruning parts byMinMaxstatistics when a key column isLowCardinalityand the predicate constant isLowCardinality(Nullable(...)). #106793 (groeneai). - Fix logical error in
parseDateTimewith non-ASCII input bytes. #106856 (Avogar). - Fix
THERE_IS_NO_COLUMNexception for distributed queries involvingoptimize_rewrite_aggregate_function_with_ifoptimization when the aggregate function argument requires a cast to Nullable type. #106908 (yakov-olkhovskiy). - Fixed a signed integer overflow (undefined behavior) in
arrayLevenshteinDistanceWeightedandarraySimilaritywhen the weight arrays contain large integer values. The weighted distance is now accumulated in a wide integer for integral weights, so large integer weights no longer overflow and stay exact. #106934 (groeneai). - Fix a crash (
Source column is not Map/SIGSEGV) when merging sorted blocks that contain aVariantcolumn with aMapvariant whose local storage order differs from its global order. #107011 (groeneai). - Fix
TYPE_MISMATCHerror (“Cannot convert string … to type …”) forORDER BY <numeric column> ... LIMIT nqueries when lazy materialization placed another column before the sort column. The top-K threshold is now read from the correct sort column. #107060 (groeneai). - Fix a compound
ALTER TABLE ... RENAME COLUMN a TO b, RENAME COLUMN c TO athat reuses a freed column name (a “swap”) between columns of different types. The materialized part recorded the wrong column type, so a laterSELECTfailed withConversion between numeric types and IPv6 is not supported(or aborted on part load in debug builds). #107064 (groeneai). - Fixed non-deterministic results of the
roundDownfunction when the boundaries array containsNaN. The same input value could return a finite boundary orNaNdepending on the surrounding rows in a batch.NaNboundaries are now ignored, so the result depends only on the finite boundaries. #107065 (groeneai). - Fixed
quantileTDigestandquantileTDigestWeightedthrowingDECIMAL_OVERFLOWforDateandDateTimearguments when the interpolated quantile is fractional but in range (for examplequantileTDigestWeighted(date, weight)on values that all fit in the type). The fractional result is now truncated to the result type, matchingquantilesTDigestWeighted; genuine out-of-range values still raise an error. #107066 (groeneai). - Fixed silent truncation of out-of-range integer values in
Enum8/Enum16type definitions.Enum8('a' = 200)now throwsARGUMENT_OUT_OF_BOUNDinstead of silently creatingEnum8('a' = -56). #107081 (groeneai). - Fix wrong row order (and a
LOGICAL_ERROR“Rows are not sorted with permutation” in debug builds) for multi-columnORDER BY ... LIMITqueries that sort byNullablecolumns when several rows tie on the leading columns. #107094 (groeneai). - Fix
Logical error: 'Bad cast from type DB::ColumnVector<...> to DB::ColumnTuple'when reading anArray(Tuple(...))column whose value is filled with defaults, e.g. afterALTER TABLE ... ADD COLUMNor after an unfinishedALTER TABLE ... CLEAR COLUMNmutation applied on the fly. #107232 (groeneai). - Reject unsupported uses of
AggregateFunctioncolumns in TTL expressions atCREATE TABLEtime (e.g.TTL toDateTime(state)) instead of failing later during TTL execution withILLEGAL_TYPE_OF_ARGUMENT. This also covers states carried insideVariantalternatives andDynamicvalues. Valid state-aware consumers such asfinalizeAggregationare still accepted. #107366 (Ria-K912). - Fix
arrayResizewith aDecimalsize argument: the size is now interpreted by its real value (e.g.arrayResize([1, 2, 3], 1.5::Decimal(2, 1))returns one element) instead of the raw unscaled representation. #107389 (alexey-milovidov). - Fix
LOGICAL_ERROR: Unexpected return type from materialize(and similar type-mismatch errors) whenapply_mutations_on_fly = 1is used on a table with a pending on-flyUPDATEwhose target column is also read as a function input by an earlier on-flyUPDATE, before anALTER MODIFY COLUMN ... LowCardinality(...)mutation. #107475 (groeneai). - Fix NULL values being silently converted to empty strings when inserting Arrow/ORC data into a LowCardinality(Nullable(…)) column. This was a regression introduced in 26.5. #107532 (Ergus).
- Fixed a
LOGICAL_ERROR(“Input nodes size mismatch in dag”) when a query withmake_distributed_plan = 1joins on a function-wrapped key whose two sides have no common type (for exampleON intDiv(-1, t1.key) = t2.keywith aUInt64right key). #107701 (groeneai). - Fixed insert deduplication computing wrong hashes for
StringandArraycolumns with the server settinginsert_deduplication_version = new_unified_hash: identical inserts could fail to deduplicate because the deduplication hash depended on the row’s position within the inserted block. #107915 (CheSema). - Fixed a server termination in
haswhen searching aMapwithDynamickeys using aLowCardinalityargument. #107956 (groeneai). - Fixed a performance regression for
Mapsubcolumns used withPREWHERE. #107988 (Avogar). - Fix a logical error when casting a
DynamicorVariantcolumn nested inside aTupleto a non-Nullableelement type withaccurateCastOrNulloraccurateCastOrDefault. #108061 (alexey-milovidov). - Fix a
Bad cast from type DB::ColumnSparse to DB::ColumnVector<char8_t>logical error exception when aLIKEquery reads from atextindex via the direct-read fallback path over a column stored sparse. #108068 (groeneai). - Fix a
LOGICAL_ERROR(“Unexpected return type from if”) when reading a column underapply_mutations_on_fly = 1after anALTER UPDATE col = ... WHERE <cond>with a non-constant or false condition followed byALTER MODIFY COLUMN col <new type>. #108128 (groeneai). - Fix
signed integer overflow(undefined behavior) indateDiffwithhourandminuteunits on extremeDateTime64values close to theInt64range limits. #108229 (groeneai). - Fix a server exception (
Logical errorinIColumn::insertFrom) when casting anArray(Dynamic)orArray(Variant)toQBitwithaccurateCastOrNull, e.g.accurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)'). #108288 (groeneai). - Fixes parseDateTimeBestEffort with timezone throwing CANNOT_PARSE_DATETIME on NULL rows of toString(Nullable(DateTime64)). #108310 (yariks5s).
- Fixed a server crash (stack overflow) caused by deeply nested expressions such as
[[[ ... ]]]orarray(array( ... ))whenmax_parser_depthis set to a large value. #108493 (Algunenano). - Fix a
SELECT *projection returning a column’s type default (e.g.0) instead of itsDEFAULTvalue (e.g.-1) when reading a column added withALTER TABLE ... ADD COLUMN ... DEFAULTafter the projection was created. Reads from the base table were already correct; only reads answered by the projection were affected, until the projection was rebuilt. #108569 (tiandiwonder). - Fixed partition and primary key pruning being silently disabled when a
LowCardinality(FixedString)(orLowCardinality(Nullable(FixedString))) key column is wrapped in a function in the key, for examplePARTITION BY sipHash64(k) % NwithWHERE k = 'literal'. Such queries scanned all partitions instead of pruning them. #108777 (groeneai). - Preserve original key order in bucketed Map serialization to fix comparison operations that depend on it. #109178 (Avogar).
- Fix schema inference for the
Arrow,ArrowStream,Avroformats and the legacyORCandParquetreaders returningNullable(Tuple)for nullable struct columns while theNullable(Tuple)type is not allowed (allow_experimental_nullable_tuple_typeis disabled).DESCRIBEreturned a type thatCREATE TABLErejects, so creating a table or inserting data using the inferred schema failed with the errorNullable Tuple type is not allowed. #109185 (nihalzp). - Fixed a bug where column
DEFAULTvalues were not applied forINSERT INTO TABLE FUNCTION(for exampleremote(...)orfile(...)) with inlineVALUESdata when the server parses the inline data itself (send_table_structure_on_insert_with_inline_data = 0). An explicitNULLinserted into a non-Nullablecolumn with aDEFAULTbecame0instead of the declared default. It now behaves like a plain tableINSERTand the HTTP protocol. #109258 (groeneai). - Fix a segfault in
groupArrayLastMerge. Deserialization of aggregated function state is now validated. So a broken state does not lead to OOB. #109485 (mstetsyuk). - Fix segfault in
largestTriangleThreeBucketsaggregate function by rejecting broken aggregate function state at the deserialization level. #109492 (mstetsyuk). - Fix reading a Parquet column with a non-nullable
Tuplewhen the requested ClickHouse type wraps it inNullable(e.g.Nullable(Tuple(...))), which previously failed withTYPE_MISMATCH. #109615 (groeneai). - The Parquet v3 native reader can now read a physically nullable struct column (a Parquet OPTIONAL group) as
Nullable(Tuple(...)). Previously it threwTYPE_MISMATCH. #109898 (groeneai). - Fixed a server crash (native stack overflow) when a deeply nested
Array/Tuple/Map/Objectliteral is copied or destroyed, for example a query with a very deeply nested literal at a raisedmax_parser_depth. #110393 (Algunenano). - Fix wrong
IS NULL/IS NOT NULL/count()results withoptimize_functions_to_subcolumnson a column that was madeNullableby a metadata-onlyALTER MODIFY COLUMN TtoNullable(T). For parts written before the conversion, the.nullsubcolumn was filled from the storage-type default (NULL) instead of being derived from the physically-present parent column, so existing not-null rows were wrongly reported as NULL. #110584 (groeneai). - Fixed a
LOGICAL_ERROR(“Bad cast from ColumnString to ColumnLowCardinality”) during primary-key index analysis when aLowCardinalitykey column is wrapped in a nestedCASTchain that re-introducesLowCardinality, e.g.WHERE CAST(CAST(s, 'LowCardinality(String)'), 'String') < '5'. In debug and sanitizer builds this aborted the server; in release it failed the query. #111050 (groeneai). - Fixed reading
ArrowandArrowStreamdata with empty nestedArrayorMapcolumns produced by Apache Arrow Java before 19.0.0 (bundled with Apache Spark), which were previously rejected with anINCORRECT_DATAerror about the offsets buffer being too small. #111101 (Algunenano). - Fixed a logical error
Block structure mismatch(in debug and sanitizer builds) and anIllegal types of argumentserror for set operations over compatible aggregate-state columns (e.g.quantileStateandquantilesState(0.9)) nested inside container columns such asTuple,Array,Map,Nullable, orVariant. #111191 (alexey-milovidov). - Added validation for corrupted replicated-index data received over the native protocol. #112331 (Avogar).
- Fixed an out-of-bounds read during insert deduplication when an
INSERTpasses through a materialized view that changes the row count before writing to a partitioned target table. #112649 (CheSema). - Fixed an out-of-bounds write when reading a
ParquetDECIMALcolumn whose physical type is wider than the type its declared precision maps to, for exampleDECIMAL(9, 2)stored as physicalINT64. Such files are validParquetand other writers produce them, but the reader sized the destination column from the declared precision while the decoder wrote the physical width, corrupting memory. Reading such a file now also raisesDECIMAL_OVERFLOWwhen a value does not fit the declared precision, instead of returning corrupted data, and reads losslessly with a type hint at least as wide as the physical type. #113046 (groeneai). - Fixed
ATTACH PARTITION FROM,REPLACE PARTITION,MOVE PARTITION TO TABLEand adding aReplicatedMergeTreereplica failing withTables have different ...,METADATA_MISMATCHorINCOMPATIBLE_COLUMNSfor tables whose definitions were written with redundant parentheses, such asPARTITION BY (a),ORDER BY (b),INDEX ix (b * c) TYPE minmax,PROJECTION p (SELECT (b) ...),CONSTRAINT c CHECK (a > 0),TTL (d + INTERVAL 10 YEAR)orDEFAULT (a + 1). #114188 (alexey-milovidov). - Fixes a bug where an access entity carrying a
Map-valued setting, such as a settings profile withhttp_response_headersoradditional_table_filters, is stored in a form that ClickHouse cannot read back, leaving the entity permanently unloadable after a restart. #114620 (groeneai). - Fixes
has,indexOf,countEqual,mapContainsKey,mapContainsValueandMapsubscript returning “not found” for a constantLowCardinalityneedle equal to the element type’s default value, such as an emptyStringor a zero number. #114624 (groeneai). - Fixed wrong results of the trivial
GROUP BY ... LIMIToptimization (settingoptimize_trivial_group_by_limit_query) for queries withDISTINCT,QUALIFY, window functions, orarrayJoinin the projection: these consume or filter the groups after the aggregation, so capping the aggregation atLIMIT + OFFSETkeys could return too few rows or wrong values. The optimization no longer applies to such queries. #114695 (alexey-milovidov). - Fixed wrong results for
SELECT count(arrayJoin(arr))with the defaultoptimize_trivial_count_query = 1. The stored row count was returned instead of the number of array elements, and onfile()andurl()the query returned0. #115227 (groeneai). - Fixed
uniq,uniqExact,uniqHLL12anduniqThetareturning a wrong result for an argument wrapped in an injective function that hides nullability, such asuniqExact(tuple(x))over aNullablecolumn. Theoptimize_injective_functions_inside_uniqoptimization removed the wrapping function, after which NULL rows were skipped instead of counted. #115466 (vdimir). - Allow KeeperMap readers to accept shared metadata when equivalent primary keys differ only by redundant outer parentheses. #115642 (skuznetsov-clickhouse).
Text index and skip index fixes
- Fix server abort when a query uses nested
coalesce/ifNullcomparisons (e.g.WHERE coalesce(a, b, coalesce(c, d), e) = const) on aMergeTreetable with multipleminmaxskip indexes anduse_skip_indexes_for_disjunctions = 1. The skip-index rewrite of<op>(coalesce(...), const)is now applied recursively to inner coalesce arguments, so the per-indexKeyConditionRPN matches the template’s RPN as the disjunction-tracking code already assumes. #103929 (groeneai). - Fix
NOT_FOUND_COLUMN_IN_BLOCKthrown byALTER TABLE ... MATERIALIZE INDEXon parts that were created in 25.8 and contain a skip index over a column that was added with a separateALTER TABLE ... ADD COLUMN. The mutation now correctly reads every column required by every pre-existing skip index and projection on the part during force-recalculation. #105039 (groeneai). - Fixed a silent under-count in
SELECTqueries whenuse_query_condition_cache = 1(default). A query of the shapePREWHERE pk_prefix = X WHERE non_pk IN (...)against a column with a bloom-filter skip index poisoned theQueryConditionCachefor thepk_prefix = Xpredicate, so a subsequent benignSELECT count() ... WHERE pk_prefix = Xreturned an incorrect, under-counted result. Affected all 26.x releases. #105686 (groeneai). - Fixed an exception when a vector search query uses a vector index and uses another skip index like
minmaxanduse_skip_indexes_on_data_read = 1#106473 (shankar-iyer). - Fix “Too many marks” for text index on an empty merged part. #106867 (azat).
- Fixed wrong results when querying a
ReplacingMergeTreetable withFINALand a filter on a text index whilequery_plan_optimize_lazy_finalwas enabled. The lazyFINALoptimization built reading steps that did not reproduce the direct read from the text index, so the filter dropped all matching rows. #106894 (Ergus). - Fix
LOGICAL ERROR(Bad cast from type DB::ColumnString to DB::ColumnLowCardinality) when aVariantconstant containing aLowCardinalitymember is compared to a key column whose key expression is a non-monotonic deterministic function (for example aminmaxskip index oversipHash64(col)). #107111 (groeneai). - Fix wrong (often empty) results from
ORDER BY <col> LIMIT nwhen theuse_skip_indexes_for_top_koptimization is active and a part with aminmaxskip index on the sort column has had rows removed by a lightweightDELETE. The optimization no longer ranks the stale minmax of lightweight-deleted parts ahead of the parts that hold the live top rows. #107320 (groeneai). - Fix set skip index not pruning granules over LowCardinality columns. #107868 (thevar1able).
- The setting
use_skip_indexes_on_data_readcan now be reverted to its pre-26.1 default (false) via thecompatibilitysetting, providing an escape hatch for a performance regression where the on-data-read path defeatsminmax/set/bloom_filterskip-index mark-range pruning. #108330 (egor-click). - Fixed direct read from multiple partially materialized text indexes. #108607 (CurtizJ).
- Fixed a text index defined on
mapValues(map)ormapKeys(map)being silently not used when a table was queried through aDistributedengine table with the analyzer. The index was used for the local table and viacluster()/remote(), but a query through aDistributedengine table skipped it (and failed withINDEX_NOT_USEDunderforce_data_skipping_indices). #109188 (groeneai). - Fixed a server crash on
CREATE HYPOTHETICAL INDEX ... TYPE set(andngrambf_v1/tokenbf_v1) when the required index argument is omitted. Such statements are now rejected with a clear error. #109294 (groeneai). - Fixed wrong results for functions
has,mapContainsKeyandmapContainsValuewith an empty needle when a text index is present. #110246 (rschu1ze). - Fix
ATTEMPT_TO_READ_AFTER_EOFerror when merging parts with a text index if one of the merged parts was empty, for example after a mutation that deleted all rows of the part. #112490 (CurtizJ). - Fixed a query plan optimization stall when a
WHEREclause contains a large string constant with many dots and the table carries abloom_filter,tokenbf_v1,ngrambf_v1ortextskip index. Matching a filter column name againstJSONAllPaths(...)index columns enumerated every dot split of the name, which made skip-index condition building quadratic in the constant’s length. #113289 (groeneai). - Fixed
ORDER BY ... LIMITreturning fewer rows than requested, possibly none, when a row policy was the only filter of the query and the sort column had aminmaxskip index. The top-K optimization narrowed the read before the row policy was applied. #114073 (alexey-milovidov).
Data lake fixes
- Fix logical error exception when reading Iceberg tables whose format version was upgraded by an external tool (e.g. Spark). #100407 (alexey-milovidov).
- Fix an exception (
LOGICAL_ERROR: 'PREWHERE passed to format that doesn't support it') when reading Iceberg tables containing ORC data files with PREWHERE optimization enabled. #101206 (groeneai). - Fix
LOGICAL_ERRORexceptions when readingIcebergorDeltaLakedata lake tables through paths that can reach the read pipeline without a pinneddatalake_table_state, such as concurrentIcebergmetadata updates ormergereads overDeltaLaketables. #102033 (groeneai). - Fix sporadic
Logical error: 'Database <name> not found'fromDataLakeConfiguration::getCatalogwhen anIcebergengine table is loaded inside a regular database during async metadata loading. #103775 (groeneai). - Fix excessive catalog/S3 metadata reads when an INSERT or DDL statement references a non-existent table in a DataLake catalog database with
show_data_lake_catalogs_in_system_tablesenabled. The typo-hint suggestion path loaded full per-table Iceberg metadata for the whole catalog, which could exhaust memory on large catalogs. #104124 (il9ue). - Fix inflated
read_bytes(and the derived bytes/s shown insystem.query_log, progress bar, etc.) when reading Parquet files. The previous implementation reported the row group’s total compressed size on every chunk, so reading K of N columns overcounted byN / K. It is now summed only across the selected columns. Also fixes file-level progress tracking for Iceberg tables, which previously never reported the data file size. #105413 (groeneai). - Fix wrong results when reading an Iceberg table with
iceberg_use_version_hint = 1after another writer (such as theicebergLocal/icebergS3table function) without the setting advances the table.version-hint.textis now kept in sync by every writer once the file exists, so subsequent readers using the hint see the latest snapshot. #105682 (groeneai). - Iceberg writes now preserve NULL values in
Nullable(T)partition columns. Previously, a NULL written by ClickHouse showed up as the default value of the inner type (0forint) when read back by Spark or other Iceberg readers. #105862 (groeneai). - Fixed
Icebergv2 merge-on-read position deletes returning wrong rows when a single delete file references multiple data files and several delete files apply to the same data file. Delete entries are now filtered by their referenced file path. #105888 (groeneai). - Fix
IcebergLocaltable engine becoming read-only after aDETACH+ATTACHcycle or a server restart, which made every subsequentINSERTfail withLocal object storage Local is readonly. (READONLY). #106016 (groeneai). - Fixed the filesystem cache being silently disabled for Azure Blob Storage (e.g. Delta Lake tables over Azure) because object metadata did not include the blob ETag. #106091 (thewisenerd).
- Added path validation for Delta Lake tables to prevent metadata from accessing objects outside the configured storage location. #106115 (scanhex12).
- Iceberg partition pruning now correctly handles
WHERE partition_col = (SELECT ... FROM ...)filters where the analyzer wraps the scalar subquery result in an internal_CAST(Const, 'TargetType')with matching source and target types. Previously such filters disabled partition pruning and triggered a full table scan. #106204 (groeneai). - Fixed
IcebergREST catalogs containing tables being incorrectly reported as empty. #106301 (LefterisXefteris). - Fixed a
NOT_FOUND_COLUMN_IN_BLOCKexception when querying an Iceberg or S3 table with a compoundWHEREcontainingIS NOT NULLon a column that is not in theSELECTlist, using the Parquet V3 native reader. #106443 (tiandiwonder). - Fix inflated progress reporting when reading from Iceberg tables with
_fileor_pathfilters. Previously,total_bytes_to_readprogress included all files from the manifest regardless of filtering. #106491 (PedroTadim). - Fixed a server exception (
std::out_of_rangelogical error) when inserting into anIcebergtable whose write block column names do not match the field ids of the latest schema (for example after a concurrent writer renames a column within theiceberg_metadata_staleness_mswindow). The insert now fails with a clean query error instead of aborting the server. #107279 (groeneai). - Fixed possible server stack overflow (crash) when reading a deeply nested schema or value in the MsgPack, BSON, ORC, Parquet, JSON, DeltaLake, Iceberg and Paimon formats. Such deeply nested input is now rejected with an exception. #107341 (Algunenano).
- Fixed a crash (
LOGICAL_ERRORin debug builds) and a silent wrong-results bug (in release builds) when reading an Iceberg table whose metadata re-binds an existingschema-idto a different schema across metadata versions. Such metadata is now rejected withICEBERG_SPECIFICATION_VIOLATION. #107370 (groeneai). - Fixed reading Iceberg v3 tables whose Parquet data files contain reserved row-lineage columns (such as
_row_id); the native Parquet reader no longer raisesICEBERG_SPECIFICATION_VIOLATIONfor reserved field ids that are not part of the table schema. #107377 (gregakinman). - Fix a spurious
filesystem error: in last_write_time: No such file or directoryexception when listing a local-disk object storage directory (e.g. an Iceberg table on alocaldisk) while files are being concurrently replaced. A concurrently removed entry is now omitted from the listing instead of aborting it. #107432 (groeneai). - Fixed ‘Account must be specified error’ when reading a Delta Lake table over Azure. #107620 (SmitaRKulkarni).
- Fix a crash when reading Iceberg tables with equality delete files. If a column is nullable in the equality delete file but non-nullable in the table schema (or vice versa), the values read from the delete file were inserted into a column of a different type through an unchecked cast (a column type confusion), corrupting the column and crashing the server. #109551 (mstetsyuk).
- Fixed a false
ICEBERG_SPECIFICATION_VIOLATIONerror when reading an Iceberg table whose decimal (or other parameterized primitive) type is serialized with different whitespace across metadata files, e.g.decimal(20,0)in the table metadata anddecimal(20, 0)in the manifest. Such spec-equivalent type strings are now compared ignoring whitespace. #109676 (groeneai). - Fix reading Iceberg tables whose default sort order references a column that needs quoting (e.g.
@timestamp). Such tables were unreadable because the synthesized storageORDER BYwas built from the raw column name and failed to parse withSYNTAX_ERROR. #110233 (groeneai). - Fixed reading Paimon tables that contain a nullable
ARRAYorMAPcolumn. Such a table could not be read at all, because the schema mapper wrapped the composite type inNullable, which ClickHouse forbids, so bothDESCandSELECTfailed withNested type Array(Nullable(Int32)) cannot be inside Nullable type. A nullable composite column is now mapped to a non-Nullablecomposite type and aNULLvalue is read as an empty one. #113450 (groeneai). - Register Iceberg namespace in the catalog before writing table files (needed for SeaweedFS) #114285 (azat).
S3/Azure/object storage fixes
- Fix “Distributed task iterator is not initialized” exception when using
url,s3, or similar table functions in queries with parallel replicas enabled. #100146 (alexey-milovidov). - Fixed a possible server segfault in cluster table functions (
s3Cluster,urlCluster,fileCluster, …) when the planner produces aSELECTwith therecursive_withflag set but noWITHexpression. #105433 (groeneai). - Fixed
ParquetandORCfilter pushdown forIN (subquery)predicates, allowing row-group/page/bloom-filter pruning to work forfile,url,s3, and object-storage reads. #105863 (arsenmuk). - Fix
LOGICAL_ERRORexception during cache predownload when a remote S3 object is overwritten with shorter content between listing and reading. #106375 (fm4v). - Fix the
s3table function silently ignoring a lowercase positionalpartition_strategy(e.g.hive). #107297 (jkartseva). - Fixed a regression where setting
compatibility = '26.6'(which implicitly enables thehivepartition strategy) silently accepted{_partition_id}inS3and object-storage table paths instead of raisingBAD_ARGUMENTS. #107437 (LefterisXefteris). - Fixed
s3and other object storage table functions throwingLOGICAL_ERRORinstead ofBAD_ARGUMENTSwhen a key-value argument is duplicated, e.g.s3('http://...', format = 'CSV', format = 'TSV'). #107670 (groeneai). - Fixed a server exception (
Logical error: 'index >= result.start') when formatting a malformed query that mixes the positional and named secret-argument forms of thes3/gcstable functions, e.g.s3('url', 'a', 'b', secret_access_key = 'c'). #107818 (groeneai). - Fix S3 settings priority so a URL-scoped
<s3>endpoint block takes precedence over the top-level<s3>defaults. #109251 (bharatnc). - Fix
411 Length Requirederrors from Azure services: the Poco-based Azure HTTP transport now setsContent-Lengthfrom the request body for SDK clients that do not set the header themselves (e.g. Azure Key Vault). #110299 (thevar1able).
S3Queue fixes
- Fix a server crash (out-of-bounds access) in
S3Queue/AzureQueuewithenable_hash_ring_filtering = 1when a batch contained a non-processable file and the Keeper request to set the batch as processing failed at the same time. #108977 (groeneai). - Fix credential leaks in
SHOW CREATE,system.query_log, server logs andEXPLAINoutput. EveryS3locator form now maskssession_tokenand Google ADC secrets,extra_credentials/headersvalues at any argument position, duplicated or expression secret keys, invalid positional forms (fail closed), and credentials embedded in S3 URLs; this covers the explicit-url and named-collections3/s3Clustertable functions, the S3-backed table engines (S3,GCS, the data-lake engines,S3Queue), theS3database engine,BACKUP ... TO S3and theBackupdatabase engine. In addition, secret arguments ofencrypt/decrypt/HMAC that are built by an expression (including ones inlined from a SQL UDF) are now hidden in projection names,EXPLAIN QUERY TREEandEXPLAIN actions. #109768 (Algunenano). - Fix
S3Queue/AzureQueueordered mode with persistent processing nodes: bucket locks are now refreshed during streaming, so that the TTL cleanup (persistent_processing_node_ttl_seconds) does not remove locks of a live processor. If lock ownership is nevertheless lost, it is detected and reported (a logical error and theObjectStorageQueueBucketLockLostOwnershipprofile event), and streaming recovers with a fresh file iterator. #110292 (kssenii).
Security and access control fixes
- Fix a server crash (SIGSEGV) reachable by any user with
CREATE TABLErights when sendingCREATE TABLE ... TO INNER UUID '...'without anENGINEclause over HTTP or the native protocol. The same bug also crashed the client. The parser now reports a properBAD_ARGUMENTSerror instead of dereferencing a null pointer. #105579 (groeneai). - Fixed a server crash when querying DeltaLake tables with
allow_experimental_delta_kernel_rsenabled and a credential or option that contained invalid bytes (the Rust FFI panicked across theextern "C"boundary). #106109 (Algunenano). - Fix multiple heap out-of-bounds reads in the Arrow IPC format reader (
ArrowColumnToCHColumn). A malformed Arrow file could declare more rows than its buffers contain, declare list/struct/map child lengths inconsistent with their parent, supply non-monotonic list offsets, or truncate a child validity bitmap, causing reads past the end of heap allocations. This is reachable by any user withSELECTprivilege viafile(),format(), table functions, or ArrowFlight inputs. All data, offsets, view-struct, and validity-bitmap buffers are now validated before any raw pointer access, and list/struct/map shapes and offsets are checked for consistency. #106395 (Algunenano). - Fixed a bug where the
used_privilegesandmissing_privilegescolumns ofsystem.query_logcould contain privilege strings leaked from unrelated earlier queries of a different user, database, or session. #106425 (alexey-milovidov). - Fixed a heap buffer overflow (server crash) in
decodeHTMLComponentwhen decoding strings containing the expanding HTML entities≫⃒or≪⃒, reachable by any user with a singleSELECT. #106741 (Algunenano). - Fixed wrong query results caused by the query condition cache when on-fly mutations (
apply_mutations_on_fly) or patch parts filtered rows beforePREWHERE. A query reading withapply_mutations_on_fly = 1could poison the cache so that a later query withapply_mutations_on_fly = 0and the same predicate skipped marks it should have read and returned too few rows. The same fix also covers row-level security policies, which are prepended as a filter ahead ofPREWHERE: a query run under a restrictive row policy could poison the cache for a later query that uses the same predicate without that policy. #107145 (groeneai). - Fixed a heap buffer overflow (server crash) in
windowFunnelwhen finalizing a crafted aggregate-function state with an out-of-range event type, reachable by any user with a singleSELECT. #107412 (uwezkhan). - Fixed
currentUser(),user(),SESSION_USERandauthenticatedUser()evaluating to an empty string on the asynchronous insert flush path (withasync_insert = 1). This affectedDEFAULT/MATERIALIZEDcolumn expressions and materialized views that reference these functions, which silently stored an empty string instead of the inserting user. #107541 (groeneai). - When several quotas are assigned to the same user or role, all of them are now enforced together (a query is rejected if any of them is exceeded), instead of only one quota being enforced and chosen non-deterministically.
SHOW QUOTAandsystem.quota_usagenow show all quotas enforced for the current user. #107664 (alexey-milovidov). SYSTEM RESET DDL WORKERnow requires the newSYSTEM RESET DDL WORKERprivilege. Previously any authenticated user (includingreadonlyones) could run it and repeatedly reset the DDL worker state, blockingON CLUSTERDDL. #108460 (groeneai).- Fixed
ssl_certificateuser identification so a single*wildcard matches exactly one name component (RFC 6125 6.4.3). Previously a wildcard in aCNorDNS:SAN subject (for example*.corp.example.com) also matched multi-label names such asevil.deep.corp.example.com, letting a holder of a certificate for a deeper subdomain authenticate as the wildcard user.URI:SAN matching is unchanged. #108472 (groeneai). - The MySQL wire protocol commands
COM_FIELD_LIST(mysql_list_fields) andCOM_INIT_DB(USE database) now enforce the same access control as their SQL equivalents (SHOW COLUMNS/DESCRIBEandUSE). Previously they could disclose column names of tables the user only had partial column grants on, and switch the current database without theSHOW DATABASESprivilege. #108508 (groeneai). - Match
http_forbid_headerscase-insensitively. HTTP header names are case-insensitive, so forbiddingAuthorizationnow also blocksauthorization,AUTHORIZATIONand other case variants. Configuredheader_regexppatterns are now matched case-insensitively without needing an explicit(?i)flag. #108509 (groeneai). - Fix a metadata-disclosure where
DESCRIBE loop('db', 'table')andDESCRIBE loop(<inner table function>)bypassed theSHOW COLUMNS/ source access check, letting an unprivileged user read a table’s column schema. #108624 (groeneai). - Fixed a startup failure where a
DataLakeCatalogdatabase created by an older version (25.12 or earlier) with a malformedauth_headercould not be attached after upgrading to 26.2 or later, preventing the server from starting. Theauth_headeris now validated only onCREATE, and onATTACHthe catalog is built lazily on first use instead of during startup, so a single misconfigured or unreachable catalog database no longer blocks server startup. #108674 (groeneai). - Hardened RabbitMQ connections against maliciously large AMQP frames and applied
remote_url_allow_hostschecks consistently torabbitmq_address. #112479 (kssenii). - Fixed a case where
CREATE TABLE ... ENGINE = Distributed(...)without a column list could reveal the structure of a local table the creating user is not allowed to see. For aCREATEthe local server executes itself, the structure is now inferred under the user’s own context, soSHOW COLUMNSon the target table is required, as it already is for theRemoteengine. ACREATEreplayed from the DDL queue (ON CLUSTER, or one inside aReplicateddatabase) is not covered. #113220 (groeneai). - Fixed a case where
CREATE TABLE ... ENGINE = Buffer(...)without a column list could reveal the structure of a destination table the creating user is not allowed to see. For aCREATEthe local server executes itself, the structure is now inferred under the user’s own context, soSHOW COLUMNSon the destination is required, as it already is forMergeandRemote. ACREATEreplayed from the DDL queue (ON CLUSTER, or inside aReplicateddatabase) is not covered. #113372 (groeneai). - Bound the size of the startup message of the PostgreSQL wire protocol, which is read before authentication. #115708 (alexey-milovidov).
Backup and restore fixes
- Fix a server abort during
RESTOREof backups containing tables with cyclic dependencies. #103824 (thevar1able). - Fixed the S3 storage class (
s3_storage_class/s3_storage_class_name) being ignored for objects written via multipart upload onS3disks and object storage, which caused large objects to be created with the defaultSTANDARDclass. The option name is now accepted both ass3_storage_classands3_storage_class_namefor disks, object storage and backups. #106214 (alexey-milovidov). - Fixed
SYSTEM RELOAD CONFIGdiscarding per-endpoint Azure Blob Storage settings (such asuse_native_copy), which caused a disk’s configured settings to be ignored forBACKUP/RESTOREuntil the server was restarted. #106357 (jkartseva). - Fixed backups failing with FILE_DOESNT_EXIST when a refreshable materialized view’s REPLACE target is collected on a Replicated or Shared database whose materialized view isn’t yet instantiated on the backup-initiating replica. #106411 (jkartseva).
- Fixed Azure BACKUP/RESTORE ignoring endpoint settings for legacy-form
azure_blob_storagedisks. #106784 (jkartseva). - Fixed
BACKUPtoAzureBlobStorage: copying a data file inside a backup wrote the destination object outside the backup directory. Backup object existence checks onS3destinations now use exactHeadObjectrequests instead of prefix listing, preventing false matches of similarly-prefixed keys. #107153 (pamarcos). - Incremental backups no longer store
S3credentials in the<base_backup>locator of the.backupmetadata file. Backups created withuse_same_s3_credentials_for_base_backup = 1, or with explicit base backup credentials matching this backup locator, store a non-secret marker and are restored without extra restore-time settings; for backups created with different explicit base backup credentials or extra base authentication arguments, pass them toRESTOREwith thebase_backupsetting. Backups created by older versions with embedded credentials remain restorable. #107357 (pamarcos). - Fixed
RESTOREforReplicatedMergeTreetables so duplicate-content parts from a backup are preserved instead of being silently deduplicated. #107652 (pamarcos). - A
{_partition_id}placeholder in the path of a file-like engine (S3,AzureBlobStorage,URL, etc.) with no explicitpartition_strategyimplies thewildcardstrategy again, regardless offile_like_engine_default_partition_strategy. This restores backward compatibility for pre-26.6 DDL that started failing withBAD_ARGUMENTS(“Partition strategy hive can not be used with a ‘_partition_id’ wildcard in the path”). #111279 (fm4v).
ClickHouse Keeper fixes
- Fix
Keepersnapshot cleanup after failed writes so partial snapshots are cleaned up safely and failed writes can be retried without advancinglatest_snapshot_meta. #105779 (antonio2368). - Fix
Keeperfailures during follower catch-up when the new request dispatcher response queue could fill before the response thread started. #106049 (antonio2368). - Fixed Keeper sometimes getting stuck on startup when setting
nuraft_max_log_gap_in_streamis set to non-default value (default is 0, i.e. disable pipelining of append_entries requests). #106220 (al13n321). - Keeper’s internal Raft TLS now honors the
openSSL.client.verificationModesetting. Previously peer certificate verification was always enabled for inter-Keeper Raft communication regardless of this setting, sononewas silently ignored. Nownoneexplicitly disables Raft peer-certificate verification, while an absent setting keeps the previous secure-by-default behavior. Configurations that explicitly setnonewill stop verifying Raft peer certificates after upgrade, matching the configured intent. #106726 (antonio2368). - Fix spurious ZooKeeper session recreation on config reload. #107096 (azat).
- Fixed a bug in ClickHouse Keeper where the snapshot metadata reported via
last_snapshot(andzk_latest_snapshot_sizeinmntr) could move backwards after a stale or duplicated snapshot install, which could also let a same-index local snapshot overwrite a registered snapshot file in place while it was still being streamed to a peer or uploaded to S3. #107321 (antonio2368). - Fixed refreshable materialized view getting stuck if zookeeper connection is lost at the wrong moment. #108234 (al13n321).
- Fix mutations with a query parameter as the partition (
ALTER TABLE ... UPDATE/DELETE ... IN PARTITION {param:Type}): the substituted partition value was serialized into the mutation entry in a form that could not be parsed back, which broke loading of the table (for replicated tables, on every replica). Mutation commands are now also verified to be parseable back before they are written to ZooKeeper or disk, so that a similar mismatch would fail theALTERquery instead of breaking the table. #111518 (al13n321). - Fixed numeric overflow while parsing data for
system.zookeeper_info. #111629 (kssenii).
Crash and stability fixes
- Fix NOT_FOUND_COLUMN_IN_BLOCK exception when using LIMIT BY with constant columns alongside DISTINCT and ORDER BY with the new analyzer. #93195 (ashrithb).
- Fixed HiveCatalog connection stability by adding automatic retry mechanism and reconnection logic for handling TTransportException errors when communicating with Hive Metastore. #98471 (otselnik).
- Fix analyzer-time constant folding for short-circuit functions (
if,multiIf,and,or, etc.) so that statically unreachable branches no longer raise exceptions at analysis time. For example,WITH 0 AS n SELECT multiIf(n = 0, 0, intDiv(100, n))now correctly returns0instead of failing with a division-by-zero error. #103157 (fastio). - Fixed a server termination when
runningAccumulatewas called on an aggregate function that returns its own state. #105085 (antaljanosbenjamin). - Fix
getServerSettingto return the live effective value for runtime-changeable server settings (such asmax_server_memory_usage,mark_cache_size,max_concurrent_queries, thread pool sizes, etc.), matching whatsystem.server_settingsreports. #105172 (alexey-milovidov). - Fix
NOT_FOUND_COLUMN_IN_BLOCKexception when combiningORDER BY ... WITH FILL INTERPOLATEandLIMIT N BYwith the analyzer enabled. #105481 (yakov-olkhovskiy). - Fix a server exception (
Trying to execute PLACEHOLDER actionlogical error) when aMATERIALIZEDCTE whose body is a correlated subquery is used as the right-hand side ofIN. Such a CTE is now rejected at analysis time, consistent with how the same pattern is already rejected when the CTE is referenced directly inFROM. #105518 (groeneai). - Fix
variant_throw_on_type_mismatch/dynamic_throw_on_type_mismatch=falsenot catching exceptions during function execution. #105543 (Avogar). - Fix NOT_FOUND_COLUMN_IN_BLOCK exception when TTL expression references a subcolumn. #105578 (Avogar).
- Fixed a server crash that could occur when a query reading from PostgreSQL — via the postgresql table function, the PostgreSQL table engine, or a dictionary with a PostgreSQL source — was cancelled (for example with KILL QUERY) and cancelling the remote PostgreSQL query failed. #105949 (rorylshanks).
- Fixed a possible crash due to a too-large string literal sent within the query. #105996 (nickitat).
- Fix
INVALID_WITH_FILL_EXPRESSIONexception when usingINTERPOLATE ()(empty) with a sorting prefix inORDER BYanduse_with_fill_by_sorting_prefixenabled. Sorting prefix columns are now correctly excluded from the implicit interpolation set, matching the behavior of explicitly namedINTERPOLATE (col). #106001 (yakov-olkhovskiy). - Malformed
AggregateFunction(uniqTheta, ...)states fromRowBinaryinput or query parameters are now rejected withCORRUPTED_DATAinstead of terminating the server. #106260 (groeneai). - Fix a crash and a possible
NOT_FOUND_COLUMN_IN_BLOCKerror when constraint-based optimization (optimize_using_constraints) is used with correlated subqueries. #106349 (Algunenano). - Fix
NUMBER_OF_COLUMNS_DOESNT_MATCHexception when querying aDistributedtable that has two or more ALIAS columns expanding to the same expression (e.g. both defined astoString(x)), or when the same expression is written both as an ALIAS column reference and directly in the SELECT list, with anORDER BYclause. #106404 (yakov-olkhovskiy). - Fixed a
LOGICAL_ERROR“Trying to get name of not a column:ExpressionList” raised by queries that pass an asterisk insidemultiIfto a table function argument, e.g.numbers(multiIf(*, ...), 2). The query now rejects the unresolvable matcher withUNSUPPORTED_METHOD. #106647 (groeneai). - Reject pathological
fileglob patterns that would cause unbounded recursion in directory listing. A maximum recursion depth of 1000 is now enforced; queries that exceed it raiseTOO_DEEP_RECURSIONinstead of aborting the server with a stack overflow. #106676 (groeneai). - Fix exception
'Trying to read from input() twice.'raised when the table functioninputis wrapped in a non-MATERIALIZED CTE that is referenced from more than one place in the query. The query is now rejected with a cleanINVALID_USAGE_OF_INPUTerror at planning time.inputis a one-shot client stream and can only be consumed by a single source in the query plan. #106682 (groeneai). - Fix inconsistent columns (that leads to LOGICAL_ERROR later) on exception (i.e. MEMORY_LIMIT_EXCEEDED) during parsing. #106802 (azat).
- Fix server crash (SIGSEGV) when reading truncated Protobuf data with
input_format_allow_errors_num > 0. #106905 (atsarevskiy). - Fix a server crash (null pointer dereference) when running
TRUNCATEorDROPon anEmbeddedRocksDBtable whose RocksDB handle was released, for example aread_onlytable whose data directory was emptied by a priorTRUNCATE. #106940 (groeneai). - Fix an exception (
std::length_errorreported as aLOGICAL_ERROR) when reading from a*Clustertable function such asurlClusterwith a very largemax_streams_for_files_processing_in_cluster_functionssetting. The number of streams is now bounded to a sane value. #106946 (groeneai). - Fixed a server termination when a distributed query was cancelled immediately before being sent to a shard. #106950 (groeneai).
- Fixed a server exception (logical error
this->visited_views == right->visited_views) onINSERTwhen two materialized views on the same source table write to the same target table and a dependent view reads that target, withmaterialized_views_squash_parallel_insertsenabled. #107027 (groeneai). - Fixed a
LOGICAL_ERRORexception when inserting into a DeltaLake table with columns that do not match its write schema (for example aNestedcolumn that flattens to subcolumns, or a table function with an explicit column subset). Such inserts now fail with a user-facingINCOMPATIBLE_COLUMNSerror instead. #107058 (groeneai). - Fix a
LOGICAL_ERROR(“Table expression … data must be initialized”) raised when a qualified asterisk matcher (for examplex.*) referenced a recursive CTE by name inside its own recursive term. Such matchers now expand the recursive table’s columns, the same way a qualified column (x.a) or an unqualified matcher (*) already does in that position. #107144 (groeneai). - Fixed a
LOGICAL_ERROR(“Unexpected exception in refresh scheduling”) that could put the server into a crash-loop on restart when a refreshable materialized view has aREFRESH ... DEPENDS ON <name>dependency whose unqualified name matches a temporary table or a CTE name. #107156 (groeneai). - Fix a
LOGICAL_ERROR(Variant N (T) has size X, but expected Y) when a function such astoStringorconcatis applied to aVariantorDynamiccolumn that holds a single non-empty variant together with NULLs, and the function returns its input column unchanged. #107374 (groeneai). - Fix a
LOGICAL_ERROR(block.rows() == getRows()) raised on an asyncINSERTinto anAliastable whenuse_strict_insert_block_limitswas enabled. #107400 (groeneai). - Fix a server exception (
Logical error: Not-ready Set is passed as the second argument for function 'in') when a key expression (ORDER BY,PRIMARY KEY,PARTITION BY, or a skipINDEX) contained anINoperator with a table on the right-hand side, e.g.ORDER BY (x IN some_table). Such key expressions are now rejected at table creation time. #107424 (groeneai). - Fixed a rare server crash in
DISTINCTprocessing that could occur when an allocation failed (for example, when hitting a memory limit) while the set of distinct keys was being initialized. #107467 (groeneai). - Fixed
DeltaLakeoperations failing after temporary S3 credentials expired by refreshing cached credentials before the next operation. STS assume-role credentials are also refreshed after authentication failures. #107480 (ahmadov). - Fixed a
Not-ready Set is passed as the second argument for function 'in'(LOGICAL_ERROR) when querying a table with aPARTITION BYkey and anIN/NOT INsubquery wrapped inside a larger expression, for exampleWHERE (c0 IN (SELECT ...)) != 0. #107515 (groeneai). - Fix a crash (null pointer dereference) that could happen when a distributed query plan was executed locally (
make_distributed_plan+distributed_plan_execute_locally) withlog_formatted_queries = 1. #107570 (groeneai). - Fix a server crash when reading a materialized view whose target is a
Distributedtable while the query runs withenable_analyzer = 0. #107653 (groeneai). - Fix server crash (SIGSEGV) when reading Protobuf data with
input_format_allow_errors_num > 0and a valid message precedes a bad (skippable) message in the same block. #107739 (atsarevskiy). - Fixed the
odbcandjdbctable functions hanging for minutes and ignoring query cancellation (KILL QUERY,max_execution_time) when the bridge becomes unresponsive while inferring the remote table structure. #107809 (alexey-milovidov). - Fixed a possible crash (null pointer dereference) when the
database/dboverride of a named collection passed toremote()/remoteSecure()is not a constant database name, e.g.remote(nc, database = (SELECT 1)). The query now fails with a clear error instead of crashing. #108271 (groeneai). - Vector search queries that SELECT from the
_distancecolumn now return a proper error instead of failing with aLOGICAL_ERROR. #108423 (rschu1ze). - Fixed a possible crash (heap-buffer-overflow) when a
quantileTDigest-family aggregate-function state column was used as aGROUP BYkey and serialized concurrently by several threads. #110263 (groeneai). - Fix incorrect pruning from primary key index analysis on tables with a reverse (descending) sorting key (
ORDER BY (g, r DESC)). A granule spanning a change of a leading key column followed by a descending key column could be pruned incorrectly, dropping matching rows. #111059 (nihalzp). - Fix a logical error
block.rows() == getRows()(an out-of-bounds read and broken insert deduplication in release builds) when anINSERTflows through a dependent materialized view whose target is anAliasand whose inner query changes the number of rows, with a deduplicating table reachable behind the alias hop. #111103 (alexey-milovidov). - Fix a segfault due to out-of-bounds memory access when deserializing a malformed aggregate function state containing a
Stringvalue. Such states are now validated and rejected instead of leading to segfaults. #111606 (mstetsyuk). - Fixed a crash when reading a Parquet file with inconsistent bloom filter metadata. Such files could also silently return fewer rows than they should. #112498 (tiandiwonder).
- Fixes a segfault and silent data corruption when an
INSERTinto theFileengine or thefiletable function appends to a non-empty file in a format that does not support appending, such asAvro. Writing through a file descriptor or a partitioned path bypassed the existing check, so the format prefix was suppressed and a second header was written after the existing bytes, leaving the file unreadable. Such anINSERTis now rejected withCANNOT_APPEND_TO_FILE, as it already is for a plain path. #112839 (groeneai). - Fix
DROP TABLEandSYSTEM STOP VIEWhanging when a Refreshable Materialized View is blocked while planning its refresh query. #113188 (evillique). - Fixed a rare server termination when asynchronous insert queue entries had identical deadlines. #113363 (mstetsyuk).
- Fixed heap memory corruption when reading Parquet through an input format that owns its read buffer, for example a dictionary with
SOURCE(FILE(... format 'Parquet')). Background prefetch and decode tasks could still read and write through the buffer after the pipeline released it, which could abort the server. #114668 (groeneai). - Fixed a hang when dropping a
TimeSeriestable whose name sorts lexicographically below its inner tables’ names, for example a table named-ts, or when dropping a materialized view declared withENGINE = TimeSeries. The drop self-deadlocked on the DDL guard and could not be cancelled withKILL QUERY. #114953 (groeneai).
Other bug fixes
- Functions
like,ilike,notLike,notILike, andmatchnow support constant haystack with non-constant needle (e.g.'foo' LIKE pattern_column), which previously threwILLEGAL_COLUMN. #100479 (Onyx2406). - Fix
NOT_FOUND_COLUMN_IN_BLOCKerror when selecting from a VIEW over a table with a normal projection. #101218 (amosbird). - Reject negative Float64 values (e.g.
-100.5) in workload settings likemax_bytes_per_second,max_cpus, etc. Previously only negative integers were validated, allowing negative floats to silently create broken scheduler nodes. #101842 (groeneai). - Object-storage reads now respond promptly to query cancellation. #103016 (SmitaRKulkarni).
- Fixed
input_format_max_block_size_bytesbeing silently ignored duringINSERTparsing whenmax_insert_block_size_bytesis0(the default). The setting now correctly limits the size of blocks produced by row input formats. #103068 (Fgrtue). - Fixed ClickHouse occasionally producing invalid GSSAPI tokens due to incorrect stripping of trailing null bytes. #103114 (EmeraldShift).
- EXPLAIN SYNTAX expands Parameterized Views. #103263 (jrdi).
- Fix data corruption when writing Parquet (and other trailer-bearing formats such as ORC and Arrow) to HDFS via
INSERT INTO FUNCTION hdfs(...). Since 26.1,WriteBufferFromHDFSdid not flush its working buffer onfinalize(), so the last up toDBMS_DEFAULT_BUFFER_SIZEbytes of every file were silently lost, including the ParquetPAR1footer. Reading such files returnedNot a Parquet file (wrong magic bytes at the end of file). #103268 (groeneai). - Fix wrong results and a possible logical error for correlated subqueries when a join size limit (
max_rows_in_join/max_bytes_in_join) is set together withjoin_overflow_mode = 'break'. The join created internally to evaluate a correlated subquery now ignores those user limits, so it can no longer stop early and drop rows. #103322 (groeneai). - Fix wrong results or missed projection when an aggregate projection contains multiple
sumIfaggregates with differentIN (...)conditions. #104765 (Ergus). - Fix
deltaSumTimestampreturning wrong results for signed integer types crossing zero. #104830 (thevar1able). - Fix
Logical error: 'Metadata is not initialized'raised byDELETE FROMon a freshly-attachedIceberg,DeltaLake, orHuditable whose metadata file is corrupted or unloadable. A regular user-facing exception is reported instead, and the server keeps running. #104917 (groeneai). ATTACH TABLE name <clauses>;queries that supply storage clauses (ORDER BY,PARTITION BY,PRIMARY KEY,SAMPLE BY,TTL,UNIQUE KEY, or engineSETTINGS) without anENGINEnow throwBAD_ARGUMENTSinstead of silently re-attaching the table with its stored definition and discarding the user-supplied clauses. Query-level sessionSETTINGS(such aslog_comment) are still applied. UseATTACH TABLE t;to re-attach with stored metadata, orALTER TABLE t MODIFY SETTING ...afterATTACHto change settings. #105068 (groeneai).- Fixed a heap-buffer-overflow when reading Arrow or ArrowStream files with corrupted intermediate offsets in a binary or string column, and a null-pointer dereference when reading geo-tagged Arrow columns. #105449 (Algunenano).
- Fixed a server termination when reading
Dynamicsubcolumns from a compressedMemorytable afterALTER. #105464 (Avogar). - Include
skip_first_linesin schema cache key forWithNamesformats. #105469 (Avogar). - Fix
histogramproducing wrong results for small unsorted inputs. #105548 (Avogar). - Fix usage of insertion table in table functions when
optimize_trivial_insert_selectis enabled. #105555 (Avogar). - Fix
estimateCompressionRatiowindow function losing accumulated data between rows. #105581 (Avogar). - Hive partition value extraction now honors the
cast_string_to_date_time_modesetting and accepts ISO 8601 timestamps with timezone suffixes (e.g.+0000,+00:00,Z) in partition keys by default. #105584 (alexey-milovidov). - Fix
Templateinput format error recovery after malformed rows. #105735 (niyue). - Fix
SYSTEM INSTRUMENT ADDformatting so handler arguments are separated by a single space, and reject invalidSLEEPinstrumentation argument lists with more than two values or a range where the minimum is greater than the maximum. #105984 (pamarcos). - Fix ALTER TABLE partition operations silently failing for Bool partition keys. #106004 (Avogar).
- Fix
JSONExtractRawandJSONHasfor typed JSON paths with default values. #106005 (Avogar). - Fixed an incorrect
/prefix on empty base paths in data lake configurations. #106013 (thewisenerd). - Fix
system.dictionariesreturning 0 rows with partialSHOW DICTIONARIESrevoke. #106105 (Avogar). - Fix incorrect results for queries against tables whose
ORDER BYcontains a monotonically decreasing function such as(c0 / -42)orintDiv(c0, -42). Predicates on the underlying column (for example,c0 < 0) could wrongly prune granules that contained matching rows, producing missing results. #106136 (nihalzp). - Added validation for malformed
DDSketchaggregate states during insertion. #106236 (yariks5s). - Fixed filesystem-cache consistency after failed
SLRUdowngrades, preventing entries from remaining stuck in an eviction state. Also fixedSystem/Datasplit-cache resizing and free-space cleanup so limits are updated atomically and space can be reclaimed from both cache segments. #106286 (kssenii). - Fixed an incorrect conversion of subnormal
Float16values toFloat32(e.g. when reading them from Numpy.npyfiles), caused by an off-by-one mantissa shift. #106343 (jh0x). - Fix
regexpExtract(haystack, pattern)so that patterns without a capturing group return the whole match instead of throwingINDEX_OF_POSITIONAL_ARGUMENT_IS_OUT_OF_RANGE. #106374 (groeneai). - Fix a logical error when building a polygon dictionary from source data containing
NaNor infinite point coordinates. Such coordinates are now rejected with a clear error. #106423 (alexey-milovidov). - HTTP dictionaries can now specify request headers through named collections. #106459 (ZelvaMan).
- Malformed
Avroenum values are now validated and rejected with an exception instead of causing out-of-bounds memory access and server termination. #106476 (mstetsyuk). - Fix
LIMIT WITH TIESand fractionalLIMIT WITH TIESnot respecting the collation fromORDER BY ... COLLATEwhen determining ties. Rows that are equal according to the collation (for example'1'and'01'under numeric collation) were compared byte-wise, so some tied rows were wrongly dropped from the result. #106539 (nihalzp). - Fix
DISTINCTin order andLIMIT BYin order optimizations (including negativeLIMIT BY) returning wrong results when the input is sorted with a collation (ORDER BY ... COLLATE). Rows that are equal according to the collation (for example'a'and'A'under a case-insensitive collation) are ordered by collation key and are not adjacent by value, so the in order optimization is now skipped when a collator is used. #106564 (nihalzp). - Fixed a race during NATS consumer shutdown that could terminate the server. #106692 (mstetsyuk).
- Fixed multiple memory-safety and resource-exhaustion issues in format readers reachable from untrusted input: a heap out-of-bounds read in the native Parquet reader’s
DataPageV2definition/repetition level-length handling, a stack overflow on Parquet files with deeply nested schemas, and allocations that ignoredmax_memory_usagewhen parsing GeoParquet WKB/WKT geometry and Avro strings/bytes. #106739 (Algunenano). - Fixed
keeper_server.http_control.secure_portserving plaintext HTTP responses to HTTPS clients. The secure port now serves HTTPS correctly. #106822 (linjiayu1025-collab). - Fix
SHOW CREATE ROW POLICYemittingrestrictive/permissivein lowercase instead of uppercase, inconsistent with other keywords. #106865 (valerypetrov). - Fixed parts being marked as broken and detached on any part reload (server restart,
DETACH, orATTACH) for tables with aLowCardinality(Nullable(...))column in the partition key. Since 26.5, the per-part minmax index file was not written when such a column’s minimum and maximum wereNULL, while the part consistency check still required the file. Parts written by affected versions lack the minmax index file and still need to be reattached manually. #106945 (PedroTadim). - Fixed
elapsed_usalways being zero, andread_rows/read_bytesbeing undercounted, insystem.processors_profile_logandsystem.query_logfor asynchronous insert flush (AsyncInsertFlush) queries. #106982 (cwurm). - Fixed a
Block structure mismatch in UnionStep streamlogical error (server abort on debug/sanitizer builds,Code: 49on release builds) that occurred when one branch of aUNION/INTERSECT/EXCEPTread aSparse-serialized column while the sibling branch read the same column as a full one (for example when pushing to a materialized view). #107041 (groeneai). - Fixed incorrect row order in
ORDER BYqueries overUNION ALLwithoptimize_read_in_orderandread_in_order_use_virtual_rowenabled. #107053 (vdimir). - Fixed a syntax error when a
FORMAT,SETTINGS, orINTO OUTFILEclause followsSHOW ROW POLICIESorSHOW MASKING POLICIES(e.g.SHOW ROW POLICIES FORMAT TabSeparated). #107061 (groeneai). - Fix
trimLeft,trimRight, andtrimBoth(and aliasesltrim,rtrim,trim) throwingTOO_LARGE_STRING_SIZEwhen the custom trim character set is longer than 16 characters. Trim sets of any length are now supported again. #107071 (fm4v). - Fixed a signed integer overflow in
quantileExactExclusive,quantilesExactExclusive,quantileExactInclusiveandquantilesExactInclusivethat could produce a wrong result forInt64inputs spanning a large range. #107154 (groeneai). - Configuration reloads no longer rerun startup scripts, preventing one-shot startup actions from executing again. #107187 (mstetsyuk).
- Fix incorrect result order for
ORDER BYoverUNION ALLwithoptimize_read_in_orderenabled when the union pipeline was narrowed due tomax_streams_for_union_stepsettings; narrowing is now skipped when the plan relies on sorted UNION output streams. #107208 (vdimir). - Fixed a possible null pointer dereference while resolving proxy configuration during late server shutdown. #107231 (PedroTadim).
- Fix
ORDER BY ... WITH FILLproducing extra rows when an ORDER BY column before the fill column uses aCOLLATEcollation. The rows are now grouped by the sorting prefix using that collation, matching the sort order. #107365 (groeneai). - Fixed undefined behavior when a non-finite floating-point value (such as
nanorinf) is passed as the timestamp/duration argument of theprometheusQuery/prometheusQueryRangetable functions. Such an argument now raisesBAD_ARGUMENTSinstead of producing a garbage timestamp. #107417 (groeneai). - Fix incorrect results from the
optimize_rewrite_aggregate_function_with_ifoptimization for aggregate functions that preserveNULLpayload values (the*_respect_nullsfamily:anyRespectNulls,first_value_respect_nulls,anyLast_respect_nulls,last_value_respect_nulls). The optimization no longer rewritesf(if(cond, x, NULL))into the-Ifform for such functions. #107430 (groeneai). - Added validation for malformed bounds in ORC input. #107580 (al13n321).
- Fix an unauthenticated memory-exhaustion denial of service on the MySQL protocol port. #107599 (tiandiwonder).
- Fixed the MySQL interface being unusable with
MySQL Connector/J8.2.0 and newer (including 9.x). Theinfofield of theOKpacket is now length-encoded, matching the MySQL server, so the JDBC driver can connect. #107693 (alexey-milovidov). - Fixed a
Block structure mismatch in UnionStep streamlogical error (server abort on debug/sanitizer builds,Code: 49on release builds) that occurred when sibling branches of aUNION/INTERSECT/EXCEPTdiffered only in theirWHEREpredicate and one branch’s predicate constant-folded to aConstcolumn. #107719 (groeneai). - Reading
ArrowandArrowStreamdata with emptyStringorBinarycolumns produced by Apache Arrow Java before 19.0.0 (including Apache Spark) no longer throwsINCORRECT_DATA. #107764 (Algunenano). - Malformed Native blocks whose
Variantdiscriminator references a nonexistent variant are now rejected safely. #107991 (uwezkhan). - Fixed a performance regression when reading
Dynamiccolumns with multiple threads. #107997 (Avogar). - The deprecated data lake setting
storage_catalog_urlis now correctly rejected by the catalog guard (previously onlystorage_catalog_typeandstorage_aws_access_key_idwere checked), and the error message lists all deprecated settings. #108040 (alexey-milovidov). - Fixed the
ArrowFlighttable function/engine rejecting a named collection that omits the optionaldatasetkey with aNo such key 'dataset'error. #108041 (alexey-milovidov). - Secrets and credentials are now masked in
system.query_views_log.view_queryinstead of being exposed in logged view SQL. #108214 (Fidelaggio). - Fix
type_json_allow_duplicated_key_with_literal_and_nested_objectnot working with typed paths in JSON. #108218 (Avogar). - Fixed undefined behavior (null pointer passed to
memcpy) in thedetectCharsetanddetectLanguageUnknownfunctions when the input string is larger than 32768 bytes and no character set can be detected. #108250 (groeneai). - Fix
NOT_FOUND_COLUMN_IN_BLOCKerror for queries that use the_part_starting_offset/_part_offsetvirtual columns in WHERE together with lazy materialization. #108287 (vdimir). - Hide secret arguments of functions such as
encrypt,decrypt, andHMACinEXPLAIN actions,EXPLAIN header, andEXPLAIN PIPELINEoutput whenformat_display_secrets_in_show_and_selectis disabled (the default). #108386 (Algunenano). CREATE OR REPLACEnow succeeds for a refreshable materialized view when itsTOtarget is already owned by that same view. Targets owned by another view remain rejected. #108392 (evillique).- Restrict the model path of
catboostEvaluateto theuser_filesdirectory, likefile()and the dictionary sources. Previously the function accepted an arbitrary filesystem path with no containment check, which allowed probing the existence of and triggering reads of files outsideuser_files. Models must now be located insideuser_files. #108463 (groeneai). - Fixed
CREATE OR REPLACE MATERIALIZED VIEW ... POPULATEleaving the new view unsubscribed from its source table, which silently dropped every row inserted after the replace. #108728 (alexey-milovidov). - Fix a segmentation fault when merging
uniqExactaggregate states withGROUPING SETS,ROLLUPorCUBEandmax_threads > 1. #108928 (Algunenano). - Fix possible logical error “Unexpected substream … for column …” during bump of compatibility setting. #109496 (Avogar).
- The
getClientHTTPHeaderfunction now treats header names as case-insensitive, according to RFC 9110; in particular, theauthorizationheader is now filtered out regardless of case. #109791 (Felixoid). - Fixed silent data loss with async inserts and deduplication (
async_insert=1,async_insert_deduplicate=1). When several async-insert entries with distinctinsert_deduplication_tokenvalues were coalesced into one flush that wrote to disjoint partitions, each token was registered in the deduplication log of every partition the flush touched, not only the partition its own rows landed in. A later insert reusing one of those tokens in a partition it never wrote to was then silently deduplicated away. Tokens are now registered only against the partition their rows actually landed in. #111049 (groeneai). - Fixed asynchronous Native-format inserts so one buffered entry that becomes incompatible after
ALTER ... MODIFY COLUMNno longer causes the whole batch to fail. #111108 (Felixoid). - Fix
CREATE OR REPLACEof a dictionary with an object of another kind: it failed withCANNOT_DETACH_DICTIONARY_AS_TABLEafter the replace was already committed, leaving an orphan_tmp_replace_*table. #111142 (evillique). - Fixed a peer-certificate memory leak during TLS handshakes with certificate verification enabled. #111425 (thevar1able).
- Fix a logical error
Block structure mismatch in IntersectOrExceptStep stream: different number of columnsthat could happen when the filter split optimization (query_plan_split_filter) ran on aWHEREwhose filter column name is also an input column name. The optimization left an internal__split_filtercolumn in the branch output header, which then diverged from the sibling branch of a set operation such asINTERSECTorUNION. #111930 (groeneai). - Fixed incorrect results for filters or
ORDER BYexpressions usingtoStringwithTime,Time64, orDateTimevalues in daylight-saving time zones. Also restored read-in-order optimization forORDER BYover a prefix of the table’s sorting key and for conversions fromStringtoNullable(String). #113291 (vdimir). - Fixed
ATTACHof aKafkatable whenkafka_num_consumersexceeds the limit derived from the number of CPU cores. #113390 (evillique). - Disabled distributed index analysis when projections are used to prevent incorrect query results. #115132 (azat).
- Fixed a bug in the function
formatRowNoNewlinethat could produce incorrect results or a logical error when a row is formatted to an empty result. #115669 (alexey-milovidov). - Do not return uninitialized memory in the result of a binary string literal whose length is not a multiple of eight, and from the LZ4 decompressor when a compressed block has no body. #115704 (alexey-milovidov).
- Included object paths in deduplication hashes to prevent distinct object values from being deduplicated incorrectly. #115866 (Felixoid).