ClickHouse release 26.9, 2026-09-21. Presentation, Video
Backward Incompatible Change
- The analyzer can no longer be disabled: the
enable_analyzersetting (and its old nameallow_experimental_analyzer) is obsolete, an attempt to set it to0is rejected, and thecompatibilitysetting no longer reverts it. The analyzer has been the default since 24.3, and the query analysis used before it is no longer supported. To compare the behaviour or the performance of a query with the old query analysis, use a ClickHouse version older than 26.9. #118629 (Alexey Milovidov). - The default compression method is changed from
LZ4toZSTD(3). Client/server and server/server network communication switches toZSTD(3)uniformly. ForMergeTreecolumn data the built-in default is now size-aware:LZ4for parts below 100 MB andZSTD(3)at or above it, judged by the part size known at write time (the size of the source parts for a merge or a mutation). TheStripeLogdata stream, the persistent files of theSetandJoinengines, andMergeTreeauxiliary files such aschecksums.txtswitch toZSTD(3)uniformly. HTTPcompress=1now uses thenetwork_compression_methodsetting too; the default is stillZSTD(3), andcompatibilityset to26.8or earlier restoresLZ4over HTTP as well. This improves compression ratios and reduces storage and network usage out of the box, at a modest increase in CPU usage. To restore the previous behavior: for network compression, use thecompatibilitysetting or setnetwork_compression_method = 'LZ4'; forMergeTreecolumn data, setCODEC(LZ4)on the column or table, or set the server<compression>default toLZ4; for theLogandTinyLogengines, set a columnCODEC(LZ4). The remaining streams always use the built-in default and have no runtime rollback; reading stays correct because every compressed frame is self-describing. #108786 (Alexey Milovidov). #119825 (Alexey Milovidov). This change is backward compatible, it is listed here for your convenience. - Removed the CatBoost integration. The
catboostEvaluatefunction, thesystem.modelstable and theSYSTEM RELOAD MODEL(S)queries are no longer available. Queries, views and grants referring to them have to be migrated before the upgrade: in particular, revokeSYSTEM RELOAD MODELfrom all users and roles beforehand, because an access entity whose grants still mention the removed privilege cannot be parsed on startup. Also let any in-flightSYSTEM RELOAD MODEL(S) ON CLUSTERentries drain from the distributed DDL queue before the upgrade: upgraded hosts can no longer parse such entries and will finish them with an error status instead of executing them. The same applies to persisted table metadata: a table whose columnDEFAULT/MATERIALIZED/ALIASexpressions, secondary indices, constraints, projections, partition/order/sample keys, or TTL expressions still referencecatboostEvaluatecannot be loaded after the upgrade (UNKNOWN_FUNCTION), so drop or rewrite such definitions beforehand. The revoke also has to cover every other carrier of serialized grants: aGRANT SYSTEM RELOAD MODELline in thegrantssection ofusers.xmlmust be removed as well, because it can no longer be parsed and the server then refuses to load the users configuration at startup; on clusters with replicated (Keeper-backed) access storage, revoke the privilege before upgrading any replica, because with the defaultaccess_control_improvements.throw_on_invalid_replicated_access_entities = 0an upgraded replica that reads a user or role still carryingSYSTEM RELOAD MODELfrom ZooKeeper cannot parse it and silently drops that entity from its in-memory copy (setthrow_on_invalid_replicated_access_entities = 1to fail loudly instead); and access backups (BACKUP ... ACCESS) taken while the grant was still present cannot be restored withRESTORE ... ACCESSon the new version, so re-create such backups after the revoke. #109710 (Robert Schulze). #116586 (Alexey Milovidov). - Removed the deprecated
read_resourceandwrite_resourcedisk options fromstorage_configuration. Attach a scheduler resource to a disk withCREATE RESOURCE name (READ DISK disk, WRITE DISK disk)instead. #115286 (Sergei Trifonov). - Removed the
WasmEdgeengine for WebAssembly UDFs.wasmtime, which has always been the default, is now the only supported value of thewebassembly_udf_engineserver setting. A server configured withwebassembly_udf_engine = 'wasmedge'will not start; remove that setting or set it towasmtime. On binaries wherewasmtimeis unavailable, including MemorySanitizer,arm_v80compat, andriscv64, WebAssembly UDFs are not available at all: the server still starts, butsystem.webassembly_modulesis absent and any attempt to create or use a WebAssembly UDF fails withSUPPORT_IS_DISABLED. #115316 (Alexey Milovidov). - The experimental
WINDOW VIEWfeature is removed, together with theWATCHstatement and thewindowIDfunction. It has been non-functional since version 24.12 (inserts into the source table were silently not delivered to window views) and was never supported by the analyzer, which is enabled by default since 24.3. The settingsallow_experimental_window_view,window_view_clean_interval,window_view_heartbeat_interval, andwait_for_window_view_fire_signal_timeoutare kept as obsolete no-ops. The time-window functionstumble,tumbleStart,tumbleEnd,hop,hopStart, andhopEndare kept. If you still have window views defined, drop them before upgrading: a server that finds a window view in its metadata fails to start (Cannot parse definition from metadata file ... (SYNTAX_ERROR)), the same way the removal of theLazydatabase engine behaves. Similar functionality will be reimplemented on top of streaming queries (issue #114738). #114747 (Alexey Milovidov). - Removed the sharded
GROUP BYaggregation (enable_sharding_aggregator, disabled by default) in favor of the adaptive aggregation (enable_adaptive_aggregator, enabled by default), which targets the same high-cardinality workloads without the weaknesses on skewed or low-cardinality keys and with support for external aggregation. Theenable_sharding_aggregatorsetting is kept as obsolete: setting it is still accepted and has no effect. #116532 (Nihal Z. Miaji). - Fixed wrong results from
runningConcurrencyunderLEFT JOINandANY JOIN, and under lazy evaluation inif,multiIf,and, andor, by treating it as non-deterministic. Queries using it may be slower. A sorting key, partition key, or text indexpreprocessor/postprocessorcontainingrunningConcurrencyis now rejected, and a table created earlier with one will not load after upgrading: remove or replace it before the upgrade. #114403 (Groene AI). BACKUP ... TO Disk(...),RESTORE ... FROM Disk(...), andCREATE DATABASE ... ENGINE = Backup(..., Disk(...))now requireSOURCESgrants for the targetDisk(...)location:WRITE ON DISKto write andREAD ON DISKto read. Previously a user withBACKUPbut withoutSOURCEScould still use any disk listed inbackups.allowed_disk; such users now need the correspondingDISKgrant, while users already grantedSOURCESare unaffected. #117406 (Groene AI).- Compression codecs are now gated by dedicated per-codec settings whose declared tier defines the codec maturity. The
ALPcodec is promoted to beta throughenable_alp_codec, andallow_experimental_codecsis now obsolete: it no longer enables any codec, so use the per-codecenable_<codec_name>_codecsettings instead. #116337 (Raufs Dunamalijevs). #117545 (Raufs Dunamalijevs). - Reading a
Filesource withrename_files_after_processingset now requires theWRITE ON FILEgrant on top ofREAD ON FILE(on the initiator forfileCluster): the setting renames the files aSELECThas read, which is a write to the source, and it used to happen for anyone who could read them. A query relying on it now needsGRANT WRITE ON FILE. A per-query renaming rule is also no longer cached by aFilesystemdatabase, where it could make an unrelated later query rename files, or be dropped silently. #117895 (Groene AI). - The
interfaceandhttp_methodcolumns ofsystem.query_log,system.query_thread_logandsystem.processesare nowEnum8instead ofUInt8, over the value setsystem.session_log.interfacealready uses, plusUnknownfor an unrecognized interface. Comparing to a number keeps working (WHERE interface = 1) and comparing to a name now works too (WHERE interface = 'TCP'), but a plainSELECTrenders the name, and arithmetic on the column (interface + 0) is no longer accepted. The default-enabledsystem.user_query_logand the opt-inall_union tables copy these types. As with any system log schema change, the existing log tables are renamed with the first free suffix (query_log_0,query_log_1, …) on upgrade; their rows read as names afterALTER TABLE system.query_log_0 MODIFY COLUMN interface Enum8(...), and the same forhttp_method, preceded byMODIFY SETTING table_readonly = 0if that table was frozen. #118136 (Groene AI). CREATE TABLE ... AS mergeTreeIndex(...)is no longer accepted, nor the same form overmergeTreeProjection,mergeTreeAnalyzeIndexes,mergeTreeAnalyzeIndexesUUID,mergeTreeTextIndexandmergeTreeCodecBlockCounts. The storage these functions return holds its source table’s storage object, so once such a persisted table had been read,DROP TABLE <source> SYNCnever returned, the source stayed insystem.dropped_tablesforever and its data was never reclaimed from disk. Reading these functions directly, as inSELECT ... FROM mergeTreeIndex(...), is unaffected. An existing table of this shape keeps loading at server startup, butATTACH TABLE,RESTOREandReplicateddatabase replica recovery now refuse it: list them withSELECT database, name FROM system.tables WHERE engine = 'Proxy', drop the ones over these six functions, and read the functions directly instead. #118969 (Groene AI).CREATE TABLE ... AS timeSeriesSamples(...)is no longer accepted, nor the same form overtimeSeriesData,timeSeriesTags, ortimeSeriesMetrics. Reading those functions directly is unaffected. Existing tables of this shape still load at server startup, butATTACH TABLE,RESTORE, andReplicatedreplica recovery now refuse them, because once such a persisted proxy table had been read,DROP TABLE <ts>dropped its live target and destroyed its rows, and later reads could fail withQueryPlan was not initialized. Find candidates withSELECT database, name, create_table_query FROM system.tables WHERE engine = 'Proxy'and keep only the ones whose outer call is one of these four functions; aview(...)wrapper is still allowed. Drop such a table on a freshly started server, before anything reads it, so the drop removes only the proxy and leaves theTimeSeriesdata intact. Do not useDETACH TABLEinstead, because a detached definition can no longer beATTACHed. If metadata loading of such a table already fails after a restart, move the metadata file out ofstore/and restart: until then, unfiltered reads ofsystem.tablescan fail withASYNC_LOAD_WAIT_FAILED. #119786 (Groene AI).- Removed the
s3_disable_checksumsetting. It existed to skip a second read of the source data for the checksum of an S3 upload; the checksum is now computed during the single read, so there is nothing left to disable. #119496 (Azat Khuzhin). Nullable(Tuple(...))is now generally available and enabled by default.Nullable(Tuple(...))columns can be created without any setting, schema inference of nullable structs in theParquet,Arrow,ORC,AvroandJSONformats returnsNullable(Tuple(...)), and aTuplesubcolumn extracted from aVariant,Dynamic,JSONorNullable(Tuple)column isNullable(Tuple(...))andNULLwhere the value is missing, instead of a tuple of default values. The previous behavior is available withenable_nullable_tuple_type = 0andallow_nullable_tuple_in_extracted_subcolumns = 0; the subcolumn setting is read at server startup, so it has to be set in the default profile. Upgrading existing tables whose partition keys, sorting keys, TTL expressions, or skip indexes depend on a tuple subcolumn extracted from aDynamic,VariantorNullable(Tuple)column or from aJSONpath not declared asTuple(...)is unsafe with the new default: tables may fail to attach, queries may fail, or data parts may be detached during startup. Before the first startup after upgrading, setallow_nullable_tuple_in_extracted_subcolumns = 0in the default profile, or preserve the previous behavior throughcompatibilityin that profile. Changing the setting after parts have been detached does not restore them automatically; those parts must also be reattached. #119222 (Nihal Z. Miaji).- New setting
validate_group_by_all_key_types(defaulttrue) gates the key-type validation thatGROUP BY ALLapplies to the grouping keys it expands theSELECTexpressions into. Since 26.7 it rejects aVariantorDynamicgrouping key, for example an untyped JSON subpath, that earlier versions accepted with the analyzer enabled (the default), with no way to keep such a query running across an upgrade. Settingcompatibilityto a version before 26.7, orvalidate_group_by_all_key_types = 0, restores the earlier behavior. An explicitGROUP BYis unaffected and still rejects such a key, as it did before 26.7. Closes #119852. #119868 (Groene AI).
New Feature
DISTINCTcan now spill data to disk, like external aggregation and external sort: the new settingsmax_bytes_before_external_distinctandmax_bytes_ratio_before_external_distinctset the threshold; by default, spilling starts once query memory usage exceeds half the available memory under the applicable server or user memory limits, or as soon as the next hash table allocation would exceed it. #116569 (Nihal Z. Miaji).- Refreshable materialized views can now refresh incrementally with
REFRESH ... APPEND INCREMENTAL, appending only the rows committed to the source table since the previous refresh instead of re-reading the whole source. #114152 (Smita Kulkarni). An incremental refresh into anIcebergtarget is now exactly-once: the refresh cursor is committed atomically inside theIcebergsnapshot summary. #114823 (Smita Kulkarni). - New
LIMITforms that select rows by boundary conditions instead of by position, following the stream order (useORDER BYto define it):LIMIT n AFTER condreturns up tonrows starting at the first row wherecondis true (SELECT number FROM numbers(10) ORDER BY number LIMIT 3 AFTER number >= 5returns5, 6, 7);LIMIT UNTIL condreturns the rows before the first row wherecondis true (LIMIT UNTIL number >= 3returns0, 1, 2);LIMIT AFTER cond1 UNTIL cond2returns the rows between the two (LIMIT AFTER number >= 2 UNTIL number >= 6returns2, 3, 4, 5);LIMIT n AFTER cond ALLopens a range ofnrows at every matching row and returns their union without duplicates (LIMIT 2 AFTER number IN (2, 6) ALLreturns2, 3, 6, 7). #99508 (Zakhar Kravchuk). - Added the
CREATE TOKENstatement, which generates a random secret, adds it to the current user as an additional authentication method and returns it together with its expiration deadline:CREATE TOKEN VALID FOR INTERVAL 30 DAY GRANTS (SELECT ON db.table). It is a convenient way to create tokens for applications: a token is tied to the user, can be limited in time and in privileges, and stops working when the user is deleted. Without an explicitVALID UNTILorVALID FORclause a token lives forcreate_token_default_ttl_seconds, 30 minutes by default. The statement requires the newCREATE TOKENprivilege, which also authorizes the equivalentALTER USER <current user> ADD IDENTIFIED ...statement. #116957 (Alexey Milovidov). - Authentication methods in
CREATE USERandALTER USER ... ADD IDENTIFIEDsupport aGRANTS (SELECT ON db.table, ...)clause which limits the access rights of sessions authenticated with that method to the intersection with the listed grants. This allows using additional credentials as tokens for applications:ALTER USER vasya ADD IDENTIFIED WITH password BY '...' VALID UNTIL '2026-12-31' GRANTS (SELECT ON db.table). Closes #109117. #110144 (Alexey Milovidov). - Added the SQL standard linear regression aggregate functions
regr_slope,regr_intercept,regr_r2,regr_count,regr_avgx,regr_avgy,regr_sxx,regr_syyandregr_sxy. #119347 (mosya415). - Added
MergeTreesettingsmax_table_size_rows,max_table_size_bytes_compressed, andmax_table_size_bytes_uncompressed, which limit the total size of a table. The limits are checked at the start ofINSERTand when new parts are committed, including the results of background merges and mutations, but not on replicated fetches. Closes #115063. #115069 (Alexey Milovidov). - Added the
max_tablesdatabase setting to limit the number of tables inAtomicandOrdinarydatabases. Every table-like object counts toward the limit, including tables, views, and dictionaries. #115202 (Alexey Milovidov). - Added bracket syntax for
JSONsubcolumns, such asjson['key1']['key2']; the parser translates it to nestedarrayElementcalls. #107039 (Pavel Kruglov). - Added the
system.statementssystem table, which exposes the documentation of SQL statements such as their name, syntax, description, and examples. #115341 (Robert Schulze). - Added virtual columns for the
Icebergv3 manifest fieldsfirst_row_idandlast_seq_num. #115603 (Konstantin Vedernikov). The same fields are now also written when inserting into anIcebergv3 table. #116171 (Konstantin Vedernikov). - Added the opt-in
MergeTreesettingskip_empty_columns_on_insert, which avoids storing columns that contain only their type-default value. It requiresserialization_info_version = 'with_missing_columns'; during rolling upgrades with servers that cannot read the new part metadata, keep the older serialization version. #98472 (Amos Bird). - Added support for
+and-betweenDateTimeandTimedata types. #82980 (Yarik Briukhovetskyi). - Added the
parseISO8601Durationfunction, which parses ISO 8601 duration strings such asPT1H30Minto seconds. #116993 (Navneet Kumar). - Added the
type_json_skip_null_typed_pathssetting forJSON. When it is enabled, typed paths inJSONcolumns that haveNULLvalues are treated as absent, matching the behavior of dynamic paths. Closes #99191. #106959 (Pavel Kruglov). - Added the
arrayFlattenedLengthfunction, which returns the total number of elements in a multidimensional array as if it was flattened witharrayFlatten. Unlikecardinalityandlength, which count only the elements of the outermost array, it counts elements at every nesting level, matching PostgreSQL’scardinality. #113696 (David Meng). clickhouse-clientnow accepts--ssh-key-filewithout a value: the key is looked up the same way assshdoes it, from~/.ssh/config, the default identity files such as~/.ssh/id_ed25519, and the keys held byssh-agent. Authentication with a key held byssh-agentis now supported without passing its path or passphrase explicitly. #115072 (Alexey Milovidov).- The
splitByRegexptokenizer, used in text indexes and thetokensfunction, now accepts an optionalextractargument. WithsplitByRegexp(re, 1),reno longer acts as a separator: each match contributes at most one token, the first capture group of the match or the whole match ifrehas no capture group. #116127 (Jimmy Aguilar Mena). - Added the
system.session_query_idssystem table, which contains the query ids of the queries executed in the current session, in execution order. It makes it easy to find “the queries I just ran” insystem.query_logwithout assigningquery_idclient-side or tagging queries withlog_comment, which is especially useful for testing and benchmarking. The history size is bounded per session by the newsession_query_ids_history_sizesetting (default1000,0disables recording), andTRUNCATE TABLE system.session_query_idsclears the current session’s history. #110536 (Vladimir Cherkasov). - Added a zero-argument form of
yearthat returns the current year, mirroringnowandtoday:year()is equivalent totoYear(today()).yearis now a function in its own right rather than a case-insensitive alias oftoYear, and is reported non-deterministic, soyear(<date>)is excluded from features that require a deterministic function: the query result cache, mutations ofReplicated*tables, on-the-fly mutation application (apply_mutations_on_fly), mutation partition pruning, and the trivial-view pushdown toDistributedtables; usetoYear(<date>)where determinism is required. Results, result types, index analysis and projection selection foryear(<date>)are unchanged. #109097 (Groene AI). - Added a memory fragmentation profiler for jemalloc. The new
system.jemalloc_sampled_allocationstable lists the sampled allocations that are currently alive, with their backtrace, age and size class; together withsystem.jemalloc_arena_binsit shows which code holds the allocations that keep fragmented slabs alive, and the same data is shown in a new “Fragmentation” tab of the jemalloc page of the server’s web UI. #115456 (Azat Khuzhin). - Support
BACKUPandRESTOREforWORKLOADandRESOURCEentities. SQL-definedCREATE WORKLOADandCREATE RESOURCEdefinitions are now included when backing upsystem.workloadsandsystem.resourcesand are recreated on restore, includingON CLUSTER. #108431 (Sergei Trifonov). - Added the
workload_admission_timeout_msquery setting that bounds how long a query waits to acquire its workload query slot and memory reservation before failing.0(the default) keeps the previous unbounded wait. #118852 (Sergei Trifonov). - Added
mode = 'exclusive'to theS3Queueengine: file processing is tracked only in the memory of the server, with no coordination through Keeper, for high-throughput ingestion on a single server, such as from a localminioinstance. #110552 (Ivan Tkatchev). - Added the
nats_ca_file,nats_client_cert_fileandnats_client_key_filesettings to theNATSengine, for verifying a broker certificate signed by a private CA and for client-certificate authentication. The feature was first proposed in #69396 by sidhmads. #116117 (Nikolay Degterinsky). - Added a four-letter-word command to
clickhouse-keeperfor the backpressure that the leader applies to slow Raft members. #117728 (Kseniia Sumarokova). - Added the
keyValuePairstext index tokenizer, which indexes aMap(String, String)column directly and answersmap['key'] = 'value'from the index without reading the map column. #115579 (Jimmy Aguilar Mena).
Experimental Feature
- Added Prometheus HTTP API support for the
/api/v1/metadata,/api/v1/labels, and/api/v1/label/<name>/valuesendpoints onTimeSeriestables. The/api/v1/labelsendpoint returns the sorted unique label names of the matched time series, and/api/v1/label/<name>/valuesreturns the sorted unique values of one label; both support the optionalmatch[],start,end, andlimitparameters. #116518 (Nikita Mikhaylov). #116731 (Nikita Mikhaylov). #117160 (Nikita Mikhaylov). - Added the
/api/v1/format_queryendpoint of the Prometheus HTTP API. It parses a PromQL expression and returns its canonical form. #117159 (Nikita Mikhaylov). - Added an embedded SQL Console UI at
/uion the HTTP server. This is the same console that is available in ClickHouse Cloud - not to be confused with the Web UI. #100406 (Luis Neves). - Reimplemented the experimental
KQL(Kusto) dialect with a dedicated lexer and parser instead of translating it to SQL text and reparsing it. This fixes expression-injection in string operators such ascontainsandhas, several results that disagreed with Kusto such as7 / 2,substringwith a negative start, andbin, and functions that were registered but did nothing. Unsupported syntax is now rejected instead of being mistranslated. #112932 (Alexey Milovidov). - Added an experimental
trinovalue of thedialectsetting (gated byenable_trino_dialect): queries written in Trino SQL are translated to ClickHouse SQL, including Trino-specific syntax (ARRAY[...]literals,TRY_CAST,UNNEST,ROWconstructors and types,VALUEStables,OFFSETbeforeLIMIT,FETCH) and a mapping of several hundred Trino function names and argument conventions to their ClickHouse equivalents. Bitwise shifts over untyped integer literals now match Trino semantics. #115383 (Alexey Milovidov). #119430 (Ethan Lin). - Added the
hierarchicalKMeansandassignCentroidfunctions, building blocks for IVF-style vector search. #112309 (Shankar Iyer). - Added
SELECTsupport forTimeSeriestables. #115622 (Vitaly Baranov). TimeSeriestables now derive their inner engine family fromdefault_table_engine, require all inner tables to use the same replication family, and always pinrecent_samples_ttl_secondsintoSETTINGSforRECENT SAMPLEStargets. #115922 (Vitaly Baranov).- Added PromQL support for
absentandcount_values, including range queries andby/withoutaggregation modifiers. #112795 (Valery Petrov). - PromQL now supports the range functions
sum_over_time,avg_over_time,count_over_time,present_over_time,absent_over_time,quantile_over_time, andpredict_linear. #112353 (Valery Petrov). #112842 (Valery Petrov). - The
TimeSeriestable engine now supports dictionary-encoded series identifiers: theidcolumn can be declared with aLowCardinalitytype, and new tables useTuple(UInt64, LowCardinality(UUID))by default while existing tables keep their declaredidtype. The previous layout remains available throughTAGS INNER COLUMNS (id Tuple(UInt64, UUID)), and the new layout gives a 1.16x geometric-mean PromQL speedup in the benchmark. #117033 (Nikita Mikhaylov). timeSeriesGroupArrayis now supported inSimpleAggregateFunction, and thetimeSeries*ToGridfunctions now also accept the samples as a singleArray(Tuple(timestamp, value))argument. #117340 (Vitaly Baranov). #117341 (Vitaly Baranov).TimeSeriestables now expose the outer samples column assamplesinstead oftime_series.INSERT INTO ts_new SELECT * FROM ts_oldstill works because the column order is unchanged. #119225 (Vitaly Baranov). TheMETRICStarget is renamed toMETRIC FAMILIES, which is what that inner table actually holds;METRICSkeeps working as an alias. #119227 (Vitaly Baranov).- Distributed query plans (
make_distributed_plan) now stop idle upstream stages promptly after a satisfiedLIMIT, instead of continuing to read and compute data that nobody consumes. They also no longer stall when the initiator pipeline has only one execution thread, because waiting for distributed plan stages no longer occupies that thread. Plans with many nodes now honor the query’smax_threadsin worker fragments, so they no longer exhaust the server thread pool or outlivemax_execution_time;use_concurrency_controlis disabled automatically for these queries because it can starve worker tasks while they wait on exchange sockets. Plans with many finished stages also no longer pay up to 100 ms of idle waiting per stage while draining completed stages, which speeds up multi-join queries several times in some cases. The data sent between nodes is now also serialized on all threads of a task instead of one thread per destination, removing a bottleneck when a query runs on a small number of workers. #115690 (Alexander Gololobov). #116017 (Alexey Milovidov). #116300 (Groene AI). #116878 (Alexander Gololobov). #117328 (Alexander Gololobov). #119067 (Alexander Gololobov). parallel_replicas_plan_basedcan now collect runtime statistics and automatically enable parallel replicas for supported queries. #115788 (Igor Nikonov).- A
Mergetable can now be read with parallel replicas: reads from the underlyingMergeTreetables are coordinated across replicas, and aggregations and joins above them are distributed too. Enabled by theparallel_replicas_allow_merge_tablessetting together withparallel_replicas_plan_based. #115001 (Igor Nikonov). - Added experimental support for the
silkfiber runtime, enabled with theenable_silk_runtimeserver setting. When it is enabled, subsystems that support it can run jobs on fibers instead of occupying an operating-system thread while waiting for I/O. #112667 (Miсhael Stetsyuk). - Adaptive codec selection (
enable_adaptive_codec_selection) forMergeTreenow also applies to columns without a specialized candidate codec: when no type-specific codec candidate exists, each block is written with whichever of the table’s default codec andNONEcompresses it smaller, so incompressible data is no longer stored larger than raw. ForFloat32andFloat64columns it now also considers theALPcodec. #115639 (Raufs Dunamalijevs). #117553 (Raufs Dunamalijevs). - Added aggregation pushdown below
JOIN(eager aggregation) to the experimental Cascades optimizer as a cost-based alternative: a partial aggregation is performed on one join input before the join and merged above it, or, when the join provably neither duplicates nor null-extends the aggregated side and the join keys are a subset of theGROUP BYkeys, the aggregation is pushed below the join entirely. Controlled by the new settingcascades_aggregation_pushdown(enabled by default; takes effect only withenable_cascades_optimizer = 1andmake_distributed_plan = 1). #115354 (Dmitry Novik). - Queries with
INTERSECTandEXCEPTnow work under the experimentalmake_distributed_plansetting. #116563 (Alexander Gololobov). Whenmake_distributed_planis enabled and no distributed plan can be built, the query falls back to local execution. #116487 (Antonio Filipovic). A failingmake_distributed_plan = 1query reports the error of the task that failed, not the closed exchange connection that failure caused; worker task failures reach the client with the worker’s error code. #118390 (Groene AI). - Fixed
Column '__text_index_...' not found in tableandQuery builder not found for text search querywhen a query using a text index read withparallel_replicas_plan_basedenabled. #116363 (Igor Nikonov). parallel_replicas_plan_basednow supportsRIGHT JOINandORDER BY ... WITH FILL; when the analyzer is disabled, the query runs locally instead of falling back to query-based parallel replicas, because plan-based parallel replicas are not supported there. #113515 (Groene AI). #116135 (Igor Nikonov). #118781 (Igor Nikonov).- Adaptive codec selection (
enable_adaptive_codec_selection) now applies to every substream of a column, such asArrayandStringsizes and null maps, instead of the main data stream only. #117348 (Raufs Dunamalijevs). - WebAssembly UDFs now split an input block that would not fit into the guest’s linear memory into smaller batches, sized by the input’s measured serialized size. The new setting
webassembly_udf_input_split_memory_ratiocontrols how much of the linear memory one call’s input may occupy. #116552 (Vasily Chekalkin). A UDF using theBUFFERED_V1ABI that returns a result buffer with a non-zero size but a data pointer at linear-memory offset0is now rejected instead of unrelated memory being read. #116548 (Vasily Chekalkin). - The experimental
ReaderExecutornow shrinks its read window and block size under memory pressure, configured viareader_executor_memory_pressure_{elevated,high,critical}_level_pct; its default read window is now 8 MiB. #115635 (Sema Checherinda). - PromQL: implemented the
max_over_timeandmin_over_timefunctions. #112354 (Valery Petrov). PromQL now also parses legacy octal numeric literals with Prometheus-compatible semantics. #113586 (Minh Vu).sgnnow preservesNaNand negative zero. #113747 (Minh Vu).stddevandstdvarno longer returnNaNfor large finite values whose variance is representable. #114250 (Minh Vu). - PromQL no longer counts consecutive
NaNsamples as changes. #113744 (Minh Vu). CREATE TABLE ... ENGINE = DeltaLake(...)can now create a newDeltaLaketable, writing the initial commit throughdelta-kernel-rs, attach to an existing_delta_log, or register an existing table into a Unity catalog. It is gated behind the newallow_delta_lake_create_tablesetting; creating a partitioned table (PARTITION BY) is not supported yet. Writes to aDeltaLaketable now cast values to the Delta write-schema type with an accurate cast that throws when a value does not fit the target type, for example300written into a Deltabyte, instead of silently truncating; the newdelta_lake_accurate_write_castsetting, enabled by default, controls this, andcompatibilitybelow26.9restores the previous truncating behavior. #106011 (Smita Kulkarni).
Performance Improvement
- Reduced memory usage and query-plan optimization time for keyed aggregations over large constant-folded literals by hashing the aggregation hash-table-statistics cache key while it is serialized instead of accumulating a full copy in memory first. For an 80 MB literal, peak memory drops by about 250 MB and optimization time by about 2.5x. #115847 (Groene AI).
- Added the
query_plan_aggregation_bucket_top_ksetting (enabled by default) to control the optimization that keeps only each two-level aggregation bucket’s bestngroups when a final aggregation feedsORDER BY ... LIMIT n. The optimization is now visible inEXPLAINoutput. #116124 (Nihal Z. Miaji). - A
WHEREequality is now merged into theJOINcondition even when its operands have different types but a common supertype, such asInt32andNullable(Int32). This lets moreCROSS JOINs be rewritten toINNER JOINs. #112630 (Hechem Selmi). - Improved performance of merges of text indexes. #114525 (Anton Popov).
- Reduce CPU usage of the post-filter used by
INandNOT INpredicates. #111690 (Elmi Ahmadov). - The
arrayJoinfunction syntax is now planned as theARRAY JOINoperator internally, so it can use the sameARRAY JOINoptimizations. A filter on a column produced byARRAY JOINis pushed into the array before it is expanded, so elements that do not match are never turned into rows and other columns are not replicated for them, which speeds up selectiveARRAY JOIN ... WHEREqueries over wide rows. A follow-up reduces the fused path’s per-block overhead by avoiding per-window filter copies and computing survivor offsets only when eager replication needs them. Controlled by thequery_plan_fuse_filter_into_array_joinsetting. #115474 (Yarik Briukhovetskyi). #116910 (Yarik Briukhovetskyi). #117660 (Yarik Briukhovetskyi). - Fixed a performance regression where a query combining a text index filter with
ORDER BY ... LIMITstopped answering the filter from the index and read the whole text column instead. #115586 (Jimmy Aguilar Mena). - Speed up query pipeline construction for queries with large expressions or many streams by computing each plan step’s output header once instead of once per stream. For a ClickBench Q29-like query on a 96-core machine, this removes about a third of the hot query time. #115677 (Alexey Milovidov).
- Speed up building the hash table of an
ANY,SEMI, orANTI JOINwhen the right side repeats the same join keys many times. #115820 (Nikita Taranov). - Speed up random data generation.
rand,rand64,randConstant,randomString,randomFixedString,generateUUIDv4,generateUUIDv7, anddateTimeToUUIDv7now generate bytes with ARS (reduced-round AES in counter mode) wherever the CPU has AES instructions: on AArch64 chosen at build time, on x86-64 chosen at run time when VAES is present. Targets and CPUs without those instructions keep the previous generator unchanged. A follow-up reduced the fixed setup cost on x86-64, which is noticeable when blocks are small. #116133 (Groene AI). #116158 (Raúl Marín). - Fix a CPU regression for queries that issue many independent small reads against the same
MergeTreepart when the table hasLowCardinalitycolumns. Such queries on tables with a smallindex_granularitywere up to several times slower since 26.6. #116134 (Groene AI). - Speed up
GROUP BYwithout aggregates by inlining some functions and by starting prefetching at the same cardinality asGROUP BYwith aggregates, which helps when the hash table stops fitting in the L2 cache. #115840 (Nikita Taranov). #116267 (Nikita Taranov). - Use the
bloom_filterskip index forINpredicates on a directly indexed column whentransform_null_in = 1and theINset contains noNULLvalues. Previously the index was skipped for such queries, forcing a full scan. #111329 (Groene AI). - The adaptive
GROUP BYaggregation (enable_adaptive_aggregator) now falls back to the ordinary algorithm when rare keys or aggregate arguments are too wide to copy profitably, so aggregations over heavy string columns run at the ordinary algorithm’s speed and memory usage. Addsadaptive_aggregator_freeze_threshold_bytesto bound each thread’s frozen table in bytes. #115755 (Nihal Z. Miaji). - Lightweight
UPDATEqueries now write patch parts that carry the table’s sort-key columns, so applying a patch no longer has to hold the whole patch part in memory. #116007 (Alexey Milovidov). - Added an alternative row-major payload layout for hash joins to speed up join output reconstruction. Controlled by
enable_hash_join_row_store(defaulttrue) andmin_rows_ratio_for_hash_join_row_store(default5). A probe that emits no right-side columns, such asSELECT count(), no longer publishes a fake zero match count into the row-store cache, so a later full-output run can still use the row-store optimization. Closes #117260. #104884 (Hechem Selmi). #117410 (Groene AI). - The
IEJoinalgorithm now chooses which twoJOIN ONinequality conditions to use as its key conditions by their estimated selectivity from the column min/max statistics, instead of taking the first two in syntax order. The remaining conditions are evaluated per candidate pair, so picking the most selective pair can speed up such joins by orders of magnitude. #115790 (Vladimir Cherkasov). - 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 thesearrayJoinforms fell back to a full scan. #109536 (Groene AI). - Reduce cancellation latency for distributed queries that use parallel replicas by not waiting for a replica’s initial announcement after the query is already cancelled. #114862 (Nikita Taranov).
- Speed up reading
system.tablesby not copying the query context for every row. #115867 (Nikolay Degterinsky). - Speed up
Array(LowCardinality(T))aggregations by preserving dictionary identity. #115961 (Ivan Babrou). - Improved the performance of the
roundDurationandroundAgefunctions on AArch64 by rewriting their comparison cascades into a branchless form that the compiler can auto-vectorize. Results are unchanged. #116164 (Groene AI). - Avoid extremely slow
BACKUPof aMemoryorKeeperMaptable whenmax_compress_block_sizeis set to a small value by sizing the temporary file stream withtemporary_files_buffer_size. #116233 (Groene AI). - Speed up server shutdown for databases with many tables by shutting tables down in parallel. Controlled by the new
database_catalog_shutdown_table_concurrencysetting;0means the number of CPU cores. #104969 (Jayme Bird). arrayElementandarraySlicenow read lazily replicated arrays (produced byARRAY JOINandJOINwhenenable_lazy_columns_replicationis enabled) directly, without materializing them. This reduces memory usage and speeds up queries that index or slice a large array. #112304 (Diego Gomes Tomé).A UNION DISTINCT Bnow deduplicates each branch in parallel before merging them, the same way itsSELECT DISTINCT * FROM (A UNION ALL B)rewrite already did. Previously the query funneled every row through a single thread, so it did not scale withmax_threads. #115173 (Groene AI).- Speed up regular-expression searches for simple anchored literals, including prefix, suffix, exact-literal, and escaped-literal matches. #116554 (Elmi Ahmadov). #117331 (Elmi Ahmadov).
- Reduce CPU and memory overhead of
TTLdeletions during merges: blocks are now filtered in one vectorized pass instead of being rebuilt column by column, and a block with nothing to delete is passed through untouched instead of being copied. #116623 (Shaohua Wang). - Optimize one-argument date conversions on
DateandDateTimecolumns. #114267 (Ivan Babrou). clickhouse-localnow attaches thesystemandinformation_schematables on first access instead of at startup. #115489 (Konstantin Bogdanov).- Speed up
GRANT,REVOKE, andSHOW GRANTSfor users with many grants by avoiding a deep copy of the access-rights tree when it is only read. #115696 (miao tang). - Reduce memory usage when inserting into a wide
MergeTreepart that writes many more streams than it has columns, for example a table with a few bucketedMapcolumns. Themin_columns_to_activate_adaptive_write_buffersetting is now compared against the number of streams the part writes, since one write buffer is allocated per stream. #115759 (Groene AI). - Fixed a performance regression since 26.6: a query filtering a
Nullablecolumn withIN (subquery)read the whole table instead of skipping the read when the subquery returned no rows. Closes #116450. #116538 (Yarik Briukhovetskyi). - Fixed quadratic complexity of
groupConcatover aFixedStringargument. The whole argument column was converted toStringonce per row, so a query over 400,000 rows took 45 seconds instead of 0.1 seconds and could overrun itsmax_execution_time, which is only checked between blocks. #116795 (Groene AI). - Push a
WHEREcondition on aUSINGcolumn through aRIGHT JOINso the leftMergeTreeinput can use it as a primary-key index condition, even when the join keys have different types. Applies withenable_analyzer = 1. #103478 (Manuel). - Reduce memory usage of Parquet dictionary-based row-group pruning (
input_format_parquet_dictionary_filter_push_down) several times by hashing integer dictionaries directly and keeping the value set as a sorted vector instead of a hash table. #115744 (Alexey Milovidov). - Reading dictionary-encoded
Parquetdata is now faster: dictionary indexes are decoded and resolved to values in one fused pass, turning runs of a repeated value into bulk fills instead of per-row gathers, for about 20% faster scans of dictionary-encoded numeric columns. #115819 (Alexey Milovidov). - Speed up some
PREWHEREqueries with text indexes by placing text-index lookups and other zero-size-column predicates before expensive predicates on the indexed column. #116546 (Jimmy Aguilar Mena). - Speed up the
numberstable function, sorting, and other bulk index fills on AArch64 by improving code generation of their sequential-fill loops. Results and x86-64/macOS code generation are unchanged. #116616 (Groene AI). - Speed up
groupUniqArrayfor 8-bit types (UInt8,Int8,Enum8,Bool) by using a 256-bit bitmap instead of a hash set. #116880 (Manuel). - Writing rows in JSON output formats that emit object keys, including
JSONEachRowand its aliases,PrettyJSONEachRow,JSON,JSONStrings,JSONStringsEachRow,JSONObjectEachRow, andGeoJSON, is now faster because each field name is no longer copied into a temporary string and re-measured for every row. Compact formats that emit no keys are unchanged. #117082 (Groene AI). - Fixed a performance regression introduced in 26.4 when writing
JSONandDynamiccolumns in text formats, includingDynamic(JSON)text output. #115852 (Pavel Kruglov). #117655 (Nikita Fomichev). - Speed up repeated insertion of the same
LowCardinalityvalue into an in-memory column, for example during joins. #115020 (Minh Vu). - Correlated subqueries with equality on columns that differ only in nullability, or on native-number columns with a least common type, are now decorrelated via equivalent-expression substitution instead of falling back to a
CROSS JOINwith a post-join filter. This avoids severe memory growth on such queries. Closes #113407. #115493 (Dmitry Novik). - Speed up division and modulo of
Int128,UInt128, andDecimal128values that fit in 64 bits.Decimal128rounding withround,floor,ceil,trunc, androundBankersis 1.5x faster on x86-64, and gains more on architectures that have no 128-bit divide instruction. Results are unchanged. #116199 (Groene AI). - Functions with several SIMD implementations, including
MD5,SHA1, hashing functions,greatCircleDistance, andgeoDistance, now choose one from the CPU’s capabilities instead of benchmarking them at runtime.MD5becomes 2-3.7x faster. Thefunction_implementationsetting is obsolete and has no effect. #116501 (Raúl Marín). - Speed up
dotProductTransposedonQBitcolumns with floating-point element types on hosts where SimSIMD has no vectorized dot kernel, which forFloat64means AArch64 and x86 without AVX-512. The reduction now uses independent partial sums instead of a single accumulator, so its summation order changes. Closes #116784. #116816 (Groene AI). - Reduce jemalloc fragmentation by lowering
lg_extent_max_active_fitto its default value6. #116836 (Azat Khuzhin). - Speed up
formatDateTimewith non-constant time zone arguments by caching resolved time zones locally. #116851 (Robert Schulze). - PromQL selector scans over
TimeSeriestables are now parallelized, which speeds up reads of the narrow, decode-heavy samples table columns. #116932 (Nikita Mikhaylov). - Speed up conversion of
TimeSeriestag arrays by reserving the final output size up front and by building extracted tag values andNULLmaps in one pass. #115620 (Minh Vu). #115687 (Minh Vu). - Speed up
timeSeriesGroupArraywhen the input samples are already sorted by timestamp. #117703 (Vitaly Baranov). - The
Nativeprotocol now batches end-of-query control messages into a single socket write by default, andsyncnow flushes them immediately. This removes one round trip of latency per query for clients on high-latency connections that idle between queries. #111034 (Kaviraj Kanagaraj). - Phrase search in text indexes now stores positions in packed blocks and reads only the blocks that cover candidate rows, reducing position-data reads and memory usage. #111550 (Elmi Ahmadov).
- Appending many default values to
ArrayandStringcolumns now pre-sizes the offsets array, reducing reallocations and peak memory usage. #113577 (Groene AI). - The preliminary per-stream
DISTINCTnow abandons deduplication when the input is almost entirely unique, freeing its hash tables because the finalDISTINCTstill deduplicates the output. This roughly halves memory usage and speeds upSELECT DISTINCTon unique data. Controlled byallow_preliminary_distinct_abandoningand observable viaDistinctTransformsAbandonedDeduplication. #116508 (Nihal Z. Miaji). - PromQL instant-vector responses now reuse the formatted evaluation timestamp within each result block. #115567 (Minh Vu).
- Speed up
TimeSeriesreads by writing sampling keys directly into the result column. #115683 (Minh Vu). - Reduce lock contention and per-lookup allocations during serialization by sharding the object pool. #116869 (Manuel).
LIKE ... ESCAPE 'c'andILIKE ... ESCAPE 'c'can now use skip indexes instead of falling back to a full scan.TYPE textindexes prune granules for both;LIKE ... ESCAPE 'c'can also use thengrambf_v1,tokenbf_v1, andsparse_gramsindexes, andNOT LIKE ... ESCAPE 'c'can usebloom_filterskip indexes and the primary key when applicable, matching plainNOT LIKE.TYPE textindexes still do not supportNOT LIKE. #105848 (Groene AI).- Distributed
ORDER BYquery plans can now useread in orderwhen the query order matches the table’s sorting key, and projections can reuse that base-table in-order read too. #115244 (Shankar Iyer). #116854 (Mikhail Artemenko). - Slightly speed up
INSERTintoJSONcolumns by making typed-path default insertion cheaper. #107359 (Pavel Kruglov). - Added the
query_plan_lift_predicate_across_joinoptimization, which copies equi-join filter conjuncts acrossMergeTreejoin inputs for better primary-key pruning. It speeds up some queries by 70-80x. #108377 (Yarik Briukhovetskyi). - Automatic parallel replicas now share prepared sets with the probe plan instead of executing them twice. #114231 (Nikita Taranov).
- Supported
LIKEandILIKEpatterns can now use text indexes. #114728 (Elmi Ahmadov). - Improve generic
arrayReverseperformance by reserving space for all nested elements. #115011 (Minh Vu). LEFT ANTI JOINandLEFT SEMI JOIN, when no column of the right table is selected, now build a hash table that stores the keys alone and release the right-hand blocks as they are built. This makes them up to 1.5x faster and can halve memory usage. Controlled by the new settingenable_join_key_only_hash_tables, which is enabled by default. #115301 (Nikita Taranov).- Speed up
timeSeriesFromGridfor dense rows by bulk-copying values. #115518 (Minh Vu). - Answer
min,max, andcountaggregations withoutGROUP BYand filters directly from per-part column statistics, collected automatically for suitable columns by theauto_statistics_typesMergeTreesetting, reading no data for the parts that have statistics materialized. This speeds up ClickBench Q6 (SELECT MIN(EventDate), MAX(EventDate) FROM hits) from tens of milliseconds to a few milliseconds. Controlled by the new settinguse_statistics_for_min_max_aggregation, which is enabled by default. #115738 (Alexey Milovidov). - On AArch64, short runtime-sized copies in hot string, join, and part-reading paths now stay inline instead of being rewritten to a
memcpycall. #117353 (Groene AI). - Improve performance of
bitmapAndCardinality,bitmapOrCardinality,bitmapXorCardinality,bitmapAndnotCardinality, andbitmapHasAnyby computing the result directly instead of first materializing the intersection bitmap. #117478 (Anand Kr Shaw). - Reduce memory usage of reading a
TimeSeriestable directly with SQL (SELECT ... FROM ts_table). The samples are now aggregated in sorting-key order instead of being buffered in a hash table, so peak memory no longer grows with the size of the scanned window, andLIMITis pushed into the read. #117726 (Nikita Mikhaylov). - Queries with join-side disjunction predicates can now push the per-side filters down to
PREWHEREonMergeTreereads, reducing unnecessary column reads. #117760 (Nikita Taranov). - Reduce
clickhouse-keeperrequest latency for concurrentRemoveRecursiverequests when many uncommitted nodes exist. #117778 (Alexander Gololobov). - Improve performance of
hasToken,hasAnyTokens, andhasAllTokensqueries with text indexes in lazy posting-list apply mode. #117905 (Anton Popov). - Speed up k-way merges: merging sorted streams with multi-column or collated sorting keys uses a sorted array of cursors instead of a heap (7-8% faster), merges of non-intersecting parts detect the whole cursor as one batch in O(1) comparisons, and runs of duplicate keys inside a part are skipped, which makes
SELECT ... FINALfromReplacingMergeTreeuse up to 40% less CPU and the insert-time deduplication ofoptimize_on_insertabout three times faster when there are many duplicates. #115869 (Alexey Milovidov). - Reading columns with many substreams, such as
JSON, from object storage is much faster and makes far fewer requests: the marks of all streams of aMergeTreepart are now loaded asynchronously and in parallel by default (settingload_marks_asynchronously). #118477 (Alexey Milovidov). Marks of streams with an empty data file, such as theSharedVariantsubstreams ofJSONpaths with values of a single type, are not loaded at all, which removes about a third of the requests. #118478 (Alexey Milovidov). The metadata streams ofJSONandDynamiccolumns are no longer read twice when prefetching. #118479 (Alexey Milovidov). A read of a file inside a packed part is bounded to the file’s slice, so it does not transfer the rest of the archive and reuses HTTP connections. #118483 (Alexey Milovidov). - Improved performance of reading individual paths and subcolumns from
JSONcolumns that use theadvancedshared data serialization. Each path and substream now starts in its own compressed block, so a selective read no longer decompresses data belonging to other paths. #118154 (Pavel Kruglov). - The join reordering optimizer uses the CD-C and CD-A conflict detectors from the SIGMOD’13 paper “On the Correct and Complete Enumeration of the Core Search Space”, so joins of any kind can be reordered, including
ANTIandSEMIjoins, not onlyINNERjoins. For seven relations, CD-C explores about 12 times more valid plans than before. #117677 (Fisnik Kastrati). - Decode
Icebergdata manifest files concurrently while the list of data files for a query is produced. The settingiceberg_manifest_decode_concurrency(default4) bounds how many manifests, delete and data alike, are decoded at a time; it replacesiceberg_delete_manifest_decode_concurrency, which is kept as an alias. #116723 (Aaron Harlap). - Use the
lower_boundandupper_boundstatistics of theIcebergmanifest list to prune data files. Closes #104567. #115817 (Konstantin Vedernikov). - Reduce peak memory of the
JSONExtract*functions on the rapidjson code path (allow_simdjson = 0): the parser’s DOM allocator is rewound between rows, so the DOM is bounded by one document instead of growing withmax_block_size. A 100-level nested document uses 84% less memory and is 30% faster, a 200-key object 61% less and 21% faster. #117618 (Groene AI). - Faster writing of
Stringvalues in the JSON output formats (JSONEachRowand its variants,JSON,JSONObjectEachRow,PrettyJSONEachRowandGeoJSON) and inJSONExtractRaw: a run of bytes that needs no escaping is copied in one block instead of one byte at a time. Values in which most bytes need escaping become slower. The output is unchanged. #117755 (Groene AI). addDays,addWeeks,subtractDaysandsubtractWeeksover aDateTimecolumn are up to 12% faster in time zones with UTC-offset changes: a per-row range check that the argument type makes impossible to fail is no longer executed. #118219 (Groene AI).toHourandtoMinuteno longer walk the calendar lookup table in time zones where the result is pure arithmetic:toHourin every zone whose UTC offset does not change after 1970 (includingUTCandAsia/Kolkata), andtoMinutein zones that keep a constant minute-of-hour, such asAsia/Kolkata,Pacific/ChathamandAmerica/St_Johns. Results are unchanged. #117562 (Groene AI).- Reduce the per-query cost of applying the
compatibilitysetting and of logging changed settings intosystem.query_log. A query on a service that sets an oldcompatibilityvalue can run more than twice as fast. #118114 (Raúl Marín). - The bound on the cost of estimating the selectivity of
col IN (...)from column statistics, controlled bystatistics_max_set_size_for_exact_selectivity_estimation, is now also applied whencompatibilityis set to 26.6 or an earlier version. #118095 (Nikita Fomichev). - Automatic parallel replicas now skip their planning overhead entirely when no read step of the query is estimated to read at least
automatic_parallel_replicas_min_bytes_per_replicatimes the number of replicas. #116521 (Nikita Taranov). - Join runtime filters now reach the local probe-side plan under parallel replicas when
parallel_replicas_filter_pushdownis enabled, so grouped probe-side queries filter rows before local aggregation instead of after it. #118650 (Nikita Taranov). The join runtime filter no longer builds a Bloom filter that the build-side key count predicts to be too dense to be useful. #118336 (Manuel). - The bucket-local top-K optimization (
query_plan_aggregation_bucket_top_k) no longer materializes every group’s key for a statistic that only automatic parallel replicas consume, soGROUP BY ... ORDER BY count() DESC LIMIT nover high-cardinality keys spends less CPU in the final aggregation. #118374 (Groene AI). - Skip analyzing the implicit
minmax_countprojection during query planning when the query aggregates with a function that projection cannot provide. Previously every aggregating query over aMergeTreetable interpreted the projection’s definition while optimizing the plan, even forsum,avg,uniqand every other aggregate it can never serve. #118723 (Groene AI). - A condition on an
ARRAY JOINelement, such asARRAY JOIN tags AS t WHERE t IN (...), is now used for skip index analysis the same wayarrayJoin(tags) IN (...)already is. #118582 (Yarik Briukhovetskyi). AWHEREcondition that compares anARRAY JOINelement with other columns of the row is applied before the expansion, so filtered-out elements are never expanded. #118904 (Yarik Briukhovetskyi). ARRAY JOINof aNestedcolumn inside a subquery, CTE,UNIONbranch or view now reads only the referenced subcolumns, like a top-levelARRAY JOINdoes. Fixed an exceptionTuple doesn't have element with namewhen a secondARRAY JOINreferenced a subcolumn of aNestedcolumn joined by the first one. #119055 (Vladimir Cherkasov).- A
bloom_filterskip index is no longer selected for a condition built only from!=orNOT IN. A bloom filter can only prove that a value is absent from a granule, so such a condition never skipped a granule while the whole index was still read.force_data_skipping_indicesnow reportsINDEX_NOT_USEDfor it. #116544 (Groene AI). - Text indexes on
mapKeysandJSONAllPathscan now pruneINpredicates even when the right-hand-side set exceededuse_index_for_in_with_subqueries_max_valuesand was built without stored elements. #118128 (Nikita Taranov). A text index built with thearraytokenizer can now serve arbitraryLIKEandILIKEpatterns by scanning its dictionary. #115649 (Elmi Ahmadov). - Speed up primary key index analysis for conditions with a large
INset by reusing per-thread buffers instead of allocating on every call. #110937 (Manuel). Avoid a redundantLowCardinalitytype unwrap per mark when evaluatingINconditions on the primary key. #117054 (Manuel). - Improved performance of aggregate functions that combine a null map with an
-Ifcondition (sum,avg,min/max/argMin/argMaxwith-If, functions with two or moreNullablearguments such ascorrandquantileExactWeighted, and thetimeSeries*functions with-If) when a block is consumed in increasing sub-ranges, asoptimize_aggregation_in_orderand window frames do. #118025 (Groene AI). - Hashing a value that has no contiguous in-memory representation (
JSON,Variant,AggregateFunction) no longer allocates and copies a buffer per row.xxHash64over aVariantcolumn is about 40% faster,sipHash64over aJSONcolumn about 5%. Counting distinct aggregate states withuniqExactis about 33% faster for 200-byte states;uniq,DISTINCTandarrayDistincthash states through the same path. #119322 (Groene AI). - Speed up compression and decompression with the
T64codec on AArch64 and on x86-64 hosts without AVX-512. The byte and bit transposes now use portable vector shuffles instead of a per-byte scalar loop. Compressed output is unchanged. #116206 (Groene AI). FasterDoubleDeltadecompression. #118787 (Nikita Mikhaylov). - Improve
LIMIT BYperformance by stopping input reads after a constant grouping key reaches its limit. #118770 (Minh Vu). - Squash small chunks before writing the intermediate table during recursive CTE evaluation. Deep recursions no longer accumulate one tiny
Memoryblock per produced chunk, which degraded per-step reads of the working table. #107068 (Zach Naimon). - Speed up
jaroSimilarityandjaroWinklerSimilarityusing AVX2. #104457 (Manuel). Speed upisValidASCIIby using SIMD kernels from simdutf. #119062 (Konstantin Bogdanov). Fasterbase58Encodeandbase58Decode. #117619 (Groene AI). Improve the performance of string functions in byte mode by avoiding unnecessary ASCII scans. #115003 (Minh Vu). - Speed up
mortonEncodeandmortonDecodeby resolving each input column and the constant range mask once per call instead of once per row. Results are unchanged. #117727 (Groene AI). - Speed up the fast Walsh-Hadamard transform used by
randomHadamardTransformand by vector quantization with AVX2 (about 28% higher throughput). #119064 (Jingxin (Philip) Li). - Faster
cbrt,fmod,fmaandhypot: in release builds the slower implementations from Rust’scompiler_builtinswere shadowing the optimizedllvm-libcones, andhypotnow uses the libc implementation. #118910 (Konstantin Bogdanov). - Reduced the time and peak memory of
s2GetNeighborsover many rows by reserving its result array once per block instead of once per row. Peak memory at four million rows in a single block drops by about 44%, and the gain grows withmax_block_size. #115919 (Groene AI). - Avoid materializing constant arguments in generic
leastandgreatestevaluation. #119108 (Minh Vu). - Faster materialization of lazily replicated sparse columns when consecutive output rows refer to the same source row. #118237 (Minh Vu).
- Skip rebuilding column TTL blocks when no row in the block is expired. #119109 (Minh Vu).
- Faster
LEFT ANTIjoins with theie_joinalgorithm when there is no residual condition: empty bitmap scans are skipped. #118584 (Minh Vu). - PromQL: a math binary operator applied to two aggregations of the same expression with the same grouping, such as
sum(x) - max(x)orsum by (job) (rate(x[5m])) / count by (job) (rate(x[5m])), now evaluates the argument once and computes both aggregations in a singleGROUP BY, instead of scanning the argument twice and joining the two results by group. #118307 (Nikita Mikhaylov). Use the constant empty group for aggregations with an emptyby()modifier. #118132 (Minh Vu). Improved the performance of thederivfunction. #118987 (Vitaly Baranov). - A PromQL selector matching a whole metric on a
TimeSeriestable no longer re-evaluates its primary-key range onidfor every row it reads; measured 23.7% faster on a 105M-row whole-metric query. #119092 (Groene AI). - Faster
timeSeries*ToGridaggregate functions: per-sample timestamp validation is skipped when the sorted bucket endpoints already prove the range. #118189 (Minh Vu). - Reduced contention on the global logger mutex in the
MergeTreeread path, which was noticeable on servers with many cores and queries touching many parts. #117498 (Manuel). Partition values are no longer formatted for a trace-level log message when trace logging is disabled. #119605 (Rory Shanks). - Push the
disk_namefilter ofsystem.remote_data_pathsinto the disk traversal, so a query that names the disks it needs no longer walks every object storage disk on the server. #118400 (Alexey Milovidov). - Speed up
clickhouse-clientstartup with many options. #118386 (Ivan Babrou). - Fewer allocations when reporting
ProfileEventssnapshots. #118305 (Ilya Yatsishin). - Speed up reading subcolumns from wide parts and from compact parts with substream marks by avoiding unnecessary full-column serializations. #111020 (Rory Shanks).
- Speed up aggregation batches with non-null states. #117009 (Ivan Babrou).
- Speed up flushing
system.opentelemetry_span_logby writing spans directly into its columns instead of boxing each value into aField. A burst of spans no longer makesSYSTEM FLUSH LOGS opentelemetry_span_loghit its timeout. #117481 (Alexey Milovidov). - Avoid join-order regressions when the selectivity estimator cannot evaluate every predicate in a
WHEREcondition: unaffected predicates are still used to estimate cardinality instead of falling back to full-table estimates. #118137 (Nikita Taranov). - Improved performance of some array functions: generic
arrayFirstandarrayLastreserve result rows,arrayExceptno longer copies the input when the exclusion array is empty, single-argumentarrayConcatno longer rebuilds the result, andarraySlice(arr, 1)no longer rebuilds the result array. #118188 (Minh Vu). #119665 (Minh Vu). #119697 (Minh Vu). #119817 (Minh Vu). - Reuse HTTP connections to object storage when a read range ends at the end of the object. Streams reading the same
MergeTreepart no longer open a new connection for each range. #118480 (Alexey Milovidov). SELECT count()can use the trivial count optimization on tables with lightweight-update patches that only change values, avoiding unnecessary table and patch reads. #118882 (Anton Popov).- Improve
Mapsubcolumn pruning:mapContainsValuecan read only the values subcolumn,mapKeys/mapValuesfilters can read only the matching keys or values subcolumn even when the fullMapis also selected, andhas/notHasover aMapcan read only the keys subcolumn when it is safe to do so. #119172 (Minh Vu). #119261 (Minh Vu). #119190 (Minh Vu). - The
advancedshared-data serialization forJSONnow sizes compressed blocks bymin_compress_block_sizeinstead of flushing per path and substream, avoiding large part-size regressions on tables with many shared-data paths. #119285 (Pavel Kruglov). - Reduce decompression overhead for chained compression codecs by constructing codec-description ASTs only when requested. #119490 (Raufs Dunamalijevs).
- Accelerate
countBytesInFilterandcountBytesInFilterWithNullon AArch64 using direct NEON vector register accumulation, improving filter counting throughput by up to 15x. #119555 (Joshua Dorst). - Partition pruning now runs before loading column statistics and before calculating skip-index ordering costs for
PREWHEREoptimization. Query-planPREWHEREcolumn sizes and statistics are now also estimated from the parts left after pruning, retaining the existing byte-cost estimate when those parts have no per-column measurements. #119558 (Rory Shanks). #119606 (Rory Shanks). #119607 (Rory Shanks). - Speed up single-argument
uniq,uniqCombined, anduniqCombined64on common scalar types when aggregating many interleaved groups. #119594 (Manuel). - UTF-8 validation is now vectorized across ClickHouse, not only inside the
isValidUTF8SQL function on x86. Text index conditions, Prometheus query parsing, format escaping and output,detectLanguage, andisValidUTF8itself now validate long strings much faster, including on AArch64. Closes #116074. #116204 (Groene AI). - Improved the performance of the
splitByNonAlphaandsplitByStringtokenizers. #119434 (Anton Popov). - Speed up
lowerUTF8andupperUTF8for mixed columns with mostly ASCII rows. #119790 (Minh Vu). - Speed up sorting of wide tables (
ORDER BYover many columns) by skipping an unnecessary per-row check in the merge step when no column can be replicated. This removes overhead that was noticeable on ARM. #110627 (Groene AI). - Speed up query analysis for large parameterized views by avoiding repeated hashing of the substituted view query during query-tree comparisons. Closes #118736. #119517 (Alexey Milovidov).
Improvement
- AI functions (
aiGenerate,aiClassify,aiFilter,aiExtract,aiTranslate,aiRedact,aiEmbed,aiSimilarity) are now beta and no longer require theallow_experimental_ai_functionssetting, which is now obsolete. Theai_function_*settings moved to the beta tier, andai_function_max_retriesnow defaults to1so that a single transient provider error does not fail the query. #116227 (George Larionov). - Added dimensional metrics for
S3Queue. #115422 (Bharat Nallan). - Very large
max_streams_to_max_threads_ratiovalues onMergetable reads are now validated correctly: stream-count calculations that overflowsize_tor exceed the maximum source count are rejected withPARAMETER_OUT_OF_BOUNDinstead of hitting undefined behavior. #113382 (Alexey Milovidov). - The Web UI no longer shows sort and filter controls in column headers when the first page of a result contains only a single row and those controls would only re-run the same query. Results that are already sorted or filtered, or truncated at the display limit, still show them. #116181 (Alexey Milovidov).
- A trace started by sampling (
opentelemetry_start_trace_probability) is now written back into the query’s client info, so remote and distributed secondary queries and DDL entries join the same trace instead of starting disjoint ones. #115619 (Diego Gomes Tomé). - The
Empty querysyntax error now says which text was empty when the text is not the query itself but a fragment parsed on its own, such as the value of theparallel_replicas_custom_keyoradditional_result_filtersetting:Empty query (parallel replicas custom key). The error for custom-key filtering requested withoutparallel_replicas_custom_keynow names the settings involved. #115959 (Alexey Milovidov). - Using
join_algorithm = 'direct'against aBuffertable now returns the ordinary unsupported-storage error instead ofCannot clone ReadFromPreparedSource plan step(NOT_IMPLEMENTED). #115309 (Groene AI). INSERT INTO ... SELECTfrom a cluster table function such ass3Clusterwithparallel_distributed_insert_selectnow expands aliases in theWHEREcondition before pruning files to read, so alias-based filters participate in pruning and no longer write a stack trace to the server log. #115932 (Alexey Milovidov).- Wrapped object-storage disks now account reads and writes to the workload of the underlying object storage, so workload scheduling uses the intended limits and priorities. #116288 (Mikhail Artemenko).
- A server started without a config file now declares the same single-node
defaultcluster as the packaged config, socluster('default', ...)andclusterAllReplicas('default', ...)work instead of failing withCLUSTER_DOESNT_EXIST. #116382 (Alexey Milovidov). - The
/commands of the client (/help,/man,/clear) are now offered by the line editor: typing/at the beginning of the input lists them as hints, andTabcompletes the command being typed. A mistake in a command name is now reported with similar commands suggested, instead of being parsed as SQL. #115039 (Alexey Milovidov). - Support
Decimaltypes when writing intoIcebergtables, including decimal partition columns and decimal min/max statistics. #115832 (Konstantin Vedernikov). - Web UI: the query text selection stays visible after the editor loses focus, so it is possible to see what the
Run selectedbutton will run. #116201 (Alexey Milovidov). ReplicatedMergeTreemutations now automatically prune affected partitions from theWHEREcondition when possible. Mutation queries also now accept multiple values in theIN PARTITIONclause. #110968 (Alexey Milovidov).- Allow
JOINon keys that have no common supertype, such asUInt64andInt64. Previously such queries were rejected withThere is no supertype for types UInt64, Int64. Keys are now converted to the type of the values they have in common, and a value outside that range does not match anything. #112951 (Alexey Milovidov). - Reduce the volume of logs from the parallel replicas coordinator: it no longer prints every part and all its mark ranges on each announcement, read request, and response. #115833 (Alexey Milovidov).
- The
Maybe you meanthint for an unknown column, function, or table is now printed before the query instead of after it, so it stays visible for long queries. When a column cannot be resolved from a table expression with an alias, the message also names the table behind the alias. #116809 (Alexey Milovidov). - Comparing a number with an empty or truncated string literal, such as
WHERE numeric_column <> '', now reportsCannot convert string '' to type Int32instead ofAttempt to read after eof. A correlated subquery returning several columns where one value is expected now also reports that directly. #116812 (Alexey Milovidov). - A
Valuesrow whose values are fine but whose,or)is missing or misplaced now reports the missing delimiter and the column it should follow, instead of claiming that the last value could not be parsed as its own type. #116877 (Alexey Milovidov). - TLS CA certificates configured with
openSSL.server.caConfig/openSSL.client.caConfigandcaConfigof composableprotocolsare now reloaded on file changes and onSYSTEM RELOAD CONFIG, allowing CA rotation without restart for server, client, and Keeper connections. #117387 (James). - Bare
UNIONnow tells you to writeUNION ALLorUNION DISTINCT, or to setunion_default_mode, instead of naming an internal AST class. TheEXCEPTandINTERSECTvariants are reworded the same way. #116815 (Alexey Milovidov). - An aggregate function used in
WHEREorPREWHERE, often through an alias such asSELECT count() AS c FROM t WHERE c > 1, is now told to useHAVINGinstead. Values that cannot be parsed asDateno longer claim to be too short when that is not the reason; the error now names the expected format. #116817 (Alexey Milovidov). - Invalid calls to the internal
viewExplaintable function now returnBAD_ARGUMENTSinstead of analyzing the invalid expression and potentially failing with an unrelated error such asUNKNOWN_TABLE. #108384 (Christoph Viebig). - Unexpected
jemallocwarnings are no longer suppressed, and the server now reports disabled per-CPU arenas insystem.warnings. #116899 (Azat Khuzhin). - Enable reading
ReplacingMergeTreedata in reverse order withFINAL. #115345 (Alexey Milovidov). - Added the
snapshot_zstd_compression_levelKeeper coordination setting to configure theZSTDcompression level used for snapshots. It defaults to3, preserving the existing behavior. #116866 (Antonio Andelic). - A typo in the key, index, or TTL expression of an
ALTER TABLEnow suggests the column that was probably meant, the waySELECTalready does. Previously it printed a list of available columns that, for aMergeTreetable, was dominated by virtual columns and truncated before the real ones. #116915 (Alexey Milovidov). - Aggregate functions that take parameters and are wrapped with the
-Arraycombinator now preserve those parameters correctly, so expressions such asargMaxArray(2)and state types such asAggregateFunction(groupArrayMovingSum(42), UInt64)no longer drop them. In debug and sanitizer builds this also fixes an internal assertion. #110143 (Groene AI). rseqis now enabled correctly on x86-64 builds that use link-time optimization; previously it was silently disabled. #117700 (Azat Khuzhin).- Take a column’s
CODECinto account when estimating how many bytes a query reads from compact parts. The estimate compressed a sample with the default codec (LZ4) no matter how the data is really stored, so a column stored with a stronger codec was overestimated, which inflateseffective_max_reading_threadsand can make automatic parallel replicas distribute a query that is cheaper to run on a single node. #114535 (Nikita Taranov). Icebergtables stored onS3can now read data files from a different bucket than the table metadata. #116771 (Konstantin Vedernikov).- An aggregate function with the
-Ifcombinator whose condition has the wrong type, or is missing, now says that the last argument is the condition and must beUInt8, instead of only reporting an illegal type for the last argument. AnASOFjoin with no inequality predicate now says that one is needed in addition to the equality predicates, instead of ending the message in, in .. #116916 (Alexey Milovidov). clickhouse-localnow exposessystem.warnings, and ClickHouse now checksrseqcompatibility at startup. #117717 (Azat Khuzhin).- The
TimeSeriestable engine, the PromQL dialect and thetimeSeries*aggregate functions are moved from the experimental tier to the private preview tier. Settingsallow_experimental_time_series_tableandallow_experimental_time_series_aggregate_functionsare renamed toenable_time_series_tableandenable_time_series_aggregate_functions; the old names remain as aliases. #118124 (Nikita Mikhaylov). TimeSeriestables now store an explicit schema version in theversionengine setting. The PromQL execution layer supports only a declared range of versions and rejects queries over tables outside that range with an instructive error. #111204 (Nikita Mikhaylov). ATimeSeriestable definition copied withCREATE TABLE ... ASnow gets the settings of the new table, and the newid_typesetting letsCREATE TABLE ... AS srccopy onlysrc’s definition without reading its target tables. #118517 (Vitaly Baranov). #119613 (Vitaly Baranov).- Reads from
TimeSeriestables now respect thejoin_algorithmand the partition-wise aggregation settings of the query instead of overriding them, and the internal join of samples and tags supportsfull_sorting_merge. #118864 (Nikita Mikhaylov). Thepromql_evaluation_timesetting defaults toautoregardless of thecompatibilitysetting. #119202 (Raúl Marín). - Join runtime filter settings are now production-tier (previously experimental). #117383 (Robert Schulze).
- Improved syntax error messages. An unclosed bracket is now reported at the place where the parser stopped, which is next to the actual mistake, and every unclosed bracket is listed with its own position; previously the outermost bracket was blamed, which in a large query can be thousands of characters away from the mistake. A mistyped keyword is now named explicitly (
Maybe you meant: SELECT.) instead of only being one item in a list of dozens of alternatives. #116806 (Alexey Milovidov). - The
psql-style\dof the interactive client now describes a table when a table name is given (\d hits), like it does inpsql; without an argument it still lists the tables. #118281 (Alexey Milovidov). clickhouse-localnow merges theconfig.dandconf.ddirectories of the current directory into its configuration even if there is no main configuration file, so a directory with aconfig.dno longer additionally requires an emptyconfig.xml. #118410 (Alexey Milovidov).- Added the
clickhouse_versionandsystem_processorcolumns to the system log tables. #117896 (Miсhael Stetsyuk). EXPLAIN ANALYZEnow shows more information about the estimation for joins. #114792 (Kirill Kopnev).- Automatic parallel replicas now support queries with
LIMITandOFFSET. #117402 (Nikita Taranov). - Object storage writes (
INSERTintos3,azureand other object storage tables) now support parallel replicas. #119214 (Konstantin Vedernikov). - Added the
min_partition_age_to_force_merge_secondsMergeTreesetting: when every part in a partition is at least this old, theSimpleandStochasticSimplemerge selectors compact that partition’s parts within themax_bytes_to_merge_at_max_space_in_poollimit. #115547 (Valery Petrov). TRUNCATE TABLEon aReplicatedMergeTreetable no longer blocks concurrentDROP,RENAMEand other DDL queries on the same table while the data is being removed. #114672 (Nikolay Degterinsky).- Allow
ALTER TABLE ... MODIFY SETTING storage_policyforMergeTreetables when newly added disks contain only a matchingformat_version.txtand an emptydetached/directory under the table path. #107736 (Maxim Orlovsky). - Added the
s3_upload_checksum_algorithmsetting to choose the checksum sent withS3uploads (MD5,CRC32orSHA256). The default is empty and keeps the current behavior. UseCRC32orSHA256on FIPS builds, whereMD5is unavailable and uploads would otherwise carry no checksum, which buckets with Object Lock reject. #107318 (Sebastian Vercruysse). - Partition field summaries are written into the manifest list of
Icebergtables. #118796 (Konstantin Vedernikov). ConcurrentINSERTs into anIcebergtable through a catalog no longer back off on a commit conflict and retry immediately. #119238 (Konstantin Vedernikov). - Log when an object storage listing returns an empty page while reporting that more objects follow. This is legal and is handled correctly, but it has twice been the trigger for silently losing objects and nothing recorded that it occurred. #119065 (Sema Checherinda).
- A warning is now logged when a CTE is declared as
MATERIALIZEDbut the settingenable_materialized_cteis disabled, in which case the keyword is ignored and the CTE is inlined at each reference. Previously the keyword was silently ignored. #118032 (Dmitry Novik). - An unknown profile event name in the
trace_profile_events_listsetting now gives a readable error message with hints instead ofstd::out_of_range: unordered_map::at: key not found. #116049 (Alexey Milovidov). - The dictionary loader now logs
neverinstead of a timestamp in the year 294247 when an object has no automatic update scheduled (for example a dictionary withLIFETIME(0)), which previously looked like a scheduling bug next to a failed-update message. #118443 (Alexey Milovidov). - Correct the error message for an unsupported attribute in an
ip_triedictionary: it claimed thatArrayattributes are unsupported, while in fact they are supported and onlyNullableattributes are rejected. #118492 (Alexey Milovidov). MEMORY_LIMIT_EXCEEDEDis reported promptly forparallel_hashjoins whose hash-table construction uses deferred memory tracking. #116477 (Konstantin Morozov).- Less verbose logging of
INSERTs intoMergeTreeandReplicatedMergeTreetables. #116486 (Azat Khuzhin). - The hash tables behind the TLD lists (
firstSignificantSubdomainCustomand similar functions), the naive Bayes classifier and text indexes use a simpler, packed string representation. #117175 (Surya Teja). - ClickHouse Keeper now counts the per-entry allocation overhead in
latest_logs_cache_size_threshold,KeeperLatestLogsCacheSize, andlgif’slatest_logs_cache_size, so the configured limit tracks cache memory rather than only serialized payload bytes. #119045 (Nikita Taranov). Thelatest_logs_cache_entry_count_thresholdsetting is effective again and limits the in-memory latest-log cache by entry count independently oflatest_logs_cache_size_threshold. #119151 (Antonio Andelic). - Show the progress percentage again for queries reading from the
filetable function andINFILE. #119213 (Raúl Marín). - Warn when
CLEAR COLUMNleaves anEPHEMERAL-derivedMATERIALIZEDcolumn stale. #115371 (Shaohua Wang). - Reduced cancellation latency for
INTERSECTandEXCEPTqueries:KILL QUERYnow interrupts the hash-table build and filter loops within a single chunk instead of waiting for the whole chunk. #118046 (Roman Vasin). - The
compatibilitysetting can now keep selected new defaults in effect: settings changes markedStartUsingNeware no longer rolled back to the previous default whencompatibilitypoints to an older version. #114190 (Mikhail Artemenko). - Added write support for
DeltaLaketables onAzurestorage. #116698 (Smita Kulkarni). - Added aliases without the
allow_experimental_prefix for existing settings whose tier already marks them as experimental or beta; the old names continue to work. #119056 (Robert Schulze). - Bump the bundled
libsshfrom0.12.0to0.12.2. #119262 (Robert Schulze). - Function
replicatenow returns a constant column when all its arguments are constant, likearrayWithConstant. #111069 (sakshichitnis27). - The
PROJECTION_NOT_USEDandINCORRECT_DATAerrors offorce_optimize_projectionandforce_optimize_projection_namenow list every projection the optimizer considered and why each was rejected. #119624 (Mikhail Artemenko).
Bug Fix (user-visible misbehavior in an official stable release)
ALTER TABLE ATTACH PARTITION FROMis no longer replicated inReplicateddatabases. #94835 (MikhailBurdukov).- Invalid Azure upload-size settings (for example
azure_min_upload_part_size = 0orazure_max_blocks_in_multipart_upload = 0) are now rejected early with a clear error instead of triggering an internal exception (second_size > 0) deep in the write path. This applies to both query settings and Azure disk configuration. #103394 (Statxc). - Fixed wrong results for comma or
CROSS JOINqueries whoseWHEREclause compares columns from the two sides through a non-deterministic expression such asrand. Such queries could return rows that contradict their ownWHEREclause because rewriting the join toINNER JOINre-evaluated the expression per row on each side. #112938 (Groene AI). S3QueueandAzureQueuetables whose metadata handle is gone no longer fail withLogical error: 'Files metadata is empty'when read, altered, or flushed; they now reportTABLE_IS_DROPPEDinstead.SYSTEM FLUSH OBJECT STORAGE QUEUEon such a table no longer terminates the server. #113695 (Groene AI).- Fix
LOGICAL_ERRORwhen filtering anIcebergcolumn thatALTER TABLE ... MODIFY COLUMNmadeNullable. Closes #85029. #114521 (Groene AI). - PromQL grouping modifiers now support quoted label names. #114545 (Minh Vu).
- Fixed reading a table while a mutation is in progress: a
MATERIALIZEDcolumn could return a stale or incorrectly recomputed value, and selecting it together with an updated column could fail with an error. #114561 (Shaohua Wang). #115372 (Shaohua Wang). - Fixed an RBAC bypass in the
Aliastable engine that allowed users without privileges on the target table to reveal its schema, row count, size, and existence. #114596 (Kai Zhu). - Fixed a column that was renamed, dropped, and added again in one
ALTERreturning the dropped column’s values instead of its own default while the mutation was still pending. #114601 (Shaohua Wang). ANY RIGHT JOINandSEMI RIGHT JOINwith severalOR-ed conditions in theONclause no longer duplicate some right-table rows and lose others. A writtenANY LEFT JOINwas affected too, because the planner may swap the tables and execute it asANY RIGHT JOIN. #114676 (Vladimir Cherkasov).- Fix invalid backslash escape handling in text,
tokenbf_v1, andngrambf_v1indexes. #115634 (Elmi Ahmadov). - Fix crashes of the
Parquet,ORC, andIcebergreaders on malformed input: aDELTA_BYTE_ARRAYpage with an empty length stream, aDELTA_BYTE_ARRAYpage of aDecimalcolumn read under a filter, an out-of-range enum in anIcebergmanifest file, and an oversized allocation in the ORC library. #115703 (Alexey Milovidov). - Reject invalid names of projections and indexes. #115824 (Alexander Tokmakov).
- A
KeeperMaptable with unparsable metadata no longer prevents server startup; it is now quarantined instead. Closes #115881. #115941 (Groene AI). - Fixed
LOGICAL_ERROR: Index with name auto_minmax_index_<column> already existswhen a singleALTER TABLEstatement combinedRENAME COLUMNwith another command, such asMODIFY SETTING, on a table with implicit minmax indices (add_minmax_index_for_numeric_columnsand friends). Renaming a plain column also no longer leaves a followingDROP COLUMNfailing withUNKNOWN_IDENTIFIER, nor a followingADD COLUMNwithout its implicit index. #116063 (Groene AI). - Fixed a crash of stateless workers with object storage. #116067 (Konstantin Vedernikov).
- Fixed distributed queries that filter or compute on
Decimal,DateTime64, orTime64constants: pushed-down constants could fail withCANNOT_PARSE_DATETIME, lose precision, or change theirDynamicsubtype when sent to remote shards. #95055 (Yakov Olkhovskiy). - Fixed
JSON,Object, andDynamiccolumns hashing logically equal values differently depending on their physical layout: howJSON/Objectpaths were split between dynamic subcolumns and shared data, or whether aDynamicvalue sat in a typed or shared variant. Hash-based joins on such a key silently missed matches, and agrace_hashspill could raise aLOGICAL_ERROR(Invalid state transition). AJSONkey needed no non-default setting;Dynamicalso requiredallow_dynamic_type_in_join_keys. #109450 (Groene AI). - Setting a Keeper coordination timeout such as
operation_timeout_ms,session_timeout_ms, orstartup_timeoutto a very large value no longer overflows and expires the wait immediately. Builds with the undefined behavior sanitizer no longer abort. #112088 (Groene AI). - Fixed a
bloom_filterskip index dropping granules that contain matching rows when aStringorFixedStringcolumn is compared for equality against a constant that is wider than the indexed type, so queries such asSELECT count() FROM t WHERE s = toFixedString('abc', 5)no longer silently return too few rows. #112639 (Groene AI). - Fixed a large
max_concurrent_threads_ratio_to_coresvalue inCREATE WORKLOADproducing an unspecified concurrent-thread limit. The ratio is now clamped before narrowing, so such a value means “no limit”. #113206 (Groene AI). - Fix wrong results when plan-based parallel replicas shipped a read pinned by
select_sequential_consistency. Follower replicas rebuilt the read without the pinned block-number boundary and returned rows the insert quorum never confirmed. Such a read is now executed locally. #114263 (Groene AI). - Fixed reading
Parquetfiles whose offset index does not start at row 0. Such a file could make the nativeParquetreader return wrong rows, or reportLOGICAL_ERRORinstead ofINCORRECT_DATA. The offset index is now validated when it is read. #114530 (Groene AI). - Fix query condition cache poisoning by
JOINqueries withquery_plan_join_shard_by_pk_ranges = 1, which made later queries with the sameWHEREcondition return too few rows. #114827 (János Benjamin Antal). - Fixed AI functions under-reporting provider usage in
system.query_logand in per-query quotas: counters accumulated before a failed request were dropped, and tokens for a response the provider billed for but that failed validation were never counted. #114905 (George Larionov). - Fixed
Coordination mode mismatch for stream <table>: got Default, expected WithOrderwhen a parameterized view is used as anINsubquery of an ordered query with parallel replicas enabled. A parameterized view used this way no longer plans its inner read with parallel replicas coordination on a replica. #114916 (Groene AI). - Fix asynchronous inserts into
JSONcolumns ignoring themax_dynamic_subcolumns_in_json_type_parsingsetting. Previously, an asynchronous insert (async_insert = 1) could store more dynamic paths than the setting allows, giving a different column layout than a synchronous insert with the same settings. The cap is now preserved when asynchronous inserts aggregate parsed data. #115329 (Mikhail f. Shiryaev). - Validate the discriminator of deserialized
Variantvalues, so malformed data is rejected instead of being read out of bounds. #115443 (Azat Khuzhin). - Fix
UNKNOWN_IDENTIFIERwhen creating a materialized view whose query uses an expression alias as the right argument ofIN. Closes #94894. #115651 (Alexey Milovidov). - Fix
RESTORE ... AS <new name>leaving theREFRESH ... DEPENDS ONlist of a refreshable materialized view pointing at the original database. The restored view refreshed in response to a table it no longer read, ignored refreshes of its own parent, and stopped refreshing entirely once the original database was dropped. #115689 (Groene AI). - Validate the deserialized states of
stochasticLinearRegression,stochasticLogisticRegression,groupUniqArray,groupArrayIntersect, andtopK, and of theResamplecombinator, so malformed data is rejected instead of being read out of bounds. #115701 (Alexey Milovidov). - Mask the
aws_external_idsetting of theDataLakeCatalogdatabase engine inSHOW CREATE DATABASEandsystem.databases.engine_full. It was previously printed in plaintext, unlike the other AWS credential settings. Closes #114999. #115791 (Groene AI). - Fixed
SELECT count()never terminating, or returning an invented row count, on a corruptedMsgPackorProtobufListfile. Theoptimize_count_from_filesfast path counted rows without requiring the read position to advance, so a two-byteProtobufListfile produced billions of rows and never returned. Such input is now rejected with the same error the ordinary read path gives. #115884 (Groene AI). - Fixed
ATTACH TABLE ... AS REPLICATEDand theconvert_to_replicatedflag file accepting a conversion whose ZooKeeper path is not a safe path. On a server whosedefault_replica_pathsubstitutes{database}or{table}, a name containing/used to resolve to a path inside another table’s subtree, letting the converted table register a replica under a table it has no privileges on. Such a conversion is now rejected withBAD_ARGUMENTS, the same way an equivalentCREATEalready was. Closes #115967. #115991 (Groene AI). - Fixed wrong results when joining against a view or
viewwhose projected column has the same name as a column of one of its own inner relations, for exampleSELECT expr(x.c0) AS c0 FROM a AS x, b AS y. The join order optimizer merged such an expression into the flattened join graph and then applied it twice, so the query silently returned skewed values. When the expression also changed the column type, the same cause producedAMBIGUOUS_COLUMN_NAMEat plan time instead. Closes #116036. #116152 (Groene AI). - Listing
tlsv1_3in<openSSL><server><disableProtocols>(or theclientequivalent) now actually disables TLS 1.3. Previously the token was dropped with no error or log line and the server kept negotiating TLS 1.3, so an operator who disabled it believed TLS 1.3 was off while it was not. Closes #79876. #116170 (Groene AI). - Fixed
Invalid number of columns in chunk pushed to OutputPort(LOGICAL_ERROR) when aSELECT ... FROM t STREAM ... ORDER BY ... LIMIT nquery read a table with aPROJECTION. Lazy materialization is no longer applied to aSTREAMread. #116187 (Groene AI). - Fixed
system.detached_tablesfailing withNOT_IMPLEMENTEDwhen the server has databases such asDictionary,Filesystem,HDFS,Overlay, orS3. Unsupported database engines are now skipped during iteration. Closes #104868. #107943 (Aditya Kumar). - Skip the Query Condition Cache for object-storage files whose
ETagis not a strong content identifier, such asHDFS. Previously a same-second, same-size overwrite could reuse stale skip marks and silently drop matching rows. Closes #112016. #112051 (Zhang Yifan). - Fixed text index functions
hasToken,hasAnyTokens,hasAllTokens, andhasPhraseoutsideWHERE/PREWHERE: they now apply the index’s tokenizer and pre/postprocessing in theSELECTlist, aggregate arguments, and withuse_skip_indexes = 0, so results match the index path. Closes #108808. #113154 (Elmi Ahmadov). - Fix wrong results for a query that calls the same table function twice with arguments that differ only in a part of the query that was not taken into account by the AST hash, such as
UNION ALLagainstUNION DISTINCT,INTERSECTagainstEXCEPT,LIMITagainstOFFSET, or the bounds of a window frame. The second call reused the result of the first one. #114171 (Alexey Milovidov). - Fix
THERE_IS_NO_COLUMN/NOT_FOUND_COLUMN_IN_BLOCKwhen a filter that runs afterFINALis a plain column reference. This affected an explicitPREWHERE bunderFINALand, with default settings, a row policy whose expression is a bare column. #114578 (Groene AI). - Fix loading old
S3tables with globbed paths andPARTITION BYafter upgrading from versions before 26.6. #115277 (Bharat Nallan). - Fix
Icebergidentity-partitioned reads: partition values are now taken from partition metadata instead of returned asNULL. Closes #110216. #116129 (Konstantin Vedernikov). KeeperMapnow writes single-expression primary keys without redundant outer parentheses, so metadata created by newer servers remains readable by ClickHouse 26.4 during supported rolling upgrades and rollbacks. #116369 (Sergey Kuznetsov).- Fixed
Kafkatables usingkafka_sasl_mechanism = 'AWS_MSK_IAM'failing authentication once an hour withSASL authentication error: Access denied. TheOAUTHBEARERtoken lifetime advertised tolibrdkafkais now capped by the remaining validity of the AWS credentials that signed the token, so the next token refresh is always scheduled before those credentials expire. Successful token refreshes are now logged, and unhelpful ClickHouse-side stack traces are omitted from broker-originated SASL errors insystem.kafka_consumers. #109125 (kalavt). - Fixed silent truncation of
DateTime64andTime64values with a scale above 6 whendate_time_64_output_format_cut_trailing_zeros_align_to_groups_of_thousandsis enabled. The printed fraction was capped at 6 digits, so aDateTime64(9)value of00:00:00.000000700rendered as00:00:00.000000even though the stored value was not zero. The documented output range of the setting widens from[0, 3, 6]to[0, 3, 6, 9]. #112854 (Groene AI). - Fixed the
dpsubanddpsizejoin-order optimizations (query_plan_optimize_join_order_algorithm = 'dpsub'/'dpsize') silently dropping single-table filter conditions from aJOIN ... ONclause, which could return extra rows. #114629 (Fisnik Kastrati). #118126 (Fisnik Kastrati). ZooKeepermulti requests now reject unsupported and mixed read/write operations. #115768 (Antonio Andelic).- You can now read
Icebergv2 tables whose manifests omit the optionalsnapshot_idcolumn, such as tables managed by BigQuery; reading one previously failed withCannot find column snapshot_id. A manifest that omitssequence_numberis also no longer read as sequence number0. Both values are inherited from the manifest list, as theIcebergspec requires. #116040 (Takayuki Enomoto). - Fixed
_pathpath normalization for globbed files and object-storage reads, soWHERE _path = '<path>'no longer misses rows because of redundant or leading separators. Globbed reads through symlinks and..names also no longer read or, withrename_files_after_processing, rename the wrong file. #116244 (Groene AI). #116252 (Groene AI). - Fixed wrong window function results for
PARTITION BYover a floating-point key (alsoJSON,Dynamic, and these types nested inNullable,LowCardinality,Array,Tuple,Map, orVariant) withmax_threads > 1: values that compare as equal, such as-0.and0., could hash into different threads, and one logical partition got several window frames. #116315 (Alexander Gololobov). - A
Native-protocol client can now forward an unknown setting to the server by name. Previously, when a client sent such a setting as a custom setting, the server left the real setting unchanged and reported it at its default value in the settings received with the query. #116317 (Miсhael Stetsyuk). - Fixed
h3Linereturning uninitialized memory in the tail of the result array when a line between two valid H3 indices cannot be drawn because it crosses pentagon distortion. Such a call now throwsINCORRECT_DATA. #116583 (Groene AI). CREATE TABLE ... AS <table function>no longer accepts aPRIMARY KEYin its column list. Previously, such a statement wrote table metadata that the server could not parse back on the next start, so the database failed to load with a syntax error. #116645 (Groene AI).- Fixed wrong row counts and dropped rows when a
DateTime64primary-key column is filtered throughtoStartOfDay,toRelativeSecondNum,toRelativeMinuteNum,toRelativeHourNum,toRelativeDayNum,toRelativeWeekNum,toMonthNumSinceEpoch, ortoYearNumSinceEpochwith values outside theUInt32-seconds range (before 1970 or beyond 2106). These functions claimed to be always monotonic to the primary index, but their standard-precision results wrapped for out-of-rangeDateTime64, breaking primary-key pruning. #110344 (Groene AI). - Fix regressions around
use_legacy_to_time:MergeTreekey expressions usingtoTimethat were created with the legacy semantics now work again, andCREATE TABLE ... AS SELECT,CREATE TABLE ... AS <table function>, andCREATE MATERIALIZED VIEWno longer fail or silently flattenNestedcolumns whenuse_legacy_to_time = 1. Closes #117001. #110958 (Groene AI). #116953 (Yarik Briukhovetskyi). - Fix
OPTIMIZE TABLE ... MANIFESTonIcebergtables: tables whose metadata file omits the spec-optional top-levelrefsobject no longer fail withPoco::NullPointerException, and an experimentalIcebergtable whose rows had all been deleted no longer crashes. Closes #112082. #112163 (Groene AI). #111241 (Smita Kulkarni). - Fix a server crash during a
JOINthat spills to disk. When an allocation failed while the join rehashed its buckets, the in-memory join was left either holding released data or absent altogether, and another build thread could dereference it. #113410 (Groene AI). - Fix wrong statistics-part pruning for negated floating-point predicates with
NaN. #113507 (Han Fei). - Fix a spurious
PreconditionFailed(Code: 499) error when creating or committing to anIcebergtable. If the object store drops the response to the metadata write after the object was written, the retry of that conditional write hits its own object and the query fails even though the write succeeded. Also stop a conditional multipart completion from reporting success over an object it did not write, silently losing the write it was meant to reject. #113994 (Groene AI). - Fixed lightweight
UPDATEonReplicatedMergeTreebeing rejected withTIMEOUT_EXCEEDEDafter a few seconds under concurrent updates, long before the configuredlock_acquire_timeoutelapsed. The Keeper lock acquisition loop was bounded by a fixed number of tries instead of by the timeout, so raisinglock_acquire_timeouthad no effect. #114125 (Groene AI). - Fix
ORDER BY ... LIMITqueries onTuple()columns raising aNOT_IMPLEMENTEDexception when top-K dynamic filtering is enabled. Direct empty tuples now skip the optimization, while supported nested composite types continue to use top-K filtering. #114182 (Langning Zhang). - Fix
Icebergtables partitioned bytoRelativeDayNumortoRelativeHourNumpublishing the non-canonical transform namesdaysandhoursin metadata. ClickHouse now writes the spec-defined singular namesdayandhour, so external readers such aspyicebergcan parse the partition spec. #114864 (yanglongwei). - Fix the server failing to start when
listen_hostcontains both::and0.0.0.0andarrowflight_portis configured, and fix two gRPC listeners silently sharing one port in the same configuration.listen_trynow also covers the gRPC and Arrow Flight protocols, which bind their listening socket when they are started. #115074 (Alexey Milovidov). - Fix a case where expensive ZooKeeper exception logging could delay session finalization and leave pending requests unresolved. #115396 (Antonio Andelic).
- An invalid
http_handlersconfiguration is now reported with its own error instead of being wrapped intoNETWORK_ERROR "Listen [host]:port failed". Previously, whenlisten_trywas in effect, the error was only logged as a warning aboutlisten_hostand the server started without serving HTTP at all. The same applies to the Prometheus listener onprometheus.port, to the Keeper control endpoints onkeeper_server.http_control, and toSYSTEM START LISTEN HTTPinclickhouse-local, which blamedlisten_hostandhttp_port. #115548 (Groene AI). - Fixed zero-precision
DateTime64andTime64text conversions returningDateTimeorTimeinstead ofDateTime64(0)orTime64(0):toDateTime64OrNull,toDateTime64OrZero,parseDateTime64BestEffort,parseDateTime64BestEffortOrNull,parseDateTime64BestEffortOrZero,parseDateTime64BestEffortUS,parseDateTime64BestEffortUSOrNull,parseDateTime64BestEffortUSOrZero,toTime64OrZero, andtoTime64OrNull. This previously prevented conversion of dates before1970-01-01and made theTime64functions silently lose values thattoTime64parses. #115618 (Mark Needham). #116979 (Navneet Kumar). - Fixed a server startup failure after creating an
Aliastable whose target did not exist yet and later became anAliastable itself. Such a table was accepted byCREATE, but rejected while loading metadata, which aborted startup withBAD_ARGUMENTS. TheAliastarget restrictions are now applied only to freshly supplied definitions. #116153 (Groene AI). - Fix
SHOW CREATE TABLEfailing instead of describing the table when the table’s storage object cannot be opened, for example aDataLakeCatalogtable the catalog reports as unreadable. TheAliastarget-access check now consults the engine name of the create query instead of opening the table. #116231 (Groene AI). - Fix
ProfileEvents['SelectedRows']andProfileEvents['SelectedBytes']being counted twice for reads from file, object-storage, data lake, queue, and executable table engines and table functions, and for executable dictionaries and UDFs. They now agree withread_rowsandread_bytes, as does theRead:line ofEXPLAIN ANALYZE. #116427 (Groene AI). #116679 (Groene AI). - Fixed
executable_pooldictionaries,executable_pooluser-defined functions, andExecutablePooltables waiting ten times longer than the configuredmax_command_execution_timewhen the process pool is exhausted, while the resulting error still reported the configured value. Closes #116467. #116560 (Groene AI). - Fixed a server crash when reading an
Icebergtable whose manifest list declares a very largemanifest_length. The declared value was used as the metadata cache entry weight, overflowing the cache accounting and terminating the server. The size measured while reading the manifest file is now used instead. #116564 (Groene AI). - Fixed a hang when a query names a database that does not exist, either through the
databasesetting (for exampleSELECT 1 SETTINGS database = 'no_such_db') or through thedatabasefield of a gRPC request. Such a query now fails withUNKNOWN_DATABASEinstead of blocking its connection forever; while it was hung it was also invisible tosystem.processesand toKILL QUERY. #116582 (Groene AI). - Fixed a use-after-free where a subscriber of workload entity changes, such as an object-storage disk, could be destroyed while its own change callback was still running. Destroying a workload entity subscription now waits for an in-flight callback and stops new ones from starting. Reachable from a
CREATE TABLEwith an inlinedisk(...)definition whose startup fails, concurrently withCREATE RESOURCEorDROP RESOURCEfrom another session. #116607 (Groene AI). - Fixed an exception when reading an
Icebergtable whose manifest marks a delete file as an equality delete without listing any equality field id. Such an entry is now rejected withICEBERG_SPECIFICATION_VIOLATIONinstead of an untypedstd::out_of_range. #116617 (Groene AI). - Fixed the
filetable function reading and writing outsideuser_files_pathwhen a..reached the path behind a directory symlink leavinguser_files_path: through brace expansion in a glob pattern, or through a..partition id inINSERT INTO FUNCTION file(...) PARTITION BY. #116767 (Groene AI). - Fixed corrupted or crafted
Gorilla-compressed data being decoded to wrong values instead of being rejected. Such data is now rejected withCANNOT_DECOMPRESS. #116820 (Groene AI). - Fixed the
looptable function disclosing the column names and types of anAliastable’s target to a user who holds no privilege on that target: a query that read no rows received them in its response header.loopnow requires table-levelSELECTon the target, matching what it already required of the table name it is given. #116873 (Groene AI). - Fixed incorrect results or an exception for
-Stateaggregates combined with-OrDefaultor-OrFillunderWITH TOTALS,ROLLUP, orCUBE. #99980 (Ilya Yatsishin). - Fixed
IcebergINSERTwriting manifest-wide aggregate column statistics into everydata_fileentry when a partition produced more than one data file. Each entry’snull_value_counts,column_sizes,lower_bounds, andupper_boundsnow describe only the data file it points at. Previously an entry could report more nulls than the file had rows, so a spec-conforming external reader could prune files that contained matching rows. #112414 (Groene AI). - Fix a server abort while committing a mutated part when its column or secondary-index sizes had not been computed yet. #112691 (Groene AI).
- Fix reading corrupted
ArrowStreamfiles. A malformed per-buffer uncompressed-length prefix in a compressed Arrow IPC record batch could reach the allocator as an enormous allocation size and produceLOGICAL_ERROR; it is now rejected asINCORRECT_DATA. #113006 (Groene AI). - Fix wrong results for
GROUP BYwhose only key is an injective function of constants, for exampleSELECT 1 FROM t GROUP BY materialize(NULL). Such a key could be removed, leaving the query with noGROUP BYand no aggregation, so it returned one row per input row instead of one row per group. Over aMergetable that mixes a local and a remote child, the same cause could also raise the exceptionChunk info was not set for chunk in GroupingAggregatedTransform. #114981 (Groene AI). - Fixed the exception
Not-ready Set is passed as the second argument for function 'in'in three cases: when selecting from aMergetable (or themergetable function) whose underlying table has a row policy containing anINsubquery, when a query withpartial_result_on_first_cancel = 1was cancelled while building the set forIN (subquery), and when a correlated subquery whose body containsIN (subquery)runs withcorrelated_subqueries_use_in_memory_buffer = 0, whichmake_distributed_plan = 1also sets. #114058 (Groene AI). #115083 (Alexey Milovidov). #115868 (Groene AI). - Fix authentication over the PostgreSQL wire protocol for users with several authentication methods. Users who also had an
ssh_keymethod, or another method with no password, were rejected withInvalid user or passwordeven when the correct password forscram_sha256_passwordwas supplied, and the wrong SCRAM salt was sent whenscram_sha256_passwordwas not the last method. #115084 (Alexey Milovidov). - Fixed
THERE_IS_NO_COLUMN(Cannot find column in source stream) forSELECT DISTINCT expr(k) ... ORDER BY kon a table with an aggregate projection grouped onk. Closes #112168. #115147 (Groene AI). - A
textindex is now used forhasAnyTokens,hasAllTokens, andhasPhrasecalled with an explicit tokenizer argument when that argument denotes the same tokenizer as the index. Previously the three-argument form always fell back to a full scan. Closes #115275. #115348 (Groene AI). - Fix an exception in a window function over a
Tuplewith a sparse element, for examplegroupConcat(t) OVER (). #115705 (Alexey Milovidov). - Conversion between named tuples with disjoint element names is now positional instead of silently filling the result with default values, and aliases that only give names to tuple elements can now repeat without error, for example
SELECT tuple(1 AS x), tuple(2 AS x). #115717 (Alexey Milovidov). - Cancel in-flight merges, mutations, and part fetches during graceful server shutdown instead of waiting for the running step to finish. Previously a single slow merge step or a large part download could delay shutdown for its whole duration. #115733 (Alexey Milovidov).
- Fixed a
WHERE _table = ...orWHERE _database = ...condition over aMergetable silently returning no rows when the matching child table reads its data from other tables, for example aDistributed,Merge,Buffer, orAliaschild. Such children are now always read, and the condition filters their rows. #116371 (Alexey Milovidov). - Fix corrupted output when
framing_output_formatis used together withhttp_write_exception_in_output_format = 1(the default forcompatibilitybelow 25.11). Data packets after the first one repeated the bytes of the first packet padded with zeros, and the query failed withstd::length_error. This affected the Web UI, which reported a JSON parse error after the first few rows. #116620 (Alexey Milovidov). - Fix links between settings, functions, and section headings on the built-in
/docspage. References to other settings or functions did nothing when clicked, and#heading anchors put a corrupted section into the URL. #116635 (Alexey Milovidov). - Fixed an exception when reading from a table after
DETACHandATTACHof a partition with patch parts created by lightweight updates. #116695 (Anton Popov). - Fixed silently wrong results when reading a
Parquetfile whose offset index disagrees with the page data on anArray,Map, or nested column. Such a page is now rejected withINCORRECT_DATAinstead of returning another page’s values under the requested row numbers. #116788 (Groene AI). - Fix background cleanup of unused
store/directories on encrypted disks. ClickHouse can now revoke permissions and remove these orphaned directories instead of failing during cleanup. #116919 (Ivan Shelestov). - Fix
Native-protocol memory allocation from truncated input: server-declared sizes no longer make the client allocate memory for data that has not arrived; exception strings are read as they arrive, the decompressed block size is bounded, and the maximum number of rows in aNativeblock is now one billion. #117011 (Alexey Milovidov). - Fix the exception
max_rows > 0(and possible incorrect merge results in release builds) inMergingSortedTransformwhen an input delivers a trailing empty chunk together with end-of-stream, for example underoptimize_read_in_order. #117048 (Alexey Milovidov). - Internal queries derived from an existing
QueryPlannow preserve execution limits and shared resources instead of losing settings such asmax_threadsand concurrency control. #109722 (Groene AI). - Fix wrong results when an
Enum8orEnum16constant is compared with aStringorFixedStringcolumn. The constant was converted to the enum’s underlying number instead of its name, so primary-key andPARTITION BYpruning, thebloom_filterskip index,INandNOT INsets, and thevaluestable function could silently use the wrong value. Matching rows could be dropped,NOT INcould keep rows it should exclude, andINcould disagree with=on the same constant. #112647 (Groene AI). - Fix wrong
ORDER BYandDISTINCTresults, andCANNOT_CONVERT_TYPEfor aggregate functions, when reading aMergetable whose declared column type does not preserve the sort order of a source table’s type, for exampleUInt64over a source holding negativeInt64. #113242 (Groene AI). - Fix
minandmaxreturning a wrong value when the implicit_minmax_count_projectionanswered them from a part-level bound that is not a real row value:NULLin aNullablesorting key,NaNin a floating-point key, or aTuplebound assembled component-wise. Such a query now reads rows instead of using the projection. #115151 (Groene AI). - Fixed a settings-constraint bypass: a
SETTINGSclause inside a subquery, a CTE, or a view’s inner query was applied without checking the settings constraints, so it could leavereadonlymode or override aCONST,MIN, orMAXconstraint such asadditional_table_filters, breaking row-level isolation. Nested clauses are now clamped to the constraints instead. #115397 (Itamar Tempelhof). - Fix
enable_adaptive_aggregatorwithmax_rows_to_group_byinthrowmode: adaptive aggregation no longer silently falls back to the regular algorithm, and the merged total is now checked against the limit in parallel two-level aggregation, including bucket Top-K and spill-to-disk paths. #116451 (Nihal Z. Miaji). - Fixed wrong results and an exception in primary-key analysis for
intDivanddivideover aDecimalkey with an integer constant divisor that does not fit the decimal’s native width. Such a query could return no rows at all instead of the matching ones. #116608 (Groene AI). - Column names such as
inf,infinity,nan,true, andfalseare now quoted when formatted, so a sorting key that refers to them no longer writes metadata the server cannot parse on the next start. Previously the table, and with it the whole database, failed to load. #116802 (Alexey Milovidov). - Fix a server crash when creating a table whose columns form a long chain of
DEFAULTexpressions, such asc1 DEFAULT c0 + 1, c2 DEFAULT c1 + 1, .... Planning such a statement no longer exhausts the thread stack. #116978 (Groene AI). - Fixed a
ReplicatedMergeTreereplication queue getting stuck forever after a new replica was added by cloning an existing one. The queue could contain twoALTER_METADATAentries for the sameALTER, so subsequentALTERs waited indefinitely andSYSTEM SYNC REPLICAtimed out. #117107 (Alexey Milovidov). - Detect a column-count mismatch between a tuple and a subquery in the
INclause during analysis, preventing constant folding from silently hiding the error. #97540 (Alexey Milovidov). - Fix
LOGICAL_ERROR(Temporary part ... already added) whenOPTIMIZE ... DRY RUNruns concurrently with a real merge, or with anotherDRY RUN, on the same parts. #110916 (Groene AI). - Fixed a server startup crash when the background updater for dictionaries and executable user-defined functions applied an empty configuration before the first configuration repository was registered. #113238 (Groene AI).
- Fixed a data race and a use-after-free on the metadata of
DeltaLakeandIcebergtables. Concurrent queries readingtotal_rowsortotal_bytesfromsystem.tablesfor the same table could crash the server. Closes #113265. #113427 (Groene AI). - Fixed
arrayROCAUCandarrayAUCPR, and their aliasesarrayAUCandarrayPRAUC, returning a different result for the same data depending on the order of the array elements when a score wasNaN. ANaNscore now makes the resultNaN. Closes #104763. #115101 (Groene AI). - Fix
RESTOREof an incrementalS3backup chain whose locator authenticates by assuming a role withextra_credentials(role_arn = ...). The role identifiers are now kept in the<base_backup>locator of the backup metadata, so each backup in the chain can reopen its base; previously chains deeper than one level could not be restored at all. Chains already written without them can still be restored withuse_same_s3_credentials_for_base_backup = 1, except when the locator is a named collection. #116223 (Julia Kartseva). - Fixed missed insert deduplication when a block reaches the sink with sparse column representation, for example
INSERT ... SELECTfrom a part with sparse serialization. Such an insert did not deduplicate against the same data inserted seconds ago from unmerged parts. #116287 (Mikhail f. Shiryaev). - Functions
h3PolygonToCellsandh3PolygonToCellsWithContainmentnow check for query timeouts andKILL QUERYwhile covering a polygon, and reject vertices whose longitude is outside-180..180or latitude outside-90..90degrees. Previously a polygon with such a vertex could keep a thread busy for tens of minutes, ignoring both. Closes #116195. #116335 (Raúl Marín). - Fixed the exception
... to have 0 rows, but it has 1: while executing function materializewhen a dictionary withLAYOUT(DIRECT())is read through themergetable function. Closes #116269. #116378 (Groene AI). - Fix a
bloom_filterskip index returning fewer rows forINon anArraycolumn when the set contains an empty array, for exampleWHERE x IN ([]). Closes #116431. #116449 (Groene AI). - Fixed wrong results from search functions (
hasPhrase,hasToken,hasAnyTokens,hasAllTokens) on a text index whosepreprocessororpostprocessorusesINorNOT IN, such asif(token IN ('the'), '', token). The transform was silently ignored whenever the predicate was evaluated on rows instead of read from the index, so matching rows could be missing. Closes #116476. #116578 (Elmi Ahmadov). - Fixed a 404 (
S3_ERROR) when reading anIcebergtable through a path that is a parent of the table directory, with the metadata document named by theiceberg_metadata_file_pathsetting. Writes and maintenance operations on such a table are now refused instead of acting outside the table. Closes #116985. #117037 (Groene AI). - Fixed incorrect results from
sum(if(cond, 0, 1))whencondhas typeLowCardinality(Nullable(...))andoptimize_rewrite_sum_if_to_count_ifis enabled, which is the default. Rows where the condition wasNULLwere not counted. Closes #116938. #117046 (Pratham Nayak). - Fixed
clickhouse-clientandclickhouse-localnot emitting the--chimealert for a long-running query that ends with an error. The threshold was checked against the query time last reported by the server, which is not refreshed when a query fails, so it could be arbitrarily behind the real duration of the query. It is now checked against the time the client actually waited. #117179 (Alexey Milovidov). - Fixed a server crash when executing
ALTER TABLE ... MATERIALIZE TTLon a table that is not aMergeTreebut whose metadata carries a TTL. This can affectAliastables whose target has a TTL andMaterializedViewtables that declare a TTL on one of their own columns. Closes #117327. #117181 (Groene AI). - Fixed a
LOGICAL_ERRORin KQLtimespanparameter handling forLowCardinalityinterval arguments. #117162 (Groene AI). - Fix
temporary_files_buffer_sizeandformat_avro_schema_registry_*accepting out-of-range values that then made every subsequent query in the session fail with no way to recover. Such values are now bounded when set. Closes #113782. #113787 (Pedro Ferreira). - Fix
allow_feature_tierrejectingmerge_tree_-prefixed settings in settings profiles as unknown and rejectingCREATE TABLEbecause ofMergeTreesettings applied bycompatibilityor themerge_treeconfig section. Also fix constraints on amerge_tree_-prefixed setting being bypassed when the setting is written through its alias, and a statement that rewrites such a setting to its current value being refused by aCONSTconstraint. #113156 (Raúl Marín). - Fix a server crash and out-of-bounds write when inserting into a column with a long chain of compression codecs, for example
CODEC(FPC, FPC, ..., FPC). Such chains are now rejected withCANNOT_COMPRESS; chains longer than 255 codecs, which previously could write unreadable parts, are rejected up front withBAD_ARGUMENTSunlessallow_suspicious_codecsis set. #113877 (Groene AI). - Fix
OpenSSLcipherListbeing silently ignored when its value is written on its own line, as XML or YAML auto-formatters do. The configured value is now trimmed before it reachesOpenSSL, and an invalid cipher list is reported instead of discarded, so the server no longer keepsOpenSSL’s default cipher list while appearing to honor the configured restriction. Closes #115808. #116053 (Groene AI). - Fix a server crash in the
ReplicatedMergeTreecleanup thread whenmax_replicated_logs_to_keep = 0. That value is now rejected, matching the documented domain of the setting. #117147 (Groene AI). - Fix path traversal in
RESTORE: backup metadata entries whose<name>is not already normalized are now rejected withINSECURE_PATHinstead of being restored outside the part directory whileRESTOREreports success. #117371 (Groene AI). - Fixed memory leaks of abandoned nested aggregate states. #113926 (Groene AI).
- Preserve row counts above the signed 32-bit range on the
PostgreSQLwire protocol. #114397 (Minh Vu). - Fixed
ILLEGAL_COLUMNforARRAY JOINqueries filtered by an emptyINset, including an empty list and an emptySettable. Closes #116018. #116057 (Groene AI). - Fixed
Aliastables ignoring row policies defined on their target tables. AnAliastable now combines the row policies of both the alias and its target table. #116290 (Kai Zhu). - Fixed concurrent writes of the same
format_schema_source = 'string'or'query'schema being rejected withCANNOT_OPEN_FILEorATOMIC_RENAME_FAIL. #116502 (Groene AI). - Fixed
moduloOrNull,intDivOrNull,divideOrNull, andpositiveModuloOrNullreturning the raw division result instead ofNULLwhen dividing by a constant zero inside a subquery whose result is read or persisted by an outer query. Closes #116500. #116594 (Groene AI). - Fixed
Icebergpartition pruning when a manifest’s partition tuple contains fields ClickHouse cannot model. Such tables no longer fail withSTD_EXCEPTION, and a manifest whose tuple length disagrees with its own spec is now rejected withICEBERG_SPECIFICATION_VIOLATIONinstead of returning deleted rows. #116615 (Groene AI). - Fixed wrong results from
sumKahanandsumKahanIfwhen the aggregated batch does not start at the first row of the block, including window frames, parallelGROUP BY, andoptimize_aggregation_in_order = 1. #116990 (Groene AI). - Fixed
GenerateRandomreads with a trivialLIMITreturning no rows because the source-count reduction could overflow to zero. Absurdly large requested stream counts are now also rejected withPARAMETER_OUT_OF_BOUND. #117171 (Groene AI). - Fixed out-of-bounds access in
timeSeriesGroupArray. #117404 (Vitaly Baranov). - Fixed
GROUP BYemitting a group from a zero-row block, returning a row withcount() = 0. Closes #116830. #117503 (Yarik Briukhovetskyi). - Fixed
arrayIntersectwith mixedNullableand not-Nullablearguments. Such calls could fail or return spurious default-valued elements for some data types;arrayUnionandarraySymmetricDifferenceare unaffected. #117577 (Groene AI). ATTACH PARTITION FROM,REPLACE PARTITION, andMOVE PARTITION TO TABLEno longer accept a non-adaptive part whoseindex_granularitydiffers from the destination table’s. Previously such a part could return wrong row counts in release builds. Closes #117524. #117594 (Groene AI).- Fixed
max_joined_block_size_rows = 0(documented as unlimited) making a hash join emit one left row per output block instead of honoringmax_joined_block_size_byteswhen a left row has multiple right matches. Closes #102007. #117604 (Groene AI). - Fixed
hasColumnInTabledisclosing whether a column exists on the target of anAliastable when the user lacksSHOW COLUMNSon the target. The function now requires that privilege on the target too. #117621 (Groene AI). - Fix silent data loss when a TTL expression applies a large interval directly to a
DateorDateTimecolumn by widening the arithmetic away from 16/32-bit overflow. #101793 (BoloniniD). - Fix
Cannot insert field with type ...when inserting a row that omits anAggregateFunctioncolumn whose argument types containLowCardinality.defaultValueOfTypeNameis fixed for the same type names. #102403 (Enric Calabuig). - Fixed a privilege-escalation gap where the
executabletable function did not enforce theTABLE ENGINE ON Executablegrant. Withtable_engines_require_grantenabled, a user deniedCREATE TABLE ... ENGINE = Executablecould still run the same server-side script viaSELECT ... FROM executable(...). It now requiresGRANT TABLE ENGINE ON Executable, matchingCREATE TABLE. #109331 (Groene AI). - Fix silently wrong
GROUP BYresults withoptimize_aggregation_in_order = 1. Groups were merged into one another and aggregate values were wrong when the matched sorting-key prefix contained a reverse (DESC) column, and, independently of reverse keys, when a group-by key was a negative monotonic function of aFloatsorting-key column around theNaNboundary. This affected a singleMergeTreetable and aMergetable over such tables. For aMergetable whose underlying tables read the matched prefix in opposite physical directions, aggregation in order is now declined because a single stream direction cannot describe both. #112200 (Groene AI). - Fix
_path/_filefiltering for object storage,file, andurlreads. AGLOBAL INsubquery over_pathor_fileof a path without globs no longer throwsNot-ready Set is passed as the second argument for function 'globalIn'; an explicitly named archive member is filtered before the archive is opened;Hivepartition columns are inferred for an explicitly named key that does not exist; andurlCluster/fileClusternow prune a filtered-out path on the initiator instead of handing it to a replica. #112968 (Alexey Milovidov). FileLogtables no longer silently skip files that appear afterCREATE TABLE. The directory watch ran as aBackgroundSchedulePooltask but never returned, so it held its slot of the per-task-type budget forever; oncebackground_schedule_pool_sizetimesbackground_schedule_pool_max_parallel_tasks_per_type_ratiotables existed, further tables never watched their directory at all andSELECTreturned fewer rows instead of erroring. The watch now runs on its own thread. #113897 (Groene AI).- A query queued on a full distributed connection pool now responds to
KILL QUERY, and tomax_execution_timeat the defaulttimeout_overflow_mode = 'throw', instead of waiting until another query happens to release a connection, and a positiveconnection_pool_max_wait_msnow actually expires. Previously the wait ended only on success at every value of the setting, so the configured timeout was ignored,max_execution_timewas reported long after its deadline, and the query could not be killed. The wait applies per replica, so an expired one is a soft failure that fails over to the remaining replicas and only then reportsALL_CONNECTION_TRIES_FAILED. #113979 (Groene AI). - Fix wrong results when a filter on a
JSONsubcolumn that mixes a literal prefix with a quoted path segment is analyzed against aJSONAllPathsskip index. The subcolumn name was misparsed, so all granules were skipped and the query returned fewer rows than it should. #114873 (Pavel Kruglov). - Fix wrong results when a
SELECTwithselect_sequential_consistency = 1on aReplicatedMergeTreetable runs with classic (task-based) parallel replicas. Every replica performed a complete local read clamped to the quorum boundary instead of a coordinator-assigned slice, so rows were returned once per participating replica. #114945 (Groene AI). - Fixed
CREATE DICTIONARYfailing withIncorrect type of ID column: must be UInt64, but it is LowCardinalitywhen the simple primary key is declared asLowCardinality(UInt64)anddictionary_validate_primary_key_typeis enabled. Closes #104539. #115139 (Groene AI). - Fix a hang in workload memory reservations when an increase races with an in-flight decrease. #116085 (Azat Khuzhin).
- A
Kafkatable withkafka_keeper_pathset (StorageKafka2) no longer skips messages it had already consumed when a streaming cycle fails part-way through; previously those messages were never delivered to the materialized views and a later cycle committed an offset past them. As a consequence, with the defaultkafka_handle_error_modean unparseable message now blocks the table instead of being silently skipped, matchingStorageKafka.kafka_handle_error_mode = 'stream',kafka_handle_error_mode = 'dead_letter_queue', andkafka_skip_broken_messagesremain the ways to skip such a message. #116485 (Groene AI). - Fixed the
Unexpected return type from materializelogical error when reading a column that has atextindex through the index after a metadata-only or not-yet-materializedALTER MODIFY COLUMN(including lazyJSONtype hints) that requires a read-time type conversion. #116549 (Pavel Kruglov). - A table created with
CREATE TABLE ... AS <table function>(...)is no longer resolved to answer aSYSTEM STOP-family lock query or asystem.tablessize query about it. Previously those statements contacted the endpoint of every such table, so one unreachable endpoint made them fail or stall. Until such a table is first accessed it now reportsNULLsizes and an emptydata_paths, andDROP TABLE ... IF EMPTYremoves it instead of reportingTABLE_NOT_EMPTY. #116774 (Groene AI). - Fixes wrong results when a
minmaxskip index,ORDER BY, orPARTITION BYis built over anArray,Tuple, orMapholding aBool, such asArray(Tuple(Float64, Bool))orMap(String, Bool), and when aminmaxindex serves anORDER BY ... LIMITover aBoolcolumn. Previously, rows that the predicate accepts could be dropped, because the stored bound and the value compared against it represented the boolean differently. #116897 (Groene AI). - Fixed an external
GROUP BYexceedingmax_memory_usagewhenenable_adaptive_aggregatoris on. Intermediate data the adaptive aggregator held and could not release kept a thread on the baseline algorithm flushing its own hash table on every block, so each block wrote a temporary file and the merge then allocated a reader per file. That data is now written out first. #117326 (Groene AI). - Malformed
Nativeblocks can no longer overflow the allocation of aggregate-function states during deserialization and cause out-of-bounds writes. #117370 (Raúl Marín). - Fixed the byte width of the
Icebergmanifestlower_boundsandupper_boundswritten forintanddatecolumns: they were 8 bytes wide where theIcebergspecification requires 4. Spec-conformant readers such aspyicebergfailed withunpack requires a buffer of 4 byteswhile planning any scan carrying a filter on such a column. #117571 (Groene AI). - Remote-write async insert flush timeouts are now handled correctly: they return retryable
503 Service Unavailableinstead of408 Request Timeout, so Prometheus-compatible senders can retry them, andwait_for_async_insert_timeoutis now clamped instead of overflowing for large magnitudes. #117632 (Vitaly Baranov). #118040 (Groene AI). - Fixed
base58Encodeandbase58Decodeof 32- and 64-byte values on big-endian builds such ass390x. The fixed-size codec byte-swapped every 4-byte word unconditionally, so on a big-endian hostbase58Encodereturned a string that disagrees with the base58 specification and with every other architecture, andbase58Decoderejected well-formed input when given a 32- or 64-byte size hint. Little-endian builds are bit-identical to before. Strings previously produced by a big-endian build will change, because they were wrong. #117649 (Groene AI). - Fixed
format_schema_source = 'query'running the schema query with full privileges when used from a background task, such as a streaming engine consumer (Kafka,NATS,RabbitMQ,ObjectStorageQueue) or aBufferbackground flush. The schema query is now rejected there; useformat_schema_source = 'file'orformat_schema_source = 'string'instead, or pre-populate the schema cache. #117737 (Pavel Kruglov). - Fix
absentandscalarPromQL queries returning no result whenempty_result_for_aggregation_by_empty_setis enabled. #117816 (Valery Petrov). - A
bloom_filterindex over anArray(Nullable(T))column is now rejected atCREATE/ALTERtime. It used to be accepted and then made every insert, merge, and mutation of the table fail, withDROP INDEXrefused until the failed mutation was killed. #117899 (Alexey Milovidov). - Fix the
GROUPINGfunction rejecting constant aliases that are validGROUP BYkeys. #97504 (Héctor Pablos). - Fixed SQL injection in the
PostgreSQLwire protocol emulation. Prepared-statement parameters, in both the extended-queryParse/Bind/Executepath used bypsycopg2, JDBC,node-postgres, Npgsql, and others, and the simple-queryEXECUTEpath, were substituted into the executed SQL by raw string splicing, so a crafted parameter could break out of its value position and inject SQL. Parameters are now bound as data. This also fixes string parameters that previously failed withUNKNOWN_IDENTIFIERwhen a client sent them unquoted. #108469 (Groene AI). - Fix a
LOGICAL_ERROR(Part ... intersects previous part ... It is a bug or a result of manual intervention) that makes aMergeTreetable impossible to load: attaching it, and every later attempt to load it, fails with that exception, and debug and sanitizer builds abort. A merge could span a block gap holding an outdated part whose mutation version is higher than the merge result’s, producing a pair of parts on disk that neither contain nor are disjoint from each other. Closes #113864. #113941 (Groene AI). - Fix a
LOGICAL_ERROR: Next task callback is not set for query with idexception whenparallel_replicas_plan_basedis enabled and the query reads a system log table. #114022 (Groene AI). - Fix
files_readandbytes_readinsystem.backupsandsystem.backup_logbeing permanently undercounted after a successfulRESTORE, because a concurrent restore task holding an early snapshot could overwrite a larger count published by another task. #114304 (Groene AI). - Fix wrong results when a non-boolean condition, such as a bare integer column in
WHERE, is left alone after the other conditions are merged into theJOINcondition or pushed down. Rows whose condition value was a non-zero multiple of 256 were skipped. #114533 (Vladimir Cherkasov). - Fixed a single
ALTERwith twoMODIFY COLUMNsubcommands on the same column silently corrupting that column’s default: a default set by one subcommand was dropped, and aREMOVE DEFAULT/MATERIALIZED/ALIASwas undone, whenever a following subcommand restated the column type. #114807 (Groene AI). - You can now access nested properties on a
Nullable(JSON)value, for examplecol::Nullable(JSON).Id. Previously this failed withFirst argument for function tupleElement cannot be Nullable(JSON), which made it impossible to combine a cast toNullable(JSON)with property access on the result. OuterNULLrows now propagate through extracted paths using the existing subcolumn semantics: paths whose type can representNULLreturnNULL, while types such asArrayandMapreturn their default values. #114863 (Luís Lizardo). - Fix an integer overflow in the deserialization of
Stringvalues in the binary formats, and bound the recursion of the binary deserialization ofDynamicandJSONvalues. #115702 (Alexey Milovidov). PostgreSQLcompatibility now handlespg_catalogqualifiers case-insensitively like PostgreSQL does, and the synthetic OIDs exposed throughpg_namespaceandpg_classare now unique, sopsqlcommands such as\dno longer duplicate tables or list them under the wrong schema. #115960 (Alexey Milovidov).- Fixed data loss in
MergeTreewhen a merge runs while anALTER TABLE ... RENAME COLUMNis still pending. The merge applied the rename but did not record it, so the mutation applied it a second time and read the renamed column as missing, filling it with defaults. Columns without a default expression, such asDynamic, lost their values. #115981 (Alexey Milovidov). - Fixed a query over an
Icebergtable returning fewer rows than the table holds when a manifest declares a lower bound above the upper bound for a filtered column. Such a pair describes an empty range, so min/max pruning dropped the data file holding the matching rows; those bounds are now ignored instead. Closes #116499. #116604 (Groene AI). - Fixed two
Binary Viewer(/binary) bugs: the image was not centered on load if the URL contained parameters such asuser, and the connection parameters (host,user) were lost from the URL after moving the view. Thepasswordparameter is no longer kept in the address bar or browser history. #117065 (Alexey Milovidov). - Fix a large performance regression, present since 26.5, for a query that filters on a column with an equality and orders by a later column of the same sorting key. Read-in-order analysis did not look through an
ALIASnode on the filter column, so the filtered column was not recognized as constant and the read was not done in order, forcing a full sort of every matching row before theLIMITapplied. This reaches a table with a normalPROJECTION, whose rewrite wraps the query filter in such an alias, and a table-levelALIAScolumn used as a predicate. #116854 separately made a base table that can serve theORDER BYitself preferred; this fixes the case where only the projection can. #116835 (Groene AI). - Fixed wrong results when reading the
.nullsubcolumn of a column that went through a metadata-onlyTtoNullable(T)ALTERand then had aRENAME COLUMNstill pending:IS NULL,IS NOT NULL,count(), and an explicitx.nullread reported rows holding real data asNULL. #116901 (Groene AI). - Fixed a stack overflow when reading hadoop-snappy data containing many blocks that decode to nothing. #116994 (Alexey Milovidov).
- The handshake response of the
MySQLwire protocol is now bounded, so a client can no longer make the server grow memory during the handshake. Themysql_require_secure_transportserver setting is now enforced from the actual state of the connection instead of a capability bit advertised by the client. #117003 (Alexey Milovidov). - Fix background
Distributedinserts that deleted unsent spool files after a split batch got a transient error. ClickHouse now keeps the files and retries the batch. #117034 (Rory Shanks). - Fix wrong results for
GROUP BYanduniq*overMACNumToString,unhex,unbin, andUUIDStringToNum. All four declared themselves injective, so the default-enabledoptimize_injective_functions_in_group_byandoptimize_injective_functions_inside_uniqgrouped and counted by the raw argument: arguments that map to the same result came back as separate groups and were counted separately byuniqExact. #117210 (Alexey Milovidov). - Fix wrong results from the default-enabled
optimize_uniq_to_count.uniq(x)over aSELECT DISTINCT xorGROUP BY xsubquery reported one distinct value too many when the column contained aNULL, and counted the extra super-aggregate rows ofWITH ROLLUP/WITH CUBEas additional distinct values. #117222 (Alexey Milovidov). - Fix
NO_SUCH_COLUMN_IN_TABLEfor every query using a text index while a mutation is pending withapply_mutations_on_fly = 1. Until the mutation materialized,hasToken,hasAnyTokens, andhasAllTokenson the indexed column could not be executed at all. #117277 (Alexey Milovidov). - Several aggregate function deserializers allocated memory from a size declared in the serialized state before reading the payload, so a state of a few bytes could request gigabytes. They now read only what the buffer already holds. #117536 (Groene AI).
getServerSetting,getMergeTreeSetting, andgetMacroreturned the values ofsystem.server_settings,system.merge_tree_settings, andsystem.macrosto any user, bypassing theSELECTgrant that reading those tables requires. They now require the same grant. #117551 (Raúl Marín).- Fixed a bug where the
analyzer_inline_viewssetting could bypass theSELECTaccess check on a view, letting a user without a grant on the view read its contents. #117555 (Dmitry Novik). ENGINE = EmbeddedRocksDB(ttl, rocksdb_dir, read_only)with an explicitrocksdb_dirnow requires theFILEsource grant thatfilerequires for the same directory:READ ON FILEto create such a table, plusWRITE ON FILEwhenread_only = 0. Previously it required no source grant, so a user holding onlyCREATE TABLEin a database of their own could point a table at another table’s directory and read its rows.ON CLUSTERandReplicated-database DDL are not covered: the replay runs with no user. The argument-less form is unaffected. Backward incompatible for anyone already using an explicitrocksdb_dirwithout them. #117428 (Groene AI). #117665 (Pedro Ferreira).- Fix
ALTERandCREATE TABLE ... ASdropping the other settings of aTimeSeriestable. #117693 (Vitaly Baranov). #117839 (Vitaly Baranov). #118119 (Alexey Milovidov). - Fix incorrect results for suffix
LIKEpatterns with escape sequences whenoptimize_rewrite_like_perfect_affixis enabled. Such patterns are now rewritten toendsWithonly when the suffix is an exact literal. #117712 (Alex Prabhat Bara). - Fix a dictionary with a
Redissource and anInt256key column silently returning the default value fromdictGetfor keys that exist inRedis. Wide integer key columns are now refused with a clear error instead of being admitted and never matching. #117735 (Pratham Nayak). - Fixed excessive memory usage when reading from
File,URL, object storage,GenerateRandom, or any other storage that uses the generic read path withmax_streams_to_max_threads_ratioabove 1. The number of output ports created after a read is now bounded bymax_threads, so aSELECTover a tiny table no longer allocates tens of gigabytes while the pipeline is still being built. #117772 (Alexey Milovidov). - Fix
ARRAY JOINproducing rows in incorrect order in some cases. #117918 (Yarik Briukhovetskyi). - Fix a potential out-of-bounds write in
formatDateTimeInJodaSyntaxwhen called with a time zone name longer than 32 characters. #117925 (Robert Schulze). - Fix
EXPLAIN QUERY TREEandEXPLAIN SYNTAXexposing column names and types of tables the user has no privileges for: the analyzer now checks that the user may see at least one column of the table at the moment a table identifier is resolved. The check also makes the error kind independent of whether the queried column exists and stops recording column names the user may not see intomissing_privilegesof the query log. Closes #78938. #117979 (Alexey Milovidov). - Fixed Keeper aborting when memory usage stays near the limit: moving finished changelogs and snapshots to object storage was refused, so the local log disk filled up. #117983 (Shaohua Wang).
- Fixed a
Kafka/RabbitMQ/NATS/FileLog/S3Queue/AzureQueuetable in a database withlazy_load_tablessilently stopping to feed its materialized views after a server restart. #118009 (Alexey Milovidov). - Fixed cancellation of a synchronous distributed
INSERT(distributed_foreground_insert) waiting for thatINSERTto finish instead of interrupting it.KILL QUERYagainst such an insert, a client disconnect, and server shutdown could block for as long as a shard was slow. #118013 (Groene AI). - Fixed a
LIMITbeing pushed intonumbers()when the query’sWHEREreferenced anarrayJointhrough aWITHalias, which could make the source stop before the expansion produced enough rows. #118045 (Yarik Briukhovetskyi). - Fix
Icebergschema evolution for additional nestedArray,Map, andStructcombinations whose inner fields are added, removed, or reordered. #118127 (Konstantin Vedernikov). - Fixed incremental backups to Azure Blob Storage storing the beginning of each file instead of its tail. Restoring such a backup silently dropped all the data written after the base backup. #114975 (Smita Kulkarni).
- Fixed potential data loss when an
INSERTintoReplicatedMergeTreewas cancelled or timed out while ClickHouse was recovering an uncertain Keeper commit. #111196 (kakao-tars-case). - Fixed object storage listing silently skipping objects when S3 returns an empty page together with a continuation token. This could make a
plain_rewritabledisk appear empty and hide table parts, and could make data lake tables read a stale snapshot. #118615 (Sema Checherinda). - Fixed a SQL injection in the PostgreSQL metadata queries. The
schemaof thePostgreSQLdatabase engine, the requested column names and the publication name were formatted into SQL literals without escaping, so a value containing a quote could execute arbitrary SQL on the connected PostgreSQL server as the role ClickHouse connects with. Reaching it throughschemaneeded onlyCREATE DATABASEplus use of a named collection whoseschemais overridable. #111516 (Shaohua Wang). - Hide the credentials that a setting value can carry, such as the password in
format_avro_schema_registry_urlorurl_base, everywhere a setting value is displayed or logged.system.query_log,system.processes,system.settings,system.settings_profile_elements,system.session_log,system.distributed_ddl_queue,SHOW CREATE USERandSHOW CREATE SETTINGS PROFILEpreviously showed them in plaintext to any user who could read them. #117523 (Raúl Marín).EXPLAINnow respectsformat_display_secrets_in_show_and_selectas well. #118129 (Kirill Kopnev). CREATE USER OR REPLACEand theOR REPLACEform ofCREATE ROLE,CREATE QUOTA,CREATE SETTINGS PROFILEandCREATE ROW POLICYnow require the correspondingDROPprivilege in addition toCREATE, because they overwrite an existing entity. PreviouslyCREATE USERalone was enough to reset the password of any other user, including a privileged one. #117960 (Alexey Milovidov).- Fix
CREATE OR REPLACE TABLE/VIEW/DICTIONARYandREPLACE TABLErequiring privileges on the internal temporary table they create (_tmp_replace_*). Its name is random, so no grant could cover it and the query failed withACCESS_DENIEDunless the user held wildcard grants on the whole database. The required privileges are now checked against the user-visible names only: replacing an object needs theCREATEandDROPgrants of its own kind, plusINSERTon it when the statement populates it. #117967 (Alexey Milovidov). TRUNCATE DATABASE ... ON CLUSTERandTRUNCATE [ALL] TABLES FROM ... ON CLUSTERran without checking any privilege: a user holding onlySELECTandCLUSTERcould destroy every table in a database, andreadonly = 1did not prevent it. Both now requireDROP DATABASE, the privilege the non-cluster spellings have always required. #118155 (Groene AI).- Fixed a privilege escalation in implicit access-rights computation: holding any single child privilege of the
ALTER TABLEgroup (for exampleALTER MODIFY COMMENT) on a view implicitly conferred the entireALTER VIEWgroup, so such a user could runALTER TABLE <view> MODIFY QUERYand rewrite the view’s query.ALTER VIEWis now implied only by the completeALTER TABLEgrant. A deployment that relied on a partialALTER TABLEgrant to alter views must now grantALTER VIEW(or one of its members) or the fullALTER TABLEexplicitly. #118194 (Groene AI). - Expressions supplied through the
additional_table_filtersandparallel_replicas_custom_keysettings are now subject to the column-levelSELECTcheck, and are no longer injected into the body ofSQL SECURITY DEFINERorNONEviews. Previously a user could evaluate predicates over columns they were not granted. #118063 (Dmitry Novik). - Forbid
CREATE TABLE ... AS viewIfPermitted(...), includingviewIfPermittednested in another table function such asremote, which now fails withBAD_ARGUMENTS, as it already does forevaland the*Clustertable functions. The function chooses between itsSELECTquery and theELSEfunction according to the current user, but a persisted table is resolved with no user and therefore full access: reading one reported the source table’s column names and types to a user with no grant on it, and theELSEfallback was unreachable. Tables created before this change keep loading; drop them to close the disclosure. #116885 (Groene AI). - Fixed a
Filesystemdatabase serving a table from its internal cache without theREAD ON FILEgrant. The grant was checked only while a table name was resolved for the first time, so once any user holding it had read a name, every user withSELECTon the database was served the contents of the file.EXISTS TABLE, which requires onlySHOW TABLES, answered from that cache and probed the directory without the grant too. Both now require it, and a user without it is refused before the existence of the file is observed. #119029 (Groene AI). - Apply
remote_url_allow_hostsbefore SQL-supplied S3 and Azure endpoints send schema, metadata, or container requests. #114357 (Rory Shanks). - Fixed the server deserializing the payload of a
Datapacket that arrives on a connection before any query. In interserver mode the connection is not authenticated until theQuerypacket is processed, so such a packet was rejected only after its Native block had been read, which let an unauthenticated peer choose the column type the server constructed. The packet is now rejected before its payload is touched. #118588 (Groene AI). - Each code for a time-based one-time password is now accepted at most once, as required by RFC 6238: reusing an already used code, or a code for an earlier time step, is rejected. A user with
time_based_one_time_passwordcan successfully authenticate at most once perperiod. #117563 (Vladimir Cherkasov). - Fixed wrong results when
join_algorithm = 'parallel_hash'is combined with a sorted consumer such asoptimize_aggregation_in_order,optimize_distinct_in_orderorLIMIT BY. With several join slots and a single-level hash map the join does not keep the order of the left table, so the read-in-order-through-join optimization must not advertise the left sort order in that case. #109225 (Groene AI). - Fixed a
LOGICAL_ERROR(Join is supported only for pipelines with one output port) raised by a mergeJOINwhen its two sides reached the join with a different number of output ports. #109393 (Groene AI). - Fix wrong results when a doubly negated expression is compared with a constant, such as
WHERE (NOT NOT c) > -0.5. Index analysis cancelled the twoNOTs and compared the column itself with the constant, pruning parts, granules and partitions that do match. #116381 (Alexey Milovidov). - Fixed wrong results after
ALTER TABLE ... MODIFY ORDER BYon a table with a descending sorting key column (ORDER BY a DESC). TheALTERsilently dropped theDESCdirection while existing parts stayed physically sorted the old way, so primary key index analysis pruned the wrong granules and queries returned missing rows. Such anALTERis now rejected. #116473 (Groene AI). - Fix the
Invalid status NotActive for associated outputlogical error that could happen for queries with a highmax_threads, for example aGROUPING SETSaggregation over a remote table. #116478 (Alexey Milovidov). - Fixed reading uninitialized memory as literal data when decompressing a malformed
LZ4-compressed block. #116992 (Alexey Milovidov). - Fix silently missing rows for a predicate on
toMillisecond,toMicrosecondortoNanosecondof aDateTime64primary key. All three claimed to be monotonic everywhere, although they restart at zero every second, so primary-key analysis treated the predicate as one contiguous key range and pruned granules that contain matching rows. #117246 (Alexey Milovidov). - Fix wrong row counts from the default-enabled
query_plan_merge_filter_into_join_conditionwhen an equality conjunct of theWHEREfilter contains a non-deterministic function such asrand(). The conjunct was moved into the join condition, where it is evaluated once per join input row instead of once per output row, and cloned into the build-side runtime filter as a second evaluation site. #117247 (Alexey Milovidov). - Fix the default-enabled
query_plan_merge_expression_into_joinreturning rows that violate the query’s ownJOIN ONcondition when a subquery computes a non-deterministic expression that is then used as a join key. The merged expression was computed twice from the raw inputs, drawing independently for the match and for the output column. #117250 (Alexey Milovidov). - Fix the default-enabled
use_join_disjunctions_push_downsilently dropping rows when the filter above a join hides a non-deterministic function inside a lambda body, as inarrayExists(z -> rand(z) % 2 = 0, [a]). The extracted pre-filter was pushed below the join while the original filter stayed on top, so the lambda was drawn twice per row and only rows passing both draws survived. #112700 (Groene AI). - Fixed a filter containing a non-deterministic function being moved below
ARRAY JOIN, which evaluated it once per source row instead of once per expanded row and made whole arrays pass or fail together. #117756 (Alexey Milovidov). Fixedrand,generateUUIDv4and other non-deterministic functions being evaluated before anarrayJoinreplicates the rows, which silently duplicated their values across the expanded rows. #118963 (Alexey Milovidov). - Reject a
CHECKconstraint whose expression containsarrayJoin. Such a constraint was accepted and then read past the end of the inserted block, surfacing as a nonsensicalArray of size 18446744073709551613 is too large, or an abort in a debug build, or blamed a violation on the wrong row. #117267 (Alexey Milovidov).arrayJoinin a table constraint is now also rejected when the definition is copied byCREATE TABLE ... AS srcorCLONE AS src, stated by a full-definitionATTACH, or declared asASSUME. A constraint containing it that is already stored in the metadata of a table is no longer used by the query-time constraint optimizer, which could remove aWHEREthat the constraint did not really imply. #117799 (Alexey Milovidov). - Reject a TTL expression that contains
arrayJoin. Such a TTL was accepted and then silently deleted rows whose own TTL was far in the future, and read past the end of the expression column when an array was empty. #117266 (Alexey Milovidov). - Fix a silent result change for a query over a trivial view over a
Distributedtable whoseWHEREor view-keyedadditional_table_filterscontains a bareIN some_tablepredicate. The default-enabledoptimize_trivial_view_pushdown_to_distributedshipped that predicate to the shards, where it was evaluated against each shard’s local table of that name instead of the initiator’s, so it disagreed with theIN (SELECT ...)spelling of the same predicate. #117278 (Alexey Milovidov). - Fixed
query_plan_aggregation_bucket_top_ksilently dropping result rows when anarrayJoinsits between the aggregation and theORDER BY ... LIMIT. #117464 (Alexey Milovidov). - Fixed
SELECT ... FINALwith aWHEREon the partition key expression returning a superseded row when the partition key is computed from a floating-point sorting-key column: partition pruning dropped the partition holding the deduplication winner. #117509 (Alexey Milovidov). - Fixed
mutations_sync = 3,lightweight_deletes_sync = 3andalter_sync = 3performing no wait at all onReplicatedMergeTree, so a mutation orALTERreturned as if it had synchronised. As documented, the value now behaves the same as2and waits for all replicas. This also affectsOPTIMIZE,TRUNCATE,DROP/DETACH PARTITION,REPLACE PARTITIONandMOVE PARTITION TO TABLE, which take the samealter_syncwait path. Statements that previously returned immediately now wait, and can raiseUNFINISHEDwhen a replica is inactive; set the value to0,1or2to choose a different wait explicitly. #117517 (Groene AI). - Fixed the logical error
Cannot add ZooKeeper operation because query is executedwhen runningTRUNCATE TABLEon aTimeSeriestable in aReplicateddatabase. #117902 (Raúl Marín). - Fix a lightweight
UPDATEsilently not applied to rows of a data part when the patch part is written in thev1format (patch_parts_version = 'v1') and covers rows of several data parts. One row was lost when a data part’s patch rows began in a later granule of the patch part, which made the result depend onmerge_tree_min_read_task_sizeandmax_block_size. All updates for a data part were lost, on disk as well as at read time, when the patch part had no final mark (index_granularity_bytes = 0) and that part’s patch rows began in the patch part’s last granule. #117962 (Groene AI). - Fix wrong results and a
NOT_IMPLEMENTEDexception when a lightweight update’s patch part is applied on top of a pendingALTER TABLE ... UPDATE col = <constant>withapply_mutations_on_fly = 1. The constant-folded column was not materialized before the patch was written into it, so the patch was either silently discarded or the read failed. #118545 (Shaohua Wang). - Fixed
system.tables.total_rows/total_bytesovercounting a non-replicatedMergeTreetable while a patch part from a lightweightUPDATEis alive, andSELECT count()returning that inflated number withapply_patch_parts = 0. #117463 (Alexey Milovidov). - Fixed a query with a
hasToken-family predicate on atextindex silently returning no rows when the query also read a column modified by a pending lightweight update. #118496 (Shaohua Wang). - Fix excessive patch-part reads for lightweight updates on tables with redundant parentheses in sorting-key expressions, such as
ORDER BY (k). #118878 (Anton Popov). - Fixed the
LOGICAL_ERRORReading from materialized CTE '...' before its materialization completedraised by a lightweightUPDATE, or a lightweightDELETEinlightweight_update_forcemode, whose predicate contains anINsubquery that defines a materialized CTE, when the set is built at run time. #119489 (Dmitry Novik). - Fixed a retried
INSERT SELECTover a join not being deduplicated when the two attempts differed only in whether a column was carried as a lazily replicated column. #118004 (Alexey Milovidov). - Fixed a logical error
Cannot write to finalized buffer(an abort in debug and sanitizer builds) in the non-replicatedMergeTreededuplication log when opening the next log file during rotation failed, for example after a transient I/O error on the deduplication log’s disk. Such a failure no longer fails the insert that triggered the rotation, so a retry of that insert is not wrongly deduplicated. #118089 (Alexey Milovidov). - Fix silent data loss on upgrade in
Distributedbackground inserts withbackground_insert_split_batch_on_failure: batch recovery no longer deletes a spool file that was never sent when a later file of the same batch was quarantined intobroken/by a previous server version. #118211 (Alexey Milovidov). - Fixed
SELECT count()returning too many rows for a negated comparison (!=,NOT IN,NOT LIKE) over aNullableprimary key column: the exact-count optimization counted the NULL-key rows that theWHEREcondition rejects. #118214 (Alexey Milovidov). - Fixed
AMBIGUOUS_COLUMN_NAMEon every read of a table that has a column named like a subcolumn of another column (for examplea.size0next to anArraycolumna) afterALTER TABLE ... MODIFY COLUMNchanged that column’s type. #118228 (Alexey Milovidov). - Fix unbounded memory growth from time zone names of the form
Fixed/UTC±HH:MM:SS. Every distinct name permanently cost ~4.6 MiB that the server never gave back, and 172801 of them were accepted. Only offsets that a time zone can have are accepted now: a whole number of quarters of an hour, no further from UTC than 14 hours. #118286 (Alexey Milovidov). - Fixed
MULTIPLE_EXPRESSIONS_FOR_ALIASunderrewrite_in_to_joinfor a query that repeats one identical aliasedIN (subquery)expression more than once. #118292 (Alexey Milovidov). - A table created with
CREATE TABLE ... AS <table function>(...)is no longer resolved to answer asystem.columnssize query about it. Previously selectingdata_compressed_bytes,data_uncompressed_bytesormarks_bytescontacted the endpoint of every such table, so one unreachable endpoint made the whole scan fail. Until such a table is first accessed it now reports zero sizes. #118302 (Groene AI). - Fixed an
Inconsistent AST formattinglogical error for an aliasedINexpression whose left operand also has an alias when it is nested inside a function-argument list, e.g.SELECT ifNull(sum((x AS a1) IN [y] AS c3 = TRUE), 0). #110229 (Groene AI). - Fix a logical error (server abort in debug/sanitizer builds) when a constant-folded comparison appears in the
SELECTlist together withgroup_by_use_nulls = 1andGROUP BY GROUPING SETS. #110703 (Groene AI). Fixed aBad casterror, and wrong results in release builds, when an aggregate reads a derived table that usesGROUP BY ALLwithROLLUPorCUBEundergroup_by_use_nulls = 1. #110921 (Groene AI). Fixed a return type mismatch error whengroup_by_use_nullsis used withGLOBAL INin aGROUP BYkey. #116980 (George Larionov). - Fixed a
LOGICAL_ERROR(“query tree node does not have valid source node”) when aMergetable wrapping aDistributedtable is joined and a bare column of the joined-away side is used as a predicate. #111327 (Groene AI). - Fixes a
LOGICAL_ERROR(Column identifier ... is already registered), aMULTIPLE_EXPRESSIONS_FOR_ALIASerror and aNOT_FOUND_COLUMN_IN_BLOCKerror for a query whoseIN/NOT IN/GLOBAL INright operand names a table expression that also appears in theFROMsection, for exampleSELECT l.x FROM l JOIN (SELECT x FROM r) AS r ON l.x = r.x WHERE l.x IN r. Also makesORDER BY <alias> WITH FILL ... INTERPOLATE (<alias> ...)inside a CTE or any other copied subquery raiseINVALID_WITH_FILL_EXPRESSION, as the same query already does when it is not copied: the check was silently skipped for the copy, and such a query returned rows instead of the error. #112219 (Groene AI). - Fixes
NOT_FOUND_COLUMN_IN_BLOCKwhenquery_plan_join_shard_by_pk_ranges = 1is combined withjoin_algorithm = 'full_sorting_merge'and a join input is filtered on a sorting-key column that is not the join key and is not selected. Closes #112402. #112664 (Groene AI). Fixed rows being silently dropped from a join whenquery_plan_join_shard_by_pk_rangesis enabled and the primary key is a floating-point column containingNaN. #118918 (Alexey Milovidov). - Fixed
Code: 476(Can not use WITH TIES without ORDER BY) raised by a remote shard, and the logical errorLIMIT WITH TIES without ORDER BYraised on the initiator, when selecting from aMergetable over aDistributedtable with aJOINandORDER BY ... LIMIT n WITH TIES. The child query kept itsLIMITclause after itsORDER BYwas removed. #113594 (Groene AI). - Fixed
LOGICAL_ERROR: There are no events in epollwhen a distributed query withuse_hedged_requestsis cancelled or completes early (for example because of aLIMIT) while a replacement replica is still pending. Closes #113981. #114065 (Groene AI). - Fixed
... PARTITION <value>statements against a table whosePARTITION BYcontainsmodulowith an unsigned left operand and a signed right operand, such asPARTITION BY (37528 % c0)withc0 Int32. Such a statement raisedLOGICAL_ERROR, or silently affected no partition. A value outside the range of the partition key type is now rejected withARGUMENT_OUT_OF_BOUNDinstead of silently matching nothing. #116606 (Groene AI). - Fix
BAD_ARGUMENTSfor a query that combines severalquantilecalls where at least one level is written as an integer literal, for exampleSELECT quantile(1)(x), quantile(0.5)(x). The default-enabledoptimize_syntax_fuse_functionsrejected the integer level while the aggregate function itself accepts it, so the query failed although each call is valid on its own. #117211 (Alexey Milovidov). - Fixed wrong results for
GROUP BY,LIMIT BYanduniq*overbech32Encode,dictGetHierarchyandreverseUTF8: the three functions declared themselves injective, so the default-enabledoptimize_injective_functions_in_group_byandoptimize_injective_functions_inside_uniqgrouped and counted by the raw argument, although distinct inputs can produce the same result. #117239 (Alexey Milovidov). #117357 (Alexey Milovidov). #118432 (Alexey Milovidov). - Fix
has,indexOfandcountEqualover an array of numbers returning a match for a needle thatequalsdoes not consider equal:has(arr, -1)matched anArray(UInt64)element equal to theUInt64maximum, andhas(arr, 16777217)matched anArray(Float32)element equal to16777216. The constant-array path already answered correctly, so the same haystack gave different results depending on whether it was a constant or a materialized column. The same phantom matches were returned for anArray(LowCardinality(T))column, which also matched a needle its element type cannot represent outside the numeric domain and reported every element equal to the default value as a match for aNULLneedle. In the other direction, a needle counting a different unit than the element, such as aDateTimesearched in anArray(Date), was found nowhere althoughequalsconsiders the pair equal; such a pair is now compared in the type the two meet in. #117313 (Alexey Milovidov). - Fixed
uniqThetaand its variants silently returning a value that is too low when reading anAggregateFunction(uniqTheta, ...)state that another Apache DataSketches implementation had written in the compressed Theta sketch form. #117422 (Alexey Milovidov). - Fixed undefined behavior and an empty result of a
SELECT ... ORDER BY <distance function> LIMIT n OFFSET mover a table with avector_similarityindex whenn + m, orLIMITmultiplied byvector_search_index_fetch_multiplier, overflowsUInt64; such a query now skips the index and runs the exact search. #117713 (Alexey Milovidov). #117892 (Groene AI). - Fixed a
LOGICAL_ERROR(Invalid number of columns in chunk pushed to OutputPort) for a vector search over a column with aQuantized(...)codec whenvector_search_use_quantized_codesand the experimentalmake_distributed_planwere both enabled. #118850 (Groene AI). - Fixed an external
GROUP BYwithenable_adaptive_aggregatorexceedingmax_memory_usageor failing withMEMORY_LIMIT_EXCEEDEDinside the aggregator’s own memory valve: the working set of the memory-pressure sweeps was sized from constants unrelated tomax_bytes_before_external_group_by, and records staged before the aggregator thawed its tables stayed resident until the merge, so a thawed thread wrote a temporary file per block. Both are now bounded by that threshold. #117880 (Alexey Milovidov). #118474 (Groene AI). - Fixed a comment
ALTERon aKeeperMaptable in aReplicateddatabase being applied only to the local replica. Keeper kept the pre-ALTERCREATEstatement and digest, so other replicas never saw the change and the next start declared the replica lost, reverting theALTERand, if no other table shared itsKeeperMappath, dropping its data. #118011 (Groene AI). - Fixes
bloom_filterskip indexes on big-endian platforms (s390x), where the index payload was never written or read, so a query using such an index returned no rows for data that is present. #118164 (Vadim Ilves). - Fixed
arrayIntersectreturning a spuriousNULLwhen it is missing from one of the input arrays. #118312 (Minh Vu). FixedarrayIntersect,arrayUnionandarraySymmetricDifferencemishandling aNullableargument whose elements do not fit the common element type:arrayIntersect([toNullable(1)], [toNullable(257)])returned[1], andarrayUnion([1], [toNullable(257)])failed withILLEGAL_COLUMNinstead of returning[1,257]. #118485 (Groene AI). - Fixed a
UInt64constant that does not fitUInt32matching an unrelated row of aDateTimecolumn inIN(and in anORchain of equalities, which is rewritten intoIN): the constant was truncated modulo 2^32 instead of being excluded from the set. #118367 (Alexey Milovidov). - Fixed
CORRUPTED_DATA(“Cannot get value from Set”) for aFINALquery withORDER BY ... WITH FILL INTERPOLATEwhose filter is anINset moved intoPREWHERE: the set placeholder column is no longer kept alive past the filter. #118420 (Alexey Milovidov). - Fixed
lcmreturning a negative result forInt128andInt256arguments when exactly one of them is negative, e.g.lcm(toInt128(-6), toInt128(4))returned-12instead of12. #118431 (Alexey Milovidov). - Fixed
text,tokenbf_v1andngrambf_v1skip indexes not being used when the searched constant has typeLowCardinality(String)(e.g.hasToken(s, toLowCardinality('rare'))ors = toLowCardinality('rare')), which caused a silent full scan. Such predicates now prune granules like their plainStringcounterparts. #110017 (Groene AI). - Fix a
textorngrambf_v1index silently dropping matching rows when the indexed column is compared for equality against aFixedStringvalue, or searched withhasAnyorhasAlloverFixedStringneedles. Happens at default settings, sinceuse_skip_indexesandenable_full_text_indexare both on. #117314 (Alexey Milovidov). - Fix rows silently dropped by an
ngrambf_v1index for aLIKEpattern with a run of escaped backslashes before a wildcard. #118673 (Alexey Milovidov). - Fixed a
bloom_filterskip index dropping granules that hold matching rows forhasAny/hasAllagainst a constant array whose elements are of a different date/time type than the indexed column, andTYPE_MISMATCHfor aDate32element. #118956 (Alexey Milovidov). - Fixed wrong results when a table declares both a
Mapcolumnmand a column named exactly`m.key_<key>`(dots are legal in column names), or has that name claimed by a subcolumn such as aTupleelement or a typed JSON path. Skip-index analysis read the name as the map’s key subcolumn and pruned every granule whose map lacks<key>, so amapKeysormapValuesindex (ngrambf_v1,tokenbf_v1,sparse_grams,bloom_filter,text) dropped rows that matched the predicate. #119457 (Groene AI). - Fixes incorrect primary-key pruning for
hasandnotHaswhen array element types differ from the key type, such asStringliterals againstEnumorFixedStringkeys. #115294 (Alexey Milovidov). - Fixed rows being silently dropped by partition pruning, primary key analysis and
minmaxskip indexes when aNaNis involved: a comparison constant that holds aNaN, possibly nested in a tuple or appearing only after conversion to the key type, as inNOT (f < 'nan'). #116763 (Groene AI). A string constant such as'nan'compared with a floating point column under an injective key transform such asORDER BY toString(f), sof != 'nan'skipped the granule holding theNaNrow. #117501 (Groene AI). AFloatprimary key holding±infwhere the predicate’s arithmetic maps that endpoint toNaN, e.g.WHERE k / inf = 0. #118468 (Alexey Milovidov). - Fix wrong results when
indexHintis given an argument that index analysis cannot read as a condition.indexHint(256)was narrowed toCAST(256, 'UInt8')= 0 and discarded every part, so the query silently returned an empty result; a wide integer such asindexHint(toUInt256(256))did the same, and aString,DecimalorNULLargument threw. Such an argument now contributes no filter, consistently for the primary key,minmax,setandbloom_filteranalysis. Closes #111684. #114048 (Groene AI). Also fixed a bare key column of a type with no boolean reading (UInt256,Int128,BFloat16, or theirLowCardinalityforms) being read ascolumn != 0insideindexHint,NOT indexHint(x)failing withILLEGAL_TYPE_OF_ARGUMENT, and a negatedindexHintin a disjunction keeping its condition un-inverted, socount()could report rows that no row of the table matches. #119209 (Groene AI). - Fixed wrong results from
optimize_functions_to_subcolumns. ATupleelement or aJSONpath named like an automatic subcolumn could be mistaken for it, so for examplelength(c.a)onTuple(`a.size` UInt64, `a` String)returned the element instead of the length;empty,notEmpty,isNull,isNotNull,count,mapKeys,mapValues,mapContains, andm['key']were affected the same way. Separately,lengthon anArrayorMapinside aNullable(for exampleNullable(JSON(`a` Array(Int64)))) returnedNULLinstead of0for aNULLrow,tupleElementon a member of aNullable(Tuple(...))column could fail withLOGICAL_ERROR, and a function is now rewritten only to a subcolumn of the same root column, so a physical column such as`j.m`is no longer confused with thempath ofJSONcolumnj. #115777 (Pavel Kruglov). #119150 (Groene AI). #119631 (Groene AI). - Declaring
STATISTICS(...)on anALIASorEPHEMERALcolumn is now rejected when the table is created or altered, instead of being accepted and making every subsequentINSERTfail withNOT_FOUND_COLUMN_IN_BLOCK. Closes #114791. #115882 (Groene AI). - Fixed
CREATE TABLEaccepting a subcolumn as aUNIQUE KEYelement, of either a user column (for exampleUNIQUE KEY (`c.null`)) or a virtual one (UNIQUE KEY (`_partition_value.1`)), which produced a table that could never be inserted into, failing everyINSERTwithNOT_FOUND_COLUMN_IN_BLOCK. Such a definition is now rejected withBAD_ARGUMENTS. Closes #114470. #115854 (Groene AI). - Fixed an in-process Keeper client (
KeeperOverDispatcher) reporting a failedmultitransaction as successful, because a rolled-back batch’s aggregate error was leftZOK. #117135 (Sergei Trifonov). - Fixed OOM when reading a
Parquetfile with an invalidnum_childrenfield in the schema. #117797 (Michael Kolupaev). - Fixed a
Parquetreader bug where a filter on aUUIDcolumn could silently return fewer rows than the file holds, or reject a valid file withINCORRECT_DATA: Statistics have min_value > max_value. Parquet sortsuuidstatistics by big-endian bytes while ClickHouse sortsUUIDby its second half, so those statistics are no longer used for row group or page pruning. Closes #118371. #118387 (Groene AI). - Fixed wrong results when reading a
Parquetfile with a nullable struct column without an explicit schema. Schema inference pushed the nullability down to the tuple elements and returnedTuple(Nullable(...), ...), which cannot hold a struct-level NULL, so a NULL struct was read as a tuple of NULLs. Such a column is now inferred asNullable(Tuple(...))whenallow_experimental_nullable_tuple_typeis enabled. That setting was also added to theParquetschema inference cache key, so a schema cached under one of its values is no longer reused under the other. #115653 (Groene AI). - Fix reading
ArrowandArrowStreamfiles containing values hidden by NULLs or unused nested ranges, which could cause validation errors or expose undefined values. Fix nullable tuple conversions and destination defaults, dictionary decoding under requested types, and NULL dictionary entries for complex types. Accept compatible shared dictionaries with differing field annotations and reject replacement dictionaries inArrowfiles. Validate nested row counts before allocation and read bufferless batches incrementally without materializing their entire declared row count. #110531 (Nihal Z. Miaji). Fix reading a flattenedTuplesubcolumn (e.g.`s.v`) from anArrow/ArrowStreamfile whose column is a nullable struct returning column defaults instead of the actual data whenallow_experimental_nullable_tuple_typeis enabled. Also fixORCreads resolving a column or struct field name to the first case-folded match underinput_format_orc_case_insensitive_column_matching, which returned another field’s data when two names differ only by case. #109741 (Groene AI). - Fix a crash and wrong results when reading the
DWARFformat with column types other than the ones the format produces, for exampleSELECT * FROM file('a.elf', DWARF, 'tag String'). Requesting a column that does not exist in the format now reports a proper error instead ofstd::out_of_range. #118794 (Raúl Marín). - Fix data silently dropped when reading a hadoop-snappy stream whose block has several subblocks and the input is refilled in the middle of that block, which happens when the file is read over a pipe or HTTP. #118705 (Alexey Milovidov).
- Fixed two defects in the legacy binary settings format, used for native-protocol clients declaring a revision below 54429. Signed integer settings (for example
max_partitions_to_readoriceberg_snapshot_id) were silently ignored, and were reported as changed while holding their default, so they overrode the table-level value with that default. Settings required to be greater than zero (for examplemax_block_size) were not validated when read from that format. #118610 (Groene AI). - Fixed a query over an
Icebergtable returning rows that had been deleted, when a position-delete manifest declares a lower bound above the upper bound for the reservedfile_pathcolumn. Such a pair describes an empty range, so the delete file was skipped for every data file it covers; those bounds are now ignored instead. Closes #118113. #118181 (Groene AI). - Fixed reading an
Icebergtable failing withICEBERG_SPECIFICATION_VIOLATIONafter a column was dropped while its data is still present in the data files. Closes #113324. #116488 (Konstantin Vedernikov). - Fixed
write_full_path_in_iceberg_metadatawriting an unresolvablelocal://URI, with a doubled root slash, into the metadata of anIcebergLocaltable, so that no external Iceberg reader could open it. A local table location is now spelledfile:///path, and a backend without a namespace no longer contributes an empty authority segment. #117828 (Groene AI). - Fixed writing
Icebergstatistics on top of Azure storage. #119369 (Konstantin Vedernikov). ATTACH TABLEof a data lake table no longer reads anything from object storage, and such tables no longer report row statistics in system tables. #117584 (Konstantin Vedernikov).- Reading a table backed by local object storage (
paimonLocal,icebergLocal,deltaLakeLocal, or a disk withobject_storage_type: local) whose metadata references a file that is missing on disk now fails with aFILE_DOESNT_EXISTexception naming the file, instead of a rawstd::filesystemerror surfaced as the opaqueSTD_EXCEPTION(code 1001). #115542 (JIaQi Tang). - Fixed a
SELECTfrom a table withpaimon_incremental_read = 1failing withREPLICA_IS_ALREADY_ACTIVE(“Failed to activate Paimon replica after Keeper reconnection”) on the first read after the server’s Keeper session was lost and re-established. #118457 (Groene AI). - Fixed a spurious
Code: 76 CANNOT_OPEN_FILEerror (Parent directory doesn't exist) on any write to anhdfsdisk. Removing a blob deleted its emptied object-key prefix directory, which could race a concurrent write that had just created the same directory and not yet opened its object. Emptied prefix directories are now kept. #118654 (Groene AI). - Fixed a server refusing to start after
remote_url_allow_hostswas tightened while a database with theHDFSengine existed: the host check ran during metadata loading and took every other database down with it. #118964 (Alexey Milovidov). - Fixed a server that refused to start after the directory backing a
Filesystemdatabase had been removed. Such a database is now loaded without tables and can be inspected and dropped, while aCREATE DATABASEorATTACH DATABASEissued by a user is still rejected when the path does not exist. #118684 (Groene AI). - With
enable_analyzer = 1(the default), fixedINCOMPATIBLE_TYPE_OF_JOINandNOT_FOUND_COLUMN_IN_BLOCKerrors when anALL INNER JOINagainst a table with theJointable engine carried anONcondition referencing only that table, such asON t.key = j.key AND j.value > 100. The condition is now applied after the join, which is what the equivalentWHEREspelling already did. Closes #116541. #116612 (Groene AI). - Fixed uneven partition distribution in the
Kafkaengine withkafka_keeper_path(StorageKafka2) whenkafka_num_consumersis greater than 1. A node running N consumers could claim N times its fair share of the topic’s partitions and hold them indefinitely, leaving other replicas idle. #116843 (Aparajita Pandey). clickhouse-localnow preserves detailedPoco::Exceptionmessages from local query execution instead of reporting them as genericSTD_EXCEPTIONerrors. This includes errors returned by themysqltable function. #116884 (Mark Needham).- Fixed
HashJoinright-side memory accounting when a memory limit interrupts a join build. A block could be stored without being counted, so the join under-reported its size to the memory limits and the spilling thresholds, and aJoinengine table held the memory of a failedINSERTfor the rest of its lifetime. #116991 (Groene AI). - Fix wrong aggregate values from the default-enabled
optimize_rewrite_aggregate_function_with_ifwhen the constant is in the first branch of theifand the condition can be NULL, for examplesum(if(c, 0, x))oravg(if(c, NULL, x)). Rows whose condition was NULL were silently dropped from the aggregate. #117221 (Alexey Milovidov). - Fixed a signed integer overflow when the effective table lock timeout, the smaller of
lock_acquire_timeoutand a non-zeromax_execution_time, was above roughly 9.2e9 seconds or a large negative value. Reading or writing aLog,TinyLog,StripeLogorFiletable built the lock deadline from it without bounding it first, so the wait was no longer bounded by the setting. #117974 (Groene AI). divideDecimalno longer returns0instead of the correct value when the dividend reduces to a single digit after being rescaled to the result scale, for exampledivideDecimal(toDecimal256(5, 0), toDecimal256(1, 0), 0)ordivideDecimal(toDecimal32(5.6789, 4), toDecimal32(2, 0), 0). The bug was present in every release since 22.12, so any stored result of such a division is wrong and should be recomputed. #118346 (Minh Vu).- Fixed
ClickHouseDictionarySource table cannot be dictionary tablebeing raised for a dictionary whose source is a table on another ClickHouse server that happens to share the dictionary’s database and table name. The check against a dictionary using itself as its own source now applies only when the source is the local server. #118441 (Alexey Milovidov). - Fix
arrayElementOrNullover an array of tuples, andarrayElementover an array ofNullabletuples, returning a tuple of default values instead ofNULLfor a constantUInt64index close to the maximum ofUInt64, such astoUInt64(18446744073709551615). #118447 (Minh Vu). - Fixed a query parameter being reported as unset (
UNKNOWN_QUERY_PARAMETER) when it is the entireINTERPOLATEexpression, as inORDER BY x WITH FILL INTERPOLATE (value AS {p:Int64}), while the same parameter nested in a larger expression worked. Closes #118458. #118568 (Groene AI). The same for a parameter that is the entire predicate of a lightweightDELETE, as inDELETE FROM t WHERE {p:UInt8}. #118667 (Groene AI). - Fix partition pruning and primary key filtering being silently disabled when
parallel_replicas_min_number_of_rows_per_replicais set inside a subquery or CTE instead of at top query level. #116529 (Yarik Briukhovetskyi). - Fixed wrong results and a
LOGICAL_ERRORforSELECT ... FINALundermake_distributed_plan = 1when aPREWHEREor a row policy is deferred until afterFINAL(apply_prewhere_after_final, or the defaultapply_row_policy_after_final). #116626 (Groene AI). - Fixed wrong results from JIT-compiled conversions of a floating point value to an integer or
Decimaltype when the value does not fit the destination: a comparison against the converted value could be evaluated against the pre-conversion value, so the same query could flip between repeated executions. Such conversions are now evaluated by the interpreter, which also means they raiseCANNOT_CONVERT_TYPEforNaNorInfandDECIMAL_OVERFLOWonDecimaloverflow where an arbitrary value was previously returned. Closes #117442. #117590 (Groene AI). Fixed wrong results from a JIT-compiledCASTof aNullablevalue to a non-Nullabletype: converting a NULL must raiseCANNOT_INSERT_NULL_IN_ORDINARY_COLUMN, but the compiled expression returned the nested value instead, so the same query silently started answering with wrong data oncemin_count_to_compile_expressionwas crossed. Such a conversion is no longer compiled. #119079 (Groene AI). - A simple
Queryin the PostgreSQL wire protocol now destroys the unnamed prepared statement and the unnamed portal, as PostgreSQL does, so a laterBindorExecuteon them is rejected instead of silently reusing stale extended-query state. #118210 (Groene AI). portRFCnow returns the explicit port of a URL whose host is an IPv6 address in brackets, such ashttp://[2001:db8::1]:8080/, instead of the default port. #118632 (Alexey Milovidov).portandportRFCnow return the explicit port for valid URLs with a query string or fragment after the port. #118482 (Minh Vu).fuzzBitsandgenerateULIDnow return an independently generated value per row when all of their arguments are constants, instead of one value repeated for every row. #118643 (Alexey Milovidov).- Fix
EmbeddedRocksDB,KeeperMapandRedisreturning no rows forWHERE key = <literal of another date-family type>, such as aDatekey compared with aDateTimeliteral. #118689 (Alexey Milovidov). - Fixed the row numbers shown in the Web UI for a page other than the first one: they restarted at 1 on every page instead of counting from the page’s position in the whole result. #116614 (Alexey Milovidov).
- Fix delayed ClickHouse Keeper shutdown when idle client sessions are blocked in socket polling. #118014 (Antonio Andelic). Fix graceful shutdown of
clickhouse-keeperhanging for up to 300 seconds when a client connection onkeeper_server.tcp_port_secureis stalled in a TLS read. #119450 (Groene AI). - Fixed a Keeper crash when a member that was removed from the cluster is added back without its process being restarted. Such a member could also replay already-applied entries. #118740 (Shaohua Wang).
- Fix handling of regular expressions ending with an unescaped backslash in
match,extractAll,countMatchesandsplitByRegexp. Such invalid patterns are no longer incorrectly treated as trivial substring matches. #118229 (Alex Prabhat Bara). - Fixed
matchandcountMatchesreturning wrong results for a pattern whose character class starts with a literal]([]a]b) or contains a literal[next to an alternation (abc[[]|b): the required-substring prefilter demanded a substring the pattern does not require. The same defect madeoptimize_rewrite_regexp_functionsturn such areplaceRegexpAllintoreplaceRegexpOne. #118342 (Alexey Milovidov). - Fix
startsWith*array functions returning suffix matches for some variants. #118672 (Minh Vu). - Fixed an out-of-bounds access that could happen with the
getURLHostRFCfunction. #119026 (Groene AI). - Fix the HTTP connection pool comparing
disk_connections_store_limit,storage_connections_store_limit, andhttp_connections_store_limitagainst the total number of connections in the group instead of the number of stored connections. A server whose concurrency exceeded the limit cached no connections at all, opened a new TCP connection for every request to object storage, and could exhaust the ephemeral port range of the host. The limit now bounds only the idle connections kept for reuse. #119078 (Alexey Milovidov). - Fixed the hash-family join algorithms treating a non-NULL
Nullable(Tuple(...))key that contains a NULL element as a NULL key, which made the result of a join depend on thejoin_algorithmsetting.INwith a subquery over such a key was affected in the same way. #119081 (Alexey Milovidov). - Fix wrong results when
analyzer_compatibility_join_using_top_level_identifier = 1and aJOIN ... USINGkey resolves to aSELECT-list alias whose name is a virtual column of the left table expression, such asSELECT upper(t._part) AS _part FROM t JOIN r USING (_part). The raw virtual column value was silently used as the join key instead of the aliased expression. #119102 (Groene AI). - Fixed a
LOGICAL_ERROR(Got read request from replica N for unknown stream <table>) whenparallel_replicas_plan_basedis enabled and a join is distributed across replicas. #118084 (Groene AI). - Fixes a case where
date_time_overflow_behavior = 'saturate'clamped an out-of-range value to the whole second and discarded the sub-second component. Closes #113152. #116122 (Yarik Briukhovetskyi). - Fix
system.dictionaries.bytes_allocatedmisreporting memory forHASHED_ARRAYdictionaries: the key containers contributed their element count instead of their buffer size in bytes, so the reported figure came out roughly 2-5x lower than the memory the dictionary actually held, and the bit-packed per-attribute null masks were counted in elements, which over-reported that term by 8x. #118641 (George Viamontes). Fixed the same figure over-reporting memory for nullableRANGE_HASHEDdictionaries, whose bit-packed nullable mask was counted one byte per flag. #118675 (Minh Vu). - Fixed
max_execution_time_leafandtimeout_overflow_mode_leafbeing ignored for queries executed with parallel replicas (includingINSERT SELECTwithparallel_distributed_insert_select = 2). #69540 (Igor Nikonov). - Fix
CREATE TABLE ... CLONE AS SELECT ...andCREATE TABLE ... CLONE AS <table_function>silently ignoring theCLONEkeyword and creating a plainCREATE ... AS SELECTinstead. These shapes are now rejected withBAD_ARGUMENTS. #105004 (Tuan Pham Anh). - Fix a logical error (a server abort in debug builds) when a non-transactional
DROP PARTITION,DETACH PARTITION,DROP PART,REPLACE PARTITION FROMorMOVE PARTITION TO TABLEcovered a part whose creating transaction had not committed yet. Such an operation now fails withSERIALIZATION_ERRORand can be retried once the creating transaction finishes; it no longer removes or replaces any part of the affected batch. #105116 (Tuan Pham Anh). - Fix a logical error when a correlated
MATERIALIZEDCTE is referenced more than once inside aJOIN. Such a CTE is now rejected at analysis time withUNSUPPORTED_METHOD, consistently with the single-reference andIN-subquery paths. #108883 (Groene AI). - Fix a logical error
Invalid cast from Nothing to native type(an abort in debug/sanitizer builds) whencompile_expressions = 1compiled an expression with aNullable(Nothing)operand, e.g.and(Nullable(Nothing), <native comparison>). #111508 (Groene AI). - Fix wrong results with
enable_parallel_replicas = 1when a join tree contains a join other than the leftmost one that cannot be applied independently per replica: a strictness other thanALLoutside aLEFTjoin, for examplet1 INNER JOIN t2 ON t1.c = t2.c ANY INNER JOIN t3 ON 1, which returned the row once per replica instead of once; aFULLjoin, which emitted every row twice; or aPASTEjoin, which pairs rows by position. Parallel replicas are now disabled for such a join tree, as they already are for the equivalent two-table join. #112317 (Groene AI). - Fix a segfault and silently wrong results when reading a
sizeNsubcolumn of a nestedArray(JSON)path. Closes #113686. #113752 (Groene AI). - Fixed wrong results and a server abort when a
JOIN ONcondition evaluated during anie_joinjoin containsarrayJoin. Such a condition is now rejected withINVALID_JOIN_ON_EXPRESSION. PreviouslySEMI/ANTI/LEFT/RIGHT/FULLjoins using theie_joinalgorithm could return duplicated or missing rows, or abort the server. #114325 (Groene AI). - Fix reading a
LogorTinyLogtable whose array or map elements are missing while their sizes are present: such a table returned rows with elements that are not there and made the server read out of bounds. It is now reported asINCORRECT_DATA. #115528 (Alexey Milovidov). - Fix a segmentation fault when reading in order from a
Mergetable overMergeTreetables whose sorting key is shorter than the key prefix chosen for the query. #116364 (Groene AI). - Fix
LOGICAL_ERROR: GroupingAggregatedTransform pushed bucket N twicewhenmake_distributed_planpicks theShuffleaggregation strategy while the aggregation must produce results in bucket order (for example withdistributed_aggregation_memory_efficient). It is now planned as a partial aggregation plus a merge. #116446 (Groene AI). - Fix wrong row order when sorting a
LowCardinalitycolumn of a floating-point type whose dictionary holds two entries that compare equal, such as-0.0and+0.0. A multi-columnORDER BYdid not apply the remaining keys to those rows, and theMergeTreewriter’s stable sort did not keep them in insertion order, changing which rowReplacingMergeTreekeeps. #116870 (Groene AI). - Fixed wrong results from the default-on
optimize_time_filter_with_preimagefortoYear/toYYYYMMpredicates at the column type’s maximum (Dateat 2149,DateTimeat 2106), aDECIMAL_OVERFLOWexception for the same predicates on aDateTime64(9)column at 2262, and wrong results for the same predicates onDateTime/DateTime64columns in time zones whose year or month boundary is not local midnight (America/Lima,America/Managua). #117451 (Alexey Milovidov). - Fixed
NOT_IMPLEMENTED(“Cannot decorrelate query, because ‘DelayedCreatingSets’ step is not supported”) for a correlated subquery whoseWHEREbuilds a set, for example anIN (subquery), or adictGet(...) >= constcomparison thatoptimize_inverse_dictionary_lookuprewrites into one. #118412 (Alexey Milovidov). - Fixed a race between
SYSTEM RESTORE DATABASE REPLICAand the DDL worker of aReplicateddatabase. The restore re-initialised the replica while the previous DDL worker was still running its own startup recovery, so the recovery could mark the wrong range of replicated-DDL log entries as finished, or move local tables to_broken_replicated_tables. The worker is now stopped before the restore touches Keeper. #118481 (Groene AI). - Fixed
WITH RECURSIVElosing its recursiveness in the second and later branches of aUNION,INTERSECTorEXCEPT. When a later branch had noWITHclause of its own, the first branch’sWITHlist was copied into it without theRECURSIVEmarker, soWITH RECURSIVE src AS (SELECT 1 AS id UNION ALL SELECT id + 1 FROM src WHERE id < 3) SELECT sum(id) FROM src UNION ALL SELECT sum(id) FROM srcwas rejected withUNKNOWN_TABLE, and returned a wrong value for the copied branch when an enclosing CTE of the same name existed.CREATE VIEWalso stored the copied branch withoutRECURSIVE. #118510 (Groene AI). - Fixed a
GLOBAL RIGHT JOINoverDistributedtables returning unmatched rows of the right table once per shard: the original left table is now broadcast and the preserved right side stays sharded. Closes #95728. #118611 (Anton Ivashkin). - Fix an endless
ORDER BY ... WITH FILLwhen theSTEPis too small to change the value it is added to. #118633 (Alexey Milovidov). - Fix the
Invalid local IN function name globalInerror for a query withINover aUNIONofDistributedtables whendistributed_product_mode = 'global'orprefer_global_in_and_joinis enabled. #118639 (Alexey Milovidov). toLastDayOfMonthandtoLastDayOfWeekof aDateargument now saturate at theDatemaximum (2149-06-06) instead of wrapping around to 1970. The wrapped result also silently dropped matching rows through primary-key pruning. #118642 (Alexey Milovidov).- Fixed a crash and a
LOGICAL_ERRORin themergeTreeIndextable function when reading a key column whoseALTER TABLE ... MODIFY COLUMNbetweenTandLowCardinality(T)has an unmaterialized mutation. The key column is now emitted in the type the current metadata declares. #118709 (Groene AI). - Fix
SYNTAX_ERRORwhen loading views, materialized views, or projections whoseSELECTlist starts with a column namedTOP. #118754 (Kirill). - Fixed
optimize_or_like_chainreturning extra rows forORchains ofLIKE/ILIKEpatterns that do not end in%: a value followed by a trailing newline wrongly matched the filter. #118766 (Jimmy Aguilar Mena). - Fixed a
LOGICAL_ERROR(“Expected CommonSubplanReferenceStep to reference CommonSubplanStep”) raised at query planning time whenquery_plan_convert_join_to_in = 1was used with a correlated aggregating scalar subquery. The optimization now keeps theJOINinstead of rewriting it when either join input carries a common subplan node. #118797 (Groene AI). - Fix a wrong result for
SELECT * APPLY (x -> f(x))overJOIN ... USING (a, b): everyUSINGcolumn was named after the lambda parameter (f(x)) instead of the matched column, so two output columns shared one name, and wrapping the query inSELECT * FROM (...)returned oneUSINGcolumn’s values under the other column’s position; a type-returning lambda such astoTypeNamefailed withAMBIGUOUS_COLUMN_NAMEinstead. The same happened forCOLUMNS(a, b) APPLY (x -> f(x)), and for two or moreARRAY JOINcolumns. The lambda form ofAPPLYnow names these columns likeAPPLY fand a plain*already did. #118825 (Groene AI). - Fixed a server crash that could happen when a
WORKLOADsetting limiting concurrency (e.g.max_concurrent_queriesormax_bytes_inflight) was lowered below the number of currently in-flight resource requests while the workload was active. #118836 (Sergei Trifonov). - Fixed a logical error (
Method == not implemented for AST) raised by aSETof a custom setting that already held an AST value such asdisk(type = 's3', ...). Assigning such a setting a second time in one session, or clamping a nestedSETTINGSclause against it, reached a comparison that was never implemented. #118993 (Groene AI). - Fixed a broken part in
detached/never being renamed with thebroken_prefix by theATTACH_PARTexecutor, which left it occupying a valid part name and failing every later attach attempt. #118999 (Alexey Milovidov). - Fix
TOO_DEEP_SUBQUERIESbeing thrown forGLOBAL INandGLOBAL JOINsubqueries in two analyzer cases: whenmax_subquery_depthis set, the depth is now counted in nested subqueries instead of query tree nodes; and when aUNIONis on the path to theGLOBALsubquery,UNIONnodes no longer count toward that depth. Closes #79345. Closes #119623. #119033 (Vladimir Cherkasov). #119650 (Groene AI). - With
prefer_column_name_to_alias = 1, an unqualified column name that is ambiguous between joined tables now resolves to the alias with the same name, as the old analyzer did, instead of throwingAMBIGUOUS_IDENTIFIER. #119192 (Vladimir Cherkasov). #119906 (Vladimir Cherkasov). - Fix a wrong-order merge (logical error
Virtual row does not cover sort columnin debug builds) when reading in order with virtual rows andORDER BYcontains constants, e.g.SELECT DISTINCT a, b FROM t ORDER BY 'x', a, 'd' COLLATE 'cs', bon a table with key(a, b). #119195 (Vladimir Cherkasov). - Fixed wrong results when a table’s sorting key expression resolves to a different result type in the query than in the table, for example a key of
CAST(json.b, 'String')read withcast_keep_nullable = 1. Read-in-order treated the two as interchangeable, so rows could come back out of order,optimize_aggregation_in_ordercould split groups and report wrong aggregates, andread_in_order_use_virtual_row = 1could fail withLOGICAL_ERROR: Virtual row has different type. #119385 (Groene AI). - Fixed
BACKUPof aMemorytable reading an unrelated file namedtmp_sizes_jsonfrom the server’s working directory: thesizes.jsonshipped inside the backup is now built in memory, so such a file can no longer make the backup fail or add foreign entries to it. #119330 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKwhen aMergeTreeskip index usesmortonEncodeorhilbertEncodedirectly and a query filters on one of the curve arguments. #119355 (Minh Vu). - Fixed an
ALTERon a view or materialized view withSQL SECURITY DEFINERdeleting the auto-created<user>:defineraccount when theALTERdid not change the definer. Every laterSELECTfrom the view, and everyINSERTinto a materialized view’s source table, then failed permanently withThere is no user '<user>:definer' in 'user directories'(UNKNOWN_USER). #119357 (Groene AI). - Fixed a materialized view whose
SELECTcontains aUNION,INTERSECTorEXCEPTin a subquery or CTE breaking afterDETACH TABLE+ATTACH TABLE, or afterRESTORE: every subsequentINSERTinto its source table failed withUNION mode UNION_DEFAULT must be normalized, and underenable_analyzer = 0it was silently evaluated as a plain union, returning wrong results.ATTACH TABLE(short form) andRESTOREnow re-run set-operation normalization on the stored definition. #119365 (Groene AI). - Fix an
ALIAScolumn that references another column (b UInt64 ALIAS a) reading back as the default value of its type when the table is read through aMergetable over aDistributedtable with a remote shard. #119561 (Alexey Milovidov). - Fix
arrayShiftLeftandarrayShiftRightwhen an explicitNULLdefault is used with a nullable array. #119626 (Minh Vu). - Fix
ALTER TABLE ... MODIFY SETTING name = DEFAULTbeing ignored. Closes #49613. #118526 (Vitaly Baranov). - Fix
arrayNormalizedGinirejecting valid rows with different array sizes in the same block. #118631 (Minh Vu). - Fix
substringIndexandsubstringIndexUTF8rejectingUInt64counts aboveInt64::max()instead of interpreting them as negative counts. #118645 (Minh Vu). - Fix a logical error for an asynchronous
INSERTcombined with a non-parallel quorum (insert_quorumgreater than one or'auto'together withinsert_quorum_parallel = 0) when the data is sent as blocks over the native protocol. Such a query is now rejected withUNSUPPORTED_PARAMETER, as it already was when the data was inlined in the query text. #118968 (Alexey Milovidov). - Fixed a graceful shutdown silently discarding the rows of a
Buffertable whose destination lives in another database or is anotherBuffertable. #118985 (Alexey Milovidov). #116898 (Jayme Bird). - Fix a use-after-free in the gRPC server when a query with a streaming input finishes while a read of the next message is still in flight. #115707 (Alexey Milovidov).
- Custom object metadata written to Google Cloud Storage over the S3 API without HMAC credentials, which is how ClickHouse Cloud on GCP accesses object storage, now takes effect: the headers that GCS spells with the
x-goog-prefix are translated for every request, not only for server-side copies. Previously GCS discarded thex-amz-spelling silently, so the write succeeded and the metadata was not applied. #119042 (Sema Checherinda). - Fixed a crash when reading a subcolumn of a
Variant,Dynamic, orJSONcolumn whose own type isNullableorLowCardinality(Nullable)from aMergeTreetable, for exampleSELECT value.`Tuple(a Nullable(UInt32), b String)`.aover aDynamiccolumn. Previously such a read hit aLOGICAL_ERRORin debug builds and crashed in release builds. #112338 (Groene AI). - With
shutdown_wait_backups_and_restores = 0, aBACKUPorRESTOREwhose I/O did not return could keep the server from terminating on a singleSIGTERM. That wait is now bounded byshutdown_wait_unfinished, and new backups and restores are refused once shutdown has begun. #115377 (Groene AI). - Fix wrong results when query plan optimizations treat non-deterministic expressions as deterministic, including lambdas and WebAssembly UDFs, which could silently drop rows. #117248 (Alexey Milovidov). #117249 (Alexey Milovidov).
- Fix
Column identifier ... is already registered(LOGICAL_ERROR) for a correlated subquery over aVIEWon aDistributedtable. Such a query is now refused withCorrelated subqueries are not supported with remote tables, the same as a correlated subquery over theDistributedtable itself. The same applies to parameterized views,Mergetables over such views, and materialized views whose target is such a view. #117335 (Alexey Milovidov). - Fixed
transformand the simpleCASE expr WHENform returning the default value instead of the matching one when the expression is aNullable(Enum)column. Only the member whose numeric value was0used to match. Closes #117206. #117520 (Groene AI). - Fix
SYSTEM RELOAD DICTIONARY <bare-name> ON CLUSTERandSYSTEM UNLOAD DICTIONARY <bare-name> ON CLUSTERso normal distributed DDL clusters resolve the bare dictionary name against the initiator’s current database before queuing the task, matching existing table-likeON CLUSTERDDL behavior. Closes #114322. #117596 (Alexander Yoon). - Fixed silently missing rows for predicates on
toUnixTimestampof aDateorDate32primary key or column with statistics: the conversion wraps aroundUInt32for dates after 2106-02-07, but index analysis assumed it was monotonic everywhere. #117709 (Alexey Milovidov). - Fixed a query getting stuck when the server fails to start a thread for a parallel task, for example when a thread pool is exhausted. #117781 (Alexey Milovidov).
- Fixed wrong results for a distributed query whose folded constant contains a
DateTimevalue. The constant is now sent to secondary servers as its raw Unix timestamp wherever the receiving side re-applies the literal’s declared type, so DST fall-back overlaps no longer reinterpret it as another instant. #117837 (Groene AI). - Fixed queries failing with
AUTHENTICATION_FAILEDafterRENAME DATABASEon aReplicateddatabase that usescluster_secret. The cached cluster object kept the old database name, which participates in the interserver handshake. #117874 (Kirill Shokhin). - Fixed
NOT_FOUND_COLUMN_IN_BLOCKwhentransform_null_in = 1and a distributed or parallel-replicas query aggregates over a predicate that an analyzer pass rewrote intoIN, such asSELECT sumIf(id, has([1, 2, 3], id)) FROM t. #117897 (Groene AI). - Fixed
THERE_IS_NO_COLUMN(Cannot find column ... in source stream) when a query shipped as a serialized query plan (serialize_query_plan = 1) reads aMergetable that spans a local table and aDistributedtable. #117969 (Groene AI). - Fixed a
SELECTreturning fewer rows than it should when aJSONsubcolumn is compared with anEnumconstant whose label is the empty string, and the table has aJSONAllPathsskip index (bloom_filter,tokenbf_v1,ngrambf_v1, orsparse_grams). #117975 (Groene AI). - An
Enumconstant wrapped inVariantorDynamicand compared against aStringorFixedStringcolumn no longer uses the enum’s underlying number instead of its name, which previously madeIN,NOT IN, and key analysis use the wrong value. #117998 (Groene AI). - Fixed a
Replicateddatabase being unable to recover a lost replica if it held aRemoteorRemoteSecuretable whose target is a table function such asmerge(...)that no longer resolves. #118221 (Groene AI). - Fixed
Not found column ... in blockfor a query that combines a constantORDER BYkey,LIMIT BY, andLIMIT ... WITH TIES. #118222 (Alexey Milovidov). - Fixed two overflow cases where
memory_usage_overcommit_max_wait_microsecondslost the wait it was asked for and timed out immediately instead of waiting for memory to be freed. #118227 (Groene AI). - Fixed
CREATE VIEWbeing refused withSUSPICIOUS_TYPE_FOR_LOW_CARDINALITYorILLEGAL_COLUMNwhen the view’s inferred column type is gated by settings such asallow_suspicious_low_cardinality_typesorenable_time_time64_type. Views store no data, so those storage-type checks no longer block them. #118298 (Groene AI). - Fixed
Not-ready Set is passed as the second argument for function 'globalIn'when aPREWHEREor row-level filter expression containing anINsubquery is evaluated by a query planned to theFetchColumnsstage. #118359 (Groene AI). SELECT count() FROM <set-table>now works for theSetengine, using the table’s stored row count instead of failing withMethod read is not supported by storage Set. Reading regular columns from aSettable is still unsupported. #118491 (Alexey Milovidov).- Fixed
sequenceMatchEventsreturning an event chain that the pattern does not authorize, for example one that skips a(?t...)time gate between two of the returned events. The returned chain now always matches a prefix of the pattern. Closes #118120. #118497 (Groene AI). - Fixed
toSecond,toStartOfMinute,toStartOfHour,toStartOfInterval, and the othertoStartOf*functions returning wrong values for pre-1970DateTime64values in time zones whose historical offset had a sub-minute component, such asEurope/Amsterdambefore 1937 orAsia/Kolkatabefore 1906. #118501 (Alexey Milovidov). - Fix array aggregation functions returning non-default values for empty arrays when the lambda result is constant. #118636 (Minh Vu).
- Conversions of 128- and 256-bit integers to
DateTime,DateTime64, andTime64now saturate like the 64-bit conversions instead of wrapping or storing an out-of-range value. This also fixes silent row loss through primary-key pruning. #118717 (Alexey Milovidov). - Fix a possible heap buffer overflow on malformed blob-storage responses. #119054 (Arsen Muk).
- Preserve input sorting for
groupArrayInsertAt,stochasticLinearRegression, andstochasticLogisticRegression, so anORDER BYfeeding them is not optimized away. #119142 (Ivan Babrou). - Fixed a crash and a
LOGICAL_ERRORfor statements that writetrim(BOTH '' FROM x)where a function is expected, such as in a column’sSTATISTICS(...)orCODEC(...)list,INDEX ... TYPE,ALTER TABLE ... ADD STATISTICS, a table function, a named collection, orSETTINGS. #119317 (Groene AI). - Fix
CHECK TABLEpermanently reportingFound unexpected projection directoriesafter a mutation when the part carries a projection that the table has since dropped. #119348 (Alexey Milovidov). - Fix a wedged mutation queue after
ATTACH PARTITIONof a partition that was detached before aDROP COLUMN: mutations of a Compact part carrying the dropped column no longer fail forever withUNKNOWN_IDENTIFIER. #119354 (Alexey Milovidov). - Fix a bug where unfiltered
TRUNCATE ALL TABLES FROMqueries permanently disabled merges on retainedMergeTreetables, causing laterOPTIMIZE TABLE ... FINALqueries to fail withABORTED. #119425 (Paul Annesley). - Fix
Unexpected value 0 in enumthrown by string functions such asLIKE,match, andpositionwhen applied to aNullable(Enum)value that isNULL, includingNULLs produced by aLEFT JOINwithjoin_use_nulls = 1. #119513 (Alexey Milovidov). - Fix
arrayJaccardIndexwhen its input arrays contain duplicate elements. #119560 (Minh Vu). modulo,positiveModulo,moduloOrZero, andmoduloOrNullno longer return wrong results when one operand is a signed integer and the other is an unsigned integer at least as wide. #119616 (Serhiy Bzhezytskyy).- A
Filesystemdatabase no longer keeps pointing at a removed directory, which previously made the server refuse to start on the next restart. #119618 (Alexey Milovidov). - Fixed a standalone
UPDATE ... SETreading the wrong table when a mutation expression names a table that a same-namedWITHelement hides but the subquery does not see because its ownSETTINGSclause disablesenable_global_with_statement. #119630 (Groene AI). - Fixed a stack buffer overflow when reading a
BITcolumn from MySQL through themysqltable function, theMySQLtable and database engines, or MySQL dictionaries. #119680 (Alexey Milovidov). - Fix
sparseGramsignoringmax_ngram_lengthwhenmin_cutoff_lengthis specified. #119713 (Minh Vu). - Fix
BACKUPandRESTOREof aLogorTinyLogtable when one column occupies zero bytes on disk while the table has rows, such as a column ofcountResamplestates over an empty range. Previously the restored table could come back empty or fail withFILE_DOESNT_EXIST. #119722 (Groene AI). - Fix a race between
ALTER TABLEandRENAME TABLE/EXCHANGE TABLES. #103044 (Nikolay Degterinsky). - Fix
BACKUPofEmbeddedRocksDBtables. Previously only the table metadata was stored in the backup and the actual data was silently dropped, soRESTOREproduced an empty table. The backup now includes all key-value pairs and restores them correctly. #109327 (Groene AI). - Fix
toStartOfWeekandtoLastDayOfWeekwith a Sunday-first week mode returning a wrapped day number for aDate32value outside the representable calendar, for example aftertoDate32('1970-01-01') + INTERVAL 2147483647 DAY. The week boundary is now computed at the calendar boundary, consistently with the Monday-first week modes. #111923 (Groene AI). - Fixed
mergeTreeCodecBlockCountsdisclosing whether a source table exists, and even its engine type, to a user without any privilege on that table. Resolving the table function, for example withDESCRIBE, now checks access before consulting the catalog. #116647 (Alexey Milovidov). - Messages of the PostgreSQL wire protocol are now parsed within their declared size, so a malformed message can no longer make the server allocate memory for a payload that never arrives. #116998 (Alexey Milovidov).
- Fixed
CREATE TABLE dst AS srccopying the schema of anENGINE = Aliastable’s target for a user who holdsSHOW COLUMNSon the alias but no privilege on its target. The statement now requires table-levelSHOW COLUMNSon the target, matchingDESCRIBEof that target. #117702 (Groene AI). - Fixed the query condition cache serving a “no matching rows” verdict to a query that differs from the cached one only in a setting that changes how a function evaluates, such as the
formatdatetime_*/parsedatetime_*settings orfunction_locate_has_mysql_compatible_argument_order, which silently dropped all matching rows. #117803 (Alexey Milovidov). - Fixed a
CAST AS Tuple can only be performed between tuple types or from Stringerror, and silently wrong results for aTuple(String, ...)key, when aMergeTreesorting, partition or skip-index key wraps a singleTuple-typed column in a deterministic function (for exampleORDER BY toString(k)) and the query filters that column withk IN (tuple(...)),k NOT IN (tuple(...))or a multi-column subquery set. #118899 (Groene AI). - Fix queries that use a higher-order function together with
ARRAY JOIN: a lambda that captures nothing is no longer moved across theARRAY JOINstep away from the function that applies it. #119186 (Yarik Briukhovetskyi). - Fix
TYPE_MISMATCHin the selectivity estimator when a predicate on aDateTime64column uses an unconvertible string literal. Closes #119126. #119265 (Han Fei). - Fix unstable ordering of equal sorting keys during inserts, which could cause
CollapsingMergeTreeto retain stale rows when cancellation and replacement rows were inserted together withoptimize_on_insertenabled, andReplacingMergeTreeto retain the wrong row when versions were equal. #119474 (Anton Kovalenko). - Fixed cleartext credentials in
system.asynchronous_insert_log.query. Secrets of table functions such ass3,urlormysqlare now masked as[HIDDEN], the same waysystem.query_logmasks them. #119487 (Sema Checherinda). - Fix a crash when reading a table with active lightweight updates whose sorting key contains a column that is missing in the data part and has a
DEFAULTexpression. #119540 (Groene AI). - Fixed Keeper replaying its local changelog tail one entry at a time after a restart when the changelog is stored on object storage. The commit read-ahead used to discard its own prefetched entries whenever it missed the serve deadline, so on storage slower than that deadline it could never catch up and every entry cost two object reads. The default of
log_readahead_commit_window_bytesis now 16 MiB instead of 500 MiB, since it bounds a prefetch window rather than a cache. #119627 (Shaohua Wang). - Fix unbounded memory growth from time zone names of the form
libc:<suffix>. These are internal interfaces of thecctzlibrary that ClickHouse never intended to expose: any suffix was accepted, each distinct name permanently cost ~4.6 MiB that the server never gave back, and the time zone silently behaved as UTC instead of the name being reported as unknown. They are rejected now. #119634 (Alexey Milovidov). - Fix incorrect pruning for space-filling-curve indexes with
UInt64arguments. #119663 (Minh Vu). - Fixed
sum(x + 1) OVER (...)returning a single row holding the overall total instead of the windowed result.optimize_arithmetic_operations_in_aggregate_functions, which is enabled by default, rewrote the windowedsumintosum(x) + 1 * count(x), an expression over plain aggregates that cannot carry theOVERclause, so the window definition was discarded. Bothenable_analyzer = 1(the default) andenable_analyzer = 0were affected. #119699 (Groene AI). - Fix
substringUTF8returning too many code points when a negative offset starts before the beginning of a string. #119840 (Minh Vu). - Fix
URLHierarchy,URLPathHierarchy, andURLHashfailing to recognize valid URL schemes containinga,z,0, or9. #119844 (Minh Vu). - Fix
mapSubtractsubtracting duplicate keys in its first argument. #119845 (Minh Vu). - Fixed the server not validating the schema of the second and subsequent data blocks that a client sends for an external table over the
Nativeprotocol. Such a block could make the data be interpreted as a type other than the one it was sent as. #119849 (Alexey Milovidov). - Fixed AST formatting of the
APPLYcolumn transformer: a column-name prefix containing a single quote or a backslash, or a function name that needs back-quoting, was emitted without escaping, soformatQueryreturned a query that either could not be parsed or parsed back to a different query. #119851 (Groene AI). - Fixed a crash of the server caused by a table with
ENGINE = NATSwhose credentials the broker started to reject, for example after a password rotation or on an expired token. Such a table now recreates its connection and resumes consuming once the credentials are accepted again, instead of staying silently idle. #119853 (Alexey Milovidov). - Fixed
timeSeriesTagsToMaptreatingFixedStringtag names and values differently between the array form and the separate-argument form.FixedStringpadding is now trimmed consistently, so the same logical tags produce the same map and lookups such asmapContains(..., 'a')work in both forms. #119859 (Minh Vu). - Fixed wrong results when
join_algorithm = 'direct'reads the right-hand table of a join from aMergeTreetable and plan-based parallel replicas (parallel_replicas_plan_based = 1) are enabled. Such a join could silently return only part of the rows that should have matched, with no error reported. The lookup read that the join performs is no longer distributed across replicas. #119861 (Groene AI). - Fixed data loss where a
MergeTreepart whosecolumns.txtwas left empty (zero bytes) by an interrupted metadata rewrite was detached as broken on load, discarding all of its rows. For a wide part the column list is now rebuilt from the part’s owncolumns_substreams.txtand the table metadata, as it already was for an absentcolumns.txt; when the rebuilt list cannot be validated, the part is left untouched for recovery instead. #111597 (Groene AI). - Integers in the
TSV,TSVRaw,TSKVandCustomSeparatedformats can now be zero-padded (007) or carry a redundant leading+(+7), spellings that previously failed to parse but thatCSValready accepted. The same reader serves other conversions from text to an integer, soWHERE i = '007'on a numeric column, query parameters andCAST('[007]' AS Array(Int64))accept them too. A field that is a lone+remains an error, now reported asCANNOT_PARSE_NUMBERon every one of these routes instead of a route-specific code. Schema inference is unchanged:007still infers asString. #113910 (Groene AI). - Fixed permanent data loss in
ALTER TABLE ... EXECUTE remove_orphan_filesonIcebergtables withiceberg_use_version_hint = 1. Whenmetadata/version-hint.textnamed an older version than the newest committed metadata file, every object of the newer committed snapshot, including its data files, was deleted as an orphan. Reachability is now computed from the authoritative current metadata, and a metadata listing this command cannot order unambiguously is refused instead of resolved by listing order. #114324 (Groene AI). - Fix buffer overflows and a server abort on malformed responses from external servers: an Azure Blob Storage endpoint that returns more data than was requested or omits the
ETagheader, and aMySQLserver that returns an oversizedBITvalue.Azurereads, copies and deletes, andS3copies made by backups and byS3Queuepost-processing, are now pinned to the object generation they selected, so an object overwritten in place is reported instead of silently mixing two generations. Also fix the decoding of aMySQLBITvalue shorter than 8 bytes on big-endian hosts. #115706 (Alexey Milovidov). - Fixed a crash inside the crash handler itself when a fatal signal arrives during startup of
clickhouse-server,clickhouse-keeperorclickhouse-local. The handler dereferenced the global context, which does not exist yet at that point, so right after logging the stack trace it took a second fault, hung for about five minutes, and never sent the configured crash report. #116245 (Groene AI). - Fixed
CLEAR COLUMNsilently leaving aMATERIALIZEDcolumn derived from the cleared column at its old value. This happened whenever the mutation had already built a stage before the recompute was appended: another pending mutation coalescing with theCLEARinto one pass, which needs no special settings, or an enabledenable_block_number_column/enable_block_offset_column. The wrong value was permanent; later merges did not repair it. #117296 (Shaohua Wang). - Fixed
ILIKEon atextindex returning rows the predicate does not match, and skipping rows it does match, when the pattern or the data contains a non-ASCII code point that case-folds onto an ASCII letter. Affected indexes with alowerUTF8/upperUTF8preprocessor and patterns whose needle containsk. #117354 (Jimmy Aguilar Mena). - Fixed wrong results in five cases where a
WHEREpredicate on a join key was pushed to the other side of aJOINwhose two keys have different types. Such a key is no longer substituted when the keys’ common type is a float, because-0.0and+0.0are join-equal but differ bit for bit; nor when it isDynamicorJSON, whose runtime contents the static type does not describe; nor when the key is unstable within the query or changes the row count; nor in a conjunct that reads a column’s representation rather than its value, asisConstantandtoColumnTypeNamedo, including when such a read or an unstable function is hidden inside a lambda body. Separately, withenable_analyzer = 1, a predicate on the wider of two differently typed join keys is now also used as an index condition on the other table of a plainINNER JOIN, so it is read through its primary key instead of in full; previously onlyANY INNER JOIN,LEFT JOINandRIGHT JOINgot this. #117973 (Groene AI). Also fixed aLOGICAL_ERROR(Unexpected return type from _CAST) when such a predicate was pushed down to a side thatjoin_use_nullswidens toNullable. #120109 (Groene AI). - Fix rows silently dropped by index analysis for
has(array_of_named_tuples, key)when the tuple fields are declared in another order and the key is a function of the column. #118706 (Alexey Milovidov). - Fixed ClickHouse Keeper returning
ZNOAUTHfor every request on a node whose ACL list is empty but is stored under a nonzero internal ACL id, which happens for Keeper data converted from a ZooKeeper snapshot or written by a very old Keeper. Such nodes are unrestricted again, as they were before 26.6. Closes #117603. #118965 (Groene AI). - Fixed
YYYYMMDDhhmmssToDateTime64returning incorrect fractional seconds for timestamps before 1970-01-01. #119240 (Raúl Marín). - Fixed a crash when a disk is configured with
metadata_type = webormetadata_type = web_indexon top of a non-web object storage. Such a configuration is now rejected withINVALID_CONFIG_PARAMETERinstead of interpreting an unrelated object storage as a web one. Closes #119798. #119818 (Groene AI). Icebergtables recovered from stored metadata no longer enable background compaction or old-file cleanup unless those settings are explicitly stored in the table definition. #119977 (János Benjamin Antal).- Fixed a
NATStable whose settings all come from a named collection (ENGINE = NATS(collection)with noSETTINGSclause) being written to its metadata file with a danglingSETTINGSkeyword. The stored definition could not be parsed again, so the table failed to load and aborted the load of its whole database, making unrelated tables in it inaccessible. Closes #119120. #120025 (Groene AI). - Fixed non-idempotent formatting of a function named
SOME: the name was printed unquoted, so the server read its own output back as theSOMEarray quantifier.formatQuery('SELECT 1 < SOME(a, b -> 1)')returned a query that re-parses toarrayExists, and a user-defined function whose body compared against`some`(...)was persisted without the quotes and then failed to load after a restart. #120096 (Groene AI). - Fix reading a column that has two streams whose names differ only by escaping, for example a
Tupleelement namedsize0inside anArray, or a typedJSONpath named like a substream of a sibling path. Such columns returned wrong values, failed withCANNOT_READ_ALL_DATAor another exception, and made the table unmergeable. #115670 (Pavel Kruglov). - Fix
least,greatest,bitShiftRight,midpoint, andavg2returning wrong results when a JIT-compiled expression has anInt128result. With the defaultcompile_expressions = 1, a negativeInt128result could be treated as unsigned after a few executions. #118363 (Groene AI). - Fix
ttl_only_drop_partspreventing expired columns from ever being cleared. A columnTTLrequires rewriting the part, so with this setting enabled an expired column could be kept forever instead of being cleared. Column-TTLrewrites are now scheduled separately and still run whenttl_only_drop_partsis enabled. #118428 (Alexey Milovidov). - Fix
mergeTreeTextIndexbypassing row policies: reading the text index is now denied whenever a row policy applies to the table, regardless of which columns the policy uses. #119032 (Elmi Ahmadov). - Fix
force_primary_keyincorrectly rejecting some queries withINDEX_NOT_USEDwhenoptimize_extract_common_expressions(enabled by default) simplifies the filter to a trivial primary-key condition wrapped in an implicit cast. #119083 (kasimtj). - Fix
groupNumericIndexedVectorreturning a value that is too large when an index repeats in the input, and returning different results depending onmax_threads. Also fixnumericIndexedVectorPointwiseMultiplyandnumericIndexedVectorPointwiseDividedropping zero-valued indices, andnumericIndexedVectorPointwiseDivideby a vector of all ones keeping the value of an index the divisor is missing instead of zeroing it. AgroupNumericIndexedVectorStatealready stored in a table is not repaired by the upgrade and has to be recomputed. #119564 (Alexey Milovidov). isNullandIS NULLnow return1for everyNULLrow, including when the column’s NULL mask holds a byte other than0or1, which theNativeformat permits and whichifcan produce from its condition column. Previously such a row could contribute its raw byte, sosum(isNull(e))returned30where20is correct.if(cond, x, NULL)with aNullablexno longer returnsNULLfor a row whose condition byte was neither0nor1. If an older server stored a value computed fromisNullon such a column (sorting key, skip index, partition key, projection,MATERIALIZEDorDEFAULTcolumn), rebuild it. #119785 (Groene AI).- Preserve explicit time zones in
timeSeriesRangeDateTime64results. #119858 (Minh Vu).
Build/Testing/Packaging Improvement
- Added a CMake file for compiling ClickHouse with the
nvcccompiler. Related: #116807. #117734 (Konstantin Vedernikov). Added thecudfcontrib library. #117869 (Konstantin Vedernikov). - Added a build option to select 4 KiB or 16 KiB jemalloc page size on AArch64 instead of the default 64 KiB. #115424 (Azat Khuzhin).
- Fixed several portability issues on
illumos, including missingtermios.h, register-macro conflicts, and floating-point environment casts. #117363 (Joshua Carp). - ClickHouse is now built as a position independent executable on Linux amd64 and aarch64 with glibc, including the release builds, so the text segment is subject to ASLR. Addresses in the bare stack trace of a fatal log are now file offsets relative to the object that contains them, annotated with that object for frames outside the main executable, so they can be resolved with
addr2line -e <object> <hex>regardless of where the binary was loaded. For the same reasonsystem.errors.last_error_trace,system.error_log.last_error_traceandsystem.crash_log.tracenow store a frame of the main executable as its file offset, keeping runtime addresses for frames in other objects. #117449 (Groene AI). #119284 (Alexey Milovidov). - Fixed compilation of
benchmark_statisticswithENABLE_BENCHMARKS=ON. #116292 (Groene AI). - Use
cctztzdata 2026c. #116539 (Konstantin Bogdanov). - Restored the bundled
aws-c-httplibrary to v0.11.0 after it had been accidentally reverted to an older submodule revision. #116911 (Alexey Milovidov). - Fix building
ArrowFlightprotobuf files with the CMakeUnix Makefilesgenerator by creating theprotocoutput directory before invokingprotoc. #116879 (Alexey Bakharew). - Reduced compile time and object file sizes by removing redundant template instantiations in comparison functions, binary arithmetic,
arrayDistance, hashed dictionaries, andargMin/argMax. #117540 (Konstantin Bogdanov). - Fix building
unit_tests_dbmswhen ClickHouse is configured with-DENABLE_LIBRARIES=OFF(and-DENABLE_RUST=OFF). #105684 (Ivan Babrou). - Harden official builds by enabling full RELRO: the global offset table is now mapped read-only after startup. #119037 (Raúl Marín).
- Cross-compilation sysroots updated: FreeBSD builds now target FreeBSD 14 (13 is end-of-life), riscv64 and loongarch64 builds use current Debian glibc and kernel headers. Unused files were removed from the sysroot submodule. #119049 (Konstantin Bogdanov).
- Fixed startup of the shell-based Docker server images when an absolute
filesystem_cachespath is a missing directory below a directory the server does not own. The entrypoint now prepares these cache directories with the same ownership handling asstorage_configurationdisk paths. #118842 (thien-ch). - Update
opensslto 3.5.8. #118927 (Actuele AI). - Update
xxHashto v0.8.3. #117597 (Actuele AI). - Update
libxml2to 2.15.4. #118649 (Actuele AI). - Update
libdivideto v5.4.0. #118660 (Actuele AI). - Update
Jieba-CPPto v1.0.0. #118889 (Actuele AI). - Update
minizip-ngto 4.2.2. #118886 (Actuele AI). - Update
miniselectto 0.4.0. #118887 (Actuele AI). - Update
openldapto 2.6.15. #118888 (Actuele AI). #119359 (Actuele AI). - Update
sparsehash-c11to v2.11.1. #118891 (Actuele AI). - Bump
croaringfrom v4.5.1 to v5.1.1. Serialized bitmaps are unchanged on little-endian platforms; on big-endian platforms the on-disk layout ofgroupBitmapstates changes to the portable little-endian format. #118917 (Actuele AI). - Update
xzto v5.8.4. #119360 (Actuele AI). - Update
librdkafkato v2.15.1. #119467 (Actuele AI). - Update
simdjsonto v4.6.11. #119508 (Actuele AI). - Fixed building ClickHouse with
clang23, which emitted alifetime-safetydiagnostic that was suppressed only forclang24 and later. #118005 (Navneet Kumar). #119211 (mosya415).
ClickHouse release 26.8 LTS, 2026-08-27. Presentation, Video
Backward Incompatible Change
- The
X-ClickHouse-FormatHTTP request header now explicitly selects the format of the response: it is an alias for theoutput_formatsetting, so it overrides theFORMATclause of the query and the path extension. In previous versions, it only set the default when the output format was unspecified, like thedefault_formatparameter. This provides an “out-of-band” option to request data in a desired format. It never changes how the request body of anINSERTis parsed - useinput_formatorformatfor that. #105249 (Alexey Milovidov). - Unquoted JSON numbers for
DateTimeandDateTime64columns inJSONEachRowand similar formats are now interpreted as Unix timestamps with optional sub-second precision, consistent withValues,CAST, andtoDateTime64. Previously, a fractional number such as1703363853.035was rejected, and a bare integer such as1703363853was read as the raw scaled value ofDateTime64, producing a1970-...timestamp. Quoted strings and ClickHouse’s own JSON output are unaffected. #108091 (Alexey Milovidov). - The default value of
max_insert_threadschanged from1toauto, which resolves to the number of CPU cores available to the server. This parallelizesINSERT SELECTby default, andmax_insert_threadscan now also parallelize the writing side of a plainINSERTwhen the destination write path can safely fan out. This can change the number of parts created by such queries and the order of inserted rows. To restore the previous behavior, setmax_insert_threadsto1, or setcompatibilityto a version below26.8. #109000 (Alexey Milovidov). #109006 (Alexey Milovidov). - The
PostgreSQLandMaterializedPostgreSQLdatabase engines now respectremote_url_allow_hosts, like thePostgreSQLtable engine, thepostgresqltable function, and DDL-created dictionaries already do. Withremote_url_allow_hostsconfigured,CREATE DATABASEand user-issuedATTACH DATABASEnow rejectPostgreSQLandMaterializedPostgreSQLdatabases that point at disallowed hosts withUNACCEPTABLE_URL. Existing databases still load at server startup. #111135 (Alexey Milovidov). - The experimental
ALP(STD)codec now performsFloat32scaling arithmetic inFloat64. This improves compression ratios and eliminates exception-heavy compression of decimal data, butFloat32values written by earlier versions may now decode 1 ULP differently. #111627 (Raufs Dunamalijevs). - Removed the
librarydictionary source.SOURCE(LIBRARY(...))now fails withUNKNOWN_ELEMENT_IN_CONFIG, and thedictionaries_lib_pathserver setting is obsolete and has no effect. #111980 (Alexey Milovidov). - Removed the Apache Arrow library-based reader and writer for the
ArrowandArrowStreamformats. The native ClickHouse implementation, which has been the default since 26.7, is now the only one. The settingsinput_format_arrow_use_native_readerandoutput_format_arrow_use_native_writerare obsolete: they are still accepted, but have no effect, so a query that set them to0to force the Apache Arrow implementation now uses the native one. #111996 (Alexey Milovidov). - Reject timespan setting (milliseconds/seconds) values that overflow Int64 microseconds. #112757 (Azat Khuzhin). This might be an incompatibility only when you used absurdly large values that overflowed.
- TLS credentials of a
MySQLsource (ssl_ca,ssl_cert,ssl_key) can no longer be specified as file paths from SQL, such as inCREATE NAMED COLLECTION, query arguments, orCREATE DICTIONARY, because the server opens those files with its own privileges. Paths remain supported in the server configuration file. Elsewhere, pass the certificate or key contents in the newssl_ca_pem,ssl_cert_pem, andssl_key_pemparameters, which are masked in logs and inSHOWqueries like passwords are. #112070 (Alexey Milovidov). - Privilege checks for the
SYSTEM ... CACHE ON CLUSTERcommands now use each command’s own privilege instead of theSYSTEM DROP CACHEprivilege group. This lets holders of a single granular cache privilege run its matching command, and prevents a holder of the group from runningSYSTEM SYNC FILESYSTEM CACHE ON CLUSTERwithoutSYSTEM SYNC FILESYSTEM CACHE. #114042 (Groene AI). - For views whose body is a plain
SELECTover a singleDistributedtable, the whole outer query is now pushed to the shards (new settingoptimize_trivial_view_pushdown_to_distributed, enabled by default). This changes observable behaviour for such views:FINALandSAMPLEwritten on the view reference are now propagated to the shard-local table instead of being ignored, andextremesis not reported on single-shard clusters. Setoptimize_trivial_view_pushdown_to_distributed = 0to restore the previous behaviour. #101791 (simonmichal). - Lightweight
UPDATEpatch parts now use a new v2 on-disk format sorted by (sorting_key..., _block_number, _block_offset) and applied with a new merging algorithm. Peak memory is bounded by the largest equal-sort-key run instead of the full patch, and updates that cross merge boundaries no longer fall back to in-memory Join apply. Old-format patch parts remain readable. During a rolling upgrade from a version before 26.8, keeppatch_parts_version = 'v1'or use thecompatibilitysetting until all replicas are upgraded. #103182 (Anton Popov). - Added the
VALID FOR <interval>clause toCREATE USERandALTER USERas a shorthand forVALID UNTIL. The expiration deadline is computed as the current time plus the given interval at query execution time and stored in theVALID UNTILform. Thevalid_untilcolumn of thesystem.userstable now has the typeArray(DateTime64(0))instead ofArray(DateTime), so that deadlines beyond the year 2106 are represented exactly; tooling that reads this column should handle the new type. #110171 (Alexey Milovidov). EXPLAIN SYNTAXnow returns the reformatted query as a singleStringrecord (with embedded newlines) instead of one record per line, so its output is a recoverable single row that is directly usable (for example,SELECT count() FROM (EXPLAIN SYNTAX ...)returns1). This is controlled by the newsingle_recordoption, which defaults to1; setsingle_record = 0to restore the historical one-record-per-line output. OtherEXPLAINkinds (PLAN/PIPELINE/AST) keep their per-line tree output. #110479 (Alexey Milovidov).- Extended the supported range of
Date32from[1900-01-01, 2299-12-31]to[0000-01-01, 9999-12-31], matchingDateTime64. Parsing and conversions now accept the extended range instead of silently clamping to the old boundaries. Backward compatibility notes: in the numeric conversiontoDate32(N), values in[120530, 2932896]are now interpreted as day numbers (dates from2300-01-01to9999-12-31) instead of Unix timestamps in early 1970, matching the rule that a number that fits into the day-number range is a day number; numbers below the day number of0000-01-01and timestamps after9999-12-31saturate to the new boundaries. #111534 (Alexey Milovidov). arrayIntersectandarraySymmetricDifferenceno longer treat a value repeated inside a single argument as if it appeared in several arguments. Queries relying on the previous behavior can now return different results:arrayIntersect([1], [2], [1, 1])returns[]instead of[1],arrayIntersect([1, 2], [2], [1, 1, 2])returns[2]instead of[1, 2], andarraySymmetricDifference([1], [2], [1, 1])returns[2, 1]instead of[2]. ForarraySymmetricDifferencetwo arguments are already enough:arraySymmetricDifference([1], [2, 2])returns[2, 1]instead of[1]. A value is now counted for an argument only when it was present in every argument before it, so the result contains exactly the values present in all of the arguments. As part of the same change,arrayIntersectbuilds its hash table from the smallest argument rather than from all of them, which makes it up to 1.85x faster and use a third less memory when the arguments differ a lot in size.arrayUnionis not affected. #113021 (Alexey Milovidov).disable_insertion_and_mutationnow prevents background consumption fromKafka,RabbitMQ, andNATStables while still allowing direct writes to external storage. GatedKafka2,NATS, andRabbitMQtables do not initialize consumers for directSELECT. The recently introducedmessage_queue_disable_insertionsetting now requires a server restart. #113660 (Christoph Wurm).- A window
PARTITION BYorORDER BYover anAggregateFunctioncolumn is now rejected withILLEGAL_COLUMN, as top-levelORDER BYover such a column already was. Previously such a query was accepted by at least one analyzer, and windowPARTITION BYpartitioned differently depending onmax_threads. The refusal also covers a state nested inArray,Tuple,Map,VariantorSimpleAggregateFunction. ASimpleAggregateFunctionover an ordinary type,QBit, andGROUP BYandDISTINCTover a state, are unaffected. #113878 (Groene AI). - The
include_fromsetting no longer defaults to/etc/metrika.xml. Previously that file was used for configuration substitutions whenever it existed, even though nothing in the ClickHouse configuration referred to it. If you relied on that implicit substitutions file, add<include_from>/etc/metrika.xml</include_from>explicitly to each affected config file; separately loadedusers.xmland XML dictionary configs need their owninclude_fromelement. #114161 (Alexey Milovidov). - The
NATStable engine accepts credentials inline in the newnats_credentialssetting (the same payload as a.credsfile), and no longer acceptsnats_credential_filefrom SQL: the path is a reference to a file on the server filesystem, which the server opens with its own privileges, so it can only be specified in a named collection defined in the server configuration file, or asnats.credential_filein the server configuration itself. A query may replace such a configured path with inlinenats_credentials, unless the operator pinned it with<nats_credential_file overridable="false">. Tables created before this restriction keep working after an upgrade. #114644 (Alexey Milovidov). - Asynchronous metrics can now have the
Mapdata type, and the per-CPU-core and per-device metrics were converted to single key-value metrics:OSUserTimeCPU0,OSUserTimeCPU1, … became a singleOSUserTimeCPUmetric with a map from the CPU core number to the value (and similarly for the otherOS*TimeCPU*metrics,CPUFrequencyMHz_*,Temperature*,EDAC*,Block*_*,Network(Receive|Send)*_*,Disk*_*,*BlobsQueueEstimate, andAsyncLogging*QueueSize).system.asynchronous_metricshas a newkey_values Map(LowCardinality(String), Float64)column (thevaluecolumn isNaNfor such metrics),system.asynchronous_metric_loglogs them as one row per key using a newkeycolumn, the Prometheus endpoint exports them with a label (e.g.ClickHouseAsyncMetrics_BlockReadBytes{device="sda"}), and the GraphiteMetricsTransmittersends them as<prefix>.<Metric>.<key>. If your monitoring reads the old metric names, set the newasynchronous_metrics_key_values_modeserver setting tolegacy_namesto publish every key as a separate scalar metric under its previous name again, or tobothto publish both forms at the same time while the monitoring is being migrated; the setting is applied bySYSTEM RELOAD CONFIG, without a restart. #115333 (Alexey Milovidov). #116791 (Alexey Milovidov).
New Feature
- Added
CREATE HANDLER,ALTER HANDLERandDROP HANDLERstatements to define custom HTTP handlers from SQL, persisted in a local or Keeper storage. Added thecurrentHandlerandcurrentRequestURLfunctions, thesystem.handlerstable, and thehttp_handler_name/http_request_urlcolumns insystem.query_log. #106231 (Alexey Milovidov). - Added a way to access tables and databases via URL paths in the HTTP interface (e.g. `/database/table.format.gz?filter=a>0`), plus new settings (`http_allow_database_as_path`, `http_allow_table_as_file`, `http_allow_filters_as_path`, `http_allow_filters_as_unrecognized_url_parameters`, `select`, `order`, `sort`, `filter`, `page`, `compression`, `format`, `input_format`, `output_format`, `default_format`, `database`) that compose with one another and with the existing `query` URL parameter. #105249 (Alexey Milovidov).
- Add framing formats, selected by the new setting
framing_output_format: they multiplex different response parts of the query in a single HTTP response stream — chunks of data, totals and extremes, progress packets, profile events, server logs, and exceptions. Implemented framing formats:None(default, everything works as before),EventStream(HTTP server-sent events),JSONEachPacketBase64, andJSONEachPacketString(a JSON object per packet with base64-encoded or string data). #110127 (Alexey Milovidov). - Added the
default_session_userserver setting: the user to authenticate as when a client connects without specifying a user name (previously hardcoded todefault; the native, MySQL, and PostgreSQL protocols now accept an empty user name instead of rejecting it, and Arrow Flight honors the setting instead of its own hardcodeddefault). Composable protocol endpoints in theprotocolssection can override it per endpoint with adefault_session_userkey, so different listening ports can serve different anonymous users. Setting it to an empty string prohibits connections without a user name. Interserver connections never use the default session user. #110179 (Alexey Milovidov). - Support pipe operators in SQL queries:
FROM t |> WHERE x > 1 |> AGGREGATE count() AS c GROUP BY y |> ORDER BY c DESC |> LIMIT 10, similar to the pipe syntax of GoogleSQL. AnySELECTquery can be followed by a chain of|>operators, and each operator wraps the query before it into a subquery, so the resulting AST is the same as for the equivalent query with nested subqueries. In a query that starts with theFROMclause, theSELECTclause is now optional and defaults toSELECT *. #111151 (Alexey Milovidov). - Added the
parseQueryToJSONandformatQueryFromJSONfunctions to serialize and deserialize ASTs as JSON, and an experimentalclickhouse_jsondialect enabled byenable_json_ast_dialect. #100412 (Alexey Milovidov). #113480 (Nikita Fomichev). - New setting
run_query_in_background. The server accepts the query, immediately returns an empty result, and runs it to completion regardless of what happens to the connection. The result is discarded. Track the query by itsquery_idinsystem.processesandsystem.query_log. Intended for long queries likeINSERT ... SELECT,CREATE TABLE … AS SELECT, orCREATE MATERIALIZED VIEW … POPULATEthat must not die with a dropped connection. #112816 (Miсhael Stetsyuk). - Added a new system table,
system.user_query_log, which shows every user their own query log records without requiring access to the query log table. The original implementation and the idea belong to Yue Ni (@niyue), #104462. #110156 (Alexey Milovidov). - Implement the remaining items of the URL unification (issue #59617). The new
s3_basesetting resolves relative URLs in thes3table function and theS3table engine (and the functions sharing their configuration:s3Cluster,gcs,oss), similarly tourl_base. The newURLdatabase engine treats table names as URLs, resolves them against an optional base URL, and dispatches by the URL scheme, so files, web and object storage are handled uniformly. It replacesFilesystemin the default (Overlay) database ofclickhouse-localwith afile://base URL, so plain file names keep working, and you can also writeSELECT * FROM 'https://example.com/data.csv'. #111512 (Alexey Milovidov). - Added the
bigquerytable function and theBigQuerytable engine for reading from and writing to Google BigQuery tables, including public datasets. The table structure is inferred from the BigQuery table schema. Authentication supports an OAuth access token, a service account key inJSONformat, and an OAuth client with a refresh token. #110166 (Alexey Milovidov). - Plain
CREATE MATERIALIZED VIEW ... POPULATEis now locally atomic: the view is subscribed to new inserts of the source table and the existing data is snapshotted together under a brief exclusive lock on the source, so rows inserted through the same server concurrently with the population are no longer missed or duplicated (new settingmaterialized_views_populate_atomically, enabled by default). The guarantee covers the local insert path only; inserts arriving on another replica or through a distributed write path are outside the cut, and it requires a source that can provide a pinned snapshot (theMergeTreefamily andMemory); other sources, as well asCREATE OR REPLACE/REPLACEand views created inReplicateddatabases, keep the legacy non-atomic population.POPULATEcan now also be used together withTOto backfill the target table. #108715 (Alexey Milovidov). - Keeper can store data on disk now, in a custom LSM tree. It has similar performance to the previous storage. Use coordnation setting
use_lsmt_storage = trueto enable,storage_memory_only = falseto store files on disk, adddata_storage_pathordata_storage_diskto config to specify where to put the files. To write to S3, pointdata_storage_diskto a disk of types3_plain. #113903 (Michael Kolupaev). - The “S3 tables” engine catalog for data lakes, the same as #103220 but with a working
INSERT. #113505 (Konstantin Vedernikov). - Add support for Snowflake Horizon. You can now query Iceberg table in Iceberg behind the horizon catalog. You can also write to the Iceberg table via the catalog. #114547 (Melvyn Peignon).
- Added support for the
Puffinfile format. It can be used with thefile,url,s3, and similar table functions. #103936 (Konstantin Vedernikov). - Support the
GROUPSframe mode for window functions (SQL:2011), e.g.any(price) OVER (PARTITION BY symbol ORDER BY ts GROUPS BETWEEN CURRENT ROW AND 1 FOLLOWING). In aGROUPSframe the boundaries count whole peer groups — sets of rows that are equal on theORDER BYkey — soN PRECEDING/N FOLLOWINGmeanNpeer groups before/after the current row’s peer group, rather than physical rows (ROWS) orORDER BYvalue distances (RANGE). #108653 (Nihal Z. Miaji). - Added the
mergeTreeCodecBlockCountstable function, which reports for each part, column, and substream of aMergeTreetable how many compressed blocks use each codec. #109623 (Raufs Dunamalijevs). - Added the
MultiPointgeo data type, stored asArray(Point), and included it in theGeometrytype. #109951 (David Meng). - Added the
_etagvirtual column forHDFSstorage. #108255 (Zhang Yifan). - The native
ORCreader and output format now supportuniontype, mapping it to the ClickHouseVarianttype. Previously, reading such columns failed withUnsupported ORC type, and writing them failed withILLEGAL_COLUMN. #110078 (Alexey Milovidov). #110085 (Alexey Milovidov). - Added a
japanesetokenizer for text indexes and thetokens,hasAnyTokens, andhasAllTokensfunctions, using the MeCab morphological analyzer. The dictionary is loaded at runtime from a location set in the server configuration and verified against a SHA-256 checksum before use. #111420 (Jimmy Aguilar Mena). - Added a
chinesetokenizer for thetokensfunction andMergeTreetext indexes. It segments Chinese text into words using a dictionary and a Hidden Markov Model (the algorithm follows jieba), withcoarse_grained(default) andfine_grainedgranularities. Continues #80174. #89945 (Amos Bird). - Added a new
icutokenizer for text indexes and thetokens,hasAnyTokens, andhasAllTokensfunctions, providing locale-aware Unicode word segmentation (including dictionary-based segmentation for languages such as Chinese, Japanese, and Thai). #109940 (Jimmy Aguilar Mena). - Added a
splitByRegexptokenizer for text indexes and thetokensfunction. It splits the input into tokens using a regular expression as the separator, for exampletokenizer = splitByRegexp('[^\p{L}\p{N}#+]+'), which allows preserving tokens containing special characters such asC++orC#that other tokenizers would break apart. #110002 (Jimmy Aguilar Mena). - The Keeper HTTP dashboard now includes a Cluster tab that shows Raft membership as a topology graph with health colors, lag, and priority, so you can see which nodes are healthy, lagging, or unreachable and open the leader’s dashboard directly. #111655 (yanglongwei).
- A new server configuration section,
create_union_system_log_tables, requests the creation and automatic maintenance ofall_...tables (e.g.system.all_query_log) that query the union of a system log table, its rotated versions and/or the same tables across all replicas of a cluster. Theremote,remoteSecure,clusterandclusterAllReplicastable functions now accept a trailingSETTINGSclause with the settings of theDistributedstorage they create, e.g.clusterAllReplicas('default', system.query_log, SETTINGS skip_unavailable_shards = 1). #112670 (Alexey Milovidov). - Add
nats_credentialssetting to the NATS table engine, allowing users to specify NATS credentials inline as a string (matching the payload of a.credsfile). #110733 (addshore). - Added the sort-based
IEJoinalgorithm for joins whoseONclause has two inequality comparisons (<,<=,>,>=) between the joined tables, enabled by addingie_jointo thejoin_algorithmsetting. Supported kinds areALL INNER/LEFT/RIGHT/FULL JOINandSEMI/ANTI LEFT/RIGHT JOIN. Previously such queries were executed as aCROSS JOINwith a filter (INNERonly), which is much slower on large tables. #109920 (Vladimir Cherkasov). - Added the aggregate function
gini, which computes the Gini coefficient of finite, non-negative numeric values, including grouped and distributed aggregations. #112280 (Amirreza Akhondi). #114643 (Groene AI). - Added the
HiveTextoutput format, which writes Apache HiveLazySimpleSerDetext. Fields are separated by\x01; rows by theformat_hive_text_rows_delimitersetting (default\n); and nestedArray,Map, andTuplevalues use Hive’s separator list. The output targets Hive’s defaultLazySimpleSerDeand is not symmetric with ClickHouse’sHiveTextinput for nested values or custom row delimiters. #107582 (Alexey Milovidov). - Added support for constant labels on the Prometheus metrics endpoint: a new
<labels>section inside<prometheus>adds the configured labels to every exposed metric, which helps distinguish multiple clusters scraped by the same Prometheus. Label values support standard config substitutions such asfrom_env. Closes #85969. #111672 (Valery Petrov). - Added the
always_fetch_mutated_partsetting. When enabled, a replica can download mutated parts from another replica instead of executing mutations locally. #113020 (Rory Shanks). - Added the aggregate function
mergedJSONPatchfor RFC 7396-style merge-patch aggregation overJSONvalues, including state-merge support andAggregatingMergeTreeusage. Users can aggregate aJSONcolumn using a timestamp or another ordering column as the sort key to compute the latest state. #108349 (larryluogit). - Added the
aiSimilarityfunction, which computes the semantic similarity between two texts using an embedding model. It returns aNullable(Float32)in[-1, 1], where1means the texts are identical, orNULLif an operand isNULL/empty or its embedding failed. #110777 (David Meng). - Add
restore_table_data,restore_access_entities, andrestore_functionsrestore settings for granular control over what gets restored. These can overridestructure_onlyfor individual categories — e.g.structure_only=true, restore_access_entities=truerestores table definitions and access entities without table data. #102402 (Nikita Fomichev). - The array subscript operator supports an array of integers as the index:
arr[indexes]returns the elements at all of the given positions, equivalently toarrayMap(i -> arr[i], indexes). #108371 (folly). - Add function
notHas, the negation ofhasfor arrays, maps, and JSON. When the haystack is a constant array,notHas(constant_array, x)is rewritten tox NOT IN constant_arraybyoptimize_rewrite_has_to_in(enabled by default), so it executes via a set lookup and can prune by the primary key index likeNOT IN. #109926 (Nihal Z. Miaji). - Functions
arrayElement(thevec[n]operator) andarraySlicenow work for theQBitdata type:qbit[n]returns the n-th vector element at full precision, andarraySlice(qbit, offset, length)returns a projection to a subset of dimensions. Both read only the bit planes of the stride groups they need, and slices aligned to stride-group boundaries reuse the stored streams without copying. This closes #109942. #109953 (Utkal Singh). - Support animated PNG in the
PNGoutput format. Atcolumn turns the result of a query into an animation, with the time scale oftset byoutput_format_image_time_multiplier_secondsandoutput_format_image_time_divisor_seconds, andoutput_format_image_streaming_animationto write the frames out as the query produces them instead of buffering them in memory. #112846 (Alexey Milovidov). - New function
aiRedactthat detects and redacts personally identifiable information (PII) in text using an LLM provider. Specify the categories to redact (e.g.['email', 'name']) or pass an empty array to use a default set of PII categories. Matched values are replaced with a token ([REDACTED]by default). #110464 (David Meng). - Add
aiFilterfunction that evaluates a natural-language condition against text with an LLM and returnsUInt8for use inWHERE,PREWHERE, andJOIN ... ON. #110594 (yanglongwei). - Support TLS/SSL connections to PostgreSQL for the
PostgreSQLtable engine, thepostgresqltable function, thePostgreSQLandMaterializedPostgreSQLdatabase engines, andPostgreSQLdictionaries:sslmodeplus the certificates and the key, given either as literal contents (sslrootcert_pem,sslcert_pem,sslkey_pem; masked like passwords) or as paths (sslrootcert,sslcert,sslkey; accepted only from a named collection defined in the server configuration file). #110615 (Alexey Milovidov). - ClickHouse server now has an introspection port. This is a native protocol TCP listener that starts before the server begins attaching tables and stops only after the tables’ detach completes. During these windows, an operator can connect to it with
clickhouse clientand run queries such asSHOW PROCESSLIST,SELECT * FROM system.stack_trace, orSYSTEM INSTRUMENT ADD 'QueryMetricLog::startQuery' SLEEP ENTRY 0.5. Additionally, the default value of theshutdown_wait_unfinishedserver setting is increased from 5 to 120 seconds. The previous default was smaller than the connection poll interval, so the server could force exit in the middle of shutdown instead of waiting for outstanding connections to finish. #110838 (Miсhael Stetsyuk). - Introduce emulated ZooKeeper metrics in Keeper
mntrcommand:zk_leader_uptime,zk_sum_election_time,zk_cnt_election_time,zk_sum_leader_unavailable_time,zk_cnt_leader_unavailable_time; Also introduce related leader-oriented metrics for Keeper only:KeeperLastLeaderElectionTime,KeeperLastLeaderUnavailableTime. #113334 (Maxim Orlovsky). - Support ALTER TABLE … MODIFY PROJECTION to change projection-level settings (e.g. index_granularity) of an existing projection without rebuilding it. The new settings apply lazily via merges. #113343 (Diego Gomes Tomé).
- Added a
finish_timecolumn tosystem.mutationsthat records when a mutation was completed. Unfinished mutations and mutations whose completion time is unknown report zero. #113474 (Nikita Mikhaylov). - Added a new
private previewfeature tier betweenexperimentalandbeta, so feature tiers are now orderedexperimental < private preview < beta < production. The server settingallow_feature_tiergains a level:0allows all tiers,1excludes experimental,2additionally excludes private preview, and3allows production settings only. Configurations that previously pinnedallow_feature_tier = 2to allow production settings only must now use3. Closes #113481. #113581 (Groene AI). - The built-in Web SQL UI (
/play) can now sort a result by its columns, filter it by their values, and page through it, without editing the query. Sorting arrows and a filter input appear in every column header, a selected cell offers the comparisons that fit its value, and a pager with an adjustable page size appears under a result that does not fit on one screen. It is all performed by the server, using theorder,filter,limitandpagequery-construction settings, so the whole result is shaped rather than the rows that happen to be displayed; the chosen sort, filters and page travel in the page URL, so a shared link reproduces the result. #115540 (Alexey Milovidov). chdigv26.8.1: ratatui, tmux panes, tmuxinator sessions, sharing logs with colors, feature tour. #115216 (Azat Khuzhin).
Experimental Feature
- Added an experimental Cascades cost-based optimizer for distributed query plans, enabled by
enable_cascades_optimizer = 1together withmake_distributed_plan = 1. It chooses between shuffle, broadcast, replicated, and local join strategies, two-phase, shuffle, and local aggregation, two-stage distributed top-N, and parallel and replicated reads by estimated cost, inserting exchange operators as needed. #86353 (Alexander Gololobov). - Added an experimental
MergeTreesettingenable_adaptive_codec_selection. When enabled, merges and mutations pick the smallest-output codec per block for columns that use the default codec. #111834 (Raufs Dunamalijevs). * Adaptive codec selection now compresses with each candidate codec at most once per block instead of measuring all candidates and then recompressing the winner. #113511 (Raufs Dunamalijevs). - The
clickhousebinary builds for WebAssembly (wasm64, via Emscripten), andclickhouse localruns queries, includingMergeTreetables, under Node.js ≥ 24 and in the browser. A newBuild (wasm64)CI job pins the build and the Node.js execution path (the browser path is not covered by CI yet) and provides the WebAssembly module as an artifact. #113404 (Alexey Milovidov). parallel_replicas_plan_basednow chooses the local/remote boundary by optimizing the query plan, can parallelize queries over views with aUNIONwithoutparallel_replicas_allow_view_over_mergetree, falls back to the local plan forIN (subquery)queries instead of failing, and now also distributes eligibleJOINs (INNER,LEFT,RIGHT, includingSEMI/ANTI). #111063 (Igor Nikonov). #112268 (Igor Nikonov). #112443 (Igor Nikonov).- Distributed query plans (
make_distributed_plan) now also support queries whose source is known at planning time to produce no rows, such as reads from an emptyMergeTreetable. #111941 (Groene AI). - Added the
use_projection_index_in_read_poolssetting, disabled by default. When enabled, ranges fully filtered out by a projection or skip index are dropped insideMergeTreeread pools before read tasks are created for them, instead of being skipped granule by granule during reading. This avoids creating read tasks and setting up readers for data that will not be read. #110291 (Nikolai Kochetov). #112296 (Anton Popov). - PromQL: fixed operations on instant vectors without tags, e.g.
vector(1) + vector(2),topk(1, vector(1)),label_replace(vector(1), ...)and binary operators withon(), which failed with a type error. #111872 (Valery Petrov). - PromQL: implemented the
changesandresetsfunctions. #112352 (Valery Petrov). - Report the error that cancelled a distributed query (
make_distributed_plan = 1) instead of a bareQUERY_WAS_CANCELLED. A failing worker task’s real error was previously visible only in the server log. #112590 (Alexander Gololobov). - When
make_distributed_plan = 1, ClickHouse now disables features that distributed query plans do not support yet instead of letting them fail later. Closes #109476. #112463 (alesapin). - Distributed query plans (
make_distributed_plan) now use lazy materialization forORDER BY ... LIMIT kqueries. #113111 (Shankar Iyer). - Support non-partitioned window functions (
OVER (ORDER BY ...)) in distributed query plans (make_distributed_plan). Previously any query with a window function failed becauseWindowStepcould not be serialized for remote execution; windows withPARTITION BYare still rejected for now. #109802 (Vighnesh Pathrikar). - Added the setting
use_query_condition_cache_for_top_k, which gates the query condition cache forORDER BY ... LIMIT n(TopK) queries. #111492 (Alexey Milovidov). The query condition cache is now enabled by default for queries that use theORDER BY <column> LIMIT n(TopK) optimization. It can be turned off again with the settinguse_query_condition_cache_for_top_k. #114539 (Alexey Milovidov). - Added static partition-to-shard affinity for
StorageKafka2via thekafka_partition_shard_numandkafka_shard_countsettings, allowing multiple ClickHouse shards to deterministically consume disjoint subsets of Kafka partitions. #108886 (johnjing). - Harden the experimental AI functions: deny insecure (
http) endpoints to remote hosts by default (new settingai_function_allow_insecure_endpoint), bound outbound API calls per query by default (ai_function_max_api_calls_per_querynow defaults to1000), and sanitize provider error responses written to the logs. #111286 (George Larionov). - PromQL:
quantilewith a quantile level outside [0, 1] now returns -Inf/+Inf/NaN like Prometheus instead of throwing an error, andhistogram_quantilenow ignores input series whoselelabel is missing or unparsable, like Prometheus. #111871 (Valery Petrov). - Allow multi-component identifiers in TimeSeries tables. #112799 (Vitaly Baranov).
- Added
TimeSeriessettingssamples_index_granularityandtags_inner_granularityto control the index granularity of inner tables. #113075 (Vitaly Baranov). - PromQL: added the
derivfunction and fixed a bug where its backing aggregate function returned values 1000x too small with millisecond-resolution timestamps. #112360 (Valery Petrov). - PromQL: reject invalid cross-delimiter escapes in strings and invalid Unicode surrogate code points. #113587 (Minh Vu). #113203 (Minh Vu).
- PromQL: preserve finite values when using modulo with an infinite divisor. #113746 (Minh Vu).
- PromQL: date/time functions
hour,minute,month,year,day_of_week,day_of_month,day_of_year, anddays_in_monthcan now be called without arguments, defaulting tovector(time())as in Prometheus. #111869 (Valery Petrov). - PromQL now supports the Prometheus HTTP API
lookback_deltaparameter for instant and range queries. #113971 (Minh Vu). - Distributed query plans (
make_distributed_plan) now supportIN (subquery)without rewriting it to aJOIN: the set is built once on the initiator and its values are shipped with the worker tasks. The forcedrewrite_in_to_joinoverride is removed; the rewrite remains available as an explicit setting. #113826 (Alexander Gololobov). - Streaming queries support watermarks. #106169 (Mikhail Artemenko).
- Added a read-through filesystem cache to the experimental
ReaderExecutorread path (use_reader_executor, disabled by default). #110029 (Sema Checherinda). - PromQL: implemented functions
clamp,clamp_min,clamp_max, andround. #111870 (Valery Petrov). - Correctly collect insert stats and queries through the Prometheus remote-write endpoint. #112825 (James Cunningham).
- PromQL aggregation operators now accept mixed letter casing, matching Prometheus. #114076 (Minh Vu).
- TimeSeries: store all tags in the
tagscolumn. #114300 (Vitaly Baranov). - Apply the read-in-order optimization to
ORDER BYqueries whenparallel_replicas_plan_basedis enabled: the sort is now shipped to the replicas and merged on the initiator, so each replica reads in the sorting key order. Also fixesUnknown function __topKFilterforORDER BYon a non-primary-key column with this setting enabled. #114315 (Igor Nikonov). - Reject literal line feeds in ordinary quoted PromQL strings. #114381 (Minh Vu).
- Fix duplicated
GROUP BYkeys in the partial aggregation strategy ofmake_distributed_plan, and allow this strategy for aggregations over a distributed read. #114523 (Alexander Gololobov). - Throw exception on violating the allowlist of hypothetical index types for WHATIF. #114646 (Yarik Briukhovetskyi).
- Restores quantized sub-column read for vector search (introduced in 26.7). #114763 (Shankar Iyer).
- The experimental
TimeSeriestable engine no longer applies theGorillacodec to auto-createdvaluecolumns of the samples inner table; they now default toCODEC(ZSTD(1)). Explicitly declared columns keep whatever codecs the user wrote. Thetimestampcolumn default is unchanged (CODEC(DoubleDelta, ZSTD(1))). #114790 (Nikita Mikhaylov). - A distributed plan query (
make_distributed_plan) now stops its upstream stages when aLIMITis satisfied, instead of computing the full result and discarding it. #114806 (Alexander Gololobov). - Added a userspace page cache tier to the experimental
ReaderExecutorread path (use_reader_executor, off by default). On a miss the executor now populates the userspace page cache and serves subsequent reads from it, zero-copy. #114890 (Sema Checherinda). - Support
ROLLUP,CUBE,GROUPING SETSand thegroupingfunction in queries executed withmake_distributed_plan = 1. #114950 (Alexander Gololobov). - Fix the error
Illegal type Decimal(18, 0) of argument of function toIntervalNanosecondwhen a PromQL query usesoffsetinside a range selector, e.g.rate(m[2m] offset 5m). #114997 (Nikita Mikhaylov). - A very large
distributed_plan_workers_numno longer makes the server abort with astd::length_errorwhen the experimentalmake_distributed_planandenable_cascades_optimizerare enabled. Such a node count is now rejected withINVALID_SETTING_VALUE. #115398 (Groene AI). - Support
GROUPING SETSaggregation in distributed plans built by the Cascades optimizer (make_distributed_plan = 1, enable_cascades_optimizer = 1). #115426 (Alexander Gololobov). TimeSeriestables can now keep a “recent samples” table: when the new engine settingrecent_samples_ttl_secondsis non-zero, the engine creates a TTL’d copy of the samples table (partitioned byrecent_samples_partition_by, by day by default) written on every insert, and PromQL queries whose time range fits in the TTL window automatically read from it, making alert/recording rules and short-range dashboards several times faster on large tables. The preference can be disabled with the new query-level settingtime_series_prefer_recent_samples_table. #115441 (Nikita Mikhaylov).- Implement SELECT query from TimeSeries. #115622 (Vitaly Baranov).
- Implement the
/api/v1/seriesendpoint of the Prometheus HTTP API forTimeSeriestables:match[]series selectors (repeated values are a union), an optionalstart/endtime range, and an optionallimitparameter. #115676 (Nikita Mikhaylov). - Distributed query plans (
make_distributed_plan) now stop idle upstream stages promptly after a satisfiedLIMIT: an idle exchange sink readsNoMoreDataNeededas soon as it arrives, and an idle exchange source notices its closed output and forwards the stop upstream. Previously such stages kept reading and computing data that nobody consumes. #115690 (Alexander Gololobov). - Automatic parallel replicas can now collect runtime statistics and enable parallel replicas for supported queries when
parallel_replicas_plan_basedis enabled. #115788 (Igor Nikonov). - Register an external recent samples table of a TimeSeries table as a referential dependency. #115944 (Groene AI).
Performance Improvement
- New adaptive algorithm for parallel
GROUP BY(controlled via settingenable_adaptive_aggregator, enabled by default): each thread aggregates into its own hash table until it holdsadaptive_aggregator_freeze_thresholdkeys and then freezes it, so frequent keys keep updating the small cache-resident tables with no coordination, while rare keys are routed by their hash into per-bucket backlogs and aggregated exactly once, inside the bucket-parallel merge. #111459 (Nihal Z. Miaji). - Reduced memory usage of
MergeTreetables with many data parts by sharing the schema-derived per-part metadata (column list, column descriptions, serializations, and columns substreams) across parts of a table instead of copying it into every part. The effect is largest for wide tables with many small parts. #109816 (Raúl Marín). - Optimize
GROUP BY ... ORDER BY ... LIMITandGROUP BY ... LIMITqueries by maintaining a bounded heap during aggregation to prune groups that cannot appear in the result, significantly reducing memory usage and execution time for high-cardinality grouping. Controlled by theenable_group_by_top_k_optimizationsetting. Based on the initial implementation by Dmitriy Terenichev (#78553). #96630 (Konstantin Bogdanov). - Reduce hash-table cell size for single-
Stringaggregation keys, improving string-heavyGROUP BYworkloads. The newenable_packed_string_keys_in_aggregationsetting is enabled by default; disabling it, or settingcompatibilitybelow26.8, restores the legacyStringHashTablemethod, which can still be faster for very low-cardinality aggregation with keys longer than 11 bytes. #110573 (Harikrishnan Prabakaran). #112089 (Harikrishnan Prabakaran). - Parallelize the final merge of single-level aggregation hash tables with the new
enable_parallel_single_level_mergesetting, enabled by default. This speeds upGROUP BYqueries whose per-thread hash tables stay below the two-level threshold but whose merge dominates the runtime. #110395 (Nihal Z. Miaji). - Improve performance of
DISTINCTwhen the input stream is sorted by a prefix of the distinct columns, for exampleSELECT DISTINCT a, b FROM table ORDER BY a. Such queries run up to 2.4 times faster. #110170 (Nihal Z. Miaji). - Speed up and reduce the memory usage of
DISTINCTqueries on partitionedMergeTreetables by keeping each partition’s rows within a single stream, so each stream’s preliminaryDISTINCTworks on a disjoint set of keys, instead of the same set of keys appearing in multiple preliminaryDISTINCTs. This applies when the partition expression is a deterministic function of theDISTINCTcolumns, and is gated by a cost heuristic on partition count and skew (which can be toggled by settingforce_distinct_partitions_independently, disabled by default). The same per-partition disjointness is propagated throughExpression,FilterandARRAY JOINsteps to the finalDISTINCT,LIMIT BYandGROUP BYconsumers so they can skip their merge too. Controlled by the new settingsallow_distinct_partitions_independently(enabled by default) andmax_number_of_partitions_for_independent_distinctto tune the heuristic. #108326 (Nihal Z. Miaji). - Optimized functions
uniq,uniqExact, anduniqHLL12in aggregation without key. #110150 (Anton Popov). - The
ParquetV3 reader can now skip whole row groups using the dictionary page, in addition to min/max statistics and bloom filters, for equality andINconditions when a column chunk is fully dictionary-encoded. Controlled by the newinput_format_parquet_dictionary_filter_push_downsetting. #106952 (Alexey Milovidov). #110567 (Alexey Milovidov). - Lazy materialization for reading
Parquetfiles from object storage, includingIcebergtables: forORDER BY ... LIMIT nqueries, the columns that are not needed for sorting and filtering are read only for thenrows that survive theLIMIT. On a 200 MBParquetfile onS3,SELECT k, s ... ORDER BY k DESC LIMIT 10reads 3.3 MB instead of 171 MB (51x less I/O, 8x faster). Controlled by the new settingquery_plan_optimize_lazy_materialization_for_object_storage(enabled by default, and also requiresquery_plan_optimize_lazy_materialization). #110970 (Alexey Milovidov). * Lazy materialization forORDER BY ... LIMIT nqueries (#110970) now also applies to local Parquet files read with thefiletable function and theFiletable engine: the columns that are not needed for sorting and filtering are read only for thenrows that survive theLIMIT. The second read of a surviving file fails close with the newFILE_CHANGED_DURING_READerror if the file was modified between the two passes. Controlled by the new settingquery_plan_optimize_lazy_materialization_for_file(enabled by default). Also fixes lazy materialization for object storage failing withNot found column or subcolumn ... in blockwhen a requested subcolumn (e.g. of aJSONcolumn) is deferred. #114262 (Alexey Milovidov). - Column statistics are now materialized on
INSERTby default when the table’s current active size plus the written block size is at most the newmaterialize_statistics_on_insert_max_table_sizesetting (default 25 GiB); the check is per written block, so a first bulk load into an empty table may still materialize statistics for each written block. This gives the cost-based join optimizer accurate estimates for freshly-loaded dimension tables and avoids pathological join orders (for example, TPC-H Q5 and Q8 no longer time out at scale factor 40), while large established fact tables keep materializing statistics during merges. #109454 (Alexey Milovidov). - Speed up window functions on partitioned
MergeTreetables by reading each partition through its own stream and evaluating the windows per partition, skipping the hash scatter that ordinarily reshuffles every row across threads before the window sort. This applies when the table partition expression is a deterministic function of the windowPARTITION BYcolumns and is gated by the same cost heuristic as per-partitionGROUP BY/DISTINCT(enough partitions relative tomax_threads, no dominant partition). Controlled by the new settingsallow_window_partitions_independently(enabled by default),force_window_partitions_independently, andmax_number_of_partitions_for_independent_window. #114783 (Nihal Z. Miaji). - Reduce memory usage when writing packed parts by streaming the final archive directly into the destination file instead of holding a second full copy in memory during part commit. #111995 (Alexey Milovidov).
- Added a new
join_algorithmvalueparallel_full_sorting_merge: for hash-compatible equality joins, it shards a full sorting merge join by the hash of the join keys into independent per-shard merge joins running on all threads. It keeps the low, streaming memory usage of a merge join while parallelizing it (in a benchmark, ~2.4x faster and ~3.3x less memory thanparallel_hash).ASOFjoins fall back to a singlefull_sorting_merge; hash-incompatible key types (floating-point,JSON,Object,Dynamic) skip only the hash-scatter rewrite and can still be sharded at the source by primary-key ranges whenquery_plan_join_shard_by_pk_rangesis enabled. The result is not ordered. #109005 (Alexey Milovidov). - Add GeoParquet spatial pruning at row-group and page levels to the
Parquetreader. Row-group pruning skips entire row groups whose bounding box does not overlap the query geometry. Page-level pruning uses thecovering.bboxcolumn index to skip irrelevant pages within row groups, and spatial predicate pushdown now also applies duringParquetrow reading. #104435 (Vasily Chekalkin). - Parquet filter push-down (row group pruning and column index) supports more type conversions:
DateTime64(x) <-> DateTime64(y),Decimal(x) <-> Decimal(y),Float32 <-> Float64. #110457 (Michael Kolupaev). - Reduce duplicated read requests on remote disks when mark ranges are fragmented, for example by primary or skip indexes. #113584 (Anton Popov).
- Speed up execution of
INover clustered (e.g. sorted by primary key) columns by reusing the previous row’s result for equal consecutive rows. #114853 (Nikita Mikhaylov). - An aggregation without
GROUP BYkeys no longer fans its single-row output out tomax_threadsstreams, so queries whose plan continues after such an aggregation get a much smaller pipeline (fewer processors to create, schedule and profile) without losing any parallelism. #115170 (Nikita Mikhaylov). - Keeper now reads changelog entries with less lock contention: catch-up reads plan under a shared lock and do disk I/O lock-free, and both follower catch-up and the commit path can pre-decode entries in a background thread pool, reducing redundant disk reads and CPU decoding on the leader. #108473 (Antonio Andelic).
- Speed up Keeper startup by reading multiple changelog files concurrently instead of serially, controlled by new settings
log_startup_read_max_streamsandlog_startup_read_buffer_size. #109881 (Antonio Andelic). - Add a new
bucketedschema type forsystem.metric_log, which stores all metrics in a singleMap(Enum16(...), Int64)column using the bucketedMapserialization with 128 buckets, plus a per-metricALIAScolumn for compatibility: the table consists of a few columns instead of thousands, zero values are not stored, and reading a single metric reads only one of the 128 buckets. In addition, aMapwithEnumkeys can now be indexed by the string name of the enum value, e.g.map['name']. #115380 (Alexey Milovidov). - Added a query plan optimization that pushes volume-reducing functions (
length,lengthUTF8,empty,notEmpty) below theSortingandFiltersteps, replacing the wideString/FixedStringargument with the fixed-size result, so it is neither buffered by a sort nor copied by a filter. Controlled by the new settingquery_plan_push_down_volume_reducing_functions, enabled by default. #106199 (Peng). - Enable
read_in_order_use_virtual_rowby default. When reading in order of the primary key (e.g.ORDER BY primary_key LIMIT n) over a table with many parts, only the parts that can actually contribute to the result are read (plus a read-ahead window of at mostmax_threadsparts that keeps reading parallel), which significantly reduces peak memory consumption. #106215 (Alexey Milovidov). - Aggregation queries without aggregate functions now use
HashSet-based methods instead ofHashMap(for supported key types). Speedups up to 1.8x times were observed. #108862 (Nikita Taranov). - Avoid
JOINruntime-filter overhead when the probe side is estimated to be small. The threshold is controlled by the newjoin_runtime_filter_min_probe_rowssetting (default1000). #104860 (Vladimir Cherkasov). - Queries with predicates like
nullIf(key, sentinel) = constcan now use primary-key, partition, and skip-index pruning. #107308 (Aditya Kumar). - Added the
jemalloc_merge_tree_arenasserver setting to control dedicated jemalloc arena(s) forMergeTreepart and table metadata. On many-core servers, a per-CPU pool can reduce allocator lock contention between concurrent merges, and the dedicated arena now only holds long-lived metadata. #109490 (Raúl Marín). - Sped up ZSTD decompression on
x86_64for columns with small match offsets, such as fixed-width integer columns, by vectorizing short-offset overlapping copies with SSSE3pshufb. For example, decompression of aUInt64column is up to ~1.2x faster on AMD Zen 5. #110909 (Konstantin Bogdanov). - Speed up
groupUniqArrayfor numeric types by up to 3x by using CRC32 hashing, as inuniqExact, and by inlining per-row insertion. #110917 (Manuel). - Faster
estimateCompressionRatiowith theNONEcodec. #111107 (Raufs Dunamalijevs). - Lowered the default
max_snapshot_commit_thread_pool_sizeto16, matchingbackup_threads, to reduce CFS throttling when committing snapshots for tables with many parts. #111417 (Han Fei). - Reduce CPU usage when committing snapshots for tables with huge numbers of files. #112297 (Han Fei).
- Skip async-insert deduplication hash prewarming when deduplication is disabled. #111549 (Sema Checherinda).
- A
JOINwhoseONcondition is always false, for exampleON 1 = 2,ON NULL, ora.t = 'A' AND a.t = 'B', no longer reads the non-contributing side. Controlled by thequery_plan_short_circuit_constant_false_joinsetting (enabled by default). #110234 (Groene AI). - Speed up reading of
Icebergtables by prefetching the next manifest file while the current manifest is being parsed, overlapping I/O with CPU work. #108543 (Asya Shneerson). - Queries with
FINALthat read in primary-key order with a smallLIMITno longer usesplit_intersecting_parts_ranges_into_layers_final. #110431 (Nikolai Kochetov). - Improve performance of
RIGHTandFULL JOINwith theparallel_hashalgorithm when the right side containsNULLjoin keys or rows filtered by theONexpression, by avoiding null-map rebuilding. #111258 (Hechem Selmi). - Speed up
countSubstringsCaseInsensitiveUTF8by fixing quadratic complexity that could make the function take minutes on a haystack of a few megabytes with many matches. #112003 (Groene AI). - The Prometheus query API (
/api/v1/query,/api/v1/query_range) of the experimentalTimeSeriesengine now executes queries in parallel instead of on a single thread. #112108 (Nikita Mikhaylov). - Auto-created
timestampandvaluecolumns of theTimeSeriessamples inner table now default toCODEC(DoubleDelta, ZSTD(1))andCODEC(Gorilla, ZSTD(1))respectively. #112110 (Nikita Mikhaylov). - Fix a performance regression in
system.query_logingestion. Building theSettingsandasynchronous_read_countersmap columns was about six times slower than before, which could makeSYSTEM FLUSH LOGS query_logexceed its 180-second timeout on servers that log many queries with many changed settings. Closes #112191. #112210 (Groene AI). - Improve performance of RIGHT and FULL hash JOIN with multiple
ORdisjuncts in the ON section, and of RIGHT/FULL JOIN with residual (inequality) conditions. #111590 (Hechem Selmi). - Reduce memory usage of
UNLOCK SNAPSHOTby not loading per-data-part metadata that the unlock path does not use, avoiding out-of-memory for snapshots with a very large number of parts. #111849 (Julia Kartseva). - Restore memory pre-allocation for dynamic paths of a
JSONcolumn during asynchronousINSERTflushes, avoiding repeated reallocations while batched rows are appended. #112222 (Groene AI). - Re-enable the consecutive-keys optimization for
TTL ... GROUP BYaggregation during merges. It had been accidentally disabled on that path, so results stayed correct but merges did more work than necessary. #112314 (Groene AI). - Speed up reading
Nestedcolumns from binary-encoded types such asNativeandRowBinarywheninput_format_binary_decode_types_in_binary_formatis enabled, and report malformed nestedTupletype names as a syntax error instead of spending exponential time parsing them. #112560 (Alexey Milovidov). - Improved performance of squashing and merging
DynamicandObjectcolumns with many dynamic variants or JSON paths. #110583 (Christoph Viebig). - Speed up
minandmaxon 128-bit and 256-bit types (Int128,UInt128,Int256,UInt256,Decimal128,Decimal256). Up to 1.8x faster for wide integers and up to 3.4x faster for wide decimals. #111965 (Manuel). - Enabled by default (and promoted to beta) two on-disk features: 1)
packed_skip_index_max_bytes = '1M': skip-index substreams up to 1 MiB are now written into a singleskp_idx.packedarchive per part, reducing object count and write requests on object storage. Compatibility: only newly written parts are affected and they stay fully readable on older versions; versions before 26.6 simply do not use the packed indices for pruning (they are treated as not materialized). Setpacked_skip_index_max_bytes = 0to keep the standalone per-file layout. 2)compute_exact_num_defaults_for_sparse_columnsplusoptimize_trivial_count_with_sparsity_filter: exact per-columnnum_defaultscounters are persisted and used to answerSELECT count() FROM t WHERE <pred>without a data scan when the predicate splits rows into defaults vs non-defaults. Compatibility: theexact_num_defaultsflag inserialization.jsonis ignored by older versions, so parts remain fully readable after a downgrade; the count rewrite only applies to parts that carry exact counters, so results stay correct on tables with mixed parts. #111816 (Raúl Marín). - Add optional caching for tokens missing from text indexes. #112742 (Rory Shanks).
- Fixed quadratic reallocation when replicating an
Arraywhose elements holdJSONvalues in shared data, for example a constantArray(JSON)passed to an aggregate function. Such queries copied a number of bytes that grew quadratically with the row count. #112897 (Groene AI). - Use the primary key index for
pointInPolygonwhen the point argument is a whole key column of typePoint(or anotherTupleof two numeric elements), e.g.pointInPolygon(coord, [...])for a table ordered bycoord. Previously only thepointInPolygon((x, y), [...])form with two scalar key columns was analyzed. Closes #54805. #112956 (Alexey Milovidov). - Skip the data-reading step entirely for
TTLDropmerges to reduce memory usage, especially for read and prefetch buffers. Closes #105639. #105859 (Pavel Kruglov). - Reduce memory allocations when reading backup metadata by moving file entries into in-memory maps instead of copying them. #111718 (Julia Kartseva).
- Use the text index when its expression contains an empty-string comparison such as
arrayFilter(s -> s != '', ...), even whenoptimize_empty_string_comparisons = 1rewrites it tonotEmpty. Closes #111788. #112115 (Jimmy Aguilar Mena). - Restore query condition cache pruning after a
lightweight DELETE: repeated selective queries over a table that had ever been touched by alightweight DELETEno longer fall back to reading every mark. #112947 (Nikita Fomichev). - Higher-order functions no longer physically copy captured columns for every array element when
enable_lazy_columns_replicationis enabled, reducing memory usage and copying time for lambdas that capture large columns. #111581 (Diego Gomes Tomé). - Fixed a ~1.5x performance regression introduced in 26.5 in
GROUP BYoverDynamickeys andJSONpath subcolumns. #112316 (Utkal Singh). text_index_posting_list_apply_modenow defaults tolazy, so text index queries decode posting lists on demand at packed-block granularity with a cursor instead of eagerly materializing them into bitmaps for text indexes withposting_list_codecset. #113521 (Anton Popov).- Speed up PromQL queries over
TimeSeriestables:timeSeriesIdToGroupnow reuses the previous row’s group when consecutive rows carry the same series id, skipping the per-row id serialization and hash lookup. #113580 (Nikita Mikhaylov). - PromQL aggregation operators
topk,bottomk, andlimitknow use a streaming, parallel execution plan with bounded memory instead of collecting all series into a single row. Queries over high-cardinality metrics that previously failed withMEMORY_LIMIT_EXCEEDEDnow run in bounded memory. #113656 (Nikita Mikhaylov). #114409 (Alexey Milovidov). - Speed up division of 256-bit integers (
Int256,UInt256, andDecimal256), affectingintDiv,modulo,Decimal256arithmetic, and conversion of these types to text. #112477 (Konstantin Bogdanov). - Improve
MergeTreeread performance forJSONsubcolumns by reusing resolved subcolumn metadata during required conversions. #113008 (Rory Shanks). - Speed up building text and bloom-filter-based skip indexes with the
sparseGramstokenizer. #110541 (UnamedRus). - Snapshot creation now uses a dedicated thread pool, so a heavy concurrent
BACKUPno longer starves it. #113509 (Han Fei). - Evaluate PromQL subexpressions shared by multiple plan steps (the
topk/bottomk/limitkoperand, the left side ofor) once instead of twice: the SQL generated from PromQL now materializes shared subqueries. This removes a duplicated scan of the samples table;topkoverrategets ~2x faster cold, and kubernetes-mixin rule queries improve by 10-29%. #113772 (Nikita Mikhaylov). - You can now enable early short-circuit folding for builtin
andandorduring analysis with theenable_function_early_short_circuitsetting. This can skip executing dead single-rowcount()scalar subqueries while preserving normal type inference and semantic validation. Resolves #83017. #83505 (fhw12345). - Combine I/O cost with selectivity in
PREWHEREcondition ordering. This fixes a performance regression ofPREWHEREexecution in some cases introduced after #101275. Part of #110462. #110695 (Pavel Kruglov). - Improved the performance of
levenshteinDistance(andeditDistance) for medium-length strings on ARM by avoiding per-row heap allocations in the blocked Myers code path. #108185 (Groene AI). - Add the
merge_use_batch_sorting_queueMergeTreesetting to optionally use the batch sorting queue for ordinaryMergeTreemerges, reducing CPU and wall-clock time for merge workloads where sorted merging is a significant cost. #108468 (Rory Shanks). - Added the
merge_tree_min_bytes_per_read_streamsetting to reduce excessive read streams and pipeline overhead for ordinary local unordered narrow-columnMergeTreescans on high core-count servers. #109035 (Jiebin Sun). - Speed up function
toStartOfInterval(aliasestime_bucket,date_bin) by up to 5x forSECOND,MINUTEandHOURintervals. #109729 (Manuel). - The native protocol now sends
Stringcolumns as a separate stream of cumulative byte offsets (the same layoutArrayuses for its offsets) followed by the concatenated data, instead of a per-value varint length prefix, once both peers are on protocol revision 54489 or newer. A client can then readStringcolumns with exact buffer preallocation and a single bulk copy, about 4 times faster than the per-value layout. Old clients and servers are unaffected: the layout is negotiated through the protocol revision. The same layout is available in theNativeandBuffersformats through the new settingsoutput_format_native_write_string_with_size_stream/input_format_native_read_string_with_size_stream(off by default, so the formats stay portable). #110320 (vahid-sohrabloo). - Avoid eager JSON serialization of Iceberg manifest entries when iceberg_metadata_log_level is below the call site’s threshold. #110437 (Andy Bradshaw).
- Improve full sorting merge join performance up to 1.5-3x times on sparse scenarios. #111200 (Vladimir Cherkasov).
- Improve efficiency of minmax and basic column statistics for floating point columns. #111221 (Christoph Viebig).
- Enable
join_runtime_filter_from_fixed_hash_tablewhen the probe and build join key types differ (for example, a Nullable probe key with a non-Nullable build key). #111244 (Hechem Selmi). - Returns
COUNT()queries directly from the text index cardinality metadata. #111494 (Elmi Ahmadov). - Sped up row-wise hashing of JSON/
Objectcolumn values stored in shared data (used e.g. byuniq/uniqExactover a JSON column and by hashedGROUP BY/DISTINCTkeys) by avoiding a per-valueColumnDynamicreconstruction. Hash values are unchanged. #111501 (Valery Petrov). - Functions
mapContainsKeyLike,mapContainsValueLike,mapExtractKeyLike, andmapExtractValueLikewith a non-constant pattern use less memory and time when enable_lazy_columns_replication is enabled. The pattern is no longer eagerly copied per map entry at capture time; the copy is deferred to the execution of the internal lambda and is freed sooner, so one fewer expanded copy of the pattern exists at peak. #111749 (Diego Gomes Tomé). - Speed up sorting and other comparison-based operations over
JSONcolumns whose paths are stored in shared data. Previously each value comparison materialized a temporaryDynamiccolumn and ran a full binary deserialization for both sides, makingORDER BYover such columns pathologically slow. #111894 (Groene AI). clickhouse-clientno longer pings the server before every query, which removes a network round trip per query. It also no longer re-establishes the connection - silently starting a new session, and so losing temporary tables, the current database and session settings - just because the server was too slow to answer a ping. #111990 (Alexey Milovidov).- Use the transitive conditions optimization more wisely: the additional filter created by transitivity is now used only for index analysis where the whole filter cannot be applied. See the
optimize_and_compare_chainsetting. #112076 (Yarik Briukhovetskyi). - Added two settings,
shrink_over_allocated_columns_min_waste_ratioandshrink_over_allocated_columns_min_waste_bytes, that make INSERTs shrink over-allocated columns (whose reserved memory exceeds used memory due to power-of-two growth of variable-length columns) to fit before materialization and part writing, reducing peak memory usage. Disabled by default.. #112161 (Pavel Kruglov). - Lazy column replication for
ARRAY JOINis no longer lost when a query plan is serialized. Withserialize_query_plan = 1, the node executing a remote plan fragment used to ignoreenable_lazy_columns_replicationand always materialize every replicated copy, even though the setting defaults to enabled. #112330 (Groene AI). - Formatting
Decimalvalues as text is much faster — up to 190 times for aDecimal256with a large scale, and about 1.6 times for aDecimal64. On processors with AVX-512 IFMA, converting 64-bit integers to text is about 1.4 times faster. Also fixed the rounding oftoDecimalString, which dropped a carry out of the fractional part:toDecimalString(toDecimal64('9.995', 3), 2)returned9.00and now returns10.00. #112457 (Konstantin Bogdanov). - A
WHEREequality is now merged into theJOINcondition when its operands have different types but a common supertype, such asInt32andNullable(Int32). This allows a CROSS join to be converted to an INNER Join. #112630 (Hechem Selmi). - Queries on Iceberg tables with many delete files now start faster. ClickHouse reads and decodes the delete manifest files concurrently instead of one at a time, so their storage reads overlap. The new setting
iceberg_delete_manifest_decode_concurrency(default4) controls how many are decoded at the same time. #112679 (Asya Shneerson). - Asynchronous logging now uses a bounded lock-free queue: threads writing log messages never block on a mutex or wake up the logging threads. #112803 (Alexey Milovidov).
randomHadamardTransformof a constant vector is now evaluated once instead of once per row. This speeds up vector search queries that rotate the query vector withrandomHadamardTransformbefore comparing it against aQBitcolumn. #112921 (Alexey Milovidov).- Restores set sharing between the part tasks of one mutation filtering on
IN (subquery)over a primary key column.enable_sharing_sets_for_mutationsis on by default, but the set built for primary key analysis stopped participating in the shared cache, so a table with N parts materialized the same set N times. #112941 (Groene AI). - Fixed cubic complexity of query planning for a JOIN with a
Mergetable over many tables with different structures. Such queries could previously spend minutes in query planning without responding tomax_execution_timeorKILL QUERY. #113140 (Alexey Milovidov). - The bucket-region cache of the
S3client now also works for data lake catalogs; previously every request to them resolved the region again. #113330 (Konstantin Vedernikov). - Fixed a performance regression where an aggregation without
GROUP BYkeys serialized its whole input plan subtree, including the full contents of constant-folded literals, on every execution to compute a hash-table-size cache key it can never use. A query such asSELECT quantileMerge(arrayJoin(arrayMap(x -> state, range(5000000))))spent about 63 ms per execution in query-plan optimization and now spends 0.15 ms. #113333 (Groene AI). - Add opt-in Parquet serialization of UInt128/UInt256/Int128/Int256 as DECIMAL to enable row group and page pruning. #113347 (Ivan Babrou).
- Speed up query planning when
uniq_v2column statistics are used. The estimated number of distinct values is now cached instead of being recomputed on every request, which query planning issues many times per query. (issue #113038). #113357 (Groene AI). - Do not prefetch unneeded substreams when reading a whole JSON path from advanced shared data. #113380 (Pavel Kruglov).
- Filter pushdown now works for
Tuplesubcolumns in Parquet and ORC files. A predicate such asWHERE tup.1 = 555555overfile,s3orurlnow prunes row groups and row index strides using the tuple element’s own statistics instead of reading the whole file. #113383 (Groene AI). - Replaced the per-bucket hash map inside the
timeSeries*ToGridaggregate functions with a flat sorted array of samples: sample ingestion becomes an O(1) append for in-order inputs (the overwhelmingly common case) and the per-bucket copy-and-sort at finalization is gone. #113681 (Nikita Mikhaylov). - Improve PromQL query performance over the TimeSeries engine: the internal selector SQL now reads the samples-table primary-key columns directly (without no-op casts) and checks the timestamp range before the series-id set, which makes cold selector-heavy queries 30-44% faster. #113768 (Nikita Mikhaylov).
- Use typed id maps in the time-series tags collector. #113839 (Vitaly Baranov).
- Skip the redundant sortedness scan when writing MergeTree parts whose sorting keys are all constant. #113899 (Perfloop Agent).
- PromQL selectors that match all series of one metric now filter the samples table of a
TimeSeriestable with a continuous primary-key range onidduring index analysis instead of a largeid IN <set>condition, when the id layout is a two-component tuple with the canonical id generator. Removes the dominant single-threaded index-analysis cost of selector-heavy PromQL queries: up to −45% cold latency on dashboard and rule query shapes, −11% cold geomean over the full suite on a 62-billion-sample table. #114131 (Nikita Mikhaylov). - Speed up vectorized TimeSeries tag transformations by replacing hash-based remapping with direct indexing when tag-group IDs occupy a compact range. #114244 (Minh Vu).
- The Prometheus HTTP API endpoints
/api/v1/queryand/api/v1/query_rangenow evaluate a PromQL subquery shared by several plan steps once, as theprometheusQueryandprometheusQueryRangetable functions already did. Previously a request made withenable_analyzer = 0, or by a user whose profile sets it, rescanned the shared subquery once per referencing step. #114261 (Groene AI). - 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 (Nikita Taranov). - Parsing an HTTP request that carries many query parameters or headers with the same name (for example thousands of repeated
role=parameters) no longer takes quadratic time. #114410 (James). - Fixed a regression in 26.7: for a
MergeTreetable ordered bytoUnixTimestamp(or another integer conversion) of aDateTime64column, a plain range filter on that column no longer used the primary key and read all granules of the matched parts. Additionally, a filter liketoInt64(ts) >= cover a table ordered by the rawDateTime64column now uses the primary key. #114413 (Alexey Milovidov). - The heavy consistency check in
ColumnArrayis now performed only in debug builds. #114469 (Anton Popov). - Do not merge-sort a distributed gather whose sort description is all-constant. #114626 (Groene AI).
- Speed up set building for
IN (subquery)on partitionedMergeTreetables by keeping each partition’s rows within a single stream and deduplicating each stream independently, so the single set-filling transform — previously hashing every row serially — only sees unique rows. This applies when the partition expression is a deterministic function of the subquery’s output columns. The optimization is not applied when the largest partition holds more than twice the rows of the average partition; the new settingforce_creating_set_partitions_independently(disabled by default) bypasses this check. Controlled by the new settingallow_creating_set_partitions_independently(enabled by default). #114645 (Nihal Z. Miaji). - Parallelize the single-level to two-level conversion of per-thread aggregation states before merging. This fixes a 2-3x regression of short
GROUP BYqueries with heavy aggregate states (e.g.COUNT(DISTINCT ...), ClickBench Q10/Q11) on machines with very many cores, introduced in 26.7 development builds when the aggregation memory accounting was made accurate. #114691 (Alexey Milovidov). - Speed up the
timeSeries*ToGridaggregate functions: per-sample bucket math now avoids Int128 division, and consecutive samples in the same bucket skip the hash-map lookup. #114889 (Nikita Mikhaylov). - Appending to a system log queue no longer deep-copies the whole queue when it grows. #115030 (Groene AI).
- Process samples of the
timeSeries*ToGridaggregate functions in runs of consecutive samples falling into one grid bucket, speeding up the sample-ingestion stage oftimeSeriesRateToGridand related functions by 1.2-2x on sorted time series data. #115041 (Nikita Mikhaylov). - Use compact presence masks for PromQL set operators. #115224 (Minh Vu).
- Faster evaluation of PromQL instant queries: the
timeSeries*ToGridaggregate functions use the vectorized sample-classification path for single-point grids, andtimeSeriesIdToGroupfills its result column directly. #115267 (Nikita Mikhaylov). - A
JOINwhoseONsection has severalOR-ed equalities no longer materializes the right-hand key columns that the query does not select. #115465 (Nikita Taranov). - Naming a
DateTimeorDateTime64type no longer builds a UTC time zone lookup table that nothing reads, which makes constructing these types — and therefore starting upclickhouse localandclickhouse client— faster. #115488 (Konstantin Bogdanov). - Attaching the system tables no longer copies each table’s metadata, including its full column description, twice just to set the table comment. #115490 (Konstantin Bogdanov).
- The client hostname is now resolved when it is first reported instead of on every
clickhouse clientandclickhouse localinvocation. #115491 (Konstantin Bogdanov). - Fixed quadratic time when the functions
h3kRing,h3ToChildren,h3PolygonToCellsandh3PolygonToCellsWithContainmentbuild their result over many rows. A query over 196 000 rows spent 838 seconds copying memory in a CI stress run; it now takes about 5 seconds. #115773 (Groene AI). - Speed up duplicate-series checks for all-zero PromQL condition vectors. #115822 (Minh Vu).
- Speeds up
GROUP BYwithout aggregate functions overString,FixedStringandLowCardinalitykeys: the query no longer rewrites an unused placeholder into the hash table for every row, only for the rows that add a new key. #115834 (Nikita Taranov). - Speed up
toUTCTimestamp/to_utc_timestampandfromUTCTimestamp/from_utc_timestamponDateTime64arguments, restoring the throughput they had before the overflow fix in #109738. Results are unchanged. Closes #115802. #115838 (Groene AI). - Reduced memory usage and query-plan optimization time for keyed aggregations over large constant-folded literals. The aggregation hash-table-statistics cache key is now hashed as it is serialized instead of being accumulated in memory first, so a plan carrying a large literal no longer holds a copy of it during optimization. For an 80 MB literal, peak memory drops by about 250 MB and optimization time by about 2.5x. The computed key is unchanged. #115847 (Groene AI).
Improvement
- Outgoing OpenAI-format HTTP requests are now tagged with the SQL name of the calling AI function for upstream endpoint identification. #110449 (George Larionov).
- Reduce cancellation latency for positive forms of
LIMIT BY:KILL QUERYand Ctrl+C now interrupt within a single chunk instead of waiting for the whole step to finish. #106070 (Roman Vasin). - When an
INSERTfails because a materialized view’sTOtarget table rejects the write while the insert pipeline is being built, the error message now names the materialized view and its target table instead of only reporting the bare storage error. #107234 (Groene AI). - With
input_format_protobuf_oneof_presence, ClickHouse no longer requires theoneofpresence enum to list exactly the tags declared in the Protobuf schema: extra tags without matching columns in the target table are now allowed, which makes schema changes easier. #109174 (Ilya Golshtein). - The transposed distance functions over
QBit(L2DistanceTransposed,cosineDistanceTransposed,dotProductTransposed, and their quantized variants) now accept a reference vector longer than the number of searched dimensions, ignoring the extra trailing elements. This allows reusing a full-size query vector for a reduced-dimension Matryoshka search without slicing it first. #109388 (Alexey Milovidov). - The
basicstatisticsNullCountsub-statistic is renamed toDefaultCountand now counts rows equal to the column type’s default value, not onlyNULLrows ofNullablecolumns. #109977 (Han Fei). - Support concurrent writes to
Icebergtables on a local disk:LocalObjectStoragenow implements conditional writes, so the compare-and-swap that publishes a new snapshot throughversion-hint.textworks there and concurrent writers cannot lose each other’s updates. #112556 (Alexey Milovidov). ALTER TABLE ... MOVE/REPLACE PARTITIONbetween twoMergeTreetables with incompatible granularity now throwsBAD_ARGUMENTSinstead ofLOGICAL_ERROR. #110535 (Groene AI).- The
Valuesformat no longer records false parse errors insystem.errorsandsystem.error_logwhen streaming parsing successfully falls back to SQL expression parsing. #111141 (Pablo Marcos). - Added the
DuplicationDataHashComputationsProfileEvent, which counts column-wise data-hash computations performed while deduplicatingINSERTblocks into*MergeTreetables. #111173 (Valery Petrov). - Highlight the
./clickhouseandsudo ./clickhouse installcommands in the universal installation script output. #111514 (Alexey Milovidov). - Cartesian joins and analyzer-planned constant-predicate joins no longer fail because of an incompatible
join_algorithmsetting when the analyzer is used. #108289 (János Benjamin Antal). bitmaskToArrayandbitmaskToListnow supportInt128,UInt128,Int256, andUInt256arguments.bitPositionsToArrayis also faster for big-integer arguments because it now scales with the number of set bits rather than the highest set-bit position. #110743 (Manuel).- Fix a crash in JIT-compiled expressions on native from-source macOS/aarch64 builds by using the correct LLVM host triple for the host OS. #111591 (Raúl Marín).
- Fix
JSON_EXISTS,JSON_VALUE, andJSON_QUERYonDynamicinput when tuple path arguments containLowCardinalityelements, avoidingLOGICAL_ERRORexceptions. Closes #110345. #109944 (Groene AI). - Corrupt
ORCfiles whose type tree declares more columns than the stripe footer now fail schema inference withCANNOT_EXTRACT_TABLE_STRUCTUREinstead of aborting in debug/sanitizer builds. #110967 (Groene AI). - Rotated system log tables, such as
system.metric_log, can now be markedtable_readonlyeven when their metadata exceedsmax_query_size, so rotation no longer logsQUERY_IS_TOO_LARGEand continues normally. #111703 (Alexey Milovidov). - In Play, added a button to close all tabs except the current one. #111835 (Mikhail Artemenko). Fixed keyboard focus after activating it with Enter or Space when the button hides itself. #111899 (Alexey Milovidov).
- In Play, holding
Ctrl(Cmdon Mac) while hovering over a table cell whose value is an image URL now shows an image preview. #109347 (Alexey Milovidov). - On Linux, ClickHouse now adds a
system.warningsentry at startup whenrseqis unavailable, because per-CPU profile counters then fall back to a slowersched_getcpupath. #109283 (Azat Khuzhin). COUNT(*)over thefiletable function no longer throws an exception when schema inference wraps columns inNullable. Closes #102044. #102509 (Rory Shanks).- Functions
L1Normalize,L2Normalize,LinfNormalize, andLpNormalize(and their aliases) now work forArrayarguments, not onlyTuplearguments, consistently withL2Normand the distance functions. #110052 (Alexey Milovidov). - Removed the legacy Apache Arrow-based
ORCreader. TheORCinput format now always uses the native ClickHouse decoder, which was already the default. Theinput_format_orc_use_fast_decodersetting is obsolete and has no effect. #110074 (Alexey Milovidov). - Made commonly used
clickhouse-clientarguments configurable from XML (<hints/>,<highlight/>,<echo/>,<echo_query_id/>,<echo_formatted/>,<print-profile-events/>), and preserved client-config values when the corresponding defaulted CLI flags are omitted, for settings such ashistory_max_entries,suggestion_limit,progress,progress-table,enable_progress_table_toggle,print-memory-to-stderr,chime-threshold-seconds, andprofile-events-delay-ms. #110607 (Larry Snizek). - Added the
analyzer_compatibility_apply_final_to_all_joined_tablessetting to restore the old behavior whereFINALon the left-most table of aJOINalso applies 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 (Nikita Fomichev). - In Play, the
+(new tab) button now renders at the correct height in Firefox. #109524 (Alexey Milovidov). - A nested correlated
EXISTSsubquery that references a column from a scope beyond its immediate outer query now fails withNOT_IMPLEMENTEDinstead of the internalNOT_FOUND_COLUMN_IN_BLOCKexception. #110310 (Groene AI). - Formatting an
EXECUTE ASquery after AST rewrites no longer throws a client-side exception, for example in the AST fuzzer. #111725 (Groene AI). - Improve
DESCRIBEquery support for parameterized views, and support parameterized views in scalar expressions in the new analyzer. Closes #66307. Closes #69598. #68978 (Dmitry Novik). - Malformed
CREATE INDEXandCREATE HYPOTHETICAL INDEXexpressions that cannot survive a format-parse-format round trip now report an exception instead of hitting anInconsistent AST formattinglogical error in debug and sanitizer builds. #109175 (Groene AI). - Web UI: fix the user/password field staying red even when the credentials are correct and the server is reachable, and re-check credentials after editing the connection so a correct value turns green. #109414 (Alexey Milovidov).
- Added the
text_index_max_processed_tokens_before_flushandtext_index_max_memory_usage_before_flushsettings to control when text index builders flush temporary segments. #111573 (Rory Shanks). - Added the
system_cache_extensionssetting to control which file extensions are stored in the system cache whenuse_split_cacheis enabled. #111575 (Kirill). - Error messages on musl-based builds now show the human-readable
strerrortext instead of an empty or numeric value such asstrerror: 0. #111620 (Konstantin Bogdanov). - The effective named collections storage type is now available as
named_collections_storage.typeinsystem.server_settingsand viagetServerSetting('named_collections_storage_type'). #111806 (Pablo Marcos). - Relaxes an overly strict permutation size check in
ColumnReplicated::permuteso that it follows the generalIColumn::permutecontract, which allows a permutation shorter than the column when a limit is set. #109897 (Groene AI). - Improve planning of streaming queries by unifying the internal streaming read plan, which avoids double-optimizing direct text-index reads. #111821 (Mikhail Artemenko).
- Web UI: the gap between the
Run oneandRun allbuttons now matches the left margin before the first button. #111988 (Alexey Milovidov). - Memory reservation scheduling (experimental) no longer evicts an allocation when a pending memory release would free the room needed by an over-limit reservation increase: the eviction decision now waits for in-flight decreases to be applied, avoiding unnecessary query kills under memory pressure. #112299 (Sergei Trifonov).
- Iceberg v2 requires
sequence_numberin manifest files, but other engines such as BigQuery can write manifest files without it. ClickHouse can now read such tables. #112431 (Konstantin Vedernikov). - Show warning when statistics for join reordering are missing. #107666 (Vladimir Cherkasov).
- Added MySQL-compatibility columns to
INFORMATION_SCHEMAviews:SCHEMATA.DEFAULT_COLLATION_NAMEandDEFAULT_ENCRYPTION;TABLES.ENGINEand related MySQL columns; andCOLUMNS.COLUMN_KEY,PRIVILEGES,GENERATION_EXPRESSION,SRS_ID. This lets MySQL-aware clients run their catalog introspection queries without hittingUNKNOWN_IDENTIFIER. #109351 (Alexey Milovidov). - An unqualified reference to an
INNER JOINkey that is equated in theONcondition (e.g.SELECT id FROM a INNER JOIN b ON a.id = b.id) is no longer reported as an ambiguous identifier, since both sides are guaranteed to carry the same value. #109366 (Alexey Milovidov). - Return HTTP code
403 Forbidden(instead of500 Internal Server Error) forACCESS_DENIEDexceptions over the HTTP interface. #111043 (Schum). - Write the UNIQUE KEY index SST directly into part storage instead of staging it in a local temporary file, removing the dependency on a local temporary volume and avoiding an extra copy. #111189 (johnjing).
UTMToGeonow accepts the MGRS latitude band letter returned bygeoToUTMas its fourth argument (in addition to the integer hemisphere flag), so ageoToUTMresult round-trips throughUTMToGeodirectly. #111521 (Alexey Milovidov).- Fix a
LOGICAL_ERROR(“Part level Min-Max index was constructed from unexpected columns set”) that could abort a background merge in debug/sanitizer builds afterpart_minmax_index_columnswas lowered (for example fromwith_block_number_offsetback topartition_key_only). #111511 (Groene AI). - Fixes
ProfileEvents['JoinResultRowCount']under-reporting the result size of aJOINthat spills to disk. Rows emitted from delayed buckets were counted only inJoinDelayedJoinedTransformRowCountand were missing from the total. Query results were always correct; only the profile event was wrong. #112673 (Groene AI). SYSTEM DISABLE FAILPOINTnow rejects a fail point name that does not exist, raisingBAD_ARGUMENTSlikeSYSTEM ENABLE FAILPOINTalready did. Previously a mistyped name reported success while leaving the intended fail point enabled, with no indication that nothing had been disabled. #112680 (Groene AI).- Added a new column
skipping_indices_typesto thesystem.tablestable. It contains the distinct types of data-skipping indices defined for each table. #106388 (Anton Popov). - Added a sanity check that a distributed query always carries a known client version, throwing a logical error instead of silently forwarding a zero version to remote shards. Server-initiated queries (background flushes, streaming consumers, dictionary reloads, asynchronous insert flushes) now report the server’s own version as the initiator version. #109408 (Alexey Milovidov).
- Reduced the verbosity of the per-part primary-key binary-search diagnostics in
MergeTreeby lowering them from trace logging to test logging. #110324 (Alexey Milovidov). - 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 (Nikolay Degterinsky). - Fixed
ReadBufferFromPocoSocketBase::setReceiveTimeoutapplying its argument as seconds rather than microseconds, and fixed builds configured with-DENABLE_LIBFIU=OFF, which did not compile. In builds without libfiu,SYSTEM ENABLE FAILPOINTand related commands now throw an exception instead of silently doing nothing. #112767 (Alexey Milovidov). - Fix
clickhouse-localunder-reportingrows_readand the other progress counters in thestatisticsof theJSON/XMLoutput and in the progress bar: a progress increment that arrived while the progress packet was being assembled was discarded. #112958 (Alexey Milovidov). - Fixed the error reported when an asynchronous
INSERTinto aDistributedtable needs a queue directory whose name exceeds the 255-byte filesystem limit (reachable withuse_compact_format_in_distributed_parts_names = 0). It was aLOGICAL_ERRORfor a shard withinternal_replicationand an unattributedCode: 1001. std::exceptionotherwise; both now reportARGUMENT_OUT_OF_BOUNDnaming the table, the cluster and the limit. #113083 (Groene AI). - Reject out-of-range
execution_timequota limits withBAD_ARGUMENTSinstead of relying on undefined behavior when scaling them to internal nanoseconds. #113178 (Alexey Milovidov). - Automatic parallel replicas now support
JOINqueries. #106073 (Nikita Taranov). - Support refresh-token authentication for the
OneLakecatalog. #110413 (alesapin). - The
write_snapshot_versionKeepersetting is now hot-reloadable. #112150 (alesapin). - Parallelize
SYSTEM DROP FILESYSTEM CACHE. #112532 (Kseniia Sumarokova). - Unsupported nesting of a
SQL SECURITY DEFINERorSQL SECURITY NONEview overs3Cluster,urlCluster, orfileClusteris now rejected with a normal query error instead of hitting aLOGICAL_ERRORin debug and sanitizer builds. #113371 (Groene AI). - 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. It also fixes the analyzer losing qualified result column names for columns expanded from*whengroup_by_use_nullsis combined withROLLUP,CUBE, orGROUPING SETS, which produced duplicate result column names and broke outer references to those columns. #110746 (Dmitry Novik). - Renamed
allow_experimental_delta_kernel_rstoallow_delta_kernel_rs. The old name is kept as an alias. #113476 (Kseniia Sumarokova). - When the
remote/remoteSecuretable functions or theRemote/RemoteSecuretable engines are given a missing named collection together with akey = valueoverride, ClickHouse now reports the missing named collection instead of reparsing the call positionally and reporting an unrelated error. #113510 (Groene AI). - Shell startup with
clickhouse-bootstrapcompletion no longer dumps environment variables when the completion is loaded from the user completion hook. #113694 (Azat Khuzhin). - Added the
sainte_laguevalue forshared_merge_tree_merge_coordinator_distribution_algorithmand made it the default instead ofwater_filling. #113442 (Mikhail Artemenko). - Added the
filesystem_cache_wait_for_concurrent_download_timeout_millisecondssetting to bound how long a read waits for another query’s filesystem-cache download of a single chunk (about 1 MiB), not a whole file segment. #113322 (Kseniia Sumarokova). - Added the Keeper setting
min_time_between_fsyncs_ms(default5ms), which batches changelog appends that arrive shortly after the previous flush instead of starting another flush immediately. #113749 (Michael Kolupaev). - Kafka tables with Keeper-stored offsets (
kafka_keeper_path) now throwABORTEDinstead ofLOGICAL_ERRORwhen the table becomes inactive after a Keeper session loss, for example during a direct read or materialized-view streaming. #113913 (Alexey Milovidov). - Fixed inconsistent AST formatting of
viewIfPermitted: the table function form no longer formats an operator such asnotincorrectly in itsELSEbranch, and the expression formviewIfPermitted(...)no longer gets a spuriousELSE. #113652 (Alexey Milovidov). - Fixed a spurious
Failed to drop temporary table after refresh. Table ... is left behind and requires manual cleanup.error logged when a refreshable materialized view refresh is cancelled (for example by server shutdown) whiledatabase_atomic_wait_for_drop_and_detach_synchronouslyis enabled. The temporary table was in fact dropped, so no manual cleanup was needed. #113957 (Groene AI). - The server now throws
UNKNOWN_ELEMENT_IN_CONFIGon unknown configuration options in the server config, helping catch typos and misconfigured options early. The check can be disabled with<skip_check_for_incorrect_settings>. #100332 (Alexey Milovidov). - In the Web UI, the browser history and the URL are no longer updated on every keypress; they are recorded when a query is successfully run or on a tab change. #113596 (Alexey Milovidov).
- ClickHouse now reports a stack overflow instead of dying silently: the fatal signal handlers run on the alternative signal stack, so
SIGSEGV,SIGABRT,SIGILL,SIGBUS,SIGSYS,SIGFPE, andSIGTRAPproduce a stack trace even when the faulting thread has exhausted its stack. #113927 (Groene AI). ALTER TABLE ... MODIFY COLUMN <col> Tuple(...)on a namedTupleis now metadata-only when only adding subfields, matching the speed of top-levelADD COLUMN. Gated behindSETallow_metadata_only_named_tuple_alter= 1. #107305 (Amos Bird).- Add
input_format_json_max_object_sizesetting to limit JSON object size on parsing. Closes #106704. #107669 (Pavel Kruglov). - Avoid logging
sasl.kerberos.kinit.cmd configuration parameter is ignored.forKafkaengine configurations that do not use Kerberos keytab authentication. #108235 (Ivan Shelestov). - Add system.s3(azure)_queue_metadata. #108522 (Kseniia Sumarokova).
- Log tolerated connection failures to remote MySQL/PostgreSQL databases as warnings instead of errors. #109472 (Shaohua Wang).
- When neither
portnorsecureis specified,clickhouse-clienttries both the default port 9000 and the secure port 9440 concurrently and uses the one that answers first, soclickhouse-client --host play.clickhouse.com --user playconnects over TLS without--secure, even though the plain port of that server is silently dropped rather than refused. If the port that answered turns out to be unusable — a secure port with an untrusted certificate, for example — the client falls back to the other one, because the protocol was not requested explicitly. #110130 (Alexey Milovidov). - Clicking the cloud logo in the Playground now opens the ClickHouse website in a new tab, so you don’t lose progress while queries are running. #110422 (William Hatcher).
- Add STREAM BOUNDED modifier, which read only the first snapshot of a streaming query, then finish instead of subscribing for updates. #110653 (Smita Kulkarni).
- Add information of internal state of joins to
EXPLAIN ANALYZE. #110892 (Kirill Kopnev). - When an
RWLockImpl::getLock()re-entrancy assertion fires (RWLock is already locked in exclusive mode/Cannot acquire exclusive lock while RWLock is already locked), the error message now names the otherquery_ids currently owning the lock and how many locks the requestingquery_idalready holds, to make such lock-ordering errors diagnosable. #110971 (Groene AI). - ClickHouse Keeper now logs the “Client has not sent any data” event at
Informationlevel instead ofWarning, matching the server’s TCP handler. This avoids spurious warnings from TCP health-check probes (for example KubernetestcpSocketliveness probes) that open and immediately close a connection to the Keeper client port. #111217 (Zeynel). MaterializedPostgreSQLnow preserves unchanged PostgreSQLTOASTvalues during updates instead of replacing them with default values. #111552 (OrpheusAgent).- keeper: Increase default
write_snapshot_versionto 8 and make it hot-reloadable. #111715 (Michael Kolupaev). - Add STREAM UNORDERED modifier: skip the per-snapshot commit-order sort. #111794 (Smita Kulkarni).
- 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 (Anton Popov). - AI text functions (
aiGenerate,aiClassify,aiExtract,aiTranslate) now reject truncated or otherwise incomplete provider responses (e.g. when the model hits themax_tokenslimit) instead of silently returning partial output. Behavior follows theai_function_throw_on_errorsetting. #111830 (George Larionov). - Improve reduced-precision
L2DistanceTransposedQuantized,cosineDistanceTransposedQuantized, anddotProductTransposedQuantizedby reconstructingp < 8QBit(Int8)codes with Gaussian conditional-mean prefix centroids. Full precision (p = 8) remains bit-exact; reduced-precision approximate distances may change, and recall/latency gains are workload-dependent. #111867 (Sergey Kuznetsov). - Fixed the query condition cache not being populated for granules eliminated by any but the last conjunct of a
WHEREclause with multipleANDconditions. #112083 (Shankar Iyer). - Added a new setting
input_format_json_max_string_column_growth_stepthat caps the power-of-two growth of internal String buffers when building a JSON column, reducing peak memory when inserting large JSON documents. Disabled by default. #112159 (Pavel Kruglov). - Reduced peak memory when writing JSON columns with bucketed shared data serialization (
map_with_bucketsand advanced) by splitting the shared data into buckets one at a time on write instead of materializing all buckets simultaneously. This is mostly beneficial for Array(JSON) columns: for scalar JSON the shared data is split per granule (bounded by index_granularity_bytes), so the saving is small, whereas a single Array(JSON) granule can hold many nested rows and thus a large amount of shared data, where the one-bucket-at-a-time split significantly lowers peak memory. #112172 (Pavel Kruglov). - The documentation of a setting in
system.documentation— shown by the built-in/docspage and by thehelpcommand — now includes the history of the changes of its default value: the version in which the setting was introduced and every later change of its default, with the previous value, the new value and the reason for the change. #112177 (Alexey Milovidov). EXPLAIN ANALYZEnow works for streaming queries. #112445 (Kirill Kopnev).- The modifiers of a column declaration -
COMMENT,CODEC,STATISTICS,TTL,COLLATE,PRIMARY KEYand per-columnSETTINGS- can now be written in any order inCREATE TABLE, and each of them at most once. Previously only one fixed order was accepted, and, for example,x UInt64 CODEC(ZSTD) COMMENT 'text'was a syntax error. InALTER TABLE ... ADD COLUMN/MODIFY COLUMN, the supported modifiers -COMMENT,CODEC,STATISTICS,TTLand per-columnSETTINGS- can also be written in any order; per-columnSETTINGSinADD COLUMNand a declaredSTATISTICSinADD COLUMN/MODIFY COLUMNare now applied instead of being silently dropped, andCOLLATEandPRIMARY KEYin theseALTERcommands now throw an exception instead of being silently ignored. #112788 (Alexey Milovidov). - The
pread_threadpoolread method needs thepreadv2system call with theRWF_NOWAITflag to read the data that is already in the page cache without handing the read off to a thread pool. It is now checked at start time whether that system call can be used, and if it cannot - the Linux kernel is older than 5.11, or aseccompprofile of a container runtime rejects the system call - the default value oflocal_filesystem_read_methodis switched topread, and the reason is reported in the server log. Previously, every read paid for a thread pool hand-off on such systems, and aseccompprofile that answersEPERMmade queries fail withCANNOT_READ_FROM_FILE_DESCRIPTOR. #112945 (Alexey Milovidov). - Report malformed Parquet thrift metadata as INCORRECT_DATA. #113311 (Groene AI).
- Fixed GCD codec handling of signed fixed-width values with negative numbers. Previously it computed the divisor from signed values directly, which could miss the common divisor and significantly reduce compression efficiency for signed integer and decimal columns. It now computes the divisor from magnitudes for signed types while preserving existing behavior for unsigned types and decompression. #113798 (Kirill Shcherbatov).
- Add settings
enable_alp_codec,enable_sz3_codec,enable_zxc_codec, andenable_quantized_codecto enable each experimental compression codec individually. #113824 (Raufs Dunamalijevs). - Allow
ALTER TABLE ... MODIFY COLUMNof a column whose subcolumns are used in the primary or partition key, as long as the subcolumns used in the key keep an on-disk-compatible type. Previously any such ALTER was forbidden. #113862 (Pavel Kruglov). - Add
Filesystem cachedashboard tosystem.dashboards. #113884 (Kseniia Sumarokova). - Put the per-buffer-refill cache logs behind
filesystem_cache_verbose_logging. #113885 (Groene AI). - When a column’s declared type and its data diverge during a
MergeTreeread (mixed type provenance, e.g. after anALTER TABLE ... MODIFY COLUMNwhose mutation has not finished), the server now reports a clear exception naming the column and both structures, instead of an unchecked cast: debug and sanitizer builds previously aborted with a bareBad cast from type A to Bnaming no column, and release builds walked mismatched memory silently. #114087 (Alexey Milovidov). - A window function with
PARTITION BYnow works undermake_distributed_plan. When the plan shape allows, the window runs in parallel across buckets that each receive complete partitions. #114111 (Vighnesh Pathrikar). - Web UI: the hourglass loading indicator in the databases panel is animated again. #114187 (Alexey Milovidov).
- 64-bit hash function is used now for external nullable fixed-width aggregation methods (avoids collision disaster for very high cardinality aggregation). #114210 (Nikita Taranov).
DistributedandBuffertables that omit their column list now always infer the structure under the creating user’s access rights. #114211 (Pedro Ferreira).x IN (subquery)over aLowCardinalitycolumn now returnsLowCardinality(UInt8)— the same type asx IN (literal list). Previously the two forms returned different types, and distributed plans with such anINneeded a special case in the plan type check. #114229 (Alexander Gololobov).- Enabled
ie_joinby default: the default value ofjoin_algorithmis nowdirect,parallel_hash,hash,ie_join. AJOINwhoseONsection has only inequality conditions (two comparisons<,<=,>,>=between expressions of the joined tables) is now executed with the sort-based IEJoin algorithm instead of aCROSS JOINwith a filter, andLEFT/RIGHT/FULL/SEMI/ANTIjoins with such conditions are supported. Sinceie_joinis last in the list, it is used only when the other algorithms do not apply. #114327 (Vladimir Cherkasov). - Fixed charts in the Web UI showing the data of a mirrored point in the hover balloon for a result ordered by
xdescending.Date,Date32,DateTimeandDateTime64columns can now be plotted; previously only integer Unix timestamps worked. Dates on the axes and in the balloons are rendered in ISO 8601, and quantities with theK/M/G/… suffixes, the same way the advanced dashboard does. #114349 (Alexey Milovidov). - Support parsing integers that exceed the 64-bit range in the
JSONdata type,JSONExtract, andisValidJSON. Such values are read into wide integer types such asInt128/UInt256instead of causing the whole document to be rejected. #114379 (Pavel Kruglov). - QueryRunner tables now start worker threads on demand and release them once idle, instead of occupying threads for the table’s whole lifetime. #114522 (Miсhael Stetsyuk).
- Added observability for the stacks of fibers, which are used for asynchronous communication with remote replicas: profile events
FiberStackAllocs,FiberStackAllocBytes,FiberStackAllocNanoseconds,FiberStackFreeNanoseconds, and metricsFiberStacks,FiberStackBytes. #114541 (Alexey Milovidov). - PromQL: support
@ start()and@ end()timestamp modifiers. #114558 (Minh Vu). - Propagate the OpenTelemetry trace context into the fibers used for asynchronous connection establishment and remote query execution (hedged requests,
async_socket_for_remote,async_query_sending_for_remote). Spans of remote queries in a distributed query are now correctly parented under the initiator’sConnection::sendQueryspan instead of being attached directly to the client-supplied trace context, and each asynchronous task execution produces its own span. #114813 (Diego Gomes Tomé). - With this change, while using the WHATIF indices, the projection-served baseline reports per-candidate
not_applicableinstead of failing the statement. #114846 (Yarik Briukhovetskyi). DROP DATABASEnow drops tables in reverse topological order of both loading and referential dependencies (previously only loading dependencies), so a crash in the middle ofDROP DATABASEcannot leave a table whose dependencies were already dropped. #114952 (Alexey Milovidov).- In the Web UI dashboards, the global error screen is replaced by a note above the dashboards, so a failing chart no longer hides the whole page. #115019 (Mikhail Artemenko).
- Spill the adaptive aggregator’s learning-phase tables under memory pressure. #115038 (Groene AI).
clickhouse-localnow answers CORS preflight requests with the same permissive headers asclickhouse-server, so the HTTP interface opened bySYSTEM START LISTEN HTTPcan be used from a browser out of the box, including the Web UI opened from afile://URL. #115045 (Alexey Milovidov).- Support PostgreSQL-style regular expression match operators:
~(an alias for thematchfunction),~*(case-insensitive match),!~and!~*(negations). The\d,\dt,\dvcommands ofpsqlnow work when connected to ClickHouse over the PostgreSQL compatibility protocol, and a failed query no longer terminates the connection. #115066 (Alexey Milovidov). clickhouse-clientno longer prints theConnecting to ...message twice when it asks for a password interactively. #115081 (Alexey Milovidov).EXPLAIN WHATIFnow says why the empirical estimate was skipped, in a newempirical_reasonline shown whenempirical_statusisunsupported. #115140 (Yarik Briukhovetskyi).- When no join algorithm enabled by the
join_algorithmsetting can execute aJOIN, the error message now names the algorithms that were tried and the strictness and kind of the JOIN that failed, instead of reporting only that none of them worked. #115226 (Alexey Elkin). - Vector search queries can now use the vector similarity index when the reference vector is an integer array literal, e.g.
ORDER BY L2Distance(vec, [1, 2]). Previously, such queries silently fell back to a brute-force scan. #115255 (Robert Schulze). - Azure client-side network failures (connection reset/refused, DNS and TLS errors) are now retried as transport errors instead of surfacing as a synthetic
500, matching the S3 client. #115269 (Arsen Muk). - The documentation of all SQL statements (e.g. name, syntax, description, examples) can now be retrieved from system table
system.statements. #115341 (Robert Schulze). BACKUPno longer leaves a lock file behind in its destination when the attempt that created it fails before writing anything — whether it fails while claiming the destination or while opening an archive. No later backup could match such a lock, so every retry to the same destination failed until the file was deleted by hand. Backups toS3andAzuredestinations also create the lock exclusively, and a lock that belongs to another backup is reported as a concurrent backup rather than as whatever error the storage returned. #115387 (Julia Kartseva).- Support bearer-token authentication in BuilderRWBufferFromHTTP (attempt 2). #115400 (Sergei Trifonov).
- Add some dimensional metrics for S3Queue. #115422 (Bharat Nallan).
- Added
keywordas an alias for text index tokenizerarrayfor improved compatibilty with OpenSearch, Elasticsearch, SolR, and Lucene. #115507 (Robert Schulze). - Allow to create own s3 tables. #115652 (Konstantin Vedernikov).
- Do not log per-thread untracked memory on non-server wide MEMORY_LIMIT_EXCEEDED errors. #115658 (Azat Khuzhin).
- The Prometheus remote-write protocol now supports asynchronous inserts: data from multiple concurrent remote-write requests is batched before forming parts, following the
async_insertsetting (enabled by default; addasync_insert=0to the handler URL to keep the synchronous behavior). A request is acknowledged only after the data is flushed to all inner tables of the targetTimeSeriestable. #115688 (Nikita Mikhaylov). - Makes all
timeSeries*aggregate functions handle duplicate timestamps by one rule (the greatest value wins, NaN loses to any other value), fixing the order-dependent results oftimeSeriesInstantRateToGrid,timeSeriesInstantDeltaToGrid,timeSeriesLastTwoSamplesandtimeSeriesResampleToGridWithStalenesswhen some values at a shared timestamp are NaN. The rule is now documented and tested. #115920 (Vitaly Baranov).
Bug Fix (user-visible misbehavior in an official stable release)
- Fix column-name corruption and
BAD_ARGUMENTSexceptions withinject_random_order_for_select_without_order_by: multi-columnSELECTqueries no longer fail, and output column names forCREATE TABLE AS SELECT,CREATE VIEW AS SELECT, and named formats such asJSONEachRoware preserved instead of being replaced with internal__subquery_column_<UUID>aliases. Closes #102812. Closes #101107. #105896 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKin the nativeParquetV3 reader when aPREWHEREhas conjuncts that share a common intermediate expression. #107059 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKfor queries that use the_part_starting_offsetor_part_offsetvirtual columns inWHEREtogether with lazy materialization. #108287 (Vladimir Cherkasov). - Fix
Not found column or subcolumn c.null in blockwhen runningWHERE col IS NULLorIS NOT NULLon a schema-evolvedIcebergcolumn that was added after older data files were written, withoptimize_functions_to_subcolumns = 1(the default). #109515 (Groene AI). - Fix false
ICEBERG_SPECIFICATION_VIOLATIONerrors when reading anIcebergtable whose decimal or other parameterized primitive type is serialized with different whitespace across metadata files, such asdecimal(20,0)in the table metadata anddecimal(20, 0)in the manifest. #109676 (Groene AI). - Fix deferred
PREWHEREwithoptimize_move_to_prewhere = 1whenPREWHEREis applied afterFINAL:WHEREconditions are no longer moved ahead of a deferred row policy, which could change query results. #109703 (Yarik Briukhovetskyi). - Fix
BAD_GETwhen comparing anArray(String)column with an array literal such asarr = ['x']and the column has atext,tokenbf_v1, orngrambf_v1skip index. Such comparisons now fall back to a full scan instead of failing the query. #110057 (Groene AI). - Fix wrong results for
has,mapContainsKey, andmapContainsValuewith an empty needle when a text index is present. #110246 (Robert Schulze). - Fix
Host is empty in S3 URIwhen a scalar subquery is used as the URL argument of thes3table function, or as an argument of any other table function, inCREATE TABLE ... AS SELECTqueries. #110254 (Sema Checherinda). - Fix
ON CLUSTERprivilege checks forSYSTEM STOP/START CLEANUPandSYSTEM STOP/START VIRTUAL PARTS UPDATE: they no longer requireSYSTEM PULLING REPLICATION LOGand now useSYSTEM CLEANUPorSYSTEM VIRTUAL PARTS UPDATE. #110289 (Groene AI). - Fix a read-only object-storage replica, with
read_only = true, not discovering new parts viarefresh_parts_interval, andtable_disk = truefailing on such a disk withtable_disk is not supported for non-ObjectStorage disks. #110460 (Julia Kartseva). - Fix writes through data-lake table functions such as
INSERT INTO FUNCTION icebergS3(...)producingParquetfiles whose string columns lost theStringtype annotation, making the written data unreadable for external readers such as Spark. #110465 (Shaohua Wang). - Fix schema inference failing with
Map cannot have a key of type LowCardinality(Nullable(String))when readingORCfiles whose map keys are dictionary-encoded, including files written by Spark and files written by ClickHouse itself withoutput_format_orc_dictionary_key_size_thresholdenabled. #110492 (Shaohua Wang). - Fix wrong
IS NULL/IS NOT NULL/count()results withoptimize_functions_to_subcolumnson a column madeNullableby a metadata-onlyALTER MODIFY COLUMN TtoNullable(T). For parts written before the conversion, the.nullsubcolumn is now derived from the physically present parent column instead of the storage-type default. #110584 (Groene AI). - Fix wrong query results from the
optimize_and_compare_chainoptimization when transitive conditions mix types with different comparison semantics, such asEnumwithString,DecimalwithFloat64, orFixedStringvalues of different widths. #110621 (Yarik Briukhovetskyi). - Fix wrong results for some read-in-order queries when the optimizer widens the sort-key prefix. #110725 (Groene AI).
- Fix
CREATEstatements with aCOMMENTclause to raise a syntax error when the comment string literal is missing, instead of silently accepting a misparsed query. For example,CREATE VIEW v COMMENT AS SELECT 1no longer creates a view without a comment. #111159 (Shaohua Wang). - Fix wrong results from
SummingMergeTreeandCoalescingMergeTreewithFINALwhenoptimize_move_to_prewhere_if_final = 1and theWHEREclause is an implicit-boolean condition on a sorting-key column, such asWHERE k. #111342 (Groene AI). - Fix spurious
Directory '...' was created concurrently with remote path '...'exceptions for metadata-only operations on object-storage-backed databases and tables, such asDROP DATABASE. #111353 (Mikhail Artemenko). - Data-lake REST catalogs now report stale credentials with the proper exception instead of silently treating them as a missing table or returning
UNKNOWN_TABLE. #111379 (alesapin). - Fix
SQL SECURITY DEFINERandSQL SECURITY NONEnot being honored for parameterized views when the analyzer is disabled (enable_analyzer = 0). Previously, selecting from such a view as a user without privileges on the underlying table failed withACCESS_DENIED, even though the same view works with the analyzer enabled. #111458 (Groene AI). - Reject a
Nullable(Nothing)column, or any other type not allowed in tables, atCREATE TABLEtime when the schema is inferred from the storage, for example in a columnlessremote,Remote, orDistributedtable over a view that doesSELECT NULL, instead of persisting metadata that fails to load on the next server restart and blocks loading of unrelated tables. #111487 (Groene AI). - Fix
std::bad_variant_accessand incorrectIcebergschema evolution for nestedArray(Map(...))columns whose innerStructis altered. #111489 (Konstantin Vedernikov). - Fix
ALTER MODIFY COLUMNfailing when converting aNullablecolumn to a different type with aDEFAULT, for example fromNullable(UInt8)toString,LowCardinality(String), orArray(UInt8). #102156 (DQ). - Fix
BAD_ARGUMENTS(Dictionary not found) fromdictGetafterDETACH DICTIONARY ... PERMANENTLYis rejected withHAVE_DEPENDENT_OBJECTS; the dictionary now remains usable when the detach is rejected. #105259 (Groene AI). - ClickHouse-written data files for
Icebergtables now embedIcebergfield IDs inAvroandORC,ORCStringcolumns are written asstringinstead of binary, and optional complexORCfields (Array,Map,Tuple) now preserve the correcticeberg.requiredmetadata. This fixes silentNULLresults after column renames and restores compatibility with spec-compliant readers such as Spark andiceberg-java. #109994 (Groene AI). #111775 (Groene AI). - Fix reading files on
plain_rewritabledisks after an existing path is rewritten with content of a different size: stale in-memory metadata could otherwise triggerUNEXPECTED_END_OF_FILE. #110304 (Konstantin Bogdanov). - Fix drift of the per-user memory tracker caused by system log records such as
query_logandquery_views_log, which could otherwise trigger a falsemax_memory_usage_for_userlimit for users with continuous workloads. #110708 (Raúl Marín). - Fix a rare race where a comment-only or settings-only
ALTERon aReplicatedMergeTreetable could silently drop a column added by a concurrentALTER ... ADD COLUMN, leaving a replica with outdated table metadata. #111029 (Shaohua Wang). - Fix incorrect primary-key pruning on tables with a descending sorting-key suffix, such as
ORDER BY (g, r DESC), which could drop matching rows. #111059 (Nihal Z. Miaji). - Fix a peer-certificate memory leak on every TLS handshake when certificate verification is enabled. #111425 (Konstantin Bogdanov).
- Fix mutations with a query parameter as the partition in
ALTER TABLE ... UPDATE/DELETE ... IN PARTITION {param:Type}: the serialized partition value can now be parsed back correctly, so theALTERno longer writes mutation entries that break table loading. #111518 (Michael Kolupaev). - Fix a macOS/aarch64 crash when a stack trace is captured on a coroutine or fiber stack, for example by the memory profiler. #111656 (Raúl Marín).
- Fix server crash when reading
Protobufdata withinput_format_allow_errors_num > 0and a valid message precedes a bad but skippable message in the same block. #107739 (Andrey Tsarevskiy | Андрей Царевский ). - Fix
NOT_FOUND_COLUMN_IN_BLOCKwhen a query over aDistributedtable uses_shard_numorshardNumthat becomesNullable, for example underFULL JOINwithjoin_use_nulls = 1, together withORDER BYand the analyzer. #109798 (Groene AI). - Fix wrong results and
UNKNOWN_ELEMENT_OF_ENUMexceptions inLEFT/RIGHT/FULL/ASOF JOINwithjoin_algorithm = 'full_sorting_merge', where non-joined rows could be filled with0instead of the column type default. #111197 (Groene AI). - Fix a
LOGICAL_ERRORexception when a higher-order function’s lambda body is a constant-conditioniformultiIfthat mixes aBoolliteral branch with aUInt8comparison branch, for examplearrayFilter(p -> multiIf(false, true, p = 'ALL'), ['ALL']). #111245 (Groene AI). - A
{_partition_id}placeholder in the path ofS3,AzureBlobStorage,URL, and similar file-like engines without an explicitpartition_strategynow implies thewildcardstrategy again, restoring compatibility for pre-26.6 DDL that started failing withBAD_ARGUMENTS. #111279 (Nikita Fomichev). - Fix
NUMBER_OF_COLUMNS_DOESNT_MATCHforGROUP BYqueries over aMergetable wrapping aDistributedtable when the grouping key is a function of a column and an aggregate reads the same column. #111334 (Groene AI). GRANT role TO roleon the same role is now rejected withBAD_ARGUMENTSinstead of silently creating a self-referential entry insystem.role_grants. #103315 (zxuhan7).- Fix writes to
Icebergtables when the metadata file has norefssection. #106896 (Aleksandr Musorin). - Fixed
system.session_logbecoming unreadable after an Arrow Flight login: theinterfacecolumn is anEnum8, but theArrowFlightvalue was missing from its enumeration, so a login over the Arrow Flight protocol wrote the raw value10and anySELECTreading such a row threw theUnexpected value 10 in enumexception. #110758 (Alexey Milovidov). - Fixed a signed integer overflow in
toStartOfIntervalwith subsecond intervals: forDateTime64values within one interval of the lower bound ofInt64, the rounded result silently wrapped to a positive garbage value; now the function throws aDECIMAL_OVERFLOWexception. #111370 (Alexey Milovidov). - Fix
readWKTPointandreadWKTreturning uninitialized (scalar) or previous-row (vectorized) coordinates for a dimension-tagged empty point such asPOINT M EMPTY. Such inputs are now rejected withCANNOT_PARSE_TEXT, consistent withPOINT EMPTY. #111517 (Groene AI). - Fix
Unexpected number of columns in result sample blockexceptions forRIGHTandFULL JOINwhen the left side carries a duplicated same-named column, for example1 AS b, 1 AS b, that survives throughUNION ALL. #111554 (Groene AI). - Fixed
CANNOT_CONVERT_TYPEandLOGICAL_ERRORexceptions in distributed queries using the-Tuplecombinator with aRESPECT NULLSorIGNORE NULLSmodifier under nested combinators, for exampleanyRespectNullsStateTuple(...) IGNORE NULLS. #111570 (Alexey Milovidov). - Fixed SQL syntax highlighting in Play on iPhone, where iOS Safari’s automatic text inflation could misalign the highlight overlay. #111683 (Alexey Milovidov).
- Fixed
UNKNOWN_QUERY_PARAMETERwhen a parameterized view is called with a subquery-valued argument whose type isArray,Tuple, orLowCardinality, for exampleSELECT * FROM v(param = (SELECT groupArray(x) FROM t)). #111790 (Groene AI). - 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, asdictGetanddictHasalready do, and aNULLkey never matches. #111857 (Groene AI). - With
fsync_part_directory = 1, renaming a part directory from its temporary to its final name is now itself made durable by fsyncing the parent directory, and for moves across parents the source parent too. Previously only the moved directory was fsynced, so a power loss right after a part was committed could leave the part missing on disk and lose rows despite the setting being enabled. #111861 (Groene AI). - Fixed hangs in
randChiSquared,randStudentT,randFisherF, andrandBinomialwith extreme parameters. Such queries could not be interrupted bymax_execution_timeorKILL QUERY. These parameters are now rejected even whenmax_rand_distribution_parameterormax_rand_distribution_trialsis set to0, andmax_rand_distribution_trialscan no longer be raised above its default of10^9forrandBinomial. #111909 (Alexey Milovidov). - Fixed wrong results when the analyzer rewrites comparison chains such as
x = c1 OR x = c2 OR ...,x != c1 AND x != c2 AND ..., orhas(const_array, x)toINandNOT IN. It also fixesIllegal type ... of argument of function inexceptions for expressions withDynamic,Array(Dynamic), orJSONstructure. #111924 (Groene AI). - Fixed wrong results and
LOGICAL_ERRORwhen selecting aNullable(Tuple(...))column together with one of its null-carrying element subcolumns (Variant,Dynamic, orLowCardinality) from aMergeTreetable. #111949 (Groene AI). - Reject native-protocol handshakes that use
USER_INTERSERVER_MARKERfor an unknown cluster, or for a cluster configured without a<secret>element. Previously such handshakes could enter interserver mode before authentication and read information about local tables. #99675 (Dan Anderson). - Fix
JOINagainstEmbeddedRocksDB,Redis, andKeeperMaptables that could silently return zero rows whenDirectKeyValueJoinis used withStringorNullable(String)keys. #105253 (Vladimir Cherkasov). - Fix coordinated refreshable materialized views in a
Replicateddatabase getting stuck after re-attach on a Keeper without theMULTI_READfeature flag; the view now stops cleanly with statusDisabledinstead of loggingUnexpected exception in refresh schedulingforever. #108890 (Groene AI). - Fix the ZooKeeper client sending an overflowed
int32length prefix for requests larger thanINT32_MAXbytes. Oversized requests are now rejected on the client side. The limit is configurable viamax_request_sizeunder<zookeeper>and is otherwise learned from Keeper. Closes #109165. #109190 (Arsen Muk). - Fix
S3Queue/AzureQueueordered mode with persistent processing nodes: bucket locks are now refreshed during streaming, so TTL cleanup controlled bypersistent_processing_node_ttl_secondsdoes not remove locks of a live processor. If lock ownership is nevertheless lost, it is detected and reported, and streaming recovers with a fresh file iterator. #110292 (Kseniia Sumarokova). - Fix wrong data and possible out-of-bounds reads when reading
Stringcolumns withstring_serialization_version = 'with_size_stream'after skipping leading rows, and when reading sub-objects ofJSONcolumns stored withobject_shared_data_serialization_version = 'map'. #110471 (Alexey Milovidov). - Fix
CREATE TABLEandALTER TABLEwith the analyzer accepting aDEFAULTorMATERIALIZEDexpression that references a virtual column such as_tableor_database. These expressions are now rejected at definition time instead of failing later on insert withNOT_FOUND_COLUMN_IN_BLOCK. #111776 (Groene AI). - Fix a race in executable UDFs, the
executabletable engine, and executable dictionaries where anfcntlon an already-closed file descriptor could corrupt an unrelated descriptor of a concurrent query and make queries hang indefinitely. #111779 (Raúl Marín). - Creating deprecated
minmaxstatistics now emits a warning instead of throwing an exception. #111785 (Han Fei). - Fix
Icebergtables written by ClickHouse being unreadable by external readers such as PyIceberg and Spark. Manifest-list and manifestAvroschemas now include the requiredIcebergfield-idproperties. #111786 (Groene AI). - Regenerate materialized-into-part
block_numberandblock_offsetcolumns during part attach/detach/move/clone operations, so they no longer become stale after part manipulation. #111801 (Mikhail Artemenko). - Fix the
query_plan_split_filteroptimization leaving an internal__split_filtercolumn in one branch ofINTERSECTorUNION, which could cause aBlock structure mismatch in IntersectOrExceptStep stream: different number of columnsexception. #111930 (Groene AI). - Fix
AMBIGUOUS_COLUMN_NAMEfor queries that repeat aJOIN ONcondition inWHEREwithjoin_use_nulls = 1; such queries now return their result instead of failing. #112007 (Groene AI). - Fix DLF authentication in the
PaimonREST catalog: every request after the first no longer fails with HTTP 401, and table-existence checks now detect HTTP 404 correctly. #112015 (JIaQi Tang). - Fix
LOGICAL_ERRORduring concurrentKafkatable cleanup in Keeper; creation or removal no longer fails if the table’s Keeper path disappears after session expiry. #112078 (Groene AI). - Fix merges and mutations when the part-level min-max index is enabled for
_block_numberand_block_offsetcolumns. #109281 (Mikhail Artemenko). - Fix failed
INSERTintoDeltaLakeLocalordeltaLaketables leaving an unfinalized data file after writing had already started. #109328 (Groene AI). - Fix credential leaks in
SHOW CREATE,system.query_log, server logs, andEXPLAINoutput fors3/s3Cluster, theS3-backed engines,BACKUP ... TO S3, and secret arguments ofencrypt,decrypt, and HMAC functions built by expressions or SQL UDFs. #109768 (Raúl Marín). - Fix reading large
Parquetfiles from uncompressedSTOREDzip entries vias3andfile. #110495 (Eva Wuuu). - Fix
EXPLAIN ANALYZEhanging on queries with a streamingFROM ... STREAMread hidden in a subquery, CTE, or view. Such queries are now rejected withNOT_IMPLEMENTED, like top-level streaming reads already are. #110935 (Groene AI). - Reject vectors whose squared magnitude overflows to infinity when using a
vector_similarityindex withi8quantization. Previously, such vectors produced silent garbage. #111085 (Groene AI). - Fsync the text index files of a merged or materialized part when
min_rows_to_fsync_after_merge,min_compressed_bytes_to_fsync_after_merge, orfsync_part_directoryare set. Previously, these files were the only ones in the part left unsynced, so a power loss right after a merge could leave a committed but broken part and cause data loss. #111335 (Groene AI). - Fix path validation against
user_files. #111442 (Alexander Tokmakov). - Fix
SYSTEM REFRESHon a stoppedRabbitMQtable sometimes failing to consume the queued backlog. The refresh operation now waits for the AMQP delivery loop to start before it spends its one out-of-order streaming cycle. #111480 (Groene AI). - Restrict local object access to the
user_filespath. #111483 (Konstantin Vedernikov). - 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. #111606 (Miсhael Stetsyuk). - Fix integer overflow while parsing
system.zookeeper_info. #111629 (Kseniia Sumarokova). - Fix
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 (Groene AI). - Fix partitioned
INSERTintoDeltaLakewithallow_experimental_delta_lake_writes = 1corrupting partition values that contain path characters and rejectingNULLpartition values. Partition values are now percent-encoded into a single path segment, andNULLor empty-string values are written as__HIVE_DEFAULT_PARTITION__with a nullpartitionValuesentry. #111793 (Groene AI). - Fix an exception and silently skipped data when reading a dynamic subcolumn through a
Buffertable. #111948 (Alexey Milovidov). - Fix
clickhouse-clientlosing the current database afterUSE {db:Identifier}. If the client had to reconnect later, it silently switched the session to thedefaultdatabase. #111982 (Alexey Milovidov). - Fix a
LOGICAL_ERRORexception (Type mismatch when building statistics for column) duringMergeTreemutations after a metadata-onlyALTER MODIFY COLUMNchanges a column type while the column carries statistics. Columns actually rewritten by the mutation now have their statistics recomputed, and untouched columns keep their existing statistics. #112009 (Groene AI). - Fix
Paimontable reads that could fail while the mutablesnapshot/LATESThint was being replaced concurrently. Invalid or stale hints are now ignored, and the snapshot is loaded from the catalog instead. #112010 (JIaQi Tang). - Fix reading
GeoParquet,Arrow, andArrowStreamfiles whose WKT-encoded geometry column uses a non-uppercase type keyword such aspoint(1 2)or an empty container such asLINESTRING EMPTYorPOLYGON(). This also fixes reading back files that store the output ofwktfor an empty geometry. #112020 (Groene AI). - Fix query-level settings overrides not being applied to Azure native copy. #112037 (Smita Kulkarni).
- Fix
query_masking_rulesrewriting the type of anEPHEMERALcolumn, which could makeCREATE TABLEstore the wrong type or fail. #112048 (Alexey Milovidov). - Table function parameters no longer accept aggregate states, which previously triggered a logical error because such parameters are unsupported. Closes #112085. #112087 (Pedro Ferreira).
- Fix wrong results for a
JOINwhoseONexpression contains a constant conjunct, for exampleON l.id = r.id AND CAST(NULL AS Nullable(UInt8)). #112155 (Vladimir Cherkasov). - Fix wrong results for
hasAllTokensand other multi-token text-index searches on builds that do not usesimdcomp, such asaarch64, whentext_index_posting_list_apply_mode = 'lazy'. #112178 (Groene AI). - Fix wrong results when a parameterized view is called with an argument that is not a
parameter = valueassignment. Such calls are now rejected withUNKNOWN_QUERY_PARAMETERon both execution paths. #112194 (Groene AI). - Fix parameterized views whose
SELECTbody usesINTERSECT,EXCEPT, or aUNIONchain that mixesUNION DISTINCTwithUNION ALLbeing misclassified as ordinary views, which made their metadata unloadable. #112211 (Groene AI). - Fix schema inference for the
TSVfamily inferringStringfor decimal values written with a leading zero, such as0.0or0.5, and consuming such a first row as a header. Also fixTSKVinferring a numeric type for an escape-encoded value such asx=1\x2E5. Closes #112105. #112226 (Groene AI). - Fix
system.s3_queue_settingsreporting incorrect values forbucketing_mode,partitioning_mode,partition_regex, andpartition_component. #112300 (Bharat Nallan). - Fix wrong results, wrongly ordered
ORDER BYoutput, andBAD_TYPE_OF_FIELDexceptions when the primary key is anArrayorTupleand the query appliesplus,minus,multiply,divide, orintDivto it. #112339 (Groene AI). - Fix remote execution of queries containing
PASTE JOIN, for example through aDistributedtable or a*Clustertable function. ClickHouse no longer formats the query as the invalid syntaxALL PASTE JOIN. #112404 (Groene AI). - 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 (Groene AI). - Fixed the
_tagsvirtual column for theS3Queuetable engine: it was declared but never populated, soSELECT _tagsalways returned an empty map. It now returns the object tags, like theS3engine and thes3table function. #108676 (Groene AI). - 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 (Groene AI). - Fix skip indices being dropped from a data part (or
CHECK TABLEfailing withUNEXPECTED_FILE_IN_DATA_PART) after a full-part-rewrite mutation, such asALTER TABLE... DROP COLUMNof aMATERIALIZEDcolumn, on aWidepart. #109616 (Groene AI). - Fixed two bugs on the
DateTime64path oftoUTCTimestamp/fromUTCTimestamp(and theirto_utc_timestamp/from_utc_timestampaliases) andtoTime64. First, a signed integer overflow near theInt64boundary (now computed inInt128and clamped to the representable range). Second, a wrong result for negative fractional values near a timezone-offset boundary: the seconds split truncated toward zero, sotimezoneOffset()inspected the next second and could pick the wrong side of a DST/offset change. #109738 (Groene AI). - Fix a logical error (“Cannot determine row level filter; 0 columns deleted, 0 columns added”) when reading from a
Mergetable whose child table has a row policy whose filter is a bare existing column (for exampleCREATE ROW POLICY... USING flag). #109843 (Groene AI). - Fixed two errors raised when a query with
GROUP BY GROUPING SETS(or a scalar or mutation subquery containing one) runs withforce_aggregation_in_order = 1:Trying to get name of not a column: ExpressionListunder the old analyzer (enable_analyzer = 0), andMemory bound merging of aggregated results is not supported for grouping sets.for a distributed query withenable_memory_bound_merging_of_aggregation_results = 1under the analyzer. #109862 (Groene AI). - Fix parsing of numeric
1/0asBoolvalues inside container types (e.g.Array(Bool),Tuple(Bool,...)). Previously[1,0]failed withCANNOT_READ_ARRAY_FROM_TEXTwhile[true,false]worked. #109976 (Groene AI). - Fixed a spurious
ILLEGAL_COLUMNerror fromALTER TABLE... ADD COLUMN IF NOT EXISTSwhen the column already exists at apply time. This happened when the same column was added twice withIF NOT EXISTSin one statement, or when a concurrentALTERadded the column between the prepare and apply phases. #110080 (Groene AI). - Fixed a wrong result where
length(and the QBit dimension) on aFixedStringcolumn returned0instead of the fixed sizeNunder parallel replicas when the query had a selective filter. #110427 (Groene AI). - Fixed
flipCoordinateslosing theGeometrytype: for aGeometryargument the result is now typedGeometryagain instead of the underlyingVariant(...), so it can be passed directly to functions likeareaCartesian. #110694 (Groene AI). - Fixed
optimize_injective_functions_in_group_bychanging query results forGROUP BY GROUPING SETSandGROUP BY... WITH TOTALS. The setting is documented as result-preserving, but eliminating an injective function of a grouping key produced a wrong value (or dropped a row) for rows where that key is absent from the aggregated set (aGROUPING SETSnon-member set) or for theWITH TOTALSrow. The wrong value could coincide with a genuine key value, making a super-aggregate row indistinguishable from a real group in the same result set. #110721 (Groene AI). - Numeric
1/0in JSONBoolparsing now honors theallow_special_bool_valuessetting. Previously JSON input such as{"v":1}forVariant(Bool, UInt32)was read asBooleven withallow_special_bool_values_inside_variant = 0, because the JSONBoolparsers ignored the setting andBoolhas a higherVariantdeserialize priority than integer types. #110835 (Groene AI). - 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). - 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). - Fixed
DISTINCTwith an orderedLIMIT/OFFSETreturning wrong rows when the DISTINCT early-stop limit hint could not bound the head of the result: a negativeLIMIT(returned the head instead of the tail), a fractionalLIMIT/OFFSET(the fraction is only resolved after a full read), and a bareOFFSETwith noLIMIT(the tail after the offset was dropped). For exampleSELECT DISTINCT intDiv(x, 100) FROM t ORDER BY intDiv(x, 100) LIMIT -1over a multi-part table returned the smallest distinct value instead of the largest. #111326 (Groene AI). - Fixed wrong results when a query has a
setskip index and a predicate of the shape(x AND <null-value>) OR y, where the NULL is produced by a function (e.g.toInt64OrNull('x'),nullIf(1, 1),CAST(NULL AS Nullable(Int64))). Such a value was wrapped by__bitWrapperFuncand propagatedNULLinstead of the “unknown” mask, so the set index could prune granules that actually match and the query returned fewer rows than it should. #111604 (Groene AI). - Fix
DELETE/UPDATEon an Iceberg table silently removing the wrong rows (or throwingNOT_FOUND_COLUMN_IN_BLOCK) when the table contains data files written both before and afterALTER TABLE... ADD COLUMNandoptimize_move_to_prewhereis enabled. #111693 (Groene AI). - Fixed a
LOGICAL_ERROR(“Invalid number of rows in Chunk”) — and, under hardened builds, a related out-of-bounds abort — forORDER BY ... WITH FILL ... INTERPOLATEover aDistributedtable with two or more shards, overclusterAllReplicas, or over custom-key parallel replicas, including on empty results.WITH FILLis now applied only on the node producing the final result, which also fixes duplication of the generated fill rows across shards/replicas. #111919 (Yakov Olkhovskiy). - Keep
randBinomialusable with the degenerate probabilities0and1for any number of trials. #112021 (Alexey Milovidov). - Fixes wrong results caused by a vector-search query poisoning the query condition cache. A
SELECT... WHERE <condition> ORDER BY <distance function> LIMIT nquery over a table with avector_similarityindex could record granules as not matching<condition>, so a later ordinarySELECT... WHERE <condition>on the same table silently returned fewer rows. Vector-search reads no longer write to the query condition cache. #112086 (Groene AI). - Fixes a bug where a
CREATE VIEWorCREATE FUNCTIONwhose definition callssubstr,midorbyteSlicein a form thesubstringgrammar cannot re-parse is accepted, but the metadata ClickHouse writes for it is not valid SQL. Reading that definition afterwards fails withSYNTAX_ERROR, and at server startup it aborts metadata loading, so the server cannot start at all. Such definitions now round-trip, and existing metadata files of the formsubstring(x, a, b, c)become readable again, so an affected server starts up without manual intervention. #112195 (Groene AI). - Fixes a
TimeSeriestable whose local metadata diverged from Keeper making replica recovery in aReplicateddatabase hang forever, so the replica never served the database again and stayed broken across restarts. The inner tables of such a table are now dropped while the recovery metadata transaction is still available, instead of being deferred to a background task that could not execute theDROPat all. #112218 (Groene AI). - Fixed reading a subcolumn of a
Nullable(Tuple(...))column whose element is a non-nullableLowCardinality(T)when the same query also reads the parent subcolumn. On a Compact part the parent returned wrong values, or the query failed withUnexpected return type from assumeNotNull, or the server was killed by astring_viewhardening assertion, because the extracted subcolumn was deserialized into aLowCardinality(Nullable(T))buffer whose substreams were then shared with the parent’s read. #112232 (Groene AI). - Fixed a permanent server hang on macOS caused by
pthread_rwlocklosing wakeups when the sampling query profiler is enabled (Apple bug FB24027930):pthread_rwlockis now replaced with a signal-robust implementation on Darwin. #112267 (Raúl Marín). - Fix
max_execution_timeandKILL QUERYbeing ignored while a query evaluatesgeohashesInBox,arrayFold,sleep,base58Decode,h3PolygonToCells, orh3PolygonToCellsWithContainment. Such queries could keep running for minutes after cancellation. This now also covers evaluations inside expressions stored in table metadata, such as sorting keys, skip indexes, andPARTITION BYkeys. #112273 (Groene AI). #113456 (Groene AI). - Fixes a logical error
Cannot add step Expression to QueryPlan because it has incompatible header with root step JoinLazyColumnsStepfor a query withFINAL, aPREWHEREfilter, a smallLIMITandmake_distributed_plan = 1, when the selected columns are listed in an order that differs from the table’s column order. Lazy materialization replaced a plan node without preserving that node’s output header, which made the query plan inconsistent. #112303 (Groene AI). - Fixes writing Iceberg tables whose schema contains a tuple nested inside a tuple. The published table metadata replaced the inner tuple’s field names with positional names
1,2,…, so with the defaultParquetformat theINSERTfailed withINCORRECT_DATAand withAvrothe column could not be read back. #112480 (Groene AI). - 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 (Anton Popov). - Fixes wrong results and a logical error when an argument that must be constant, such as the scale of
toDecimal32or the timezone oftoDateTime, comes from a scalar subquery and the old analyzer is used. Such an argument was analyzed as if its value were zero or empty, so the declared result type disagreed with the computed value, andCREATE VIEWandCREATE MATERIALIZED VIEWpersisted a wrong column type. #112492 (Groene AI). - Fixes a
LOGICAL_ERROR(“Part… contains column… that is absent in table…”) when aReplicatedMergeTreereplica mutates a part it fetched from another replica before applying its own pendingALTER... ADD COLUMN. Such a mutation is now postponed until the metadata change is applied. #112510 (Groene AI). - Fixed incorrect query results when using GROUP BY with ORDER BY and
arrayJoinin the projection. #101775 (Yash ). - 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 (Groene AI). - Fix a logical error
Stream <col>.variant_discr... is not found(server abort in debug and sanitizer builds) whenALTER TABLE... MODIFY COLUMNchanges a column into a type with dynamic subcolumns (for exampleVariantintoDynamic) on a table with Wide parts, and the part is later read or merged. #110204 (Groene AI). - Fix a signed-integer overflow (UBSan) when converting an extreme
DateTime64value (e.g.INT64_MIN) toTime/Time64in a timezone with a negative offset. #110451 (Groene AI). - Fixed a MergeTree table with a
_part_offsetor commit-order projection becoming permanently unattachable afterallow_part_offset_column_in_projectionsorallow_commit_order_projectionwas disabled and the table was detached or the server restarted. These two settings are CREATE-time gates, so they are no longer re-checked on ATTACH. #110570 (Groene AI). - 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 (Dmitry Novik). - Fixes an issue where unauthenticated requests could cause ClickHouse to resolve hostnames supplied in forwarded client-address headers. ClickHouse now accepts only numeric IP addresses from these headers. Invalid values are ignored for forwarded-address quota attribution without DNS resolution. When
auth_use_forwarded_addressis enabled, invalid forwarded addresses are rejected during authentication. Rejections are logged at debug level. #111060 (Dmitriy Borisenko). - Fix
NOT_FOUND_COLUMN_IN_BLOCKwhen a row policy andadditional_table_filtersreference the same column that is not otherwise selected by the query. #111099 (Groene AI). - Fix
UNKNOWN_IDENTIFIERerror for columns qualified by CTE name (cte_name.column) in queries stored in views when the analyzer is enabled. #111386 (Dmitry Novik). - Fix a
LOGICAL_ERROR(Got read request from replica N for unknown stream...) that could abort the server when reading with parallel replicas and the query is fully answered by a projection optimization (exact-count, minmax-count, or a stored aggregate/normal projection selecting no ranges) on the initiator. #111689 (Groene AI). - Fixed a signed integer overflow in the three-argument overload of
toStartOfInterval: for anoriginargument near the lower bound ofInt64the function returned a wrapped-around value instead of reporting an error. #112045 (Alexey Milovidov). - Fixes a
LOGICAL_ERRORexception (Block structure mismatch in joined block stream) on a multi-table join whose two sub-joins both produce no output columns, for exampleSELECT count() FROM t1, t2, t3, t4 WHERE (t1.b = t2.b) AND (t3.a = t4.a)withquery_plan_optimize_join_order_limitset to0or1. #112205 (Groene AI). - Fixed the
valuestable function rendering a non-literalBoolconstant (e.g.CAST(true, 'Nullable(Bool)')) inserted into aString/textual column as1/0instead oftrue/false. #112308 (Yakov Olkhovskiy). - Fix a
LOGICAL_ERROR(partitions_count > 0) when partitioningIcebergdata chunks emptied by position deletes, e.g. during compaction of a partitionedIcebergtable with fully deleted data files. #112432 (Pedro Ferreira). - Fixed schema inference proposing a numeric type for text values the value parser cannot read back. Inference accepted a dangling exponent (
1e+), a missing mantissa (.) or a repeated sign (++inf), whichreadFloatTextPrecisethen rejected withCANNOT_PARSE_NUMBERwhen reading the inferred schema; on aDynamiccolumn this was an error at INSERT time. Inference now validates the number with the parser the reader actually uses. This also removes a case where the inferred type depended onmax_read_buffer_size, and lets valid leading-zero exponent forms such as0e5inferFloat64in TSV as they already do in CSV. Follows #112226 and closes the exponent half of #112105. #112453 (Groene AI). - Report the correct position for errors in PromQL queries. #112494 (Minh Vu).
- Fixes a
LOGICAL_ERROR(Cannot add transform Resize to Pipes because it has no outputs) when a query aggregating over a cluster runs withserialize_query_plan = 1and plan-based parallel replicas, caused by the merge step resizing the pipeline to zero streams. #112506 (Groene AI). - Fixes an unsigned underflow in the table name length check that allowed creating a table which could never be dropped. When the escaped database name reached 214 bytes, the limit computed for the
metadata_droppedfilename wrapped around, soCREATE TABLEwas accepted and the subsequentDROP TABLEorDROP DATABASEfailed withFile name too long. Such a name is now rejected withARGUMENT_OUT_OF_BOUND, the same error already returned just below that boundary. #112527 (Groene AI). - Fix the
Context has expiredexception whengetClientHTTPHeaderis used inside a subquery. #112533 (Alexey Milovidov). - Fixed
s3_allow_server_credentials_in_user_queriesincorrectly rejecting a query-suppliedextra_credentials(role_arn = '...'). STS assume-role with an explicit role is now always allowed: it does not expose the server’s own credentials to the query, and it is the documented way to grant access to a private S3 bucket. #112603 (Raúl Marín). - Fixes the read counters (
read_rows,read_bytes,ProfileEvents['SelectedRows'],ProfileEvents['SelectedBytes']) and theREAD_ROWSandREAD_BYTESquotas being over-charged for queries whoseORDER BYspills to disk. Rows re-read from the external sort temporary files were counted again as source reads, so a spilling query over-reported what it read and could be rejected withQUOTA_EXCEEDEDeven though it stayed within its quota. #112645 (Groene AI). - Fixes an Iceberg table whose write format is
Avroserializing a field declared"required": falsewhose type is alist,maporstructas required, with no["null", T]union, so that the data file’s own schema disagreed with the table metadata and other Iceberg readers saw a required field. Such a field is now written as the["null", T]union the Iceberg spec uses for an optional one. #112648 (Groene AI). - Fixes
DeltaLaketables returning too few rows when theWHEREpredicate contains a sub-expression the delta-kernel predicate translator cannot handle, positioned under aNOT. Such a sub-expression is now reported to delta-kernel as an explicit unknown predicate instead of as the end of the child iterator, which used to silently truncate the enclosing conjunction. #112652 (Groene AI). - Fixes heap corruption, which could crash the server at shutdown, caused by the
constmethodAccessRights::getFiltersmodifying an access-rights tree shared by concurrent queries. #112692 (Groene AI). - Fixes a logical error in query formatting when an
ARRAY JOINclause carries no expressions. Such a clause is now rejected while parsing withSYNTAX_ERROR, consistent with an emptyUSING, instead of being accepted and formatted into text that cannot be parsed back. #112699 (Groene AI). - Fix a query hang in local execution of distributed query plans (
distributed_plan_execute_locally = 1): the in-memory exchange reader could block the only pipeline thread before the sources producing its data were started. #111762 (Alexander Gololobov). - Fix
Icebergfields declared with"required": falsewhose type islist,map, orstructbeing written asREQUIREDin theParquetfooter. Such fields are now written asOPTIONAL, matching the publishedIcebergschema and other readers. #112669 (Groene AI). - Fixed a heap-use-after-free in the pipeline executor that could crash the server when a query removes processors at runtime (for example
FINALwith lazy reads or external sort), found by the AST fuzzer. #111017 (Groene AI). - Fix a use-after-free (segmentation fault) when a query with a shared storage snapshot (setting
enable_shared_storage_snapshot_in_query) strips data parts from the snapshot — e.g. a streaming subquery reading the sameMergeTreetable that another part of the query reads concurrently. #111192 (Alexey Milovidov). - 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 Khatoniar). - Fix a
LOGICAL_ERROR(CTE '...' does not have query tree, but was not planned yet) when aMATERIALIZEDCTE is referenced from more than one join-tree position (for example two joined subqueries, or a joined subquery plus a scalar subquery inWHERE) in a query over aDistributedtable. The query now executes instead of raising the exception (it aborted the server in debug/sanitizer builds). #108924 (Groene AI). - Preserve original key order in bucketed Map serialization to fix comparison operations that depend on it. #109178 (Pavel Kruglov).
- Fixed
made_current_atinsystem.iceberg_historybecoming1970-01-01for a retained snapshot afterALTER TABLE... EXECUTE expire_snapshotson an Iceberg table. Also fixedsystem.iceberg_historyreturning no rows for a table whose metadata has nosnapshot-log. #111781 (Groene AI). - Fixes a
FixedStringtext try-parse that leaves partially appended bytes in the column when parsing fails, which can cause aSizes of nested column and null map of Nullable column are not equallogical error during serialization ofVariant/Array/Nullablecolumns, or silently shifted result bytes. #111908 (Groene AI). - Fixes
replaceOne,replaceAll,replaceRegexpOneandreplaceRegexpAllignoringmax_execution_timeandKILL QUERY. A single call now checks for cancellation while it works, so a long-running replacement over a large value or a large number of rows stops instead of holding a server thread until it finishes. Such a call has no partial result to return, so undertimeout_overflow_mode = 'break'it raises the deadline as an error: always when constant-folded, and in the pipeline whenever this checkpoint is reached before the executor’s between-block check, which still stops the query silently. #112483 (Groene AI). - Fixes a logical error and a wrong dependency record when an ordinary
VIEWbody references a table or dictionary through a query parameter, as inCREATE VIEW v AS SELECT x FROM {db:Identifier}.t. Such a view no longer records a referential dependency on a same-named table of the current database, so unrelated tables can be dropped again. #112704 (Groene AI). - Fixes a wrongly typed read of a
Nestedelement subcolumn whose column was dropped and re-added. Selecting such a subcolumn together with its own parent column returned the whole element in the subcolumn’s slot while the block still declared the element type, which produced arbitrary values in release builds and a logical error in debug and sanitizer builds. #112769 (Groene AI). - Fixed
Cannot read all data of type FixedStringwhen reading theproduct_quantization_codebooksubcolumn of a column with aQuantized('product',...)codec. The per-part codebook is written after the data of all granules, so it is not delimited by marks, and a read whose mark range ended before the part’s final mark could read it short. #112818 (Alexey Milovidov). - 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 (Groene AI). - Fix
connectionIdraisingContext has expiredwhen it is used inside a subquery by capturing the client’s connection id when the function is built. Closes #112533. #112870 (ClickGap AI Bot). - Fixed parsing of integers that do not fit into the target type in
Poco::NumberParser, which is used to read JSON numbers. Such a number was silently parsed as a wrong value (for example,18446744073709551617became1) instead of being rejected, and aUInt64number above theInt64maximum did not survive an AST JSON round trip. #112904 (Alexey Milovidov). - Fix
IS DISTINCT FROMforArrayandMapvalues compared withNULL. Closes #103042. #103162 (yanglongwei). - Prevent exhausted retries for leader-executed replicated distributed DDL from permanently blocking subsequent
ON CLUSTERDDL queries. #108505 (Ahaan Limaye). - Fix a
LOGICAL_ERROR(“Trying to extract chunk from ChunkBuffer before all inputs are finished”) when a set operation (INTERSECT/UNION ALL/EXCEPT) combines branches that use correlated subqueries andcorrelated_subqueries_default_join_kind = 'left'. #108554 (Groene AI). - Conversion of out-of-range floating-point values (
BFloat16,Float32,Float64) and ofUInt64values aboveInt64::max()toDateTimeandTimenow reliably saturates to the range boundaries on all architectures (previously the result of an out-of-range conversion was architecture-dependent and could wrap around on x86-64), and non-finite values (NaN,inf) now throw an exception instead of producing an arbitrary result. The same fix is applied to the float-to-Dateconversion path oftoDateand to the conversions ofUInt64and of wide integers ((U)Int128,(U)Int256) toDateandDate32, which could return a pre-epoch day instead of saturating. Conversion of a number toTimenow saturates to the range of the type for every numeric source type (previously values from narrow unsigned or wide integer sources were stored unclamped and clamped only when printed), and the accurate cast toTimeno longer rejects the negative values thatTimesupports, nor silently saturates the values that do not fit into it. The accurate cast of a number toDate32(accurateCast,accurateCastOrNull) no longer silently saturates an out-of-range or non-finite value, but throws or returnsNULLas it already did forDateandDateTime, and theOrDefaultflavours return the default value ofDate32for such an input. The accurate cast of a non-integral floating-point number toDate,Date32,DateTimeorTimeis now rejected instead of being silently truncated. Also fixed thetoDateTime32function documentation, which mistakenly showedtoDateTime64examples and described theDateTime64value range. #110459 (Alexey Milovidov). ALTER TABLE... DETACH PARTITION/PARTnow fsyncs the clone it creates underdetached/(the part subtree plus the directory chain up to the disk root) when the table’sfsync_part_directorysetting is enabled, for both Full (directory) and Packed part storage. Previously the clone was never fsynced while the empty covering part that removes the rows from the active set was, so a power loss right after the acknowledgement could destroy the detached data on btrfs (the un-synced clone directory entries roll back, leavingdetached/empty and nothing toATTACH). Gated on the existingfsync_part_directorysetting; default behavior is unchanged. #111426 (Groene AI).- Fix
CREATE OR REPLACEleaving the replaced object behind under an internal name when the caller lacks the drop privilege on it. #111466 (Nikolay Degterinsky). - Fixed a crash when running a
STREAMread (enable_streaming_queries = 1) over a table with more than one partition and a row policy defined on it. In debug and sanitizer builds it failed with theFilter column... not found in DAG outputslogical error; in release builds it could segfault. #111572 (Groene AI). - Fix
count()on Iceberg tables whose snapshot summary is inaccurate or corrupted: the trivial count optimization now derives exact row counts from the manifest files, and falls back to a real scan when row-level deletes make metadata counts inexact. Also fix IcebergOPTIMIZE TABLEwriting incorrect manifest-list counts and lineage, and maketotalBytesmetadata robust against corrupted summaries. #111617 (Melvyn Peignon). - Fix a DEFAULT column missing in a part being filled with the type default instead of the DEFAULT expression when the PREWHERE condition was split into multiple read steps. Closes #111757. #111795 (Yarik Briukhovetskyi).
- Fixed
Expected UInt64 column for __grouping_set, got BLOBandColumnBLOB should be converted to a regular column before usagelogical errors on a distributed query executed on a shard withenable_parallel_blocks_marshalling(enabled by default), for example withGROUP BY GROUPING SETSover a cluster that has a local replica, or when reading aMergetable that spans a local and a distributed table.BlocksMarshallingStepis no longer added to plans whose blocks are consumed in the same process. #111997 (Groene AI). - Operations now fail when corrupt MergeTree statistics are loaded instead of ignoring the error. #112201 (Sergey Kuznetsov).
- Fixes a logical error when PREWHERE is used on a Merge table over another Merge table or a materialized view whose column type differs. Also fixes a row policy being silently ignored on tables that read from remote servers (a Distributed table, or a table wrapping one), which could expose rows the policy was meant to hide; such queries are now rejected with an ILLEGAL_PREWHERE error. Define these policies on the underlying local tables on each remote server instead; note that such a policy is still not applied to reads shipped with
serialize_query_plan = 1, which is a separate, pre-existing bug. #112326 (Pedro Ferreira). - Fixes
connection_pool_max_wait_msso that its documented and default value0means an infinite timeout. A query that found the connection pool full used to retry in a tight loop, consuming CPU and loggingNo free connections in pool. Waiting 0 ms.on every iteration. It now waits until a connection is returned to the pool. Closes #112053. #112380 (Groene AI). - Fixes silent loss of acknowledged Iceberg writes on HDFS: an Iceberg commit publishes each new metadata file with a conditional write, but
HDFSObjectStoragedropped the condition and performed a plain overwrite, so concurrent writers were all acknowledged while one writer’s snapshot became unreachable. HDFS now refuses a conditional write instead, so storage-managed Iceberg writes on HDFS,CREATE TABLE... ENGINE = IcebergHDFS(...)with an explicit column list included, now fail. Reads are unaffected. #112437 (Groene AI). - Fix an out-of-bounds read (a crash in release builds) in insert deduplication when an
INSERTflows through a materialized view whose inner query changes the number of rows and the deduplicating target table is partitioned.DeduplicationInfo::filterToPartitionattributed each deduplication token to partitions by walking the token’s source-row range over a partition selector sized to the (smaller) view-output block, reading past its bounds. It now keeps every token in every partition for any materialized-view target — where the source-row-to-partition mapping no longer exists after the row count changed — instead of the out-of-bounds walk (and instead of theNOT_IMPLEMENTEDthat a later guard raised for the same insert). #112649 (Sema Checherinda). - Fixes a logical error (which aborts in debug and sanitizer builds) when
finalizeAggregationis applied to a column whose aggregate states come from different functions that share a state representation but finalize to different types — for examplequantileStateandquantilesState(0.9)brought together by aUNIONor produced viaarrayReduce. Such queries now raise a normal error instead of crashing. #112662 (Zain Ul Abidin). - Fix
DELETEonKeeperMaptables deleting only the firstmax_block_sizematched rows while reporting the mutation as successfully completed. Also fixDELETEwithkeeper_map_strict_mode = 1not being atomic: it could fall back to unversioned removals and delete rows that were concurrently updated, and it applied the matched rows block by block so a conflict could leave the delete partially applied. #112777 (Alexey Milovidov). - Fix
ALTERonMergeTreetables being applied while an incompleteRENAME COLUMNalter-mutation is still in progress. That could update the storage metadata incompatibly and block later mutations completely. #112783 (Mikhail Artemenko). - 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 (Nikolay Degterinsky). - Fixes a logical error when a
Jointable engine is used on the right side of a JOIN whoseONsection contains a condition referencing columns of both tables, for exampleON (t.key = j.key) AND (t.a < j.a). Such a query is now rejected with a clear exception instead of raisingrequired columns:... but not found any in left tableorstd::bad_variant_access. #112815 (Groene AI). - Fixes wrong results for a
JOINwhoseONclause carries a mixed condition, that is a cross-side non-equi residual such asON (t1.key = t2.key) AND (t1.a * 10 < t2.a). Only the hash family evaluates such a condition, butfull_sorting_merge,partial_mergeand the direct key-value join claimed they could run these joins and then silently ignored the residual, returning extra rows. They now decline, so a hash algorithm is used instead. #112831 (Groene AI). - 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). - Fix a quadratic slowdown when parsing a PromQL query with a long tail of unrecognized characters (e.g. a
FixedStringvalue padded with NUL bytes): the parse of a megabyte-sized invalid input used to keep a thread busy for tens of minutes and was uncancellable, because it happens during query analysis. Now the parser stops at the first error. #112944 (Alexey Milovidov). - Reject PromQL durations whose units are repeated or not ordered from longest to shortest. #112954 (Minh Vu).
- Fix a hang when writing
Parquetwithoutput_format_parquet_parallel_encodingenabled (the default) andmax_threadsgreater than 1. If the encoder failed to schedule an additional thread, its live-thread counter underflowed and the write could stop making progress permanently instead of finishing or reporting an error. #112959 (Groene AI). #113170 (Alexey Milovidov). - Fixed
geohashesInBoxspending an unbounded amount of time on a box of zero area, such asgeohashesInBox(0., 0., 180., 0., 12). Such a query returned the correct single geohash but burned roughly 5e8 empty loop iterations per row and ignored bothmax_execution_timeandKILL QUERY. #112976 (Groene AI). - Fixed undefined behavior (null pointer passed to
memcpy) inreplaceRegexpOne/replaceRegexpAllwhen the replacement string substitutes a capturing group that did not participate in the match, e.g.replaceRegexpAll('abc', '(a)|(b)', '\\2'). #113012 (Alexey Milovidov). - Reject a
SETTINGSchange marked as written without a value when it carries a value other thantrue, and never elide the value of such a change when formatting a query. Previously a crafted AST JSON payload could execute aBoolsetting withfalsewhilesystem.query_logandformatQueryFromJSONshowed the valueless form. #113025 (Alexey Milovidov). - Fixed undefined behavior and a silent scheduling error when a background task is scheduled with a very large delay, for example by a refreshable materialized view with a huge
REFRESH AFTERperiod. Delays are now bounded to the largest representable value instead of overflowing. #113041 (Groene AI). - 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 (Groene AI). - Fixed
intDivon a non-constant column with the constant divisor -1 silently wrapping the division of the minimal signed number (e.g.intDiv(-9223372036854775808, -1)) instead of throwing theILLEGAL_DIVISIONexception like the other execution paths do. The silent wrap could also produce wrongORDER BY/DISTINCTresults, because the read-in-order optimization correctly treatsintDivby a negative constant as monotonic, and the wrapped value violated the resulting sort order. #113048 (Alexey Milovidov). - Fix an incompatibility that text indexes created in ClickHouse 26.3 with
unicode_wordtokenizer cannot be loaded in later versions. #113061 (Robert Schulze). - Fixed a
Pipeline stucklogical error in queries that scatter data by partition, such as a window function withPARTITION BYor a join withjoin_algorithm = 'parallel_full_sorting_merge', when one shard’s downstream finished while a block was only partially distributed. #113190 (Groene AI). - 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 (Groene AI). - Fix
ALTER TABLE ... ADD PROJECTIONover a table-levelALIAScolumn leaving the table unusable, with subsequentINSERTfailing withUNKNOWN_IDENTIFIER(Missing columns), when the session hadoptimize_respect_aliases = 0. #109091 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKandLOGICAL_ERRORexceptions in adirectJOINover aMergeTreeright table, and related aborts in debug and sanitizer builds. #109932 (Groene AI). - Fix comparisons that previously threw
ILLEGAL_TYPE_OF_ARGUMENTwhen the operands have no least common supertype. Arrays such asArray(Int64)vsArray(UInt64)andArray(Int256)vsArray(UInt256)can now be compared lexicographically with=,!=,<,<=,>,>=,IS DISTINCT FROM, andIS NOT DISTINCT FROM.isDistinctFromandisNotDistinctFromnow also compare supported non-array numeric and decimal pairs by value instead of throwing, and equality comparison for arrays nested insideTuple(Nullable(...))is also fixed. Closes #33897. #110245 (Diego Gomes Tomé). - Fix 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 (Groene AI). - Fix wrong results for a
FULL JOINon aJoinengine table withUSINGwhen the left key isNullableand the storage key is not: an unmatched left row with aNULLkey returned0instead ofNULL. #111371 (Groene AI). - Fix stale and deleted row versions being visible when a
MaterializedPostgreSQLdatabase is read through aMergetable. Such reads now go through theMaterializedPostgreSQLwrapper, with the sameFINALand_sign = 1filtering as direct reads. #112382 (Alexey Milovidov). - Fix
Bad cast from ColumnNullable to ColumnStringwhen a mutation that rewrites the whole part runs on a part whose column type is older than the one in the table metadata, for example afterALTER TABLE ... MODIFY COLUMNfollowed byALTER TABLE ... MATERIALIZE PROJECTION. #112501 (Alexey Milovidov). - Fix row-based input formats ignoring
KILL QUERYandmax_execution_timefor minutes while parsing a block. They now check for cancellation every 8192 rows, so a killedINSERT(including a background async-insert flush) stops promptly instead of running to the end of the block. #112646 (Groene AI). - Fix
RENAME TABLEchecking the maximum table name length against the source database instead of the destination one. Renaming a table into a database with a long name could produce a table thatDROP TABLEcould not remove, and renaming a table out of such a database was wrongly rejected. #113019 (Groene AI). - Fix
UNKNOWN_IDENTIFIERwhen selecting from aVIEWwhose declared column types differ from the types its inner query produces, for exampleSELECT sum(length(arr)) FROM vwherevdeclaresarr Array(UInt8)over aStringcolumn. With the defaultoptimize_functions_to_subcolumns = 1, the optimizer rewrotelength(arr)into a read of thearr.size0subcolumn and forwarded that name into the inner query, which has no such subcolumn. #113057 (Groene AI). - Fixed an exception (in release builds, an error that prevents the server from starting) when a mutation predicate uses the
mergetable function without an explicit database name. The database of the mutated table is now used, the same way as for table names. #113185 (Alexey Milovidov). - Fix wrong results and a
LOGICAL_ERRORwhen reading a subcolumn of a dropped-and-re-addedNestedmember together with a present member of the same group, on aMergeTreetable withshare_nested_offsets = 1. The present members returned values from a later block whenever the read spanned more than one block. #113225 (Groene AI). - Fix a hang of
ALTER,OPTIMIZE,TRUNCATE, and partition-manipulation statements withalter_sync = 2onReplicatedMergeTreewhen the table starts shutting down while the statement waits for another replica, for example because of a concurrentDROP DATABASE ... SYNC. Such a statement now fails withUNFINISHEDand also honorsmax_execution_timeandKILL QUERY. #113228 (Groene AI). - Do not write ANSI escape sequences to
INTO OUTFILEwhenstdoutis a TTY. #113252 (Azat Khuzhin). - Fix a rare use-after-free in the async insert queue when different entries have identical deadlines. #113363 (Miсhael Stetsyuk).
- Fix silently empty tables when more than one
ENGINE = Backupdatabase is created from the same backup, or when such a database is recreated under a different name. The storage policy that backs aBackupdatabase is now identified by a name that also covers the local database name, so each database gets the disk built for its own data path. #113378 (Groene AI). - Fix rows never being deleted when a
MergeTreetable has two or moreTTL ... DELETE WHERErules whose time expression is identical and which differ only in theWHEREcondition. After a TTL delete merge, the part’srows_where_ttl_infowas reset to zero, so no further TTL merge was ever scheduled for it and the expired rows were retained indefinitely with no error or log message. Closes #113116. #113384 (Groene AI). - A query over a
Mergetable (or themergetable function) that matches many tables now reacts toKILL QUERYandmax_execution_timewhile the per-table query plans are being built, instead of only after the planning of all children has finished. Withtimeout_overflow_mode = 'break', it now also stops building query plans for the remaining matched tables and returns the partial result without an error, as that mode documents. #113415 (Alexey Milovidov). #113642 (Groene AI). - Fix
clickhouse-clientexiting with code139instead of0after cancelling a query with Ctrl+C, or after anINSERTthat reads data from stdin. #113431 (Groene AI). - Allow the
preprocessorandpostprocessorexpressions of a text index to referenceALIAScolumns. #110014 (Jimmy Aguilar Mena). - Fixed several cases where parallel replicas returned duplicated rows:
distributed_aggregation_memory_efficientwas ignored by plan-based parallel replicas, so the buckets of the memory-efficient merge arrived out of order and were merged twice; and a shard was read from all of its replicas although the data was not split between them, when parallel replicas were not applicable to the query or whenparallel_replicas_moderequested custom-key filtering withoutparallel_replicas_custom_key. #112942 (Nikita Taranov). - Fixed
CREATE TABLE ... AS SELECTbecoming unkillable when its populatingSELECTfailed anddatabase_atomic_wait_for_drop_and_detach_synchronouslywas enabled: the internal cleanupDROPof the temporary table waited for the background drop queue and ignored bothKILL QUERYandmax_execution_time. #113504 (Groene AI). - Fixed
ALTER TABLE ... EXECUTE remove_orphan_filesdeleting a livemetadata/version-hint.textfile of anIcebergtable. Its reachable-set entry was built by string concatenation assuming a trailing slash on a value that never has one, so the real hint file was never recognized as reachable and was removed once older than theolder_thanthreshold. Withiceberg_use_version_hint = 1, the table then failed to read at all. #113548 (Groene AI). - Fixed a parameterized view losing its database when a query referencing it without qualification was sent to a shard, so the shard resolved the name against its own default database. Depending on what that database contained, the query either failed with
UNKNOWN_FUNCTIONor silently returned rows from a different view. AffectsIN,JOIN, andremotethrough aDistributedtable. #113550 (Groene AI). - Fixed a
LOGICAL_ERRORwhen a query filterssystem.databaseson thenamecolumn with a subquery insideindexHint, for exampleSELECT count() FROM system.databases WHERE indexHint(name IN (SELECT 'foo')). #113556 (Groene AI). - Fixed an endless loop in background merges and
OPTIMIZEwhenmerge_max_block_size_byteswas set below thebyteSize()of an empty column. An emptyLowCardinalitycolumn still carries its dictionary, so the byte limit could be reached before a single row was merged; the merge then produced empty blocks forever, burning 100% of a CPU core and never releasing its background-pool slot. #113585 (Groene AI). - Fixed a query over a
Variantcolumn ignoringmax_execution_timeandKILL QUERY. Calling a function with severalVariantarguments resolved the function once per alternative of every argument, and neither of the two loops doing that work checked for cancellation, so such a query could not be stopped until it finished. #113612 (Groene AI). - Fixed
Unknown compression methodfor theautoandnonecompression hints when written in any letter case other than all-lowercase, for examplefile('data.csv.gz', 'CSV', 'x String', 'AUTO'). Codec names such asGZIPwere already accepted case-insensitively; the two special hints now behave the same way. #113631 (Groene AI). - Fix constant folding under the new analyzer changing the type of a constant
Geometryvalue.Geometryis a namedVariantwhose alternatives can share the same storage layout (LineString/Ring,MultiLineString/Polygon, and empties), so two folded constants that differed only in their alternative could collapse into one, e.g.MULTIPOLYGON EMPTYbecameLINESTRING(). #110709 (Groene AI). - Fix an exception (
Cannot calculate columns sizes when columns or checksums are not initialized) during a merge of a single-columnMergeTreetable whose only column has a fully expiring columnTTL, withmin_bytes_for_wide_part = 1. #111169 (Groene AI). - Failing to start a background schedule pool (for example the
icebergpool under global thread-pool exhaustion) no longer aborts the server: the error is now a recoverable exception. Readingsystem.background_schedule_poolalso no longer creates those pools as a side effect. #111209 (Groene AI). - Fix an out-of-bounds read in the native protocol on corrupted index data. #112331 (Pavel Kruglov).
- Fix a deadlock that permanently hangs a
FilesystemorHDFSdatabase when two queries resolve the same table name at the same time. Every later query against that database blocks forever and cannot be interrupted, so the server needs a restart to recover. #112495 (Groene AI). - Fix
max_execution_timeandKILL QUERYbeing silently ineffective for a distributed query that is establishing connections to replicas. Such a query now stops at the next connection attempt instead of working through every remaining replica and retry. #112689 (Groene AI). - Fix
DROP TABLEandSYSTEM STOP VIEWhanging when a refreshable materialized view is blocked while planning its refresh query. #113188 (Nikolay Degterinsky). - Fixed
CREATE TABLEwithENGINE = Distributed(...)orENGINE = Buffer(...)and no column list revealing the structure of a referenced table the creating user is not allowed to see. For a localCREATE, the structure is now inferred under the user’s own context, soSHOW COLUMNSon the referenced table is required. ACREATEreplayed from the DDL queue (ON CLUSTER, or inside aReplicateddatabase) is not covered. #113220 (Groene AI). #113372 (Groene AI). - 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. 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
countSubstrings,countSubstringsCaseInsensitive,countSubstringsCaseInsensitiveUTF8,countMatches, andcountMatchesCaseInsensitiveignoringKILL QUERYandmax_execution_time: a call over many rows, many matches, or one large value could run for minutes after the query was cancelled. #113369 (Groene AI). #113886 (Groene AI). - Fixed a mutation of a Compact part producing a different result depending on whether the part’s serialization info was still in memory or had been reloaded from
serialization.json, when the table usesserialization_info_version = 'basic'. OnReplicatedMergeTree, this made two replicas holding a byte-identical source part write different mutated parts, and the mutation failed withCHECKSUM_DOESNT_MATCH. Closes #113500. #113588 (Groene AI). - Fixed
made_current_atinsystem.iceberg_historyreporting the earliest time a snapshot became current instead of the latest one, when the samesnapshot-idappears more than once in theIcebergsnapshot-log(as a rollback leaves it). #113598 (Groene AI). - Fix wrong values for virtual columns such as
_tableor_databaseselected from the right side of aJOINagainst a key-value source such asEmbeddedRocksDB,KeeperMap,Redis, or a dictionary. The query could return a data-column value instead, or fail with aLOGICAL_ERRORexception. #113698 (Groene AI). - Fix
EXPLAIN ANALYZEover aMergetable with several children, a bare-columnPREWHERE, and a separateWHEREfailing withRequired output position N is out of range for pass-through inputs. Closes #113621. #113725 (Groene AI). - Fixed
clickhouse-disks moveof a directory failing withDIRECTORY_ALREADY_EXISTSon disks withmetadata_type = plain_rewritable(for examples3_plain_rewritable), which also left an empty destination directory behind. #113727 (Groene AI). - Fix
Mergetable reads failing withNo set is registered for key ...when a child declares anALIAScolumn containingINand the children disagree about that column’s default. #113757 (Groene AI). - Fixed
UNKNOWN_IDENTIFIERwithenable_analyzer = 0when aWHERErefers to a column produced byuntupleinside a subquery, for exampleSELECT t.keys FROM (SELECT untuple(arrayJoin(m)) AS t FROM ...) WHERE t.values > 0. Theenable_optimize_predicate_expressionrewrite pushed such a predicate into the subquery as aHAVING, where the name does not yet exist. #113760 (Groene AI). - Fix
ALTER TABLE ... MODIFY COLUMNfailing withCannot specify codec for column type ALIASwhen one statement both turns anALIAScolumn into a physical one (DEFAULTorMATERIALIZED) and specifies aCODEC. Closes #113693. #113853 (Groene AI). - Fix
ORDER BY ALLandGROUP BY ALLover a joinedMergetable under the old analyzer (allow_experimental_analyzer = 0). The query no longer fails with an internal exception, and debug and sanitizer builds no longer abort. #109139 (Groene AI). - Fix a sporadic
Cannot parse string ... as UInt64 ... While executing ValuesBlockInputFormatexception that could occur when inserting values whose expressions contain a numeric cast, such asinitializeAggregation('sumState', 0::UInt64). #110637 (Groene AI). - Fixed the periodic local disk check reporting failures for a healthy disk. When a server runs an embedded Keeper alongside a
localdisk, two check threads could probe the same file, transiently logFILE_DOESNT_EXIST,CANNOT_READ_ALL_DATA, orCANNOT_UNLINK, and temporarily count the disk in theBrokenDisksmetric. #110773 (Groene AI). - Fixed wrong results and a logical error
Cannot serialize FutureSetFromSubquery with no query planfor queries overMergetables and themergetable function when plan-based parallel replicas were enabled. #112849 (Alexey Milovidov). - A table in the
URLdatabase engine no longer discloses whether a local file exists to a user without the read source grant. BothEXISTS TABLE, which requires only theSHOW TABLESprivilege, and table-name resolution now wait for the grant check before probing the filesystem. #113029 (Alexey Milovidov). - Fixed a TTL expression becoming unusable when constant folding pruned the columns it refers to, for example
TTL d + INTERVAL 1 DAY DELETE WHERE isNull(x)over a non-Nullablex, which made everyINSERTinto the table fail withMissing columns. Also fixed the server failing to start when a table had a TTL expression over aVariantcolumn created withvariant_throw_on_type_mismatch = 0. #113042 (Alexey Milovidov). - Fixed cancellation of
postgresqltable function andPostgreSQLtable engine reads. Cancelling while the read was still starting up could race on the transaction pointer and be lost, leaving the query running until PostgreSQL finished it. #113150 (Groene AI). UNDROP TABLEcan now be interrupted byKILL QUERYwhile it waits for running queries to release the dropped table. #113263 (Alexey Milovidov).- Fix a memory leak of the whole XML parser when a
PocoXML handler throws mid-parse, for example onPoco::XML::NamePooloverflow while parsing a document with many unique element names. #113348 (Alexey Milovidov). - Fixed writes to the
HDFSdisk: they no longer fail withParent directory doesn't existwhen the generated object key contains nested directory prefixes, because the missing parent directories are now created. #113396 (Alexey Milovidov). - Fix wrong results and, in builds with assertions enabled, an aborted assertion for a
JOINonto a dictionary whoseONclause has a non-equi condition over both tables, such asON (t.key = d.key) AND (t.a * 10 < d.a), whenjoin_use_nullsis enabled. #113534 (Alexey Milovidov). - Fix a query hanging for up to
receive_timeoutseconds when it finishes very quickly on the initiator. #113551 (Nikita Taranov). - Fix
UPDATEand lightweightDELETEreading the wrong tables when the database of the updated table differs from the session database. Unqualified table names and themergetable function are now resolved against the database of the updated table, so the statement no longer silently updates or deletes rows selected from a different table. #113748 (Groene AI). - Fix a spurious
TOO_MANY_PARTSrejection of a parallelINSERT: whenmax_insert_threadsparallelizes a plainINSERT, the query no longer counts parts committed by its own sibling sinks. Closes #114015. #114016 (Alexey Milovidov). - Fixed
NO_SUCH_COLUMN_IN_TABLEwhen a query with parallel replicas selects anALIAScolumn of a table shipped as aGLOBAL JOINtemporary table,MULTIPLE_EXPRESSIONS_FOR_ALIASwhen both sides of a distributedJOINdeclare anALIAScolumn with the same name, andUNKNOWN_IDENTIFIERwhen aDistributedtable declares anALIAScolumn over anotherALIAScolumn, including as aJOIN USINGkey. #107700 (Yakov Olkhovskiy). - Fixed reading a CSV
Tuplewhose leading element isNULL. Withinput_format_csv_deserialize_separate_columns_into_tupleandinput_format_null_as_defaultenabled, a leading\Nin a row such as\N,1was taken for the whole column beingNULL, so the row was replaced by a default and the remaining element cells caused a parse error. The leadingNULLis now the value of the first element, withinput_format_null_as_defaultapplying to that element. A row that gives a single\Nfield for a whole bareTupleis now short by the remaining elements and is rejected; setinput_format_csv_deserialize_separate_columns_into_tuple = 0to read such a field as the whole column again. #109744 (Groene AI). - Fix a rare
Logical error: 'No more packets are available.'for a valid distributed query with aLIMIT. In debug and sanitizer builds it also aborted the server. #110334 (Groene AI). - Fixed a logical error (
!part.empty()) when aDistributedtable defined with an empty remote database name is used in aJOINwithdistributed_product_mode = 'local'. #110677 (Groene AI). - Fix resolution of fully qualified column names such as
db.table.columnin the analyzer for tables that have the same name as their database. Closes #82084. #110976 (Alexey Milovidov). - Fixed hash joins losing their post-build optimizations (conversion to a fixed hash table, the shared runtime filter, right-table reranging) whenever an automatic spill-to-disk threshold was configured, which has been the default since 26.5. #111972 (Alexey Milovidov).
- Fixed a bug where
ALTER TABLE ... MODIFY COLUMNthat changes aJSONtype hint (withallow_experimental_json_lazy_type_hintsenabled) on a column whose subcolumn is used in the primary/sorting key, partition key, or an explicit skip index could corrupt the on-disk key or index. Ordinary reads masked it via the cached structure, but after it was reloaded (for example on server restart) queries failed withCANNOT_READ_ALL_DATAor returned wrong results. SuchALTERs are now rejected whenever they change the on-disk type of a referencedJSONsubcolumn. Type-hint changes on columns outside those structures, or changes that leave the on-disk type of the referenced subcolumns unchanged (for example adding an unrelated typed path), remain metadata-only. #112302 (Pavel Kruglov). - Fix wrong results when
query_plan_join_swap_tableswaps anANY JOINwhilejoin_any_take_last_row = 1: ClickHouse now keeps the original join side order soANY JOINstill returns the last matching row. Closes #111645. #112458 (Vladimir Cherkasov). - Fixed
listObjectson a prefixed-endpointAzureBlobStoragedisk returning wrong blob names on every page after the first, because pagination bypassed the client wrapper that strips the endpoint prefix. Pagination now re-enters the wrapper via the continuation token so every page’s blob names are correct. #112872 (Arsen Muk). - Fixed unbounded memory allocation when reading a
Parquetfile whose Thrift metadata declares a container or string length larger than the metadata itself. Such a length is now rejected instead of being allocated for. #113212 (Groene AI). - Fixed
Cannot insert element into Set(NOT_IMPLEMENTED) whenread_in_order_use_virtual_rowis enabled and aMergeTreeread-in-order query combinesWITH FILL ... INTERPOLATEwith anINorhasfilter. #113264 (Groene AI). - Fix
optimize_read_in_orderbeing silently skipped for someORDER BYqueries, including queries that use a virtual row ortoString/CAST(..., 'Nullable(String)')over aStringsorting key. Also fix wrong results for filters orORDER BYontoStringofTime,Time64, orDateTimevalues in time zones with daylight saving time. #113291 (Vladimir Cherkasov). - Reject invalid
parallel_replicas_custom_keyexpressions such astuple()or(x, y)withILLEGAL_TYPE_OF_COLUMN_FOR_FILTERinstead of reading past the end of the custom-key type list. #113359 (Nikita Taranov). - Fix a server restart failure after the server is killed during
DROP TABLEof a table that uses a named collection: a laterDROP NAMED COLLECTIONcould succeed, leaving table metadata that references a missing named collection and making the next startup fail withNAMED_COLLECTION_DOESNT_EXIST. #113524 (Alexey Milovidov). - Fixes two cases where an AWS Glue
DataLakeCatalogdatabase reported a table as absent instead of reporting an error.SHOW TABLESandsystem.tablesno longer fail withDATALAKE_DATABASE_ERROR(“Exception calling GetTables … not found”) when a Glue database is absent while its tables are listed, for example because an unrelated database in the same AWS account was dropped concurrently; such a database now contributes no tables instead of aborting the listing.EXISTS TABLEno longer returns0for a table that exists when the underlyingGetTablecall fails for a reason other than the table being absent, such as an authentication, DNS, or 5xx failure. Every other Glue error still propagates in both paths. #113591 (Groene AI). - Fixed a Keeper durability bug where a crash while persisting the Raft state file (storing
termandvoted_for) could leave the node with no valid state and no backup. On restart the node could reset toterm = 0and grant a vote it had already granted in that term, which could cause two leaders and loss of committed data. The previous state is now kept until the new state file is fully written and synced. #113654 (Alexey Bakharew). - Fix a data race when a
MergeTreetable is destroyed while its background statistics-refresh, parts-refresh, or outdated/unexpected-parts-loading tasks are still running. #113722 (Alexey Milovidov). - Fix
ORDER BY ALLin aWINDOW VIEW, andUNKNOWN_IDENTIFIERerrors forINTERPOLATE,WINDOW, andLIMIT BYin a query over aMergeorDistributedtable with a join, with the old analyzer. #113759 (Alexey Milovidov). - Fix a memory leak in the experimental
SZ3compression codec: when compression of poorly compressible or corrupted data failed with an exception, temporary scratch buffers were left allocated. #113916 (Alexey Milovidov). - Fix quadratic complexity of parsing the address argument of the
remote,mysql, and similar table functions: a very long address (for example a megabyte-sized zero-paddedFixedString) made the query hang during analysis, where it could not be cancelled. #113918 (Alexey Milovidov). - Fixed
OPTIMIZE TABLEon anIcebergtable failing withUnsupported snapshot's operation type OVERWRITEwhen the table’s history contained a row delete that removed more than one row per position-delete file. Closes #113745. #113964 (Groene AI). - Do not replicate
ALTER TABLE ATTACH PARTITION FROMfor replicated db. #94835 (MikhailBurdukov). - Invalid Azure upload-size settings (for example
azure_min_upload_part_size = 0orazure_max_blocks_in_multipart_upload = 0) are now rejected early with a clear error instead of triggering an internal exception (second_size > 0) deep in the write path. This applies to both query settings and Azure disk configuration. #103394 (Statxc). - Fixed incorrect SQL literal escaping in
StorageSQLiteandsqlite()table function when pushingWHEREpredicates to SQLite: single quotes and control characters (\n,\r,\t,\) were escaped with backslashes, which SQLite does not interpret, causing syntax errors or wrong query results. Also fixed the escaping of string literals pushed down to PostgreSQL: strings nested insideINlists kept ClickHouse escaping, and control characters were sent as backslash sequences that PostgreSQL reads back as different bytes. #104217 (Shaohua Wang). - Fix
NOT_FOUND_COLUMN_IN_BLOCKexception inINNER JOIN ... ON arrayJoin(...) = ...queries whenquery_plan_convert_join_to_inis enabled and the SELECT references the source array column. #104809 (Shaohua Wang). - Fix IN and NOT IN expressions with non-constant right-hand side operands referencing columns from the current row, and align new analyzer tuple right-hand side handling with existing ClickHouse IN semantics. Under the old analyzer, a bare source column as the right-hand side (
x IN (arr)) still resolves as a table name and stays out of scope. #104993 (Yue Ni). - Fixed the error
Cannot add column ...: column with this name already existsonINSERT SELECTfrom a table function such asfile,s3orinput, when the same source column is selected more than once. #105982 (etienne). - Reject
max_replication_lag_to_enqueue = 0onReplicateddatabases. The value made the post-recovery unsynced check trivially true and aborted the server withLOGICAL_ERRORin debug and sanitizer builds.0is now rejected at parse time withBAD_ARGUMENTSfrom every source (CREATE DATABASE ... SETTINGS,<database_replicated>server-config block,ATTACHreplay, and upgrade-time replay of existing metadata). The smallest valid value is1. Closes #98823. #106006 (Groene AI). - Fix
Logical error: 'Pipeline stuck'in queries that useenable_sharding_aggregator = 1together with aUNION ALLandmax_streams_for_union_stepsmaller than the pipeline width.BufferedShardByHashTransformnow finishes empty-queue output ports as soon as its input is exhausted, and keeps pulling input when a demanded empty port has nothing drainable even if a sibling queue hit the back-pressure cap. #106251 (Groene AI). - Fixed a signed integer overflow when a wait-timeout setting, such as
interactive_delay, was set to a huge value: the wait could time out immediately instead of waiting, and the server could abort under the Undefined Behavior Sanitizer. #106961 (Groene AI). - Exporting
Time/Time64values outside a valid time-of-day (negative or>= 24h) to theArrowformat is now rejected with a clear error instead of writing invalid Arrowtime32/time64data. #107179 (Shaohua Wang). - Fix wrong results for
GROUP BYon aDistributedtable over duplicateALIAScolumns that expand to the same expression (e.g. two columns both defined astoString(x)) under two-level / memory-efficient distributed aggregation. The duplicate keys were collapsed into one on the shards but merged by the full key set on the initiator, so under two-level aggregation equal groups from different shards landed in different buckets and were not merged, returning a group once per shard with a splitcount(). #108855 (Groene AI). - Fixed a spurious
Inconsistent AST formattingerror forALTER TABLE ... MOVE PART ... TO SHARD '<path>'. The query formatter dropped theSHARDkeyword, so the reformatted query could not be parsed back, raising aLOGICAL_ERROR(a handled exception in release builds, an abort in debug and sanitizer builds). #109060 (Groene AI). - Rejects non-monotonic
Arrayoffsets on every read path that decodes them as absolute values, instead of only in theNativeformat. A corruptsetskip index granule previously passed unchecked and was then read out of bounds. #109212 (Groene AI). JSONExtractnow honourscast_string_to_date_time_modewhen converting string JSON values toDateTime/DateTime64, consistently withCAST. Closes #109126. #109252 (Utkal Singh).- Fix possible logical error “Unexpected substream … for column …” during bump of compatibility setting. #109496 (Pavel Kruglov).
- set missing coordination component in system.detached_parts size calculation. #109553 (Den Kalantaevskii).
- Fixed the block-wait timeout of streaming inserts (
input_format_max_block_wait_ms) potentially never expiring while the query profiler is active: the file-descriptor poll restarted with the full timeout after every profiler signal, so a stalled input source could delay the partial-block flush indefinitely instead of flushing when the wait limit is reached. #109602 (Shaohua Wang). - Constant folding during query planning no longer executes a function whose argument type differs from the type the function was resolved for during analysis. Such a mismatch used to raise a
LOGICAL_ERRORwhile the output header was being computed, which is an assertion failure in debug and sanitizer builds. Folding is now skipped instead, and a genuinely invalid query still reports a recoverableILLEGAL_TYPE_OF_ARGUMENTerror from the normal execution path. #109747 (Groene AI). - Fixes a mutation that references the
_sample_factorvirtual column failing mid-execution withUnexpected const virtual column: _sample_factorand leaving the mutation stuck. A mutation now reads it as1, the same value a query withoutSAMPLEreturns. #109813 (Groene AI). - Fix three issues with
use_constant_folding_in_index_analysis: a logical errorInvalid partition key sizethat could abort aSELECTusing a normal projection when the table setspart_minmax_index_columns = 'with_block_number_offset'; wrong results (silently dropped rows) for a filter on a modulo partition key such asPARTITION BY id % 200; and a crash (data race) when atextindex with asparseGramstokenizer is queried with aLIKEpredicate over many partitions withmax_threads > 1. #109896 (Groene AI). - Fix a data race (and rare crash) when a parsing/analysis error is reported while reading a file/object storage table. A parse error raised during lazy
KeyConditioninitialization was shared as a single exception object across reader threads, and two threads could concurrently append(in file/uri ...)to its message, racing on the exception message string. #109911 (Groene AI). - Fix propagation of query settings in
accurateCastOrDefault, and preserve sourceNULLs encoded byDynamicandVariant. Closes #109943. #109946 (Pavel Kruglov). #114912 (Alexey Milovidov). - Fixed incorrect results from
subBitmap,bitmapSubsetInRangeandbitmapSubsetLimitfor bitmaps still held in the small representation, includingUInt64andInt64element values above2^32, which were truncated to 32 bits. Comparisons in bitmap functions over signed element types now consistently use the unsigned value of the element type, so in anInt8bitmap the element-1is compared as255instead of as the sign-extended4294967295; this also fixesbitmapMin,bitmapMax,bitmapContainsandbitmapTransformon bitmaps that have grown past the small representation. Queries that passed sign-extended thresholds have to be adjusted: over anInt8bitmap,bitmapSubsetInRange(bm, 4294967168, 4294967296)becomesbitmapSubsetInRange(bm, 128, 256). Also fixedgroupNumericIndexedVectorreturning different results forInt8andInt16index columns than for wider index types, andnumericIndexedVectorGetValuereturning0for negative indexes. Corrected the bitmap function documentation, including the subset functions that were described as using 1-based indexing and the signedbitmapBuild/bitmapToArraysupport. #110072 (Rami Darwiche). - Fix
optimize_aggregation_in_orderignoring query cancellation.AggregatingInOrderTransformnow checks for cancellation while aggregating a chunk, so a query stopped byKILL QUERYor bymax_execution_time(in the defaulttimeout_overflow_mode = 'throw') stops promptly instead of running the whole chunk to completion. #110104 (Groene AI). - Fixed a race between
KILL TRANSACTIONandALTER TABLE ... UPDATE/DELETEexecuted inside a transaction: a rollback landing between the mutation’s registration in the transaction and its registration in the table left an orphaned mutation entry, which raised a logical error (Cannot find transaction ... that has started mutation ...) in background jobs and blocked all subsequent mutations of the affected parts until server restart. #110226 (Shaohua Wang). - Fix a
LOGICAL_ERROR(Left and right columns have same names) in the join order optimizer that could be triggered by a comma join over a multi-table view whenquery_plan_merge_expression_into_joinis enabled. #110227 (Groene AI). - Join-order cardinality estimation now composes column statistics over the parts surviving partition/PK pruning instead of all active parts. Previously a query pruned to a small partition was planned against table-wide statistics (observed 2500x row overestimation flipping the hash-join build side), and disabling statistics paradoxically produced a better plan. Also fixed: lazy FINAL was silently disabled for MergeTree relations under a JOIN because the join-order optimizer’s memoized index-analysis result was mistaken for an applied projection. #110283 (Sergey Kuznetsov).
- Fixed wrong results from correlated scalar subqueries when the outer query has duplicate values for the correlated column and the subquery is decorrelated via the CROSS JOIN path. Previously aggregates such as
count()andsum()were multiplied by the duplicate count. This affects the experimentalallow_experimental_correlated_subqueriesfeature. #110311 (Groene AI). - Fix a logical error (
Function node with name '...' is not resolved as ordinary function) that could occur withoptimize_or_like_chainenabled when an aggregate or window function appeared on the left-hand side of aLIKE/ILIKE/matchinside anORchain. #110641 (Groene AI). - Fix a
TTL ... DELETE WHERE <cond>never removing rows that started matching<cond>because of anALTER TABLE ... UPDATEon a column referenced in theWHERE. The mutation now recalculates the row TTL, so the newly matching expired rows are deleted instead of being silently retained. #110648 (Groene AI). - Fix an accounting leak in memory tracking: when an allocation was rejected by a parent memory tracker (for example, the server-wide memory limit), the thread, query, and user level trackers kept the rejected amount. The error accumulated over time, inflating
MemoryTrackingand per-query/per-user memory usage, and could lead to spuriousMEMORY_LIMIT_EXCEEDEDerrors. #110784 (Seva Potapov). - Fixed non-canonical WKB serialization of an empty polygon:
wkb(POLYGON EMPTY)now emitsnumRings = 0instead of a spurious single zero-point ring, so a WKB round-trip of a standard empty polygon is identity-preserving. #110796 (Groene AI). - Fixes a case when using CTE column aliases with
INTERSECTorEXCEPTqueries, e.g.WITH t (a, b) AS (SELECT 1, 2 INTERSECT SELECT 1, 2) SELECT a, b FROM t, the query was failing with UNKNOWN_IDENTIFIER error. Closes #104770. #110885 (Yarik Briukhovetskyi). - Fixed a
std::length_error(LOGICAL_ERROR) when reading a MergeTree table with a pathologicalmax_streams_for_merge_tree_readingvalue (near the maximum ofUInt64) together withallow_asynchronous_read_from_io_pool_for_merge_tree = 1. The setting is now clamped to the same ceiling asmax_threads. #110936 (Groene AI). - Fixes a crash (null pointer dereference during query analysis) when
getSubcolumnis called on aJSONargument with an internal type-hint subcolumn name, that is one starting with a backtick type marker. #110940 (Groene AI). - Fixed
Nested type LineString cannot be inside Nullable type (ILLEGAL_TYPE_OF_ARGUMENT)when reading a nullable MySQL spatial column (LINESTRING,POLYGON,MULTILINESTRING,MULTIPOLYGON,MULTIPOINT, or the genericGEOMETRY) through themysqltable function or theMySQLtable/database engines. Such columns now fall back toNullable(String)holding the value as MySQL returns it (a 4-byte SRID prefix followed by the WKB payload).POINTkeeps mapping toNullable(Point). #110943 (Groene AI). - Fixes
Nativeserialization ofSimpleAggregateFunctionwrappers containing versioned aggregate states for older peers. #110997 (Groene AI). - Fixed a
LOGICAL_ERROR: ReadBuffer is canceled. Can't read from it.that could occur in agrace_hashjoin when reading spilled blocks failed mid-read while multiple threads shared the reader. #111056 (Groene AI). - Each SSH key now counts individually toward the
max_authentication_methods_per_userlimit, so the limit applies consistently regardless of syntax. Previously, multiple keys in a singlessh_keymethod counted as one. #111181 (Yecine Megdiche). - Fix a
LOGICAL_ERROR(Reading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query plan) when a reused materialized CTE (enable_materialized_cte) is read on a branch whoseWITH TOTALSorextremesoutput is discarded, including outer aggregation,INSERT ... SELECT, set operations andEXPLAIN ANALYZE. #111194 (Groene AI). - Fixed
map[key]returning the value of a later duplicate key instead of the first one. When aMapcolumn contained duplicate keys, the result ofmap[key]could depend on preceding rows in the same block and on theoptimize_functions_to_subcolumnssetting, so aSELECTand aWHEREover the same row could disagree. #111246 (Groene AI). - Fix a logical error
!rhs_literal->getValue().isNull()in the logical-expression optimizer when anANDchain compares a column against a NULL-valued constant of a non-Nullabletype (for example a NULL-valuedVariant) withuse_variant_default_implementation_for_comparisons = 0. #111292 (Groene AI). - Fixed
NOT_FOUND_COLUMN_IN_BLOCK/THERE_IS_NO_COLUMNerrors (and, on some releases, silently wrong results) for aRIGHT JOINwhenparallel_replicas_min_number_of_rows_per_replicais set and a left-table column is projected. #111332 (Groene AI). RESTOREnow fsyncs the restored part files when the destination table hasfsync_after_insertenabled, so a restored part is as durable against power loss as an inserted one. Previously restored files were only written and closed (never fsynced), so a power loss right afterRESTOREreturnedRESTOREDcould leave the parts torn and the table empty. #111378 (Groene AI).- Fix a rare Keeper data-loss window on local snapshot disks: the snapshot write path now fsyncs the snapshot directory after removing the
tmp_marker, so a power loss can no longer drop the marker unlink while keeping the snapshot content. Previously such a crash made Keeper treat a good, fully-synced snapshot as incomplete and delete it on restart, losing acknowledged writes even withforce_sync=true. Snapshot disks backed by object storage are not covered. #111397 (Groene AI). - Fix an out-of-bounds read (release) / logical error (debug) in the lazy materialization optimization, and a logical error in
Pipe::unitePipesforMergetables, when the direct-read-from-text-index optimization leaves an unused index virtual column in the read header of aMergeTreetable with multipletextindexes. #111467 (Groene AI). - Fixed the
_timevirtual column of theurl/urlClustertable functions always beingNULLon musl-based builds, caused by non-portable parsing of the HTTPLast-Modifiedheader. #111619 (Konstantin Bogdanov). - Fixed a
LOGICAL_ERROR(Cannot create part with type Compact and storage type Full because table does not support polymorphic parts) raised when aMergeTreetable loads a pre-existingCompactpart while its current settings disable polymorphic parts (non-adaptive granularity). This could happen, for example, when a read-only table shares an on-disk path with another table and reloads its parts viaSYSTEM RESTART DISKor on server startup. In debug and sanitizer builds the exception aborts the server. #111626 (Groene AI). - Fixed
CREATE TABLE ... ENGINE = KeeperMapfailing withCoordination error: No node, path .../metadata/drop_lock_versionwhen another table on the same Keeper path is dropped concurrently. The create now treats the vanished metadata subtree as a completed cleanup and retries, as it already does for the same situation one statement later. #111966 (Groene AI). - Fix a race between a
ReplicatedMergeTreemutation and the removal of old temporary directories that could publish a mutated part with some of its files missing, making reads of that part and all its later mutations fail. #111992 (Alexey Milovidov). - Fix
quantileDeterministic,quantilesDeterministicandmedianDeterministicreturning different results for the same data on every run when the query uses parallel replicas, a distributed table, or external aggregation, or when the states are stored in a table (including inside aDynamicvalue). States written before this version under the unversioned type spelling keep the previous behavior, since their layout cannot change. #112052 (Alexey Milovidov). - Fixes
serialize_string_in_memory_with_zero_bytebeing dropped from the serialized query plan. Withserialize_query_plan = 1, a cluster running with the setting disabled could diverge on the in-memory string representation between the initiator and the node executing the deserialized plan, because the setting was read on deserialization but never written on serialization and therefore always resolved to its default on the executing node. #112131 (Groene AI). - Fixed a stack frame being displayed as
?instead of its function name in fatal log messages and in thetrace_fullcolumn ofsystem.crash_log. It affected frames of ordinary functions that have code attributed to a libc++__functionalheader, which is common in release builds. #112152 (Alexey Milovidov). - Fixes silently missing rows when a query filters on
intDiv(constant, key)ordivide(constant, key). Primary-key and partition analysis reports the wrong direction of monotonicity for a constant divided by a key column, so matching granules are pruned away and the query returns fewer rows with no error. Also fixesintDivwith an unsigned constant dividend whose high bit is set, stops claiming monotonicity when aDecimaloperand makes the division compute in the decimal’s native width, and stops key analysis from raisingCannot compare DB::IPv4 with longfor a valid query that divides anIPv4/IPv6constant by a key column. #112156 (Groene AI). - Fixed
DROP TABLE ... SYNChanging forever when a query oversystem.replicashad been killed before its status requests were processed. #112164 (Nikolay Degterinsky). - Fixed a server abort (
SIGABRT) when aBUFFERED_V1WebAssembly UDF returns an empty result buffer; the query now fails with a catchableWASM_ERRORand the server stays up. #112182 (Nikolai Ovchinnikov). - Fixed a use-after-free when a
JOINwithjoin_algorithm = 'direct'onto a dictionary was given a join key that is stored with sparse serialization.getColumnVectorDatareturned a reference to a temporary column, so the dictionary lookup read freed memory: release builds could return wrong results and debug or sanitizer builds aborted. #112327 (Groene AI). - Fixes cases where row policy was not used for MergeTree Projections during query execution. #112329 (Yarik Briukhovetskyi).
- Fixed data corruption when inserting into an Iceberg table reached through a
MATERIALIZED VIEW. The data file was written against the target’sCREATE-time column types instead of its live Iceberg schema, so aDateTimevalue was stored as a bare Avrointand read back as microseconds, and withDateTime64(0)orDateTime64(9)the file could not be read back at all. As a consequence,INSERT INTO <materialized view>against a target whose Iceberg schema is wider than the view’s declared columns now raisesTYPE_MISMATCHinstead of writing a corrupt row. #112359 (Groene AI). - Keeper no longer refuses a
Setrequest with empty data when it is overmax_memory_usage_soft_limit. Such a request cannot increase the amount of stored data, and refusing it prevented clients from re-establishing their session, which could keep tables read-only for the whole duration of a Keeper memory event. #112386 (Shaohua Wang). - Fixed a Keeper follower dropping out of quorum for a long time, causing mass
Session expirederrors, after it successfully installed a large snapshot: the leader discarded the follower’s acknowledgement whenever applying the snapshot took longer than the snapshot-install timeout, and then walked that follower’s log index backwards one entry per round trip. Also added the Keeper settingnuraft_snapshot_sync_ctx_timeout_msto control that timeout, which previously could only be changed throughraft_limits_response_limitand therefore not without also slowing down dead-peer detection. #112405 (Shaohua Wang). - Fix data races in profile events and memory tracker. #112466 (Miсhael Stetsyuk).
- Security related bugfix. #112479 (Kseniia Sumarokova).
- Fixes reading a stale secondary (skip) index after an
ALTER TABLE ... MODIFY COLUMNtype change whose mutation never ran, for example becauseKILL MUTATIONremoved it: the granules on disk were written with the old type but decoded with the new one, raisingLOGICAL_ERROR, requesting multi-exabyte allocations, or silently returning a wrong result. Also fixes a wrong result from an index over an expression whose meaning changes while every stored byte stays identical, so no mutation is created at all: aMODIFY COLUMNaltering only aDateTimetimezone, or only a custom type name such asUInt8toBool. Such an index is now skipped for the affected part. Closes #112213. #112484 (Groene AI). - 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 (Shaohua Wang).
- Fix AsynchronousBoundedReadBuffer’s readBigAt data race. Closes #109678. #112573 (Kseniia Sumarokova).
- Fixes a column alias list such as
(SELECT 1) AS t(x)orWITH t(x) AS (SELECT 1)not being visible inside theviewtable function, where a reference tot.xfailed withUNKNOWN_IDENTIFIERalthough the same construct works outsideview. #112690 (Groene AI). - Fixed the logical error
SortingAggregatedTransform already got bucket with number Nthat could occur in multi-layer distributedGROUP BYqueries using two-level aggregation. #112794 (Nikita Taranov). - Fixes a
NATStable withnats_streamset silently consuming nothing after the NATS server is restarted. TheJetStreamsubscription is now re-established automatically instead of requiringDETACH TABLEandATTACH TABLE. #112828 (Groene AI). - Fixed a transient Azure Blob Storage error on the read or merge path — an RBAC permission-propagation
403 Forbidden, a credential authentication failure, or a connect timeout surfaced as408— being misclassified as non-retryable and reported asPOTENTIALLY_BROKEN_DATA_PART(Code 740), raising a false critical alert for a healthy part. These transient failures are now treated as retryable, and a genuinely persistent one surfaces as a plain Azure error instead of a phantom broken data part. #112871 (Arsen Muk). - Fixed Azure batch object deletion recording no
system.blob_storage_logDelete events when the batch request itself failed, leaving the whole batch unlogged. A Delete event is now recorded for each object on a batch-level failure. #112873 (Arsen Muk). - Fix the per-part minmax index over
_block_numberand_block_offsetbeing lost after a table reload when the part was produced by a mutation that does not rewrite the whole part. #112878 (Alexey Milovidov). - Fixes a logical error and wrong results when a non equi
JOIN ONcondition that is evaluated during the join containsarrayJoin. Ahash,parallel_hashorgrace_hashjoin now rejects such a condition withINVALID_JOIN_ON_EXPRESSION. Where the expansion depends on one side only, move it into anARRAY JOINin a subquery before the join; a condition whosearrayJoinargument reads columns from both sides has to be restructured. #112889 (Groene AI). - Fix wrong results of
ORDER BYwhen reading from aMergetable overDistributedtables: rows could be returned out of order, and rows belonging in the result could be missing whenLIMITwas used. #112931 (Alexey Milovidov). - Fixed a
Boolconstant on the right-hand side ofINbeing converted to aStringleft-hand side as'1'/'0'instead of the canonical'true'/'false'(now consistent withCASTand thevaluestable function). #113051 (Yakov Olkhovskiy). - Fixes
viewscolumn inquery_logfor inserts to anAliastable whose target triggers materialized views, which was always empty. #113076 (Enric Calabuig). - Fixed
LOGICAL_ERRORwhen reading a table with asetskip index defined on an expression and the query repeats that expression with aNullableoperand, for exampleWHERE intDiv(id, (SELECT 1000)) = 3overINDEX b_set intDiv(id, 1000) TYPE set(100). A scalar subquery is enough to trigger it, since it is typedNullable. #113244 (George Larionov). - Fix a logical error (exception)
Chunk info was not set for chunk in MergingAggregatedTransformwhen the settinginject_random_order_for_select_without_order_byis enabled and an aggregation query reads from aMergetable containing aDistributedchild: the randomORDER BY rand()wrapper is no longer injected into queries planned only up to an intermediate stage. #113266 (Alexey Milovidov). - 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. Closes #113003. #113289 (Groene AI). - Fixed
ATTACHof aKafkatable whenkafka_num_consumersexceeds the limit derived from the number of CPU cores. #113390 (Nikolay Degterinsky). - Fixed a permanent
DROP TABLEhang and memory leak after a query using a materialized CTE failed. The table stayed stuck in the drop queue until the server was restarted. #113397 (Shaohua Wang). - Fix a logical error
IDENTIFIER is not a table expressionwhen a remote-family table function with aview(...)argument is used on the left side of aJOIN ... USINGwhose key is aSELECTlist alias, withanalyzer_compatibility_join_using_top_level_identifier = 1. #113400 (Groene AI). - Fixed reading
Paimontables partitioned by aTIMESTAMPcolumn with a precision higher than milliseconds, which failed withscale 6 is not supported, only support scale <= 3. Closes #112768. #113401 (JIaQi Tang). - Fixes a segfault and a
LOGICAL_ERROR(No host found for exchange stream final_result__0_0) when a subquery setsdistributed_plan_execute_locallyin its ownSETTINGSclause undermake_distributed_plan. The distributed plan and the code executing it read the setting from two different contexts and could disagree, so the initiator built a self-contradictory pipeline. #113422 (Groene AI). - 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. Closes #113337. #113450 (Groene AI). - Fix part and granule pruning for a
JOIN ONcondition involving constant columns of the other side. #113484 (Vladimir Cherkasov). - Stopped writing a part whose
Maplayout contradicts its own metadata, for aMapvalue inside aDynamiccolumn. Tables differing only inmap_serialization_versionshared one cached serialization object, so a part could get thebasicMap layout while its metadata declaredwith_buckets, and reading it later failed withLOGICAL_ERROR: Stream ...buckets_info ... is not found. Parts an earlier version already wrote this way stay unreadable and have to be dropped. #113514 (Groene AI). - Fixed the inferred column type depending on the order of previous queries for a source whose schema is cached. Settings that change an inferred type were missing from the schema inference cache key, so the first query’s value decided the type every later query saw:
input_format_try_infer_exponent_floats,max_parser_depth,input_format_json_infer_array_of_dynamic_from_array_of_different_types, and forParquetalsoinput_format_parquet_local_time_as_utc,input_format_parquet_allow_geoparquet_parser,input_format_parquet_skip_columns_with_unsupported_types_in_schema_inferenceandschema_inference_make_json_columns_nullable. Also registers the missing cache key getter forFormand makes theTemplategetter use its own row format’s escaping rule. #113533 (Groene AI). - Fix a theoretical data race in profile events when using the
trace_profile_events_listsetting to write stack traces of certain profile events tosystem.trace_log. #113553 (Miсhael Stetsyuk). - Fixed
RENAME DATABASEaccepting a target name long enough to make the database’s tables impossible to drop. The table name length check now runs regardless ofcheck_table_dependencies, and it also covers detached tables, which were never checked and so were affected even at default settings. Closes #101747. #113557 (Groene AI). - Fixed the
LOGICAL_ERRORReading from materialized CTE '...' before its materialization completed - DelayedPortsProcessor gate is missing in the query planraised when aMergetable with more than one child reads a materialized CTE that the outer query references. #113558 (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
Unsupported JOIN keys of type keys256 in StorageJoinwhen reading aJoin-engine table whose key is composite (several columns) or a single 16/32-byte value such asUUID,Int256orFixedString(4). Such a table could be created, written and joined against, but never read back withSELECT. Closes #74362 and #77394. #113578 (Groene AI). - In the Web UI, opening a link with
run=1no longer makes other tabs’ URLs auto-run their queries on the next page reload. #113595 (Alexey Milovidov). - Fix a logical error comparing arrays whose element type is Nothing. #113609 (Groene AI).
- Backups now report the underlying lock-file access error instead of incorrectly reporting a concurrent backup when the destination storage cannot read the .lock file. #113637 (Kirill Shokhin).
- Fix a logical error
Sending a distributed query with unknown (zero) client versionwhen a structure-lessDistributedtable over a remote shard is attached or loaded from metadata written by an older server version. #113675 (Alexey Milovidov). - Treat a NUL byte as an ordinary literal in match() patterns. #113690 (Vitaly Baranov).
- Fix
theilsUover a window frame returning an arbitrary value instead of 0 when the first argument is constant within the frame. #113691 (Alexey Milovidov). - Fix
Logical error: Duplicate announcement received for replica number Nwhen automatic parallel replicas (automatic_parallel_replicas_mode) adopts a plan whose single-node variant was sharded byquery_plan_join_shard_by_pk_ranges. #113730 (Alexey Milovidov). - Fix
CANNOT_CONVERT_TYPEand an exception inGroupingAggregatedTransformwhen reading aMergetable with one child being aDistributedtable under custom-key parallel replicas (parallel_replicas_mode = 'custom_key_sampling'or'custom_key_range'). Closes #113741. #113742 (Alexey Milovidov). - Fixed a
LOGICAL_ERRORwhen aSELECTused theSTREAMmodifier on a named table together with parallel replicas in the read-tasks mode. With a materialized CTE used as anINset inPREWHERE, the server raisedReading from materialized CTE ... DelayedPortsProcessor gate is missing in the query plan(a server abort in debug and sanitizer builds). A table carryingSTREAMis now rejected when parallel replicas are requested: atenable_parallel_replicas = 2the query fails withSUPPORT_IS_DISABLED, at1it runs without them, exactly as already happens forFINAL. #113754 (Groene AI). - Fixed a server crash when joining with a constant
ONexpression against a right side that contains anARRAY JOIN. Reading a lazily replicated right-side column used a freedColumnReplicated. Closes #113859. #113901 (Groene AI). - Fix undefined behavior and wrong results in
avgoverDate/DateTime/DateTime64/Time/Time64: the average is now computed exactly in integer space, fixing both theInt64-boundary overflow (UB, wrong result on x86) andFloat64precision loss above 2^53 (visible at nanosecond scale). #113912 (Alexey Milovidov). - Fix wrong results in
JOINwithjoin_algorithm = 'partial_merge'when the right side carries totals: the right side could be left unmerged, soLEFTjoins substituted default values for real matches andINNER/RIGHTjoins returned no rows at all. In theRIGHT/FULLnon-joined path the same state dereferenced a null pointer, which crashed the server. #113936 (Groene AI). - Fixed a defect in the
MySQLintegrations where overriding a TLS credential of a named collection with an emptyssl_ca_pem/ssl_cert_pem/ssl_key_pemvalue was accepted when the collection stored the credential in the contents form, silently dropping the configured CA or client certificate instead of rejecting the override. #113947 (Alexey Milovidov). - Fixes a
std::out_of_rangeexception (Logical error: 'std::exception. Code: 1001, type: std::out_of_range', which also aborts the server in debug and sanitizer builds) in the Parquet v3 reader when a column needed only for filter evaluation was scheduled for decoding after its output slot had already been dropped. #113956 (Groene AI). - Fix a logical error (
Unexpected return type) when a filter over a view whose column type differs from the underlying storage (e.g.information_schema.tables, whereengineisNullable(String), oversystem.tables, where it isString) is pushed down to the storage. #113984 (Alexey Milovidov). - Fix ClickHouse Keeper refusing to start with
CORRUPTED_DATAafter a crash during cross-segment Raft log truncation (writeAt), which could leave an acknowledged log entry stranded behind stale changelog segments. #114003 (Nishant Agarwal). - A table or database whose name is substituted into a
ReplicatedMergeTreeZooKeeper path through the{database}or{table}macro is now rejected if the name would not be a single safe path component. Previously a name containing/was spliced in unescaped, so the table registered its znodes inside another table’s keeper subtree and permanently brokeALTERandOPTIMIZEthere. A.or..component, a control character and macro syntax are rejected too. Existing tables keep loading and attaching. #114006 (Groene AI). - Fixes a memory leak with
optimize_aggregation_in_order = 1when the table sorting key is a strict prefix of theGROUP BYkey and an aggregate function whose state owns heap memory is used, such asquantileDD. Server memory grows with every such query until restart. #114010 (Groene AI). - Fixes a logical error when a distributed query plan contains a window function producing an aggregate function state, for example
theilsUState(a, b) OVER (ORDER BY a)withmake_distributed_plan = 1. Affects thecramersV,cramersVBiasCorrected,theilsUandcontingencyfamilies. #114020 (Groene AI). - Fix wrong results for
SELECT DISTINCTwith aLIMITthat has to read its whole input:LIMIT n WITH TIESdropped tying rows,exact_rows_before_limit = 1reported a truncatedrows_before_limit_at_least, andGROUP BY ... WITH TOTALScomputed the totals row from a prefix of the stream. #114025 (Groene AI). - Fixed
isProbablePrimeonUInt128/UInt256ignoringmax_execution_timeandKILL QUERY. A block of wide values ran to completion inside a single function call with no cancellation point, so a query could run for minutes past its deadline. #114032 (Groene AI). - Fixes a missing
system.query_views_logrow for a materialized view that fails while its dependencies are being collected withmaterialized_views_ignore_errorsenabled. In debug and sanitizer builds this also aborts the server withstd::out_of_rangeinstead of logging the view. #114064 (Groene AI). - Fixed
Code: 46. DB::Exception: Unknown function exists. (UNKNOWN_FUNCTION)thrown when aPREWHEREclause contains anIN (subquery)predicate andrewrite_in_to_join = 1(ormake_distributed_plan = 1, which force-enables it) is set. The same query spelled withWHEREworked correctly. #114067 (RohithPariki). - 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). - Fixes
hasAny,hasAll,has,indexOf,mapContainsKey,mapContainsValueandmapContainsreturning too few rows, or failing withTOO_LARGE_STRING_SIZE, when abloom_filterindex is queried with aFixedStringconstant. The index hashed the padded form of the constant while the function compares the unpadded one, so a matching granule was skipped. #114089 (Alexey Milovidov). - Fixed a
LOGICAL_ERROR“Not-ready Set is passed as the second argument for functionglobalNullIn” and the loss of the query’s real error message, which could happen when statistics part pruning speculatively executed anIN/GLOBAL INsubquery during index analysis and that subquery failed. #114121 (Groene AI). - Respect the
allow_calculating_subcolumns_sizes_for_merge_tree_readingsetting in the PREWHERE optimization. #114146 (Pavel Kruglov). - Reject corrupted/malicious dictionary where
lcpexceeds the previous token orlcp + data_sizeoverflows, before the buffer write. #114155 (Elmi Ahmadov). - Fix
minandmaxonDateTime64columns returning wrong results once the aggregate is JIT compiled and the data contains timestamps before 1970.is_signedwas not specialised forDateTime64andTime64, which derive fromDecimal64, so the generated code compared tick counts as unsigned integers and a pre-1970 timestamp wonmaxand lostmin. #114168 (Groene AI). - Fixed an exception when reading a
MergeTreetable by primary-key range layers when a layer produces an empty pipe. #114177 (Alexey Milovidov). - Fixed the error code reported for some malformed
Replicated-serialized columns received over the Native protocol: these are now rejected withINCORRECT_DATAinstead ofLOGICAL_ERROR(which aborted the server in debug and sanitizer builds). #114186 (Pavel Kruglov). - 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). - Fixed
ALP,FPCandGCDomitting their type-derived parameter from the codec hash. In a Compact part the writer shares one compressed stream per distinct codec hash, so two columns of different value width under the same codec collided and shared one codec object carrying the wrong width. This rejected valid inserts withCANNOT_COMPRESSwhen the widths disagreed, and otherwise compressed one of the columns worse than it should have. #114189 (Groene AI). - Fix
std::out_of_range: map::at: key not foundwhen aMergeTreekey expression contains amortonEncodeorhilbertEncodecall that is not itself a key column, for exampleORDER BY mortonEncode(hilbertEncode(x, y), x, y)orPARTITION BY mortonEncode(x, y) % 4. #114233 (Groene AI). - Clear plain LIMIT/OFFSET in the window-view backfill source query. #114247 (Alexey Milovidov).
- Fixed a
LOGICAL_ERRORinarrayAutocorrelationwhen the argument is a non-empty array whose element type isNothing, for exampleSELECT arrayAutocorrelation([arrayMax([])]). Such an argument is now rejected withILLEGAL_COLUMN. The empty array literal[]keeps returning[]. #114249 (Groene AI). - Fix a Keeper server never joining the cluster when
nuraft_use_bg_thread_for_snapshot_iois enabled: the log batch sent to a joining server was silently dropped, so the membership change never completed. #114275 (Shaohua Wang). - Fix
XDG_CACHE_HOMEbeing read fromXDG_STATE_HOME. #114278 (Alexey Milovidov). - Register Iceberg namespace in the catalog before writing table files (needed for SeaweedFS). #114285 (Azat Khuzhin).
- Fix inconsistent results when a filter on a non-key column of the right table was pushed down below an ANY INNER JOIN. #114313 (Kirill Shokhin).
- Fix bash completion with bash-completion 2.12+ (_comp_get_words). #114339 (Azat Khuzhin).
- Fixes a crash when reading a data lake table whose schema declares a column with an empty name. Malformed Iceberg metadata is rejected with
ICEBERG_SPECIFICATION_VIOLATION; a schema supplied by a catalog, Delta Lake or Paimon is rejected withAMBIGUOUS_COLUMN_NAME. The check is unconditional, so an Iceberg table that merely retains an unused historical schema with an empty field name also becomes unreadable instead of aborting once that schema is read. #114394 (Groene AI). - Fixes a bug where a client connecting to ClickHouse Keeper during a Raft leader change could be held for the whole
session_timeout_ms(30 seconds by default) before its connection was rejected, instead of being rejected as soon as the in-flight request was dropped. The connecting client can now reconnect to another replica sooner. #114401 (Groene AI). BACKUP,RESTOREandENGINE = Backupnow authorize the backup location against the user’sSOURCESgrants, the same ways3(),file()andazureBlobStorage()do. Previously a user holdingBACKUPbut notSOURCEScould write a backup to, and read one from, any location the server could reach. Writing a backup now requires theWRITEdirection on the destination’s source (WRITE ON S3,WRITE ON AZURE,WRITE ON FILE) and reading one requiresREAD;Disk(...)destinations stay restricted bybackups.allowed_diskonly. #114405 (Groene AI).- Fixes
CREATE OR REPLACEleaking an internal_tmp_replace_*table, andCREATE OR REPLACE VIEWfailing withNOT_IMPLEMENTED, whenignore_drop_queries_probabilityis set. The DROPs it issues internally are steps of one user statement, so DROP fault injection no longer applies to them. #114420 (Groene AI). - Fixed a
LOGICAL_ERROR(Bad cast from type DB::ASTLiteral to DB::ASTPartition) and unparseable formatted SQL when anALTER TABLE ... MOVEcommand deserialized from a JSON AST (dialect = clickhouse_json) paired thePARTform withTO TABLE, or thePARTITIONform withTO SHARD. Such payloads are now rejected withBAD_ARGUMENTS. #114429 (Groene AI). - Do not remove columns when it’s referenced in both
PREWHEREandWHEREfilter conditions even if it’s rewritten into a text index virtual column. #114460 (Elmi Ahmadov). - Fixed a
Not-ready Set is passed as the second argument for function 'in'error when a mutation whose predicate containsIN (subquery)is cancelled, for example byKILL MUTATIONorDETACH DATABASE, while the subquery’s set is still being built. Related: #107619. #114463 (Groene AI). ALTER TABLE ... DROP COLUMNof a column that is used in the sorting, primary or partition key now fails withALTER_OF_COLUMN_IS_FORBIDDENand an explanation, the same asALTER TABLE ... CLEAR COLUMNdoes. Previously it failed with a confusingUNKNOWN_IDENTIFIER: Missing columnserror coming from the recalculation of the key expressions. The same applies to dropping or clearing a wholeNestedgroup by its common prefix when a column of the group is used in a key; previously that could silently destroy the group’s data or leave a mutation that never finishes. Dropping a column that is used only in aTTLexpression now also reports which TTL expression it breaks. #114468 (Maksim Dergousov).- Fixed reading a
Tuplecolumn whose first element isNULLin theCustomSeparated,RegexpandTemplateformats with theCSVescaping rule. A bareTupleoccupies one field per element there, so the leading\Nfield is that element and not the whole column. Previously it was consumed as the whole column, shifting the remaining element fields onto the following columns, soCustomSeparatedcould not read back its own output. Closes #114402. #114471 (Groene AI). - Fixes
arrayExists(x -> x = needle, arr)returning a wrong result, or failing withTOO_LARGE_STRING_SIZE, when the array element and the needle are different string types (for example aStringneedle against anArray(FixedString(N))element). Theoptimize_rewrite_array_exists_to_hasoptimization, enabled by default, rewrote such a call tohas, which does not compare zero-padded the way=does. #114496 (Groene AI). - Reading an Iceberg table whose metadata describes a schema evolution that the Iceberg specification forbids no longer aborts the server. Four spec violations in
IcebergSchemaProcessorwere reported asLOGICAL_ERROR, which is treated as a failed assertion, or reached a fatal assertion unchecked; they now raiseICEBERG_SPECIFICATION_VIOLATION. #114518 (Groene AI). - Fixed the
Regexpinput format silently discarding the unparsed rest of a matched field, which stored a truncated or fabricated value instead of reporting an error:v=-1intoUInt64read0, andv=2020-01-01junkintoDateread1975-07-14under theJSONrule. Malformed fields are now rejected under theEscaped,CSVandJSONrules, matching the formats those rules are documented as behaving like. UnderRaw, a matched field containing a tab is now read as a whole instead of being truncated at the tab. #114520 (Groene AI). - Fix
LOGICAL_ERRORwhen filtering an Iceberg column thatALTER TABLE ... MODIFY COLUMNmadeNullable. Closes #85029. #114521 (Groene AI). CREATE TABLEandALTER TABLEnow reject lossy codec such asSZ3on a column used in the sorting key. #114531 (Groene AI).- Fixed a
LOGICAL_ERRORwhen reading a Delta Lake table whosemetaData.partitionColumnsnames a column thatmetaData.schemaStringdoes not declare. Such metadata is now rejected withBAD_ARGUMENTSon the delta-kernel reader andINCORRECT_DATAon the legacy reader, whenever the table or its schema is read from a snapshot, not only when the query carries a predicate. #114538 (Groene AI). - Reject a Variant whose ORC branches read back as one type. #114540 (Groene AI).
- Fix text index evaluation of
LIKE/ILIKEoperator built on Map or JSON containers. #114544 (Elmi Ahmadov). - Support quoted label names in PromQL grouping modifiers.. #114545 (Minh Vu).
- Fixes incorrect, often sign-flipped,
Time64literals andIN-list constants produced when rescaling a lower-scaleDecimal64overflowedInt64. Such a conversion now reportsDECIMAL_OVERFLOW, matching theDateTime64branch and explicitCAST. #114546 (Groene AI). - Accept trailing commas in PromQL grouping label lists.. #114548 (Minh Vu).
- Support quoted metric and label names in PromQL selectors. #114551 (Minh Vu).
- A query could be cancelled up to 1 ms before its
max_execution_timehad passed, failing with a self-contradictoryTimeout exceeded: elapsed 999.672 ms, maximum: 1000 ms. #114559 (Alexey Milovidov). - Fixed reading a table while a mutation is in progress: a
MATERIALIZEDcolumn could return a stale value, and selecting one together with an updated column could fail with an error. #114561 (Shaohua Wang). - Fixes
clickhouse-localaccepting aCREATE TABLEwhose name is too long for the configured--default_database, which produced a table that could not be dropped.DatabaseOverlaynow checks the table name length like the on-disk database it writes to. #114567 (Groene AI). - Fixed an RBAC bypass in the
Aliastable engine that allowed users without privileges on the target table to reveal its schema, row count, size, and existence. #114596 (Kai Zhu). - Fixed hash-table statistics — and with them aggregation hash-table preallocation — being silently and permanently disabled for the whole server when a query using the lazy
FINALoptimization (query_plan_optimize_lazy_final) was the first aggregation to run after server startup. #114597 (Alexey Milovidov). - Fixed a column that was renamed, dropped and added again in one
ALTERreturning the dropped column’s values instead of its own default while the mutation was still pending. #114601 (Shaohua Wang). - Fixed an infinite, uncancellable loop in functions
hopandwindowIDwhen the span of an interval argument in seconds is a multiple of 2^32 (for example,toIntervalDay(2147483648)): the wrapped subtraction dodged the time-overflow check, and with constant arguments the loop ran at analysis time, where the query could not even be killed. The same interval could also spin a background thread of aWINDOW VIEWforever; such a window view is now rejected at creation. #114607 (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 (Groene AI). - Fixed a refreshable materialized view leaking its rotated-out target table when
ignore_drop_queries_probabilityis enabled. TheDROPa refresh issues to clean up the previous target is a step of the refresh, not aDROPthe user asked for, so the fault injection no longer applies to it. #114622 (Groene AI). - 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 (Groene AI). - Fixed logical error
Multi-block postings must be compressedin queries over tables with a text index in the lazy posting-list apply mode, when the query was canceled during the read. #114636 (Anton Popov). - Fixed formatting of a subquery argument of the
viewandviewIfPermittedtable functions when the enclosing query has a trailingSETTINGSclause. Such a query was formatted asview((SELECT ...)), which cannot be parsed back, so the query failed the internal format-parse-format check and raisedInconsistent AST formatting. #114658 (Groene AI). - 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 (Groene AI). - Fix reading a subcolumn (
.size0,.null, a tuple element,String.size) through aMergetable when the underlying table declares the parent column asALIAS. Such a read returned the type default, and when the parent was selected in the same query it could return the value of an unrelated column. #114673 (Groene AI). - Fix
ANY RIGHT JOINandSEMI RIGHT JOINwith severalOR-ed conditions in theONsection returning some rows of the right table twice and losing the matches of others. A writtenANY LEFT JOINwas affected too, because the planner may swap the tables and execute it asANY RIGHT JOIN. #114676 (Vladimir Cherkasov). - 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 rows missing from the result of a
SELECTfiltered bypointInPolygonover a MergeTree primary key when the polygon argument is an invalid constant literal andvalidate_polygons = 0. Primary key analysis derived granule pruning from a polygon it never validated, and dropped granules holding matching rows. #114710 (Groene AI). - Fixes a server crash that happens when aggregate states of the
-OrNullor-OrDefaultcombinators are merged withgroup_by_overflow_mode = 'any'and a non-zeromax_rows_to_group_by, for example when a query reads through an aggregate projection. #114740 (Groene AI). - Fixed a
LOGICAL_ERROR(“Unexpected number of kept output positions after removing unused columns fromReadFromMergeTree”) raised by aSELECT ... FINALwhosePREWHEREuses a column thatFINALneeds for merging (ver,is_deleted,sign) and which does not select that column. #114746 (Groene AI). - Fix a logical error (
Block structure mismatch) when reading aMergetable withmake_distributed_planenabled over children with internal set operations. #114753 (Alexey Milovidov). - Reject an absurdly large
kafka_num_consumerswith a clear error instead of failing an allocation inside theKafkatable engine. Previously, withkafka_disable_num_consumers_limitenabled, such a value produced astd::length_errorexception. #114764 (Alexey Milovidov). - Fixed a
LOGICAL_ERROR: Context has expiredexception when a stored expression containingaccurateCastOrDefaultor ato<Type>OrDefaultfunction is evaluated after the query that created it has finished, for example aMATERIALIZEDcolumn default onINSERTor a mutation expression. #114769 (Groene AI). - Fixes a
LOGICAL_ERROR(Cannot find input column ... on its position in inputs of expression actions DAG) when a query has aJOINabove a table whose text-indexed column is used by both aPREWHEREand aWHEREtext-search predicate. #114771 (Groene AI). - Fix lost wakeup of restarting thread on startup from the attach thread. #114802 (Azat Khuzhin).
OPTIMIZE TABLEon an object-storage table whose engine does not implement compaction reported success while doing nothing. It now raises an error, like every other engine that does not support the statement. This affectsDeltaLake,Paimon,Hudiand plain object-storage engines (S3,GCS,COSN,OSS,AzureBlobStorage,HDFS, and object-storage-backedURL);Iceberg, which does implement compaction, is unchanged. Closes #114765. #114805 (Groene AI).timeSeriesRangeandtimeSeriesFromGridthrew a falseDECIMAL_OVERFLOWfor timestamps before 1970 because the start/end timestamps were read as unsigned values. Also, forDateTime/UInt32timestamps the step was silently truncated to its lower 32 bits. Now all the calculations are done inInt64. #114815 (Vitaly Baranov).- Fixes a server abort (
Logical error: Part patch-... doesn't exist) when aDROP TABLEruns concurrently with a lightweightUPDATEon aReplicatedMergeTreetable. The update now holds the table’s shared lock until its patch part is committed, so theDROPwaits instead of removing it. #114826 (Groene AI). - Fix few bugs in async inserts (possible crash in case of some queries failed with
MEMORY_LIMIT_EXCEEDEDand never workedasync_insert_queue_flush_on_shutdown). #114839 (Azat Khuzhin). - Fixed
LOGICAL_ERROR: Unexpected return type from tuple. Expected Tuple(..., UInt8). Got Tuple(..., LowCardinality(UInt8))when aLowCardinalitycolumn compared withIN (subquery)is read throughtuple(...)across a subquery boundary andenable_analyzer = 0. With the old analyzer,x IN (subquery)over aLowCardinalitycolumn now returnsLowCardinality(UInt8), the same type asx IN (literal list)and the same as withenable_analyzer = 1. #114856 (Nikita Fomichev). - The AI-function quota settings (
ai_function_max_api_calls_per_query,ai_function_max_input_tokens_per_query,ai_function_max_output_tokens_per_query) were enforced per block rather than per query, letting a query exceed the configured limit in proportion to the number of blocks and threads processed. They now bound the whole query per server: the API-call limit is an exact cap (atomic reservation), and the token limits are best-effort. A distributed query enforces the limits independently on each participating server / fragment. #114885 (George Larionov). - Fixes a server abort that happens when the global thread pool is momentarily saturated while tables are still loading.
AsyncLoadernow keeps running if it cannot spawn an extra loader worker and some worker will still drain the queued jobs, instead of callingstd::terminate. #114897 (Groene AI). - Fixed undefined behavior and incorrect boundary results in
quantileandquantilesforDateTime64and wideDecimalvalues. #114919 (Alexey Milovidov). - Fix server abort on a corrupt ORC stripe footer. #114924 (Groene AI).
- Fix possible crash due to ThreadGroup use-after-free (for async INSERTs/MVs/EXPLAIN ANALYZE). #114940 (Azat Khuzhin).
- Fixed a hang when dropping a
TimeSeriestable whose name sorts lexicographically below its inner tables’ names, for exampleDROP TABLE `-ts`or dropping a materialized view declared withENGINE = TimeSeries. The drop self-deadlocked on the DDL guard and could not be cancelled withKILL QUERY. #114953 (Groene AI). - Fix
BAD_DATA_PART_NAME(“Trying to get part name in new format for old format version”) on aReplicatedMergeTreecreated with the deprecated positional syntax underallow_deprecated_syntax_for_merge_tree. A mutation could be reported as done on a replica that had not applied it, and the table could stay readonly after a restart. #114980 (Groene AI). - Fix the logical error
Not-ready Set is passed as the second argument for function 'in'for a query with anINsubquery reading from a remote cluster: the query now fails with the actual error from the subquery, such as a connection failure. #114983 (Alexey Milovidov). - Fix logical error for IN with an identical non-constant tuple on both sides in the old analyzer. #114988 (Groene AI).
- Fix reading a tuple element through a positional Tuple structure hint. #115000 (Groene AI).
- Do not alias pre-aggregation states of a zero-size aggregate in arrayReduceInRanges. #115008 (Groene AI).
- Fixed an
INSERTinto aLog,TinyLogorStripeLogtable that fails while committing the recorded file sizes. Such an insert could keep its rows in the table even though it reported an error, or leave the data files of an array column inconsistent with each other. Reading aLogorTinyLogtable whose array column holds no elements while its offsets claim some now raises an error naming the column instead of reading past the end of the elements. A partially written elements column was already rejected. #115027 (Groene AI). - Fix an adaptive aggregator abort on lazily replicated columns. #115034 (Groene AI).
- Fixed an out-of-bounds read in
pointInPolygonwith a constant polygon whose bounding box is unbounded, for example when a coordinate reaches+-DBL_MAX. Such a polygon is now rejected withBAD_ARGUMENTS, and a polygon with an empty ring is treated as having no interior. Previously the query could return a wrong result, or abort the server in builds with hardening or sanitizers enabled. #115035 (Groene AI). - Fixed an
out_of_rangeexception raised as an internalCode: 1001error when asequenceMatch,sequenceCountorsequenceMatchEventspattern contains the event number0, for examplesequenceMatch('(?0)'). Such a pattern is now rejected withBAD_ARGUMENTS. A temporal condition holding a lone sign, such assequenceMatch('(?1)(?t>+)(?2)'), was silently treated as(?t>0)and is now rejected withSYNTAX_ERROR. #115056 (Groene AI). - Fixed
Found patch part ... that intersects mutation with version ...(LOGICAL_ERROR) on tables with lightweight updates. A merge of patch parts could produce a patch whose range of data versions spans the data version of an existing part; that patch can then be neither applied nor skipped, so every later operation on the partition failed and the replication queue stalled. Such merges are no longer assigned. #115064 (Alexey Milovidov). - Fixes a
LOGICAL_ERROR(Cache file segment is in detached state) when reading through the filesystem cache with the experimentaluse_reader_executorsetting. The regression was introduced by #110029 and is not in any release, so no backport is owed. #115070 (Groene AI). - Arrow Flight server: accept
Basicauthentication credentials encoded in Base64 without padding, as sent by Go-based Flight clients such as the ADBC Flight SQL driver, and return a proper authentication error instead of a genericUnexpected error in RPC handlingwhen theauthorizationheader is malformed. #115085 (Alexey Milovidov). - Fix autocompletion (hints and TAB completion from
system.completions) in the embedded client used by the SSH interface and the Web terminal: suggestions were loaded through a separate connection that authenticated as thedefaultuser with an empty password, which failed on servers wheredefaulthas a password, and otherwise leaked names of entities the logged-in user has no access to. Suggestions are now loaded through the session’s own connection. #115086 (Alexey Milovidov). - Fixed a server that refuses to start after a table was created with
CREATE TABLE ... AS url('http://host/**/', ...)whileallow_experimental_url_wildcard_from_index_pageswas enabled. Loading such a table’s metadata re-evaluated the experimental check and failed withSUPPORT_IS_DISABLED, aborting startup. #115095 (Groene AI). - Rewrite bucketIndexForTimestamp in 64-bit arithmetic. #115097 (Vitaly Baranov).
- Fixed the formatting of
ALTER TABLE ... MATERIALIZE INDEX,MATERIALIZE STATISTICSandMATERIALIZE PROJECTION, which dropped theIF EXISTSclause, so the formatted query was not the query that was parsed. Also rejected fourALTER ... STATISTICSAST JSON payloads that the SQL parser cannot produce and that formatted into a different command. #115099 (Groene AI). - Fixed an exception (
Block structure mismatch in Expression for FilterSortedStreamByRange) for someSELECT ... FINALqueries withPREWHEREover a table whose sorting key is an expression. #115113 (Shaohua Wang). - Fix clickhouse-local CORS CLI overrides. #115129 (Alexey Milovidov).
- Disable distributed index analysis with projections (wrong results). #115132 (Azat Khuzhin).
- Fixed
ifandmultiIfreturning a large positive value instead of a negative one when aTimebranch is combined withTime64,DateTimeorDateTime64and the expression is JIT-compiled. #115146 (Groene AI). - A web terminal embedded in another page, such as the SQL console or
play.html, receives its credentials from that page and no longer opens a connection of its own before they arrive. Previously it connected twice - once with an empty password, then again with the real credentials - and printedConnecting...twice. #115148 (Alexey Milovidov). - Fixed wrong results when a
WHEREclause contained aNULLexpression under aNOT, for exampleSELECT count() FROM t WHERE NOT (id >= 20 AND NULL). Index analysis treated such a condition as provably true for the whole range, so the filter was skipped:count()returned rows the query rejects, andALTER TABLE ... DELETEwith that condition removed rows it should have kept. #115152 (Groene AI). - Fixed
EXPLAIN ANALYZElosing the join statistics of a view declaredSQL SECURITY DEFINERorSQL SECURITY NONEwhose body contains a JOIN. In debug and sanitizer builds the query aborted with the logical errorJoinStep analyzed without the analyze mode. #115156 (Groene AI). - Fixed an out-of-bounds read while deserializing corrupted posting lists of a text index. #115222 (Anton Popov).
- 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. Closes #115123. #115227 (Groene AI). - Fixes
NOT_FOUND_COLUMN_IN_BLOCKon everyINSERTinto a table that declaresSTATISTICS(...)on anALIASorEPHEMERALcolumn, which made such tables read-only. #115231 (Groene AI). - Fix the final statistics of a finished query (
N rows in result,Read ... rows) being rendered in an invisible color in the Web UI. #115245 (Alexey Milovidov). - Fixed silently incorrect results and undefined behavior when reading a malformed
AggregateFunction(uniq, ...)state. Theskip_degreefield of the serialized state was used as a shift exponent without validation, so an out-of-range value produced an arbitrary cardinality instead of an error. Such states are now rejected withINCORRECT_DATA. #115276 (Groene AI). - 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 (Yarik Briukhovetskyi).
- Fixed
CREATE QUOTAandALTER QUOTAsilently discarding all but the lastFOR INTERVALblock when the separating comma between intervals was omitted. Such a statement succeeded while installing none of the earlier limits. The intervals now accumulate again, as they did before 2020. Closes #115282. #115320 (Groene AI). - Fixed wrong results from
if,multiIfandCASEwhen one branch is aDateorDate32and the result type isDateTimeorDateTime64. Withcompile_expressions = 1(the default) the compiled expression copied the date’s day count into the timestamp column without converting days to seconds, soif(cond, toDate32('1900-01-01'), toDateTime64('1970-01-01', 3))returned1969-12-31 23:59:34.433. Closes #115272. #115325 (Groene AI). - Do not leave metadata referencing a dropped named collection. #115326 (Groene AI).
- Fixed
timezoneOffset(aliastimeZoneOffset) returning an offset wrong by exactly one day for time zones whose UTC offset differs from their 1970-01-01 offset by a whole day, such asPacific/KiritimatiandPacific/Apiaafter they crossed the international date line, and for most zones before 1970. This also fixesparseDateTime,parseDateTimeOrNull,parseDateTime64,parseDateTimeInJodaSyntax,EXTRACT(TIMEZONE_HOUR / TIMEZONE_MINUTE ...),formatDateTime’s%z,toUTCTimestampandfromUTCTimestamp, which consume that offset. Closes #115281. #115332 (Groene AI). - Fixed a bypass of settings constraints:
SET <name> = DEFAULTreset a setting without checking the constraints from the user’s profile, so aMIN/MAX/CONSTconstraint could be escaped by resetting the setting instead of assigning to it, and a session could leave readonly mode withSET readonly = DEFAULT. #115334 (Alexey Milovidov). - Arrow Flight server: reject malformed Basic authentication credentials that omit the username/password separator. #115347 (Alexey Milovidov).
- Fixed a
LOGICAL_ERROR(Join is supported only for pipelines with one output port) for afull_sorting_mergeJOIN withquery_plan_join_shard_by_pk_rangesenabled when one of the two sides is pruned to no parts at all - by the primary key, by column statistics, or because the table is empty. #115352 (Alexey Milovidov). - Disable the query condition cache for filters over _part_starting_offset. #115358 (Azat Khuzhin).
- Fixed
randConstantreturning two different values in one query when its calls carry different aliases.randConstantis documented to hold a single value for the whole query, andSELECT randConstant() = randConstant()already returned1, but adding aliases as inSELECT randConstant() AS a, randConstant() AS bproduced two unrelated values. #115384 (Alexey Milovidov). - 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 (Vladimir Cherkasov). - Fix
GroupingAggregatedTransformproducing duplicate chunks for the same bucket. #115487 (Nikita Taranov). - Fixed the error message of
geoToH3naming the wrong argument position and the wrong type when a coordinate is notFloat64. Under the defaultgeotoh3_argument_order = 'lat_lon'the message pointed at the other argument and printed that argument’s type. Closes #101813. #115503 (Groene AI). - Reject a bare carriage return (
\r), in addition to a line feed (\n), in HTTP header names and values that pass through the HTTP header filter. This closes an HTTP header injection (request/response splitting) gap for features that pass user-provided headers, such as theurltable function and engine, HTTP dictionaries, and data lake catalogs. #115510 (Sergei Trifonov). - Fixed caches configured by a maximum number of entries (
SLRUpolicy) silently stopping to admit new entries once that many entries had been accessed at least twice. Affected caches include the Iceberg and Paimon metadata file caches, the Parquet metadata cache, the text index caches, the vector similarity index cache, the compiled expression cache and the ObjectStorageQueue file status cache. #115517 (Groene AI). - Fixed a hang of up to one hour in
BACKUP/RESTORE ... TO S3, GCS disks and thes3table function when the named collection setshttp_client = 'gcp_oauth'and the Google OAuth2 token endpoint accepts the connection but never answers. The bearer token request no longer inherits the caller’s data transfer request timeout; its response wait is bounded at 10 seconds, matching the STSAssumeRolerequest cap. #115531 (Groene AI). - Fix
dictGetand its variations in distributed queries: an unqualified dictionary name is now bound to the current database of the initiator, instead of being resolved against the current database of each shard, where it either was not found or resolved to a different dictionary of the same name. #115541 (Alexey Milovidov). - Fix a race that could make a
STREAM BOUNDEDquery return fewer rows than were committed before it started, usually none. #115543 (Alexey Milovidov). - Fixed Keeper snapshots being written as empty files when
compress_snapshots_with_zstd_formatis disabled. The server loggedCreated persistent snapshotbut the snapshot file was 0 bytes, and the node then refused to start withCORRUPTED_DATA. Closes #115388. #115553 (Groene AI). - 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 (Groene AI). - Fixed an out-of-bounds read of the cached dictionary hashes when aggregating or joining on a
LowCardinality(String)key whose dictionary grows while it is being aggregated, reachable fromTTL ... GROUP BY. It could yield a wrong hash, and a reported heap-buffer-overflow in sanitizer builds. #115604 (Groene AI). CREATE TABLEandALTER TABLEnow reject a lossy codec such asSZ3on a column used in the partition key. #115626 (Groene AI).- Fix invalid backslash escape characters in text, tokenbf_v1 and ngrambf_v1 indexes. #115634 (Elmi Ahmadov).
- Fixed
removePartAndCoveredPartswhen it is called for a part that is present in the active data part set. #115640 (Mikhail Artemenko). - Allow KeeperMap readers to accept shared metadata when equivalent primary keys differ only by redundant outer parentheses. #115642 (Sergey Kuznetsov).
- Fixed a bug where restoring a database or table under a new name dropped the table aliases from the bodies of stored views, so reading a restored view failed with
UNKNOWN_IDENTIFIER. Closes #115479. #115645 (Groene AI). - Fixed
Code: 349. Cannot convert NULL value to non-Nullable typewhen ahasornotHaspredicate carries a NULL array element and the primary key is aString,Array(String)orMap(String, String), and fixed wrong results when that element is aDynamicorVariantholding NULL. The NULL is now dropped from the set during key analysis, as it already was for other key types. #115647 (Groene AI). - 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). - Reject zero and negative
stepvalues in one-point Prometheus range queries. #115679 (Minh Vu). - Reject PromQL timestamps and durations that exceed the Int64 range. #115682 (Minh Vu).
- Fix server crashes on deeply nested input in
readWKB,JSONMergePatch, the address parser of theurl/remote/cluster/mysql/postgresqltable functions, theCURSORclause parser and the CapnProto schema parser. Fix a crash in the parser of theEXECUTEstatement when an argument is not a literal. #115700 (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).
- Bound the size of the startup message of the PostgreSQL wire protocol, which is read before authentication. #115708 (Alexey Milovidov).
- Fix the
MULTIPLE_EXPRESSIONS_FOR_ALIASerror in queries where a column alias coincides with the alias of a table expression in theFROMsection (an analyzer regression in version 25.2). #115714 (Alexey Milovidov). - Fixed
clickhouse-localterminating the whole process when a connection handler of a listener started withSYSTEM START LISTENthrew, for example because a client sent a malformed packet or reset a keep-alive socket. Such a process now logs the error and keeps serving, likeclickhouse-serverdoes. #115715 (Groene AI). - Fix
LOGICAL_ERROR: No available columnswhen a query reads no columns from a table expression that has no columns at all, for exampleSELECT count() FROM loop(db, tbl)wheretblis anAliastable whose target was dropped, or a parameterized view. Such a query now fails withUNSUPPORTED_METHODinstead of aborting the server in debug and sanitizer builds. #115716 (Groene AI). - Fix
LOGICAL_ERROR“Reading from materialized CTE ‘X’ before its materialization completed - DelayedPortsProcessor gate is missing in the query plan” when aMATERIALIZEDCTE is read from inside anINsubquery over aDistributedtable. Closes #113184. #115740 (Groene AI). - Reject invalid names of projections and indexes. #115824 (Alexander Tokmakov).
- Reject PromQL vector matching modifiers when one operand is a scalar. #115828 (Minh Vu).
- Fixed
cast_keep_nullablenot preserving nullability when the target type isLowCardinality. Casting a NULL-capable value toLowCardinality(T)threwCANNOT_INSERT_NULL_IN_ORDINARY_COLUMNinstead of producingLowCardinality(Nullable(T)). Closes #103485. #115851 (Groene AI). - Add Objects’ paths to deduplication hashing, preventing incorrect deduplication. #115866 (Mikhail f. Shiryaev).
- Fix
TYPE_MISMATCH(“CAST AS Array can only be performed between same-dimensional array types”) for a query with a constant of typeArray(Map(...)), such ashas([map('k', 'v')], m), executed over aDistributedtable or with parallel replicas. #115883 (Alexey Milovidov). - Fix
Unknown identifierraised during query plan optimization undermake_distributed_plan = 1when a window query’s sort column passes through anExpressionstep that does not mention it. Closes #115737. #115890 (Groene AI). - Fixed
h3kRing,h3HexRing,h3Lineandh3ToChildrenignoringmax_execution_timeandKILL QUERYwhile expanding a block of rows. #115893 (Alexey Milovidov). - Reading through a
Mergetable that matches anAliastable whose target is a parameterized view no longer raisesLOGICAL_ERROR: Table has no columns.(which aborts the server in debug and sanitizer builds). Such a table now reportsSTORAGE_REQUIRES_PARAMETER, the same error the parameterized view itself reports. Any other matched table that cannot supply columns now reportsUNSUPPORTED_METHODinstead of an internal error. #115896 (Groene AI). - Fixed the on-the-fly preview of a pending mutation whose expression references
_sample_factor. Withapply_mutations_on_fly = 1and aSAMPLEclause, the expression was evaluated with the reading query’s sample factor instead of the value the background materialization persists, so previewed rows disagreed with the eventual materialized result, and a pendingALTER TABLE t DELETE WHERE _sample_factor > 1could make aSAMPLEread return no rows at all. The query’s own_sample_factorcolumn is unchanged. #115906 (Groene AI). - Fixed a case where
ATTACH TABLEcarrying anENGINE = URL(...)definition did not check theTABLE ENGINEgrant of the engine the URL scheme dispatches to. A user holding onlyTABLE ENGINE ON URLcould attach and then read aFile,S3,AzureBlobStorageorHDFSbacked table, whichCREATE TABLEcorrectly rejects. #115914 (Groene AI). - Do not let an unparsable KeeperMap metadata node stop the server from starting. #115941 (Groene AI).
- Fix a crash of the
showCertificatefunction on a server that obtains its TLS certificate with ACME (Let’s Encrypt). The function now reports the certificate that is actually served, also after a certificate reload. #115976 (Alexey Milovidov). - Fixes a server abort in debug and sanitizer builds when inserting into a materialized view whose
TOtarget is another materialized view. Such an insert already failed on released versions, with an uninformativeCode: 1001 STD_EXCEPTION; it now reportsNOT_IMPLEMENTEDnaming the offending view. #115985 (Groene AI). - Statistics files with format version
V3are now read instead of rejected withILLEGAL_STATISTICS. Such files were produced only by builds ofmasterfrom a narrow window, but parts containing them were completely unreadable, and on a readonly diskALTER TABLE ... MATERIALIZE STATISTICScannot regenerate them. #116030 (Alexey Milovidov). - Fixed
LOGICAL_ERROR: Index with name auto_minmax_index_<column> already existswhen a singleALTER TABLEstatement combinedRENAME COLUMNwith another command, such asMODIFY SETTING, on a table with implicit minmax indices (add_minmax_index_for_numeric_columnsand friends). Renaming a plain column also no longer leaves a followingDROP COLUMNfailing withUNKNOWN_IDENTIFIER, nor a followingADD COLUMNwithout its implicit index. #116063 (Groene AI). - Fix stateless workers crash with object storage. #116067 (Konstantin Vedernikov).
Build/Testing/Packaging Improvement
- Provide signed artifacts for macOS. #115169 (Konstantin Bogdanov).
- Fix building from source with clang 23. #112288 (Azat Khuzhin).
- Reduced the dependencies and the code size of the SQL parser, which can now be built on its own — see
utils/wasm-parserfor a standalone WebAssembly build of it. The tables of SQL keywords and access types are now built at compile time instead of on every server start. #112067 (Alexey Milovidov). - Building from source now fails during CMake generation instead of corrupting
StorageSystemLicenses.generated.cppwhen license generation fails. #111222 (Mikhail Artemenko). - Updated the bundled Apache Thrift library to version 0.24.0. #111278 (Groene AI).
- Add
libucontextfor musl builds, enabling theboost::contextucontextbackend used by sanitizer builds. #111437 (Konstantin Bogdanov). - Fix source-level portability issues when building with musl. #111631 (Konstantin Bogdanov).
- Editing
Core/ProtocolDefines.hno longer triggers a near-full rebuild when building from source: the include was removed fromBlockInfo.hand added only in the files that use its constants. #111650 (Alexander Gololobov). - Fix a startup abort in macOS debug builds by disabling memory-tracker debug checks for allocations made by system libraries. #112080 (Arsen Muk).
- Updated the bundled
libarchiveto version 3.8.9. #112434 (Konstantin Bogdanov). - Updated
StringZillato version 5.0.5. #112319 (Konstantin Bogdanov). - Update
jwt-cppto v0.7.2. #112595 (Konstantin Bogdanov). - Update the bundled SQLite amalgamation from 3.41.2 to 3.53.4. #112599 (Konstantin Bogdanov).
- Updated
aws-c-httpto version 0.11.0. #112413 (Govind R Nair). - Update
libcotpto v4.2.1. #112596 (Konstantin Bogdanov). - OpenSSL can now be built from its portable C sources on architectures that have no hand-written assembly in the build description, instead of failing at the final link with undefined symbols. The new
OPENSSL_NO_ASMCMake option selects the same path explicitly. #112863 (Alexey Milovidov). - Added an
ENABLE_ORCCMake option (on by default), so a build can have Parquet without ORC and without the protobuf andprotocthat ORC brings with it. #112864 (Alexey Milovidov). Common/Exception.cppno longer requires ClickHouse’s patched libc++ to compile, so a build linking a different C++ standard library gets exceptions without a throw-site stack trace rather than not compiling. #112865 (Alexey Milovidov).- Stack unwinding on aarch64 musl builds now continues through signal frames and blocked syscalls instead of stopping at the libc frame, improving stack traces from the fatal error handler and the sampling query profiler. #112592 (Konstantin Bogdanov).
- Update the vendored
libexpatto 2.8.2. #112593 (Konstantin Bogdanov). - Update
simdjsonto v4.6.5. #112594 (Konstantin Bogdanov). - Update Apache Arrow to 25.0.0 and Apache ORC to 2.3.1. #112604 (Konstantin Bogdanov).
- Coverage builds (
WITH_COVERAGE) now link the profile runtime built in-tree from the vendored LLVM sources instead of the archive bundled with the host clang toolchain. #112607 (Konstantin Bogdanov). - Update Protocol Buffers to v35.1 and gRPC to v1.83.0. #112614 (Konstantin Bogdanov).
- Added an experimental WebAssembly (
wasm64, via Emscripten) target:emcmake cmakenow configures the tree and the lower layers build. Also fixed-DENABLE_LIBFIU=OFF, which did not build on any platform. #112911 (Alexey Milovidov). - Fixed every
-Wunique-object-duplicationsite: header-defined mutable singletons that would get one copy per shared object instead of one per process. Mostly by moving the definition into a.cpp. #112995 (Alexey Milovidov). - Installing a
tgzpackage over a dangling symlink now preserves the symlink chain and applies the packaged target’s mode and ownership instead of aumask-derived mode. #112766 (Alexey Milovidov). - In
aarch64musl builds,memmovenow uses the ARM optimized-routines assembly implementation (shared withmemcpy) instead of the generic C word-at-a-time loop. #113502 (Konstantin Bogdanov). - In musl builds,
getaddrinfowithAI_ADDRCONFIGnow follows glibc semantics, solocalhostno longer resolves to an unusable::1first in IPv4-only environments, andsysconfreturns glibc’s buffer-size hints forgetpwuid_r/getgrgid_rinstead of -1, unbreaking libhdfs3. #113485 (Konstantin Bogdanov). - In musl builds,
sched_getcpuis now an rseq read (~1ns) instead of a syscall, matching glibc and removing the system-time overhead of jemalloc’spercpu_arenaon allocation-heavy workloads; musl also registers rseq eagerly and exports the glibc__rseq_*ABI. #113501 (Konstantin Bogdanov). - Fix local (non-CI) builds compiling all vendored Rust code (the
PCOcodec, Delta Lake reads viadelta-kernel-rs,prqlc,chdig,wasmtime, the client’s fuzzy history search viaskim) withopt-level = 0. TheSANITIZECMake variable was declared withoption, so its default value was the BOOLOFF, which failed theSTREQUAL ""“no sanitizer” checks, and every build configured without an explicit-DSANITIZE=...took the sanitizer workaround path that disables Rust optimization. #114083 (Alexey Milovidov). - Push docker image layers zstd-compressed. #114342 (Alexey Milovidov).
- Build Debian packages for the release builds only. #114739 (Alexey Milovidov).
- Fixed building
unit_tests_dbmsin configurations without the full library set (ENABLE_LIBRARIES=0orENABLE_ROCKSDB=0). #115655 (Alexey Milovidov).
ClickHouse release 26.7, 2026-07-22. Presentation, Video
Backward Incompatible Change
- S3 access originating from user SQL no longer resolves the server’s own cloud credentials (environment, IMDS/IRSA, instance profile, AWS config files,
role_arn-based STS, GCP OAuth metadata) by default; such a request must use explicit credentials orNOSIGN. Named collections now defaultuse_environment_credentialsto0. The previous behaviour can be restored per request withuse_environment_credentials = 1(or globally via the<s3>config) together with the new settings3_allow_server_credentials_in_user_queries(disabled by default). Explicitly supplied and operator-provisioned config credentials are unaffected. On server startup orRESTORE, a persistentS3/S3Queuetable, dynamic S3 disk, orDataLakeCatalogwhose definition resolves such credentials is loaded anonymously (inaccessible until re-credentialed) instead of aborting startup, controlled by the new server settings3_load_table_anonymously_if_credentials_restricted(enabled by default). #106855 (Raúl Marín). - The
**/glob (any number of directories) now also matches the same directory. Previously,**/in glob patterns was not handled as a special case, sodata/**/file.txtwould not matchdata/file.txt(zero directory levels). #97676 (Alexey Milovidov). - Reject the
zip/zipxbackup archive format for backups stored on object storage — directS3(...)/AzureBlobStorage(...)destinations andDisk(...)destinations backed by S3 or Azure — for bothBACKUPandRESTORE. Zip requires seeking to read its central directory, which is very slow over object storage. Use a tar-based format such astar.gzinstead. #101770 (Yash ). - Extended the supported range of
DateTime64from[1900-01-01, 2299-12-31]to[0000-01-01, 9999-12-31]. Values outside the former range are now computed correctly (via cctz) instead of being clamped to the boundary. With precision 8 or 9 the range remains narrower because the ticks are stored asInt64(with nanosecond precision the maximum is still2262-04-11). Backward compatibility: if you used out-of-range date-times before, but relied on the very specific saturation rules inside the old range, keep in mind that now the results are changing to be more correct. #107907 (Alexey Milovidov). AggregatingMergeTreenow rejects, at table creation time, schemas where a column is neither part of the sorting key nor an aggregate-state measure (AggregateFunction/SimpleAggregateFunction). Such columns are silently collapsed to an arbitrary value during background merges, producing wrong results for queries thatGROUP BYor filter on them. Setallow_dimensions_outside_sorting_key = 1to restore the previous behavior. Closes #751. #108087 (Alexey Milovidov).- Removed the config-based workload scheduling configuration (the
resourcesandworkload_classifiersserver config sections). UseCREATE RESOURCEandCREATE WORKLOADqueries instead. The obsolete config sections are ignored with a warning. #108286 (Sergei Trifonov). - ClickHouse now always uses the unified insert deduplication hash for both synchronous and asynchronous inserts; the legacy per-insert deduplication behaviours are removed. The server setting
insert_deduplication_versionis kept as a migration guard: the server refuses to start if it is set to a legacy value (old_separate_hashesorcompatible_double_hashes). To upgrade from a version that used a legacy value, first run a release that supportscompatible_double_hashes(which writes both the legacy and unified hashes). For replicated tables run it for at leastreplicated_deduplication_window_seconds(one hour by default; the default windows retain the unified hashes of all inserts for that window, which is considered enough for an insert retry loop). For non-replicated tables withnon_replicated_deduplication_window> 0 that window is count-based rather than time-based, so runcompatible_double_hashesfor at least that many inserts. Then remove the setting (or set it tonew_unified_hash) before upgrading to this version. #108361 (Sema Checherinda). If you never setinsert_deduplication_version, you can ignore this item. - Removed the long-deprecated functions
snowflakeToDateTime,snowflakeToDateTime64,dateTimeToSnowflakeanddateTime64ToSnowflake. They were deprecated back in v24.6 in favor ofsnowflakeIDToDateTime,snowflakeIDToDateTime64,dateTimeToSnowflakeIDanddateTime64ToSnowflakeID, which should be used instead. The settingallow_deprecated_snowflake_conversion_functions(which used to re-enable them) is now obsolete and has no effect. #108711 (Alexey Milovidov). - The setting
use_legacy_to_timeis now0by default, sotoTimeconverts values into theTimedata type instead of converting a date with time to a fixed date. The legacy behavior is still available via thetoTimeWithFixedDatefunction or by settinguse_legacy_to_time = 1. #108729 (Alexey Milovidov). - Naive Bayes models (used by
naiveBayesClassifier) are now configured as a dictionary with theNAIVE_BAYESlayout, built at load time from a table of pre-aggregated per-class n-gram counts, instead of the previous server-side configuration (an XML config file referencing serialized.binmodel files), which is no longer supported — existing models must be recreated as dictionaries. Three new functions are added alongsidenaiveBayesClassifier:naiveBayesClassifierWithProbreturns the predicted class together with its probability,naiveBayesClassifierWithAllProbsreturns every class with its probability, andnaiveBayesNgramstokenizes text into n-grams the same way the dictionary does, for building the training data from raw labelled text. Additionally, several performance optimizations have been applied: on a 9.7 MiB code-point trigram language model, it uses ~49× less memory (from 1.84 GiB to 38 MiB), loads ~11× faster, and classifies ~11× faster. #108773 (Nihal Z. Miaji). - The
hasColumnInTablefunction no longer accepts the optionalhostname,username, andpasswordarguments for checking a column on an arbitrary remote server; only thehasColumnInTable(database, table, column)form remains. The removed remote mode was a security concern: it let any user trigger outbound connections to arbitrary hosts and leaked credentials into query logs, and it was not gated by any privilege. #110881 (Alexey Milovidov).
New Feature
- Added
EXPLAIN ANALYZEfor examination of query performance: the query is executed, and the actual execution metrics are rendered in the familiar query plan format. #106586 (Kirill Kopnev). #110668 (Kirill Kopnev). - Added support for
WHEREclauses in projection definitions. Projections withWHEREonly materialize rows matching the predicate, and the optimizer can use them (cost-based) when the query’sWHEREimplies the projection’sWHERE. #102347 (S Bala Vignesh). - Added the
skip_unavailable_shards_modesetting (also available as aDistributedengine setting) to control which exceptions from a remote shard are silently ignored whenskip_unavailable_shardsis enabled. #79091 (cjw). - Add
groupFormataggregate function that formats rows in each group using a specified output format and returns the result as a string. #93201 (Yang Hu). - Added
AWS_MSK_IAMas a supported value forkafka_sasl_mechanism, enabling ClickHouse to authenticate with Amazon MSK using IAM roles without managing SASL/SCRAM credentials. #96100 (kalavt). - Add aggregate function combinator
-Tuple, which applies the underlying aggregate function to each element of aTuplecolumn independently and returns aTupleof the results, preserving element names:sumTuple(t)fort = (a, b)returns(sum(a), sum(b)). Aggregate functions with several arguments take one tuple per argument, paired by position:corrTuple((a1, a2), (b1, b2))returns(corr(a1, b1), corr(a2, b2)). Unlike-ForEachover arrays, elements may have different types, and per-element result types and names are preserved. #98190 (RinChanNOW). - Text indexes now support a
postprocessorargument — an arbitrary expression that transforms each token after tokenization (for example,lower). #98939 (Jimmy Aguilar Mena). #108606 (Jimmy Aguilar Mena). - Added the
system.stemmerssystem table, which lists all languages that can be specified for thestemfunction. #100611 (Jimmy Aguilar Mena). - Add support for
WITH TIESfor negativeLIMIT. #100930 (Nihal Z. Miaji). - Added support for the standard SQL
AT TIME ZONEandAT LOCALpostfix operators as syntactic sugar fortoTimeZone. The expressionexpr AT TIME ZONE zoneis now equivalent totoTimeZone(expr, zone), andexpr AT LOCALis equivalent totoTimeZone(expr, timeZone()). #106092 (lizepeng). - The
URLtable engine andurltable function now dispatch to the appropriate backend based on the URL scheme:file://is served by theFileengine,s3:///gs:///gcs:///oss://byS3,az:///azure:///abfss:///abfs://byAzureBlobStorage,hdfs://byHDFS, andhttp(s)://by theURLengine as before. Theurl_basesetting is applied before scheme dispatch. Only the S3 schemes resolved by the defaulturl_scheme_mappersare dispatched; other S3-compatible vendor schemes (cos,obs, …) are not, and require using thes3engine/function directly. #106093 (Alexey Milovidov). - Added the
RemoteandRemoteSecuretable engines, the persistent counterparts of theremoteandremoteSecuretable functions.CREATE TABLE ... ENGINE = Remote('addresses', db, table, ...)now works in addition toCREATE TABLE ... AS remote(...). #106189 (Alexey Milovidov). - Added engine-agnostic
SYSTEM STOP,SYSTEM START,SYSTEM PAUSE,SYSTEM CANCEL, andSYSTEM REFRESHcommands, and their... ALL BACKGROUNDserver-wide forms, to control the background activity ofKafka,RabbitMQ,NATS,S3Queue/AzureQueuetables and refreshable materialized views through one unified interface. For refreshable materialized views they alias the existingSYSTEM ... VIEWcommands. As part of supporting these controls on NATS, JetStream tables now acknowledge messages only after a successful insert (at-least-once, previously messages were auto-acknowledged on delivery and could be lost if the insert failed). A newnats_wait_for_flush_intervalsetting (defaultfalse, preserving the previous low-latency behaviour) optionally keeps a consumption cycle open for the whole flush interval instead of flushing as soon as the queue drains. A newnats_commit_on_selectsetting makes a directSELECTon a JetStream table consume (acknowledge) the messages it reads. #107476 (Samuel Krempaský). - Added support for the
mysql,postgresql, andsqlitetable functions and table engines to accept a user’s query (instead of a table name) and pass it to the external database as is, written either as a subquery(SELECT ...)or asquery('SELECT ...'). The structure of the resulting table is inferred from the query result, and such a table is read-only. Closes #46758. Based on the initial implementation by Denis Vidiaev (#79652). #107740 (Alexey Milovidov). - Added tabs to the ClickHouse Web UI (Play) for working with multiple queries at once. Tabs, their titles, parameters, active state, and small result snapshots are persisted across reloads (large and image results are not restored), integrate with browser history and the URL, and can be switched with the mouse wheel. #107826 (Alexey Milovidov).
- Introduce the
QueryRunnertable engine. Records inserted into aQueryRunnertable represent queries that the engine executes. The engine can be used for asynchronous query execution, batch execution of generated queries, directing queries to remote clusters, benchmarks, fuzzing, and testing with shadow traffic. #107888 (Miсhael Stetsyuk). - Add the
GeoJSONoutput format for writing GeoJSONFeatureCollectiondocuments, producing one feature per row. The single geo-typed column (Point,LineString,MultiLineString,Polygon,MultiPolygon,Ring, orGeometry) becomes each feature’sgeometry; a column namedidbecomes the featureid; and any remaining columns become the featureproperties, where a lone object-typed column namedproperties(aJSON,Map, or namedTuple) is written directly as thepropertiesobject. ARingis written as a single-ringPolygon. The newformat_geojson_validate_geometrysetting (enabled by default) controls whether geometries that are not valid GeoJSON shapes — such as aPolygonwith fewer than four points or an unclosedPolygonring — are rejected when reading and writing. Additionally, theGeoJSONinput format now infers theidcolumn asNullable(String)instead ofString, so a feature with an absent or explicit"id": nullmember is read asNULLand kept distinct from an empty string"". Based on the initial implementation by Mark Needham (#98124). #108065 (Nihal Z. Miaji). - Added the
dotProductTransposedfunction (aliasscalarProductTransposed) that computes the approximate inner product between aQBitcolumn and a reference vector, complementing the existingL2DistanceTransposedandcosineDistanceTransposedfunctions. #108100 (Alexey Milovidov). Added quantized transposed distance functionscosineDistanceTransposedQuantized,L2DistanceTransposedQuantizedanddotProductTransposedQuantizedthat operate on aQBit(Int8)ofquantizeBFloat16ToInt8Lloyd-Max codes, dequantizing the stored codes on the fly. A floating-point reference vector is the full-precision query, compared atFloat32precision (aFloat64query is narrowed); anArray(Int8)reference is itself dequantized, for a symmetric quantized-vs-quantized distance. #109405 (Alexey Milovidov). - Added an optional stride parameter to the
QBitdata type (QBit(T, dimension, stride)) that stores groups of dimensions in separate streams, so a vector search can read only the first dimensions efficiently (e.g. for Matryoshka embeddings). The transposed distance functions accept an optional fourthused_dimsargument to read a reduced number of dimensions. #108103 (Alexey Milovidov). - Added support for the
Int8element type in theQBitdata type, enabling storage and transposed-distance vector search (L2DistanceTransposed,cosineDistanceTransposed) over quantized 8-bit integer vectors. #108105 (Alexey Milovidov). - New function
randomHadamardTransform(vector[, seed[, output_dims]]): a deterministic randomized Hadamard transform of a float vector — an orthogonal, norm-preserving rotation useful for preprocessing embeddings before quantization, and (when truncated) as a Johnson–Lindenstrauss / subsampled-randomized-Hadamard random projection. #108227 (Alexey Milovidov). - Support configuring lazy loading of dictionaries on a per-dictionary basis with the
dictionary_lazy_loadsetting in the dictionary definition, overriding the globaldictionaries_lazy_loadserver setting, so that some dictionaries can be loaded lazily while others are loaded eagerly. #108314 (Miсhael Stetsyuk). - Added a built-in documentation search page, available at the
/docspath of the HTTP interface, that provides instant search over thesystem.documentationtable and renders the reference documentation (with syntax highlighting, math, and cross-links). #108345 (Alexey Milovidov). - Added function
xxHash64Spark, which computes Spark-compatiblexxHash64values forStringandNULLinputs using seed42and returnsInt64. #108436 (Lalit Yadav). ALTER USER,ALTER ROLEandALTER SETTINGS PROFILEnow acceptSET name = valueas an alias forMODIFY SETTING name = value. It changes individual settings in place while keeping the rest, unlike the bareSETTINGSclause which replaces the whole settings list. This makes it less likely to accidentally wipe a user’s other settings. #108722 (Groene AI).- Support
ALTER TABLE ... MODIFY CONSTRAINT [IF EXISTS] name CHECK exprto change the expression of an existing constraint in place. #108768 (Alexey Milovidov). - Web UI: added a per-column color coding switch (the 🌈 icon in a column header) to toggle between bar, heatmap, categorical, and no visualization. The selected modes are remembered in the URL and browser history. #108873 (Alexey Milovidov).
Keepernow correctly handlesZooKeeper’sCreateContaineropcode (19), gated behind a new opt-increate_containerfeature flag (disabled by default, likecreate_ttl). Once enabled after a full ensemble upgrade, externalZooKeeperclients (e.g. JavaZooKeeper3.9+) can create container nodes againstKeeperinstead of gettingConnectionLoss; container nodes report the expectedephemeralOwnersentinel value, and a background GC thread on the leader auto-deletes childless containers. A plainCreaterequest carrying theCONTAINERcreate-mode flag without opcode 19 continues to be rejected (ZBADARGUMENTS): no knownZooKeeperclient emits that combination. This is server-side protocol compatibility only: ClickHouse’s ownZooKeeperclient (zkutil) is unchanged and has no API to create container nodes itself. #108908 (unintended).- Added functions
geoToUTM,UTMToGeo,geoToMGRSandMGRSToGeofor converting between WGS84 geographic coordinates and the UTM and MGRS coordinate systems. #108939 (Alexey Milovidov). - Added the
digits(n, offset[, length])function, which returns the digits ofnstarting at the 1-basedoffsetand spanninglengthdigits, or to the end of the number iflengthis omitted. #109012 (Umang Agrawal). - Add the
sqrarithmetic function for calculating the square of a number. #109061 (Lalit Yadav). - Added a new function
dictGetRootwhich returns the topmost ancestor (the root) of a key in a hierarchical dictionary. It is a convenient equivalent ofdictGetHierarchy(dict_name, key)[-1]. #109459 (Alexey Milovidov). - Add
SYSTEM UNLOAD DICTIONARYandSYSTEM UNLOAD DICTIONARIEScommands to release dictionary memory without dropping the dictionary definition. Dictionaries will be reloaded lazily on the next access. #109639 (Matheus Nerone). - Added functions
geometryIntersectCartesianandgeometryIntersectSphericalthat return whether two geometries intersect. UnlikepolygonsIntersectCartesian/polygonsIntersectSpherical, they accept any geometry data type (Point,LineString,MultiLineString,Ring,Polygon,MultiPolygon), including the commonGeometrytype, and the two arguments may be of different types. #110062 (Alexey Milovidov). - Query parameters (
{name:Type}substitutions) can now be used as setting values, both in theSETTINGSclause of a query (such asSELECTorINSERT) and in standaloneSETqueries, e.g.,SELECT ... SETTINGS max_threads = {threads:UInt64}andSET max_threads = {threads:UInt64}. #108760 (Alexey Milovidov).
Experimental Feature
- Wildcard expansion for the
urltable function and theURLtable engine: wildcards in the URL path are expanded by listing HTTP index pages (HTML or plaintext directory listings) and extracting matching URLs, with limits on the index page size and on the number of directories read. Enabled by theallow_experimental_url_wildcard_from_index_pagessetting. #95181 (Yue Ni). - Text indexes can now store token positions (the
support_phrase_searchindex argument) to enable exact phrase matching with direct reads for thehasPhrasefunction. Requires enabling theMergeTreesettingallow_experimental_text_index_phrase_search. #103172 (Elmi Ahmadov). The argument was initially introduced under the namepositions. #109900 (Elmi Ahmadov). - Support manifest file compaction for
Icebergtables viaOPTIMIZE TABLE ... MANIFEST(guarded by theallow_experimental_iceberg_compactionsetting). Closes #95174. #98178 (Smita Kulkarni). FixOPTIMIZE TABLE ... MANIFESTforIcebergtables when manifest partition tuples do not match their partition spec. #111368 (Smita Kulkarni). - Add a Real Doubles (RD) variant and an optional
ALP(AUTO|STD|RD)argument to the experimentalALPcodec. BareALPnow auto-selects between the existingSTDscheme andRDinstead of always usingSTD. #99654 (Nazarii Piontko). - Add an in-memory SLRU cache for deserialized
Paimonmetadata files (manifest lists and manifests). When enabled via theuse_paimon_metadata_files_cachesetting, repeated queries against the samePaimontable skip re-downloading and re-parsing metadata from object storage. #104657 (XiaoBinMu). - Added “drivers” for executable user-defined functions. A driver declared in
<user_defined_executable_function_drivers_config>can be used inCREATE FUNCTION name ARGUMENTS (...) RETURNS T ENGINE = DriverName(...) AS '...code...'to compile or otherwise process a user code snippet at function-creation time and produce a runnable executable UDF. The resulting configuration is stored in<dynamic_user_defined_executable_functions_path>, and the originating query is persisted asATTACH FUNCTIONso the function survives server restarts. A proof-of-conceptc_function_bodydriver compiles and runs C function bodies inside sandboxed Docker containers inexecutable_poolmode. Based on the initial implementation by Daniil Timižev (#77128). #105131 (Alexey Milovidov). - Serve
SELECT count(*) FROM t WHERE col <op> default(col)from per-column sparsity statistics inserialization.jsonwithout any data scan when the predicate exactly partitions the column into defaults and non-defaults (under the new experimental settingoptimize_trivial_count_with_sparsity_filter, off by default). #105890 (Raúl Marín). - Prometheus Query API requests to
/api/v1/queryand/api/v1/query_rangeare now recorded insystem.query_logwithread_rowsandread_bytesmetrics. #106611 (James Cunningham). - The experimental
ReaderExecutorread path (use_reader_executor, off by default) can now hold a remote source connection open and reuse it across sequential reads, reducing the number of object storage requests on scans. #107735 (Sema Checherinda). It now also supports reading encrypted files, with a global encryption-header cache configured by theencryption_header_cache_sizeserver setting and cleared bySYSTEM DROP ENCRYPTION HEADERS CACHE. #109702 (Sema Checherinda). - Support distributed query-plan reads for
SELECT ... FINALonMergeTree-family tables whenmake_distributed_planis enabled. #108148 (Alexander Gololobov). - Add experimental plan-based parallel replicas execution for
MergeTreequeries. #108504 (Igor Nikonov). - Added the experimental
Quantizevector codec family and an opt-in two-stage approximate vector-search rewrite over quantized companion streams. #108565 (Shankar Iyer). - Revive the experimental
SZ3error-bounded lossy compression codec forFloat32/Float64(and arrays of them) columns, originally implemented by Konstantin Vedernikov (#83088). It requiresallow_experimental_codecs. #108788 (Alexey Milovidov). Fixed reading data compressed withSZ3('ALGO_LORENZO_REG', ...), which previously failed withCORRUPTED_DATA, and avoided undefined behavior when compressing non-finite floating-point values (NaNand infinities). #110762 (Alexey Milovidov). - Added the experimental
ZXCcodec — an asymmetric LZ codec with slow compression and very fast decompression, with a compression ratio betweenLZ4andZSTD. It requiresallow_experimental_codecs = 1, andsystem.compression_codecsreports it as experimental. #110620 (Alexey Milovidov). #111007 (Alexey Milovidov). - You can now authenticate to OneLake using a pre-obtained bearer token via the
onelake_bearer_tokensetting, instead of aonelake_client_idandonelake_client_secret. This avoids sharing a long-lived client secret. The token is not refreshed, so the database must be recreated once it expires. #109104 (Asya Shneerson). - AI functions no longer take the named collection as the first positional argument. Credentials come from the
ai_function_text_default_credentials/ai_function_embedding_default_credentialssettings or from acredentialskey in an optional trailingMap(String, String)argument, which also carries tunables (model,max_tokens,temperature,system_prompt,instructions,dimensions). #109232 (George Larionov). TheaiEmbedfunction now takesmodelas a required positional argument (aiEmbed(text, model[, params])) instead of reading it from the named collection, which ensures reproducibility for embeddings. #110619 (George Larionov). - Fix
data_uncompressed_bytesfor skip indices packed intoskp_idx.packed(viapacked_skip_index_max_bytes): the reported uncompressed size was the compressed size, which could also preventdistributed_index_analysisfrom activating. #109272 (Raúl Marín). - Added experimental packed data part storage for
MergeTreetables, which stores most of a part’s files in a singledata.packedarchive instead of a file per stream (projections and a few service files, such astxn_version.txt, are still written separately). It is controlled by themin_bytes_for_full_part_storage,min_rows_for_full_part_storage, andmin_level_for_full_part_storagesettings and is disabled by default. Once a table writes packed parts, older server versions cannot read them, so enabling this format prevents downgrading the server. #108118 (Raúl Marín). - Added an experimental table function
eval, which evaluates a constant expression to a query string and executes the resulting singleSELECTquery. The feature is disabled by default and can be enabled with the settingallow_experimental_eval_table_function. Author: Yue Ni. #110132 (Alexey Milovidov). - Add
zstdcompression support to the experimental Prometheus remote-write v1 HTTP handler. #110907 (James Cunningham). - Writing to
DeltaLaketables (theallow_experimental_delta_lake_writessetting) was promoted to Beta. #107034 (Kseniia Sumarokova). - Added
ProfileEventsDistributedPlanRemoteTasks,DistributedPlanLocalExecution, andDistributedPlanHostsUsedto observe the execution of experimental distributed query plans (make_distributed_plan). #107985 (Shankar Iyer). - Removed the experimental RocksDB-based storage in Keeper (
experimental_use_rocksdb). A better new on-disk storage is coming soon. #108000 (Michael Kolupaev). - Distributed index analysis (an experimental feature controlled by the
distributed_index_analysissetting) now sends big lists of data part names to remote servers as scalars instead of embedding them into the query text. This avoids possible failures due to themax_ast_elements/max_query_sizelimits and removes the AST parsing overhead. #110419 (Azat Khuzhin). - Optimize the experimental
timeSeries*ToGridaggregation functions: buckets are now aligned to both step and window, and the final aggregation is much faster when the window is much larger than the step. The serialization format of the aggregation state was changed in an incompatible way (these functions are experimental). #106724 (Vitaly Baranov). - External target tables of a
TimeSeriestable are now registered as referential dependencies: similarly to materialized views, this disallows dropping an external target table before dropping theTimeSeriestable that references it (ifcheck_referential_table_dependenciesis enabled). #108388 (Vitaly Baranov). - Add the PromQL function
increase. #111023 (Vitaly Baranov).
Performance Improvement
JOINs can now use the primary key index or skip indexes on the left-hand side table to prune granules. Controlled by the settingenable_join_runtime_filters_index_analysis. #109085 (Shankar Iyer).- Serialization and deserialization of vectors of trivially serializable types now use a single buffer I/O call instead of processing individual elements. #89842 (Jimmy Aguilar Mena).
- Optimize inverse dictionary lookups: a constant equality predicate such as
WHERE dictGet(dict, attr, key_expr) = valueis now constant-folded directly into a key filter (key_expr = const,key_expr IN [...], orWHERE 0) instead of being rewritten to anIN (SELECT ... FROM dictionary(...))subquery, and the constant path ofdictGetKeysnow executes in parallel. #91164 (Nihal Z. Miaji). - Add a new setting
merge_tree_generic_exclusion_search_max_stepsthat limits the number of steps the generic exclusion search algorithm spends analyzing the primary key index of each data part. The budget is spent on the largest remaining key ranges first, so even a small budget prunes the bulk of the data; ranges that were not fully analyzed are read whole, so query results stay correct but more granules may be read. The limit is applied loosely: it may be exceeded by at mostmerge_tree_coarse_index_granularitysteps, plus one step for each range the part is already divided into (for example, by the query condition cache). The default value 0 means unlimited steps. #92779 (Michael Jarrett). - Queries with
ORDER BYandLIMITon views overDistributedtables now use the merge-sorted-streams optimization: the outerORDER BY/LIMITis pushed into a simple view’s inner query, so each shard sorts its data locally and the coordinator merges pre-sorted streams instead of performing a full sort. #94102 (matanper). - Enable
optimize_or_like_chainby default. Closes #87779. #94517 (Alexey Milovidov). - Mark rotated non-replicated
MergeTreesystem log tables without TTL astable_readonlyto avoid unnecessary background operations. Thetable_readonlyMergeTreesetting now also suppresses all background work on a plainMergeTreetable — regular, TTL (DELETE/MOVE/recompression) and recompression merges, background mutations, and background part moves — and rejects the mutating partition commands (ATTACH/MOVE/DROP/DROP DETACHED/FETCH/REPLACE PARTITIONandMOVE PARTITION ... TO TABLEinto the table), in addition to the inserts, mutations, andOPTIMIZEit already rejected. As a result, atable_readonlytable with a TTL no longer reclaims its expired data while the setting is enabled. #95079 (Mathuranath Metivier). - Improve the performance of fetching a single user record from
system.userswhen the server has many users. #96699 (Alistair Evans). - Reading in order with parallel replicas now uses the same logic of splitting the table into
max_threadsparts as local reading, for better parallelism. #101434 (Nikita Taranov). - Use partition minmax index bounds to prune more granules during primary key analysis for
MergeTreetables, when a primary key column is also an input column of the partition key. For example, in aMergeTreetable withORDER BY (id, event_time)andPARTITION BY toYYYYMM(event_time), ClickHouse will use the partition minmax index onevent_timeduring primary key index analysis to make more informed granule-pruning decisions. Controlled by the new settinguse_partition_minmax_for_primary_key_pruning(enabled by default). #103480 (UnamedRus). - Enable the query condition cache for queries that use Top-K dynamic filtering (
ORDER BY ... LIMIT n). The cache entry is partitioned by the Top-K plan parameters, so the same query reuses cachedWHEREfilter results, while a differentLIMIT, sort column, or sort direction produces a fresh entry. #104478 (Alexey Milovidov). - Added the
use_constant_folding_in_index_analysissetting (disabled by default). When enabled,MergeTreeprimary-key,MinMax, and skip-index analysis fold partition-level constants into the filter predicate separately for each part, improving pruning for filters whose branches depend on partition values, e.g.(a = 1 AND b >= 1) OR (a = 2 AND b > 10)withPARTITION BY a. #104582 (Mikhail Artemenko). - Push
LIMITinto aggregation-in-order to enable early termination when theGROUP BYkey matches theORDER BYkey and the table sorting key, significantly reducing the number of rows read. #104859 (Konstantin Bogdanov). - Updating profile events is now up to 30 times faster, using per-CPU atomics for server-wide and per-user counters. Controlled by the
user_profile_events_per_cpuserver setting (it uses around 640 KiB per user on 64 cores, so with a very large number of users it may make sense to keep it disabled). #105056 (Azat Khuzhin). - Enable
allow_aggregate_partitions_independentlyby default. When aGROUP BYkey suits the partition key, ClickHouse can aggregate each partition independently and skip the global merging step. Runtime heuristics automatically skip the optimization when the partition layout would make it unfavorable (too few partitions, too many partitions, or significantly skewed partition sizes). #105128 (Alexey Milovidov). - Vector search queries with rescoring (
vector_search_with_rescoring = 1) now compute the exact distance only for the rows returned by the vector index, applying an exact row-position filter instead of brute-force rescoring neighbouring rows from the sameMergeTreegranule. #105591 (Sergey Kuznetsov). #108846 (Sergey Kuznetsov). - Improve the performance of the
partial_mergejoin algorithm onFixedStringkeys by comparing runs of values at once instead of one comparison call per value. #105737 (Artem Zuikov). SHOW TABLESandsystem.tableson data lake catalogs (Iceberg REST, Glue, Unity, Hive, Paimon) now push namespace-bound predicates down to the catalog, avoiding a full catalog scan. Closes #105022. #106029 (Smita Kulkarni).- Bound untracked memory per CPU to avoid overcommit and out-of-memory errors (the limits are configured with the
max_per_cpu_untracked_memoryandper_cpu_untracked_memory_thread_bufferserver settings). #106055 (Azat Khuzhin). - Speed up operators that scan a sorted stream for runs of equal key values —
DISTINCTin order,LIMIT BYin order, negativeLIMIT BYin order,full_sorting_mergeandpartial_mergejoins. #106502 (Nihal Z. Miaji). - Implemented a native reader and writer for the
ArrowandArrowStreamformats that does not use the Apache Arrow library, avoiding extra data copies and conversions. It is now the default (settingsinput_format_arrow_use_native_readerandoutput_format_arrow_use_native_writer) and is faster for both reading and writing. #106522 (Alexey Milovidov). - Re-enable LTO for jemalloc after fixing a thread-cache corruption that appeared with LTO, which improves performance. #106898 (Azat Khuzhin).
- Reduced memory usage and improved the performance of
JOINs. The right-hand side of a hash join now uses a compact 8-byte index-based row reference, so the hash-table entries ofALLjoins are as small as those ofANYjoins for every key type. Benchmarked on largeparallel_hashjoin queries —INNERandANYjoins of 100–300 million row tables onUInt64andStringkeys, with both unique and duplicated keys: the median query became about 12% faster and used about 15% less peak memory, with no query becoming slower.INNERjoins onUInt64keys gained the most (median about 21% faster with 38% less memory). #107189 (Harikrishnan Prabakaran). - Single-column non-Nullable
LowCardinality(String)join keys are now natively supported in the hash join. #107264 (Nikita Taranov). - Added the
dpsubjoin-order enumeration algorithm (dynamic programming over subsets), providing optimal join plans with lower optimization overhead thandpsizeand support for non-inner joins. #107351 (Fisnik Kastrati). - Speed up filesystem cache loading on startup by encoding each cache file’s size in its name (
<offset>_<size>), avoiding astatper file. Loading of cache files written by older versions remains supported. #107415 (Alexey Milovidov). - Improve the performance of
arrayElementonArray(LowCardinality(String))and of the mapLIKEfunctions onMaps withLowCardinality(String)keys or values, by avoiding unnecessary string materialization. #107450 (Michael Jarrett). - Avoid converting single-level aggregation to two-level aggregation when memory usage is small, by tracking the memory of the aggregation state itself instead of the memory of the whole query. #107490 (Hechem Selmi).
- Speed up analysis of aggregating queries: the cache key for the aggregation hash-table size statistics is now computed from the query plan instead of building the full query AST. #107643 (Dmitry Novik).
- Improve the performance of
INTERSECT ALLandEXCEPT ALL(the default mode forINTERSECTandEXCEPT) by several times, by keying the multiset on the row value instead of hashing each row with SipHash. #107649 (Raúl Marín). - Rebuild row policy filters without holding the cache lock, improving query scalability under concurrent
CREATE ROW POLICYandDROP ROW POLICY. #107917 (Azat Khuzhin). - Speed up the
match,extract,extractAll,replaceRegexpOneandreplaceRegexpAllfunctions for simple regular expressions by compiling them to native code with LLVM. Controlled by the new settingcompile_regular_expressions(enabled by default); patterns outside the supported subset transparently fall back to the RE2 engine. #108004 (Alexey Milovidov). - Sped up ZSTD decompression on AArch64 (ARM) for columns with small match offsets, such as fixed-width integer columns, by vectorizing short-offset overlapping copies with NEON. For example, decompression of a
UInt64column is up to ~2.3x faster on AWS Graviton 4. #108049 (Alexey Milovidov). - Use the
libdeflatelibrary for gzip/zlib/deflate compression and decompression, making it faster (compression ~1.15× with a better ratio, decompression ~1.4–1.5×) for.gz/HTTP/url/s3data and the Parquet GZIP codec. #108074 (Alexey Milovidov). - Improved performance of text-search queries combined with a primary key filter. #108114 (Anton Popov).
- Use runtime statistics collected during the first run of a query to optimize subsequent runs: the
hashjoin algorithm can automatically switch toparallel_hashbased on the collected statistics. #108125 (Hechem Selmi). The size of join runtime filters is optimized using the hash table size from runtime join statistics, controlled by the new settingjoin_runtime_filter_size_from_hash_table_stats. #108313 (Hechem Selmi). - LZ4 decompression speed was improved for fixed-size, low-cardinality columns. #108175 (Nikita Taranov).
- Speed up the default-whitespace
trimLeft/trimRight/trimBothfunctions (and their aliasesltrim/rtrim/trim): consecutive rows that need no trimming are copied in a single batch, and the per-row space scan runs only for rows that actually have a leading or trailing space. #108177 (Groene AI). - Improve the performance of
replaceAllandreplaceRegexpAllwhen the pattern is a single character and the replacement is a single character (for examplereplaceRegexpAll(s, ' ', '_')). Such replacements no longer change the string layout, so the column is now copied once and matching bytes are rewritten in place instead of running a per-match search loop. #108178 (Groene AI). - Improve performance of the
pointInPolygonfunction with a constant polygon. The preprocessed-polygon cache is now keyed on the raw constant arguments, so a constant polygon is parsed only once (on a cache miss) instead of being re-parsed on every input block. #108184 (Groene AI). - Speed up parsing of the canonical
YYYY-MM-DD hh:mm:ssdate-time representation in best-effort mode (date_time_input_format = 'best_effort',cast_string_to_date_time_mode = 'best_effort'), which is the default. This recovers a parsing performance regression introduced when those defaults were switched frombasictobest_effort. #108187 (Groene AI). - Avoid maintaining
system.predicate_statistics_logselectivity counters on theMergeTreeread path when the feature is disabled (predicate_statistics_sample_rate = 0, the default). This removes a per-granule atomic update and anO(rows)filter popcount from every read, recovering a performance regression that was most visible on AArch64. #108190 (Groene AI). - Speed up parsing of floating-point numbers from text with
precise_float_parsing = 1, making it as fast as or faster than the default parser on almost all inputs. Also bumps the bundledfast_floatlibrary to v8.2.10. #108205 (Raúl Marín). - Use the
simdutflibrary for base64 encoding and decoding functions, improving their performance. #108333 (Konstantin Bogdanov). - Optimize
DISTINCTfor expensive high-cardinality keys. #108366 (Nihal Z. Miaji). - On non-Linux builds (macOS and FreeBSD), jemalloc no longer purges dirty pages eagerly (a
madvisesyscall perfree); it now uses a background purging thread with a finitedirty_decay_ms, like on Linux. This significantly speeds up allocation-churning workloads such as recursive CTEs (~2x on a recursive-CTE benchmark on macOS) with negligible RSS impact. #108430 (Alexey Milovidov). - Speed up query planning under the analyzer for expressions that reference the same
WITHalias or repeat the same subexpression many times (for example deeply nestedif/multiIfchains), by not rebuilding shared subexpressions when constructing the actions DAG. #108523 (Dmitry Novik). - Runtime filters are now built on equality keys even when the
ONclause also contains non-equality predicates, reducing the number of rows entering the hash join for joins that mix equality and non-equality conditions.LEFT ANTI JOINis unaffected. #108579 (Antonio Álvarez Caballero). - Enable
-fno-math-errnoglobally across the codebase, which allows the compiler to optimize math functions better. #108628 (Nikita Taranov). - Lower the software-prefetch threshold for aggregation and join hash tables from
4 * L2 cache sizetoL2 cache size, so prefetch is enabled once the hash table no longer fits in L2. This recovers a regression onGROUP BYandJOINover medium-sized hash tables (~1-8 MiB) on platforms whose reported L2 is large (e.g. AArch64 with a 2 MiB L2). #108655 (Groene AI). - Improve window function performance. Window queries over wide tables that include
SELECT *now use significantly less memory and run faster. Window aggregates, includingquantile*,uniq*, andgroupArray, are faster withOVER ()andOVER (ORDER BY ... RANGE ...). Thecume_distfunction is also faster, and windows usingPARTITION BYorORDER BYnow perform better on columns with many repeated values. #108688 (Nihal Z. Miaji). - Sped up query analysis for queries with many or very large
AND-chains of comparisons: theoptimize_and_compare_chainoptimization is now bounded by a work budget (new settingoptimize_and_compare_chain_max_hash_work) instead of hashing a large fraction of the query tree, and lambda resolution no longer recomputes lambda-body hashes for its recursion guard. #108757 (Alexey Milovidov). - Fix a performance regression when reading
JSON/Dynamiccolumns with multiple threads: a per-value lookup of theinput_format_binary_max_type_complexitysetting caused reference-count contention on the shared query context, serializing parallel reads; the setting value is now cached per thread. #108797 (Seva Potapov). - Fixed a performance regression (introduced in #71781) 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 and low-concurrency reads of lots of tiny files. #108872 (Nikita Fomichev). The initial small-object prefetch is now also issued when object storage reads go through the filesystem cache (filesystem_cache_name), so reads of many small files (e.g.S3Queueingestion) with the cache enabled are no longer synchronous and latency-bound. #109478 (Nikita Fomichev). - Parse deeply nested array and tuple literals in linear instead of quadratic time. #108892 (Alexey Milovidov).
- Reduce the overhead coming from lock contention in the
parallel_hashjoin algorithm. #108938 (Hechem Selmi). - Speed up
estimateCompressionRatioforT64-encoded columns by computing the compressed size analytically instead of compressing. #109054 (Raufs Dunamalijevs). - Remove a single-threaded bottleneck in the shuffle step of distributed query plans: each upstream stream now scatters its rows by destination bucket independently instead of funneling the whole data stream through a single transform. #109206 (Alexander Gololobov).
- Reduced Keeper server idle CPU usage. #109255 (Michael Kolupaev).
- Speed up serialization and merges of
JSONcolumns whose shared data contains many sparse paths: when flattening shared data into per-path columns, the per-row scan over all accumulated path columns is removed, and gaps are backfilled in bulk instead of inserting default values one cell at a time. #109341 (Groene AI). - Reduce CPU overhead of expression evaluation for queries with a large number of columns (e.g. vector search over a
QBitcolumn with a small stride, where each vector expands into hundreds of bit-plane sub-columns that are all fed into a single*DistanceTransposedcall). #109380 (Alexey Milovidov). - Improve the performance of H3 geo functions (
h3ToGeoBoundary,h3ToGeo,h3CellAreaM2/h3CellAreaRads2,geoToH3) by computing paired sine/cosine together and eliminating redundant trigonometric calls in the coordinate transforms. Results are unchanged (bit-for-bit identical). #109399 (Alexey Milovidov). - Improve performance of comparisons (
<,>,<=,>=) of wide integer types (Int128,UInt128,Int256,UInt256and types based on them, such asDecimal128) by up to 7 times, and of converting signed integers toInt256(up to 7 times on mixed-sign data), by making the comparison and sign-extension code branchless. #109474 (Manuel). - Optimized
uniqCombined(including the case of aggregation without keys) anduniqHLL12. #109794 (Anton Popov). #109831 (Anton Popov). - Functions
arraySortandarrayReverseSortare several times faster over numeric arrays (includingDecimalandDateTime64) when called without a lambda. #109832 (Manuel). - Speed up
addDays,addWeeks,subtractDays, andsubtractWeeksonDateTimeandDateTime64values in fixed-offset time zones (such as UTC) by taking an arithmetic fast path. #109836 (Manuel). - Optimized analysis of the text index. #109886 (Anton Popov).
- Parallelize processing of non-joined rows in the
parallel_hashjoin algorithm in two more cases: when there is a residual filter, and in the case of small join keys (single-level hash map). #110008 (Hechem Selmi). - Built-in web UI responses (the Play UI, dashboards, and static-file handlers) are now compressed according to the client’s
Accept-Encodingheader, using zstd, gzip, deflate, brotli, lz4, xz, snappy, or bzip2. For example, the/playpage shrinks from ~350 KB uncompressed to under 120 KB with zstd, reducing load times on slow connections. Already-compressed responses are left untouched, andVary: Accept-Encodingis emitted for correct CDN and cache partitioning. #110108 (Sayantanu Dey). - Push a filter below a window function or below
LIMIT BYwhen it is safe: a predicate written above them (an outerWHEREaround the subquery, or a conjunct inQUALIFY) that references only the windowPARTITION BYcolumns, or only theLIMIT BYkey columns (forLIMIT n BYwithn >= 1and noOFFSET), now reaches storage and enables primary key and partition pruning, skip indexes, and projections. For example,SELECT ... row_number() OVER (PARTITION BY key ORDER BY ts) AS rn ... QUALIFY rn = 1 AND key = 'x'no longer reads and windows the whole table. #110114 (Groene AI). #110116 (Groene AI). - With
join_use_nulls = 1, a null-rejectingWHEREthat references columns from both sides of an outer join (e.g.WHERE l.k = 42 AND r.k = 42) now converts the join toINNER(orLEFT/RIGHT) and prunes the primary key, the same as withjoin_use_nulls = 0. Previously the conversion was skipped in this case and both tables were read in full. #110121 (Groene AI). - Functions with a single non-const
Nullableargument now share the argument’s null map with the result instead of allocating and merging a new one. #110151 (Manuel). - Avoid a heap allocation per hyperrectangle check in primary key index analysis, speeding up mark filtering by 5-26% depending on the query shape. #110153 (Manuel).
- Improve performance of functions
arrayMinandarrayMaxover numeric arrays by ~1.3-1.5x by using a vectorized reduction instead of a per-element comparison loop. #110163 (Manuel). - Vectorize decompression of the
Deltacodec. Decoding is now 1.5–5 times faster for 8/16/32-bit data types, making scans ofDelta-compressed columns up to 20% faster. #110189 (Manuel). - Speed up string search functions (
like,position,match,countSubstrings,hasToken, etc.) overEnumcolumns with a constant needle by searching only the distinct enum names and mapping the results back per row, instead of searching every row. #110325 (Alexey Milovidov). - Speed up aggregate functions
groupBitOr/groupBitAnd/groupBitXorand the variance family (varPop,varSamp,stddevPop,stddevSamp,skewPop,skewSamp,kurtPop,kurtSamp,covarPop,covarSamp,corr) with vectorized batch processing: up to 4x faster with the-Ifcombinator on unpredictable conditions, and up to 3x faster for the variance family without it. #110461 (Manuel). - Speed up the analysis of the text index (the stage that selects which granules to read): use exclusion search instead of iterating over all granules, and avoid creating a temporary bitmap for each range check. #110530 (Anton Popov).
- Account for the on-disk size of
Mapsubcolumns in the automaticPREWHEREoptimization. This fixes a performance regression inPREWHEREintroduced in #99200. Part of #110462. #110623 (Pavel Kruglov). - Speed up parsing of
UUIDvalues from text (e.g.JSONExtractintoLowCardinality(UUID),toUUID,CAST AS UUID) by validating and converting hex digits in a single pass instead of two. #110625 (Groene AI). - Significantly improve performance of the
timeSeries*ToGridaggregate functions by using faster sorting and hash table implementations. #110875 (Nikita Mikhaylov). - Queries like
SELECT * FROM t WHERE idnow use index skipping on theidcolumn. Closes #89222. #89603 (Aditya Chopra). - Added the
query_plan_merge_expression_into_joinsetting (enabled by default) to allow merging expression steps intoJOINsteps during the join reordering optimization. This enables join reordering across subqueries that wrap joins (e.g., when aJOINis inside a subquery with computed columns), leading to better optimization of complex join trees. #98533 (Vladimir Cherkasov). - Optimize
ANDchains with multiple comparison conditions on the same expression: detect contradictions (e.g.,a < 3 AND a > 5→false) and prune redundant conditions (e.g.,a = 3 AND a < 5→a = 3). #99736 (Xiaozhe Yu). - Materialized CTEs referenced from multiple branches of a
UNIONquery are now materialized once and shared across all branches. Previously, each branch received its own copy of the CTE, which was inlined and evaluated separately. #102107 (Dmitry Novik). - Threads in
BackgroundSchedulePoolare now created lazily on demand instead of all at once at server startup. A new server settingbackground_schedule_pool_initial_size(default16) controls how many workers are pre-spawned; the pool grows up tobackground_schedule_pool_sizewhen needed. This reduces the number of idle threads on lightly-loaded servers. Closes #85265. #105066 (Alexey Milovidov). - Skip unnecessary mark file loads for the
JSONtype’s advanced shared data serialization. #107051 (Pavel Kruglov). - The cache of preprocessed constant polygons for the function
pointInPolygonis now shared between queries and threads and bounded by the new server settingpoint_in_polygon_cache_size(default 256 MiB,0disables the cache, changeable at runtime). Previously, the cache kept up tomax_threadscopies of each preprocessed polygon, grew without bound across distinct polygons, and was never released until server restart. It can be cleared withSYSTEM DROP POINT IN POLYGON CACHE, and the current usage is reported insystem.metricsasPointInPolygonCacheBytes,PointInPolygonCacheCells, andPointInPolygonCacheSizeLimit. Closes #106393. #107247 (Nihal Z. Miaji). - Keeper no longer holds its internal snapshots lock while serializing and writing a snapshot to disk or moving snapshots between disks, so snapshot transfers to other nodes and Raft processing are no longer stalled by local snapshot creation. #107595 (Antonio Andelic).
- Parallelize the filesystem cache background eviction (controlled by the
keep_free_space_ratiosettings). Added a new settingkeep_free_space_eviction_threadsto control the parallelism, and increased the default ofkeep_free_space_remove_batchfrom100to250. #108147 (Kseniia Sumarokova). - Limit the number of concurrently staged parts in the Azure Blob Storage read-then-write copy (used by backups when native copy is unavailable) to
max_inflight_parts_for_one_file, preventing excessive memory usage when many large files are copied in parallel. #108232 (Smita Kulkarni). - Enabled all three text index caches globally — previously, they were only enabled within queries. Also, the posting lists cache size is now zero, which effectively disables it again, because posting lists are large and caching them is too costly. #108274 (Robert Schulze).
- Add streaming in-memory marks compression during marks loading to reduce peak memory usage. Closes #108285. #108325 (Pavel Kruglov).
- The new filesystem cache setting
reserve_granularity(default 4 MiB) reserves space ahead in coarser granules, reducing lock contention on the filesystem cache space reservation hot path. #108369 (Kseniia Sumarokova). - Reduce the amount of memory used by the filesystem cache metadata (per file segment and per key). #108477 (Kseniia Sumarokova).
- Queries to
system.iceberg_historywithWHEREfilters on thedatabaseandtablecolumns now access only the matching databases, which can save time if you have many unrelated remote databases on the server. #108492 (Den Kalantaevskii). - Removed unnecessary locking in the filesystem cache to reduce lock contention. #108932 (Kseniia Sumarokova).
- Reduced memory usage of
BACKUPandRESTOREmetadata handling. Opening a backup (forRESTORE, or as the base of an incrementalBACKUP) now parses the.backupmetadata as a stream instead of loading it into an in-memory XML document tree, which for large (especially incremental) backups avoids allocating a multi-gigabyte DOM tree. #109107 (Julia Kartseva). Finalizing aBACKUPno longer copies the file infos of all files into a temporary vector, which, for backups of millions of files, transiently cost several gigabytes. #109861 (Julia Kartseva). Writing backup entries also no longer copies the current host’s file-info list. #111162 (Julia Kartseva). - Reduce memory consumption in the aggregator. #109224 (Konstantin Vedernikov).
- Support the query condition cache for local
Parquetfiles read via theFiletable engine (previously supported only for object storage and data lakes). #109247 (Alexey Milovidov). - Reduced the memory usage of the text index header cache by 2-2.5 times. More headers of data parts fit into the cache (setting
text_index_header_cache_size), reducing disk reads for text search queries. #109332 (Anton Popov). - The transposed vector distance functions
L2DistanceTransposed,cosineDistanceTransposedanddotProductTransposednow apply the partial bit-plane read optimization toNullable(QBit)columns, reading only the requested bit planes instead of the whole column. #109358 (Alexey Milovidov). 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 (Groene AI).- Pooled connections are no longer pinged before each use. This removes a
Ping-Ponground trip that was added to every reused connection, reducing the latency of distributed queries and ofclickhouse-benchmark. A stale pooled connection is detected with a zero-timeout poll (a non-blocking check that adds no round trip) and recovered by reconnecting. #110068 (Alexey Milovidov). - Fixed spurious reconnections of pooled HTTP keep-alive connections over TLS (HTTPS, S3). The stale-connection check used
pollon the socket, which misreports a live secure connection carrying an unread TLS post-handshake record (a session ticket orKeyUpdate) as closed; it now uses a non-blockingMSG_PEEKon plain sockets andSSL_peek/SSL_has_pendingon TLS sockets, which also correctly detects an orderly TLS shutdown and a TLS record that has only partially arrived. #110402 (Alexey Milovidov). - Queries accelerated by TopK dynamic filtering (
ORDER BY ... LIMIT k) now make fuller use of the query condition cache: the cache is populated even when lazy materialization is applied to the query, and such queries can reuse entries previously written by an ordinary query that had the sameWHEREpredicate. #110507 (Shankar Iyer). - A
LIKE/NOT LIKEpattern without wildcards (%,_) now uses an exact primary key range, so it reads the same number of granules as the equivalent=/!=predicate instead of a wider prefix range. #107077 (Groene AI). - Fix redundant file segment lock contention (a performance regression introduced in 26.1) when reading data through the filesystem cache. #109577 (Kseniia Sumarokova).
- Fixed skip indexes defined on
Tuplesubcolumns not being used when the field is accessed viatupleElement(t, 'name'),tupleElement(t, N), ort.Nwhile the full tuple is also read in the same query (e.g.SELECT *). All of these forms now prune granules the same way as the named subcolumn accesst.name. #110056 (Groene AI). - Fixed slow
ORDER BY ... LIMITqueries onDistributedtables whenprefer_localhost_replicaselects a local replica: the preliminary limit was removed from the local-shard plan, preventing lazy materialization and dynamic top-K filtering. #110136 (Michael Jarrett). - Fixed the text index not being used for the
ILIKEoperator when the index is defined over an expression rather than a bare column (for exampleassumeNotNull(col)with alower(...)preprocessor): such queries were reading all granules instead of using the index. This closes #110350. #110595 (Elmi Ahmadov). - Reduce lock contention in the filesystem cache: queries reading from the cache no longer block on the priority queue lock when updating an entry’s LRU priority. #109065 (Antonio Andelic).
- Text index queries that use a filter-only
postprocessorexpression (for exampleif(..., '', token)) now discard empty tokens up front instead of materializing them row by row, improving performance. #109049 (Elmi Ahmadov). - Reduce lock contention in system log queues, lowering query tail latency on busy clusters. #110539 (Sean Haynes).
- Improved the performance of substring search functions (
position,countSubstrings,multiSearch*,replaceAll,replaceOne, and their case-insensitive and UTF-8 variants) with a non-constant needle by up to 1.5x by using SIMD-backed string searchers on the per-row path instead of a naive implementation. #110580 (Raúl Marín). - Lazy materialization is now applied to
ReplacingMergeTreequeries withFINAL, a filter, and a smallLIMITeven withoutORDER BY. Columns not needed by the filter and theFINALmerge are fetched only for the rows that remain after the limit, which makes such queries much faster when they select wide columns with a selective filter. Controlled byquery_plan_optimize_lazy_materializationandquery_plan_max_limit_for_lazy_materialization. #110722 (Nikolai Kochetov). - Improved async insert performance when deduplication is enabled and one flush is split across multiple partitions: ClickHouse now reuses the computed deduplication hashes across partitions instead of recomputing them for each one. #111150 (Valery Petrov).
Improvement
- Added a setting
input_format_csv_missing_nullable_as_empty_string(disabled by default). When enabled, a missing value of aNullable(String)column in CSV input is read as an emptyStringinstead ofNULL, regardless ofinput_format_csv_empty_as_default. #58225 (kevinyhzou). #107577 (Alexey Milovidov). - Functions
toDateOrNull,toDateTimeOrNullandtoDateTime64OrNullnow accept integer arguments of all native integer types (interpreted the same way as bytoDate,toDateTimeandtoDateTime64, with an optional timezone argument), returningNULLfor values out of range of the result type. For example,toDateTimeOrNull(1583851242, 'Asia/Shanghai')returns2020-03-10 22:40:42andtoDateTimeOrNull(4294967296)returnsNULL. #79791 (Jitendra). - Added an
is_wildcardcolumn to thesystem.grantstable that indicates whether a grant uses wildcard prefix matching (e.g.,GRANT SELECT ON db*.*). Previously, wildcard and exact grants on the same name were indistinguishable insystem.grants. Closes #92835. #98577 (DQ). - Allow Snappy compression in the HTTP interface (
Accept-Encoding: snappy) and add thesnappy_modesetting to choose between the Hadoop Snappy block format and the Snappy framing format for genericfile/urlsnappy I/O. #100752 (Alexey Milovidov). - Support compatibility with the old analyzer under the
analyzer_compatibility_allow_non_aggregate_in_havingsetting. If enabled, non-aggregate conjunctions are moved fromHAVINGtoWHERE. #104232 (Dmitry Novik). - Added a new server setting
memory_worker_rss_speculative_reserve_ratio(default1.0) which makes the global memory tracker speculatively reserve memory on top of the observed RSS when the RSS growth outpaces the tracker’s bookkeeping between samples. With it, allocations getMEMORY_LIMIT_EXCEEDEDearlier, and the kernel OOM-killer is less likely to fire first. Set the ratio to0to disable the speculation. #104976 (Alexey Milovidov). - Added opt-in Prometheus metrics for filesystem cache eviction activity (
filesystem_cache_evictions_total,filesystem_cache_evicted_bytes_total,filesystem_cache_evicted_segment_hits,filesystem_cache_evicted_segment_size_bytes, and their per-user variants labeled withuser_id), exposed per cache viasystem.dimensional_metrics,system.histogram_metrics, and the Prometheus endpoint. They are controlled by the cache disk-config settingsexpose_prometheus_eviction_metricsandexpose_prometheus_eviction_metrics_per_user(both off by default), which can be toggled at runtime viaSYSTEM RELOAD CONFIG. #105020 (Sacheendra Talluri). - Make
EXPLAIN [PLAN] actions=1, compact=1, pretty=1the default. #105036 (Kirill Kopnev). - Bump
delta-kernel-rs(the library behind theDeltaLakeintegration) to v0.23.0. #105861 (Smita Kulkarni). - Add
duandwccommands toclickhouse-disks. They, respectively, print the total size in bytes for a given file or directory, and list the number of bytes, lines, and words in a file. #106268 (Asya Shneerson). - Added a new asynchronous metric
UntrackedMemory(visible insystem.asynchronous_metrics) that reports memory already allocated by threads but not yet accounted in the global memory tracking counter: each thread accumulates small allocations locally and reports them in bulk. This helps explain discrepancies betweenMemoryTrackingand the process’s actual memory usage.MEMORY_LIMIT_EXCEEDEDerror messages now also include the amount of untracked memory, making it easier to understand why a query or the server hit its memory limit. #106386 (Miсhael Stetsyuk). - Upgrade ClickStack (the observability UI) to version 2.28.0. #106406 (Aaron Knudtson).
- Added support for
BFloat16indotProductand improved its performance by batching the SIMD path. #106569 (Nikita Taranov). - Made the settings
max_named_collection_num_to_throw,max_table_num_to_throw,max_replicated_table_num_to_throw,max_view_num_to_throw,max_dictionary_num_to_throw, andmax_database_num_to_throwchangeable without a server restart. #106821 (Maxim Orlovsky). - Support the
REDUCED_REDUNDANCY,STANDARD_IA,ONEZONE_IA,GLACIER_IR, andEXPRESS_ONEZONEvalues (in addition toSTANDARDandINTELLIGENT_TIERING) for thes3_storage_class_namesetting. #107251 (Aditya Kumar). - 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). - The
SOME/ALLarray quantifier (expr OP SOME(array)/expr OP ALL(array)) now also supports the keyword comparison predicatesIS DISTINCT FROMandIS NOT DISTINCT FROM, and the string-search predicatesLIKE,ILIKE,NOT LIKE,NOT ILIKE, andREGEXP, rewritten toarrayExists/arrayAll. #107454 (Alexey Milovidov). - Fixed a memory leak that occurred when opening a SQLite database failed (for example, when the
sqlitetable function or theSQLitedatabase engine is given a path that cannot be opened). #107807 (Alexey Milovidov). - In the Web UI (
play.html), the run shortcut hint now showsCmd+Enteron Mac andCtrl+Enteron other platforms instead of always showingCtrl/Cmd+Enter, and the, +Shift to run allpart of the hint is shown only when there are multiple queries. #107817 (Alexey Milovidov). #108957 (Alexey Milovidov). - The
Aliastable engine now supports reading with parallel replicas when the target table is of theMergeTreefamily. #107830 (Kai Zhu). - Added the
uniq_v2column statistics type — a lightweight alternative to theuniqstatistics, based on theuniqCombined64sketch. #107863 (Han Fei). Deprecated theminmaxcolumn statistics type and changed the default value ofauto_statistics_typestobasic, uniq_v2. #108680 (Han Fei). - AI functions (
aiGenerate,aiEmbed,aiClassify,aiExtract,aiTranslate) now retry transient network failures (connection resets, TLS connect failures, timeouts, unreachable addresses) whenai_function_max_retriesis set, matching the retry behavior of theurltable function. Previously, only provider-side HTTP error responses were retried. #107927 (Alexey Milovidov). INSERTinto aMergeTreetable now honors query cancellation andmax_execution_timewhile writing many parts, instead of potentially running long after being killed. #107929 (Michael Kolupaev).- In the Web UI (
play.html), the Web Terminal icon can now be opened in a new browser tab with a middle-button click or Ctrl/Cmd/Shift+click. #108006 (Alexey Milovidov). - AI SQL generation in the client no longer sends the
temperatureparameter unless it is explicitly set viaai.temperaturein the configuration. This fixes AI SQL generation for models that reject thetemperatureparameter. #108014 (Alexey Milovidov). - Added the
system.masking_policiestable andSHOW MASKING POLICIESintrospection to open-source builds. Masking policies themselves remain a ClickHouse Cloud feature, so the table is empty in open-source builds, but introspection queries no longer fail with an error. #108030 (Alexey Milovidov). - The Keeper-based Kafka consumer now randomizes the order in which it acquires temporary partition locks across replicas, improving fairness of partition distribution and reducing lock contention. Previously, the intended shuffle had no effect. #108033 (Alexey Milovidov).
- Added autocompletion to the Web UI (
play.html), based onsystem.completionsand the WASM-based SQL lexer. #108059 (Alexey Milovidov). clickhouse-clientandclickhouse-localnow show as-you-type autocompletion hints (inline “ghost” text) for the best matching suggestion when the cursor is at the end of the input. The most relevant suggestions (recently used and identifiers already present in the query) are ranked first. Navigate with Up/Down (or Ctrl-Up/Ctrl-Down); accept a single or selected hint with Tab or Right, and accept a selected hint with Enter; Tab also opens the classic completion list. Controlled by the new--hintsoption (on by default; requires--highlight). #108070 (Alexey Milovidov).- Support the
lengthfunction for theQBitdata type — it returns the dimension of the vector as a constant. #108071 (Alexey Milovidov). SupportCASTfrom aQBitto anArray, reconstructing the original vector — the inverse of the existingArraytoQBitconversion. #108072 (Alexey Milovidov). - Requests to REST data lake catalogs (such as OneLake) now include a ClickHouse
User-Agentheader. #108117 (Konstantin Vedernikov). arrayFoldnow respects query cancellation andmax_execution_time. Previously, a fold over a very long array ran entirely inside a single function call and could not be interrupted, soKILL QUERYand time limits were ignored until the fold finished. #108192 (Groene AI).MVTEncodeGeomnow snaps geometry to the integer pixel grid before clipping and clips polygons with thewagyulibrary, so the clipped output is valid (self-intersecting rings are repaired) and edge-aligned, matching PostGISST_AsMVTGeom. #108248 (Saarthak Gupta).- Add per-phase query pre-execution
ProfileEvents:QueryParseMicroseconds,QueryAnalysisMicroseconds,QueryPlanBuildMicrosecondsandQueryPipelineBuildMicroseconds. They expose where time is spent before query execution (parsing, analysis, query plan building, pipeline building) and are available insystem.query_logandsystem.events. #108282 (Jordi Villar). ALTER TABLEoperations that would produce table metadata exceedingmax_query_sizeare now rejected upfront, preventing tables from becoming unloadable by components such as DDL distribution and replica recovery. #108283 (Andrew Kravchuk).- Added
settingsandengine_settingscolumns tosystem.backupsandsystem.backup_log.settingsexposes the backup/restore-specific settings requested for an operation (e.g.,allow_s3_native_copy,deduplicate_files,structure_only), andengine_settingsexposes the settings effectively used by the backup engine’s reader and writer (e.g., the S3 request settings such asallow_native_copy, which may differ from what was requested after merging the endpoint configuration). This makes it possible to see which settings aBACKUP/RESTOREoperation actually ran with. #108334 (Julia Kartseva). - Added a
sourcecolumn tosystem.documentationcontaining the path of the source file where each entity’s documentation is defined. The table now also documents compression codecs, profile events, current metrics, asynchronous metrics, and the system tables themselves (with their columns), and the documentation of settings now includes their type and default value. #108346 (Alexey Milovidov). An empty setting default value is now rendered as empty string instead of empty backticks. #108708 (Alexey Milovidov). - Support asynchronous reads from remote replicas (
async_socket_for_remote) on macOS by implementing the epoll-based polling primitives on top ofkqueue. This lets distributed queries read shards in parallel on macOS instead of serially. #108403 (Raúl Marín). - Support
BFloat16in binary math functions. #108442 (Zhang Yifan). MergeTreecan now read a compressed stream whose blocks use different codecs. This is the read-side prerequisite for adaptive codec selection (#105404). #108592 (Raufs Dunamalijevs).- The automatic value of
max_threadsand similar settings is now shown insystem.settingsasauto(8)instead of'auto(8)'; the surrounding single quotes were a long-standing artifact baked into the value. Cross-version compatibility is preserved: the legacy quoted form is still accepted when parsing settings received from older servers. #108657 (Alexey Milovidov). - Several usability fixes for the
/schemaWeb UI: load the schema on Enter, theme-aware scrollbars, readable table names, consistent per-database grouping of independent tables, no text selection while dragging, and aplay-style authentication form (Credential Management API, URL-supplied credentials with password stripping, and live credential validation). #108724 (Alexey Milovidov). - The text index lazy posting-list apply mode is no longer experimental and can be selected with
text_index_posting_list_apply_mode = 'lazy'withoutallow_experimental_text_index_lazy_apply. The density-threshold setting was renamed fromtext_index_density_thresholdtotext_index_lazy_intersection_density_threshold. #108814 (Anton Popov). - Add a
delta_sharingcatalog type toDataLakeCatalogfor Databricks Delta Sharing’s Iceberg REST endpoint, whose namespaces are flat and which ignores theparentlisting filter. Use it instead ofcatalog_type = 'rest'for such endpoints, whereSHOW TABLESwould otherwise hang. #108865 (Seva Potapov). - Added a new
clickhouse-client/clickhouse-localoption--echo-query-separatorthat prints a custom separator before the formatted echoed query, making it easier to tell the typed query apart from its reformatted echo. Disabled by default. #108888 (David Meng). - Improvements to the database panel of the Web UI: the number of tables is shown in parentheses next to a database name when it is expanded. #108891 (Alexey Milovidov). A refresh button next to an expanded database reloads its list of tables. #108958 (Alexey Milovidov). When the panel is reopened, the previously expanded databases are restored. #108964 (Alexey Milovidov).
- Allow calculating the combined skip-index benefit in
EXPLAIN WHATIF: it shows the data ratio for the intersection of all existing suitable hypothetical indices. #108934 (Yarik Briukhovetskyi). - Fixed the horizontal scroll position of the result table being reset in the Web UI when clicking a link in a cell and returning to the page. #108941 (Alexey Milovidov).
- The
MySQLdatabase engine, table engine, and table function now map MySQL’s spatial column types (LINESTRING,POLYGON,MULTILINESTRING,MULTIPOLYGON, and the genericGEOMETRY) to the corresponding ClickHouse geometric types instead ofString. This is controlled by the newgeometryflag of themysql_datatypes_support_levelsetting, enabled by default.POINTis still always converted toPoint. The genericGEOMETRYcolumn maps to the umbrellaGeometrytype; reading a value whose subtype has no ClickHouse counterpart (MULTIPOINT,GEOMETRYCOLLECTION) throws an exception at read time. #108944 (Alexey Milovidov). - Web UI (
play.html): full keyboard navigation — arrow-key navigation in the database panel and result table, keyboard access to the toolbar buttons, theme switcher, and download menu, and visible focus outlines. #108972 (Alexey Milovidov). - HTTP interface: when credentials are provided both via URL parameters (
user/password) and anAuthorizationheader, the URL parameters now take precedence instead of the request being rejected. This fixes downloading results from the Web UI (play.html) failing withAUTHENTICATION_FAILED(error 516) when the browser has remembered Basic credentials. #108980 (Alexey Milovidov). - Restore
show_data_lake_catalogs_in_system_tablesas the setting that controls onlyDataLakeCatalogvisibility insystem.tables,system.columns, andsystem.completions. Addedshow_remote_databases_in_system_tables, enabled by default, to let users hideMySQLandPostgreSQLdatabases from those system tables separately. #109082 (Pablo Marcos). - Use the precise (closest-representable) float parsing algorithm by default and apply the
precise_float_parsingsetting to input formats (CSV,TSV,JSON,VALUES, …) and numeric literals, not justtoFloat*/CAST. Setprecise_float_parsing = 0for the previous, faster in some cases but less accurate, behavior. Closes #60146. Closes #74647. Closes #68914. #109086 (Raúl Marín). - A query with a single CTE is now formatted with the same newline and indentation as a query with multiple CTEs. Previously
WITH a AS (...)kept the CTE on the same line asWITH, while two or more CTEs putWITHon its own line with each CTE indented. #109092 (Groene AI). - Web UI: when the highlighted completion is the same as the already-typed word, or the same word in a different case (e.g.
HASHoffered for a typedhash), pressing Right/Tab/Enter no longer rewrites the word or gets swallowed by the autocompletion — the key moves the caret or inserts a newline as expected. #109106 (Alexey Milovidov). #109384 (Alexey Milovidov). - Added rainbow parentheses, matched-bracket, matching-identifier, and digit-group highlighting to the Web UI (
play.html), matchingclickhouse-client. #109108 (Alexey Milovidov). - In the Web UI,
TabandShift+Tabnow indent and unindent the selected lines by 4 spaces. #109110 (Alexey Milovidov). - Web UI: highlight the position of a syntax error in the query editor with a red background. The highlight is cleared as soon as the user returns focus to the editor. #109112 (Alexey Milovidov).
clickhouse-compressor --statand default-codec detection for old parts now report corrupted block headers as corruption instead of a misleading end-of-file error. #109157 (Raufs Dunamalijevs).- ClickHouse Keeper now respects the
os_collect_psi_metricssetting and skips PSI metrics collection when it is disabled. #109179 (Maxim Orlovsky). - In the Web UI, when query tabs are shown, the connection parameters (host, user, password) are hidden behind a key button in the top-right corner and shown in a drop-down on demand. #109243 (Alexey Milovidov).
- Web UI: show a single-value result (one row, one column, e.g.
SHOW CREATE TABLE) with full height instead of clamping it to three lines. #109245 (Alexey Milovidov). - In the Web UI, clicking a table in the databases panel with the middle mouse button, with Shift, or with the platform’s new-tab modifier (Cmd on macOS, Ctrl elsewhere) now opens its query in a new Web UI tab. #109246 (Alexey Milovidov).
- Key the query condition cache for remote (object storage)
Parquetfiles by ETag in addition to the path, so that overwriting an object in place no longer serves stale cached results. #109310 (Alexey Milovidov). - In the Web UI, empty strings and NULLs are no longer colorized in the categorical coloring mode. #109342 (Alexey Milovidov).
- Web UI: clicking a table’s icon in the database panel now shows the list of its columns, with type icons, a size bar proportional to the compressed size, and a tooltip with the compressed/uncompressed size and compression ratio. #109346 (Alexey Milovidov).
- Web UI: show the full tab title as a tooltip on hover when it is truncated. #109354 (Alexey Milovidov).
- In the Web UI, middle-clicking a tab’s title (or Ctrl/Shift/Cmd+clicking it) now duplicates the tab. #109357 (Alexey Milovidov).
- Web UI: resize the final progress and query statistics areas uniformly so they do not wrap awkwardly when the browser window is narrow. #109363 (Alexey Milovidov).
- Web UI: selecting a database in the database panel now uses it as the default database for queries run from the editor. #109372 (Alexey Milovidov).
- Support
reinterpretof anArrayof fixed-size elements as aString, the inverse of the existingreinterpretof aString/FixedStringas anArray. #109383 (Alexey Milovidov). - In the Web UI, do not display the per-column color-coding toggles when the result has no more than a single row. #109385 (Alexey Milovidov).
- Allow
CASTbetweenQBittypes that differ in the element type and/or the stride, as long as the dimension stays the same (for exampleCAST(x AS QBit(Float64, N))from aQBit(Float32, N)). Stride-only changes are lossless; element-type changes follow the correspondingArrayconversion semantics (for exampleFloat32toBFloat16may lose precision, andaccurateCast/accurateCastOrNullreject rows that are not exactly representable). #109387 (Alexey Milovidov). - Functions
quantizeBFloat16ToInt8anddequantizeInt8ToBFloat16now also acceptArrayandQBitarguments, applying the Lloyd-Max codec to the whole vector (returningArray/QBitof the corresponding element type), in addition to the existing scalar overloads. #109398 (Alexey Milovidov). - Web UI: the Documentation link now carries the current user name in the URL. #109419 (Alexey Milovidov).
- Support
arraySum,arrayAvg, andarrayProductfor arrays ofBFloat16. #109420 (Alexey Milovidov). - The MySQL-style format specifier
%finparseDateTime/parseDateTime64(and theirOrZero/OrNullvariants) now accepts between 1 and 6 fractional digits, interpreted as left-aligned microseconds like MySQL’sSTR_TO_DATE, instead of requiring exactly 6. Also fixed misalignedPrettyCompacttables in the built-in function documentation examples. #109421 (Alexey Milovidov). - Web UI: query tabs are now persistent — each tab keeps its rendered result (including images and charts) and its running query when you switch away and back, and long queries continue running in the background. Tab titles show a spinner, progress bar, and completion check-mark for their query. #109425 (Alexey Milovidov).
- Web UI: correctly display an error when a query fails after some of its result has already been streamed, instead of showing a client-side
SyntaxError: Unexpected end of JSON input(or, withhttp_write_exception_in_output_format, marking the failed query as successful). #109430 (Alexey Milovidov). - Added pinned columns to the Web UI: a column can be pinned from its header so that it stays visible (stuck to the edge) while the results table is scrolled horizontally. #109439 (Alexey Milovidov).
- In the advanced dashboard (
/dashboard), charts for specific metrics can now be added directly by the metric name as it appears in the source code or documentation, which makes it easier to add multiple metrics during debugging sessions. #109449 (Mikhail Artemenko). - Web UI: fixed the connection settings drop-down closing when selecting text with the mouse and dragging past its border. #109451 (Alexey Milovidov).
- Web UI: hovering over a result table column header now shows the full column name and type as a tooltip, so truncated headers can be read in full. #109463 (Alexey Milovidov). Fixed column header titles being clipped with an ellipsis even when the column was wide enough to show the full title. #110397 (Alexey Milovidov).
- Support SSD cache dictionaries (
SSD_CACHElayout) and theFileLogtable engine on macOS builds. #109493 (Raúl Marín). - Web UI: do not restore tabs with empty queries when the page is opened. #109529 (Alexey Milovidov).
- Fix unreadable as-you-type autocompletion hints and bright colors in the interactive client on terminals whose
TERMdoes not contain256(e.g. Ghostty, kitty, Alacritty, foot): bright colors are now emitted as aixterm bright color codes unconditionally instead of falling back to bold + dark color, which modern terminals render as a dark, hard-to-read color on dark backgrounds. #109622 (Alasdair Brown). - Enable jemalloc per-CPU arenas and allocation profiling on macOS builds. #109684 (Raúl Marín).
- Allow altering some authentication settings of a
OneLakedata lake catalog database withALTER DATABASE ... MODIFY SETTING. #110019 (alesapin). - The
Hiveengine now readsORCfile metadata (min/max indexes, row counts) with ClickHouse’s nativeORCreader instead of the Apache ArrowORCadapter. #110086 (Alexey Milovidov). - Reduced the binary size by ~10.5 MB by executing comparison and arithmetic operations on rarely used mixed type pairs (
Decimalvs integer of a different width, and pairs involvingInt128/UInt128/Int256/UInt256) via a conversion to a common type instead of a dedicated compiled kernel for every combination of types. Same-type pairs, commonly used pairs, and the memory-boundplus/minus/multiplykeep their dedicated kernels; results, result types and exceptional cases are unchanged. #110131 (Alexey Milovidov). - A subquery on the right side of
INwhose single column is an array one dimension deeper than the left argument is now interpreted as the set of the array’s elements (like an array literal or an array-returning function), instead of failing with a confusing type-mismatch error. For example,x IN (SELECT groupArray(x) FROM ...)now works. #110169 (Alexey Milovidov). - Reading from a
SQLitetable engine orsqlitetable function no longer busy-spins a full CPU core when the SQLite database is locked by another connection. The read now idles while waiting for the lock and stays cancellable. #110248 (Groene AI). - Round elapsed time, rate, and ratio values in log and exception messages to three digits, so numbers like
1.345844286 sec.are no longer printed at full precision. #110277 (Alexey Milovidov). - In the Web UI (Play),
BFloat16is now recognized as a floating point number and its columns are right-aligned and colorized accordingly. #110433 (Alexey Milovidov). - Support the
SETTINGSclause for thePostgreSQLtable engine and thepostgresqltable function (for exampleSETTINGS postgresql_connection_pool_size = 50), bringing feature parity with theMySQLengine. #110614 (Alexey Milovidov). SHOW CREATE TABLE(andSHOW CREATE VIEW/SHOW CREATE DICTIONARY) now suggests a similarly-named table in the error message when the requested table does not exist, the same waySELECTqueries do. #110633 (Alexey Milovidov).- Enable the
merge_selector_enable_heuristic_to_lower_max_parts_to_merge_at_oncesetting by default: the merge selector now automatically lowers the maximum number of parts to merge at once based on how full the partition is. See #91163. #110726 (Mikhail Artemenko). - Accept PostgreSQL cleanup commands
RESET,UNLISTEN, andDISCARDas no-ops in the PostgreSQL wire protocol instead of failing them with a syntax error. This improves compatibility with drivers such as Skunk that sendRESET ALLandUNLISTEN *during connection setup and cleanup. #110780 (Alexey Milovidov). - Change the default value of the
auto_statistics_typessetting frombasic, uniqtobasic, uniq_v2. #110878 (Han Fei). randomHadamardTransformnow computes an exact, length-preserving transform for any vector length whose largest odd factor is at most 64 (for example3584 = 512 * 7, common in embedding models), extending the previous2^N,2^k * {12, 20}, and2^k * 9families. A full transform of a length that cannot be represented exactly now raises an exception instead of silently zero-padding to a longer vector; passoutput_dimsto compute a truncated projection of an arbitrary length. #111006 (Alexey Milovidov).- Fixed a
LOGICAL_ERRORexception during backup of aReplicateddatabase that is being dropped and recreated concurrently; such backups now fail cleanly withCANNOT_GET_REPLICATED_DATABASE_SNAPSHOT. #100651 (Alexey Milovidov). - Surface the real underlying error when a zip archive cannot be unpacked (for example, when the archive is read from S3 and the read buffer refuses a seek). Previously, the actual error was hidden behind the generic
Couldn't unpack zip archive: Code = -100/Couldn't open zip archivemessage. #105103 (Groene AI). - Fix a confusing “Maybe you meant X?” hint after a server restart (or
DETACH DATABASE/ATTACH DATABASE): dropping an already-dropped table could suggest the just-dropped name as the alternative. #106238 (Groene AI). - Fixed a logical error (
Logical error: 'removed', aborting the server in debug builds) in the background table-drop queue, triggered when the same explicit UUID is reused across severalCREATE OR REPLACE TABLEqueries, which enqueues more than one dropped table sharing that UUID. #107031 (Groene AI). - Fixed an
Inconsistent AST formattinglogical error that could abort the server in debug and sanitizer builds when an aliased lambda was used as the operand of an access operator (tuple element.Nor array element[]) at a non-first position of an expression list, e.g.SELECT 1, ((p0, p1) -> p0 AS a7).4[3] FROM t. #107092 (Groene AI). - A cluster table function (
urlCluster,fileCluster,s3Cluster, …) nested inside another distributed query, such asclusterAllReplicas(..., urlCluster(...)), is now rejected with aBAD_ARGUMENTSerror instead of failing with a logical error (Distributed task iterator is not initialized). #107107 (Groene AI). OPTIMIZE ... DRY RUNinterrupted by a query timeout (max_execution_timewithtimeout_overflow_mode = 'break') now returnsTIMEOUT_EXCEEDEDinstead of a logical error aboutrows_sources(which aborted the server in debug/sanitizer builds). #107114 (Groene AI).- Stop logging a benign
Net Exception: Socket is not connectederror duringZooKeepersession finalize on macOS.clickhouse keeper-clientno longer prints this spurious error to stderr at exit. #107438 (Groene AI). - Fixed a signed integer overflow when a refreshable materialized view retries a failed refresh with
refresh_retriesset to a very large value (nearInt64max). The overflow could abort the server in builds with the undefined behavior sanitizer. #108005 (Groene AI). - Fix a
LOGICAL_ERROR(server abort in debug/sanitizer builds) when aJOINuses the null-safe comparison operator (<=>/IS NOT DISTINCT FROM) and one of the keys is a scalar subquery, e.g.... JOIN t2 ON (SELECT x FROM t1) <=> t2.k, with the old analyzer (enable_analyzer = 0). Such a query now returns a regularNOT_FOUND_COLUMN_IN_BLOCKerror instead of a logical error. #108123 (Groene AI). - Vector search queries that select the
_distancecolumn now return a proper error instead of failing with a logical error. #108423 (Robert Schulze). - Fix a
std::future_error(The associated promise has been destructed prior to the associated state becoming ready) that could surface, and abort the server in debug and sanitizer builds, when scheduling the final asynchronous S3/Azure multipart-upload completion task failed (for example under thread-pool exhaustion). The real scheduling error is now reported instead. #108730 (Groene AI). - Avoid excessive server log output and an oversized error message when compiling a very large regular expression (for example a
LIKEormatchpattern with hundreds of thousands of wildcards); such patterns now fail with a clearCANNOT_COMPILE_REGEXPerror. #108821 (Raúl Marín). - Fixed undefined behaviour when stringifying an out-of-range protocol packet type (e.g. in the
Unexpected packet from server/Received ... packeterror messages) for a desynced or fuzzed connection. #108885 (Groene AI). - Fixed a confusing internal error (
Method getResultType is not supported for TABLE query tree node) when a table expression was used as the left argument of theINoperator; such queries now produce a clear error message. #109412 (Alexey Milovidov). - Fixed reading an Iceberg table with a metadata file whose version number is all digits but exceeds the 32-bit integer range (for example
v99999999999999999999.metadata.json). Such a name previously produced an opaquestd::out_of_range(STD_EXCEPTION) instead of a clearBAD_ARGUMENTSerror. #109619 (Groene AI). - Fixed a possible
Logical error: 'ReadBuffer is canceled. Can't read from it.'when a row-based input format (e.g.TSV/CSV) failed to parse input and the underlying read had already been canceled (for example a malformed HTTP chunk or a truncated body). Building the verbose parse diagnostics no longer reads from a canceled buffer. #109708 (Groene AI). - Row policy filter expressions using
arrayJoin(or itsunnestalias) are now rejected with a clear error; previously such policies raised acolumn->size() == num_rowslogical error at query time. #109753 (Raúl Marín). #109973 (Raúl Marín). - Reading a Paimon table whose schema contains an unsupported nested type (for example a
ROWfield) now reports a clearBAD_ARGUMENTSerror naming the unsupported type, instead of a bareDB::Exception. (OK)with error code 0 and no message. #109762 (Groene AI). - Fixed a
LOGICAL_ERROR(std::length_error) when a query with the experimental settingmake_distributed_plan = 1used a very largedistributed_plan_default_reader_bucket_countordistributed_plan_default_shuffle_join_bucket_count. Such values are now rejected withINVALID_SETTING_VALUE. #109770 (Groene AI). - Fix a
LOGICAL_ERROR(query tree node does not have valid source node) when a recursive CTE resolved an identifier from an outer scope as a correlated column (withallow_experimental_correlated_subqueries = 1). Such queries now return a clearUNSUPPORTED_METHODerror. #109863 (Groene AI). - Fix a signed integer overflow when
ORDER BY ... WITH FILLskips a very large gap over anInt64/UInt64column (e.g. a step of 2 across a gap near 2^63). The overflow was undefined behavior under sanitizers and silently wrapped in release builds. #109937 (Groene AI). - Fix a
Bad cast from type DB::FunctionNode to DB::ConstantNodelogical error (server abort in debug/sanitizer builds) when runningSELECT ... ORDER BY ... WITH FILLagainst aDistributedtable with a lowoptimize_const_name_size. #109938 (Groene AI). - Fixed an
Invalid number of rows in Chunklogical error when anINTERPOLATEtarget is an alias of aWITH FILLcolumn with the old analyzer (enable_analyzer = 0). Such queries are now rejected with a clearINVALID_WITH_FILL_EXPRESSIONerror. #110103 (Groene AI). - Fix a logical error (server abort in debug/sanitizer builds) when the
indexHint/ignore/isZeroOrNullfunctions are given an argument whose type resolves toNothing, e.g. inside expressions likeindexHint(assumeNotNull(materialize(NULL))). #110192 (Groene AI). - Fixed a logical error
Too large size (...) passed to allocatorthat could occur when an out-of-range value was set for a read buffer size setting such asmax_read_buffer_sizeormax_read_buffer_size_local_fs. Such values are now clamped to 256 MiB by the settings sanity check, and additionally at the consumption site forINSERT ... FROM INFILE, which reads files insideclickhouse-clientwhere the sanity check does not apply. #110207 (Alexey Milovidov). CHECK TABLEnow reports the actual corruption for a projection part that failed to load its metadata, instead of a misleadingColumns doesn't match ... Expected: 0 columnserror. #110262 (Raúl Marín).- A type mismatch when a value read from a PostgreSQL source (e.g. the
postgresqltable function or thePostgreSQLtable engine) cannot be parsed into the declared column type (for example atextcolumn declared asInt32) is now reported as a proper query error; previously it aborted the server in debug and sanitizer builds. #110264 (Groene AI). - Support the query profiler, memory and trace profilers, and
system.trace_logsymbolization on macOS. #109825 (Raúl Marín). - Update
chdigto v26.7.1: compressed stack traces for sharing, query patterns, separate-arena memory support, Perfetto improvements, and compatibility fixes. #110938 (Azat Khuzhin). - Fix incorrect monotonicity inference for
intDivon an unsigned key divided by a signed constant, which could disable primary-key index pruning forIN/NOT INpredicates that cross the signed boundary of the result type; debug builds also hit aLOGICAL_ERRORInvalid binary search result in MergeTreeSetIndex. #107586 (Groene AI). - Added the
allow_lossy_numeric_supertypesetting (disabled by default). When enabled,if,multiIf,coalesce,ifNull,array, andmapover numeric arguments that have no lossless common type (for exampleDecimalandFloat64, orInt64andFloat64) resolve toFloat64instead ofVariant, so the result can be used with aggregate functions such assum,avg,min, andmax. Relevant aggregate-function error messages now mention the setting by name. Closes #106707. #107236 (Groene AI). - Start the Prometheus endpoint (for metrics-only configurations) and asynchronous metrics collection before tables are loaded, so metrics are visible during the potentially long metadata loading phase. #108402 (Christoph Wurm).
Bug Fix (user-visible misbehavior in an official stable release)
- Fix
TRUNCATE TABLEandDROP PARTITIONfailing on tables with many deduplication blocks, where removing them in a single ZooKeeper request could exceed the default 1 MBjute.maxbufferlimit. #105991 (Clayton McClure). This only affects you if you use Apache ZooKeeper (not recommended) instead of ClickHouse Keeper. - Fix the usage of qualified column names (
database.table.column) in theWHEREclause of mutations, such asDELETE FROMandALTER TABLE ... UPDATE/DELETE, overMergeTree-family tables; previously such queries failed with a missing-columns error. Closes #71760. #109491 (Mikhail Artemenko). - Fix the query result cache for PromQL queries. The
promqldialect bypassed the non-deterministic-function check and could serve stale results anchored atnow(); the Prometheus HTTP API (/api/v1/query,/api/v1/query_range) never stored cache entries at all. #110887 (Nikita Mikhaylov). - Fix the server failing to start when the
TZenvironment variable is empty. Closes #68920. #68921 (Ardenwick). - Fixed the server failing to start when a
Backupdatabase engine refers to a backup that has become unavailable (for example, when its files were deleted or the underlying storage is inaccessible). The database is now loaded without tables instead of preventing the whole server from starting. #83188 (Vitaly Orlov). - When using background inserts into tables with the
Distributedengine, delays caused by repeated errors when sending data to remote shards now decrease once the errors are resolved. Previously, the delay would only increase and never reset. #87378 (Andrei Kochemirovskii). - Fix
broken_data_filesinsystem.distribution_queueand theBrokenDistributedFilesToInsertmetric always reporting0for broken files discovered when scanning theDistributedasync-insert queue at startup. #92124 (KG.Xu). - Fix recovery of logging after a disk-full error. Previously, when the log disk became full, ClickHouse would enter a failed state and continuously spam error messages to syslog (potentially writing 100+ GB/hour), never recovering even after disk space was freed. Now the logging system automatically recovers once disk space becomes available, without requiring a server restart. #93127 (jaehanbyun).
- Forward static S3 credentials to Unity
DataLakeCatalogtable reads whenvended_credentialsis disabled, preventing anonymous object-storage access failures. #96910 (kgeg401). - Fix a crash in the schema parsing code of the
DeltaLaketable engine. #97112 (Kseniia Sumarokova). - Fix a security issue where an unauthenticated TCP client could probe table existence and replication status via the interserver port. #99854 (Shaohua Wang).
- Fix a syntax error when an alias follows a subquery in
DESCRIBE TABLE. Fixes #100031. #100205 (Yarik Briukhovetskyi). - Fixed an exception in correlated subqueries when outer columns become
Nullableundergroup_by_use_nullswithROLLUP/CUBE. #100365 (Alexey Milovidov). - Fixed a server abort (in sanitizer builds) and silent data loss during table startup when a rolled-back transactional
MergeTreepart intersects a committed part. #100992 (Tuan Pham Anh). - Fixed
indexOfAssumeSortedreturning incorrect results forArray(LowCardinality(String))columns inMergeTreetables. #101771 (Yash ). - Fix incorrect primary-key pruning when a table’s sorting key wraps a
Datecolumn intoDateTime(for example,ORDER BY toDateTime(date_column)) and a query filters on the original column with a comparison likeWHERE date_column >= '...'.toDateTime(Date)overflows forDatevalues beyond theDateTimerange (after2106-02-07), so the stored key is non-monotonic; ClickHouse no longer uses primary key pruning for this key/predicate combination because doing so could drop granules that contain matching rows. Closes #101744. #101814 (Nihal Z. Miaji). - Fixed
intDivOrNull,moduloOrNullandpositiveModuloOrNullreturning0instead ofNULL, andintDivOrNullandintDivOrZeroraising an exception instead of returningNULL/0, when the division leads to a floating-point exception (division by zero orINT_MIN / -1), including for mixed signed/unsigned arguments. #101976 (Yarik Briukhovetskyi). - Fix
LOGICAL_ERRORexceptions when readingIcebergorDeltaLaketables in corner cases such as concurrentIcebergmetadata updates or reads through themergetable function overDeltaLaketables. #102033 (Groene AI). - Fix outbound HTTP requests (e.g. the
aiGeneratefunction, theurltable function, S3) failing withNo route to hoston hosts that advertise both IPv4 and IPv6 addresses when only one address family is routable. The HTTP connection pool now falls back to the next resolved address when the first one fails with a network error, instead of propagating the error on the very first request. #103786 (Alexey Milovidov). - Fix a server abort during
RESTOREof backups containing tables with cyclic dependencies. #103824 (Konstantin Bogdanov). - Schema inference for Arrow
time32/time64columns (e.g.SELECT * FROM file(..., 'Arrow')) now infersTime64instead ofDateTime64; anything downstream relying on the old inferred type will observe the new type after an upgrade. Also,Time/Time64values can now be exported to Arrow with the appropriate Apache Arrow time type selected by precision. Fixes #104038. #104316 (/bin/cat). - Fixed a race between
ALTER TABLE ... RENAME COLUMNand a concurrentOPTIMIZE TABLE ... FINAL(or any background merge) inMergeTreethat could silently replace the renamed column’s data with default values. #104822 (Groene AI). - Fixed a
Block structure mismatchlogical error during a concurrentINSERTwhile anALTER TABLE ... RENAME COLUMNis in flight, in anAtomicdatabase withlazy_load_tables = 1afterDETACH DATABASE/ATTACH DATABASE. #104852 (Groene AI). - Fix
groupConcatwhen the parametric and two-argument spellings are mixed, e.g.groupConcat(',', 2)(x, '/'): the row-limit parameter was silently dropped, so every row was returned instead of the requested number; the delimiter from the second argument now correctly overrides the parameter. #104882 (Yarik Briukhovetskyi). - Fix a
LOGICAL_ERROR(Expected one block from input stream) thrown byKILL QUERY/KILL MUTATION/KILL PART_MOVE_TO_SHARD/KILL TRANSACTIONwhen theirWHEREclause contains a per-row subquery, or whenmax_block_sizeis small enough that the internalSELECTover the relevantsystem.*table emits more than one block. #104927 (Groene AI). - Fixed
CASTfrom smaller to larger interval units returning wrong results (for example,CAST(toIntervalSecond(60) AS IntervalMinute)returned0instead of1). Closes #104986. #105058 (Yarik Briukhovetskyi). - Fix a logical error (
Assertion 'row < chunk.getNumRows()' failed) inLIMIT ... WITH TIESqueries running with the read-in-order pipeline (optimize_read_in_order = 1andread_in_order_use_virtual_row_per_block = 1). #105102 (Groene AI). - Fix a leak in refreshable materialized views (
MATERIALIZED VIEW ... REFRESH ...): the temporary inner table that a refresh rotates out viaEXCHANGE TABLEScould not be dropped if it was larger thanmax_table_size_to_drop, so every subsequent refresh created yet another temporary inner table, growing the view’s data directory until the disk was exhausted. The refresh task’s internal drop now bypassesmax_table_size_to_dropandmax_partition_size_to_drop; those safety nets still apply to user-issuedDROP TABLEof the view itself. Closes #104900. #105106 (Groene AI). - Fix an unexpected
DATA_TYPE_CANNOT_BE_USED_IN_KEYerror onALTERqueries that do not change the sorting key (changing settings, comments, codecs, adding a non-key column, etc.) forMergeTreetables that have aSimpleAggregateFunction(or another type allowed only withallow_suspicious_primary_key = 1) in the sorting key. #105111 (Groene AI). - Fixed a use-after-free when querying
system.clustersreplica-state columns (such asis_active,unsynced_after_recovery,recovery_time) while aReplicateddatabase is being dropped or detached. Also, benign Keeper exceptions swallowed in this code path (the affected database is treated as transiently unavailable and skipped) are now logged at theInformationlevel instead ofError, so they no longer reach clients at the defaultsend_logs_level = 'warning'. #105149 (Groene AI). - Fixed an issue where running multiple statements in
clickhouse-local --ignore-errorwould echo every subsequent statement inside the error message for each lexical error or unmatched-parenthesis error. #105480 (Groene AI). - Fix a rare server crash when refreshable materialized views are dropped or replaced concurrently with their refresh scheduling. #105588 (Groene AI).
- Reject
ALTER TABLE ... DELETEandALTER TABLE ... UPDATEonIcebergtables whose data file format is notParquetwith a clearNOT_IMPLEMENTEDerror instead of crashing the server or silently corrupting the table. #105893 (Groene AI). - Fix wrong results from a view defined with
EXCEPTorINTERSECTwhose operand is aUNIONchain, afterDETACH/ATTACHor a server restart. The formatter was missing parentheses aroundUNIONchildren ofINTERSECT/EXCEPT, so the stored SQL was reparsed with reversed precedence. #105935 (Groene AI). - Fix
JSONdata misdetected asTSKVduring format auto-detection. Closes #100797. #106009 (Pavel Kruglov). - Forbid creating a
minmaxskip index directly onJSONcolumns — it could later fail inserts with aNO_COMMON_TYPEexception when mixed-type arrays were inserted. Create the index on typed subcolumns instead (e.g.INDEX idx json.field TYPE minmax). #106094 (linhaojie). - Fixed a logical error (
Parsed partition value ... doesn't match partition value for an existing part with the same partition ID) thrown byOPTIMIZE TABLE ... PARTITION ...and other queries that resolve a partition value, on tables with aTime-typed partition key. #106202 (Groene AI). - Fix a data part being incorrectly marked as having a broken projection after a lightweight delete leaves no projection part behind — either when the projection is rebuilt with zero output rows or when it is dropped (
lightweight_mutation_projection_mode = 'rebuild'/'drop'). The broken state previously disabled projection optimization for queries on that part. #106273 (Shaohua Wang). - Fixed
removeDirectoryonplainobject storage disks (such ass3_plain) removing all files inside a non-empty directory as if the removal were recursive; removing a non-empty directory now fails withCANNOT_RMDIR, and recursive removal handles the contents explicitly. #106281 (RinChanNOW). - Fixed a logical error (
Part ... doesn't exist) that could abort the server during recovery of a quorumINSERTfrom a Keeper hardware error when the quorum was concurrently marked as failed. #106424 (Alexey Milovidov). - Fix a
LOGICAL_ERRORexception about duplicate column names when applying row policies. #106438 (János Benjamin Antal). - Fix
CREATE OR REPLACE TABLEandREPLACE TABLEleaving a stranded_tmp_replace_*table on disk and replacing the original table with an empty one when the existing target exceedsmax_table_size_to_drop. The size check now runs before the swap, so a violation aborts cleanly with the user-visible table name in the error. #106782 (Groene AI). - Fix
JSON_QUERY/JSON_VALUE/JSON_EXISTSreturningDynamicinstead ofString/UInt8onDynamicarguments. Closes #106461. #106877 (Pavel Kruglov). - 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 (Jimmy Aguilar Mena). - Apply
query_masking_rulesto messages appended to exceptions, so URL-encoded credentials in(in file/uri ...)suffixes of errors from thejdbc/odbctable functions are not leaked when masking rules are configured. #106916 (Gaurav Dubey). - Fixed parts being marked as broken and detached on any part reload (server restart,
DETACH/ATTACH) 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 re-attached manually. Closes #106837. #106945 (Pedro Ferreira). - Fix a
LOGICAL_ERROR(Unexpected expression in JOIN ON section. Expected boolean (UInt8), got 'Nothing') when a non-equiJOIN ... ONpredicate references aNothing-typed column, such as one produced byARRAY JOIN []. #106981 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - Fix incorrect row order in
ORDER BYqueries overUNION ALLwithoptimize_read_in_orderandread_in_order_use_virtual_rowenabled. Closes #106879. #107053 (Vladimir Cherkasov). - Fixed a
LOGICAL_ERROR(Unsupported argument types) in thegeohashesInBoxfunction when its coordinate arguments mixed constant and non-constant values, or when a coordinate was aBFloat16. Mixed const/non-constFloat32arguments now work, andBFloat16arguments are rejected with a clear error. #107063 (Groene AI). - Fixed wrong results (duplicate rows) for
SELECT DISTINCTover aGROUP BYwithWITH CUBE,WITH ROLLUP, orGROUPING SETSon the same keys. Thequery_plan_remove_redundant_distinctoptimization no longer removes theDISTINCTin these cases, because the grouping modifiers emit extra rows with the key columns defaulted, which can collide with real group values. #107072 (Groene AI). - Fix a wrong result in an
OUTER JOINwhen theWHEREfilter is a conjunction that contains a constant term (for examplep AND 1, orWHERE p QUALIFY NULLwhere theQUALIFY NULLis merged intoWHERE). The constant conjunct could be pushed into the non-preserved side of the join and removed from the post-join filter, so the join produced non-matched rows with the side columns defaulted, and those rows incorrectly passed the filter. #107084 (Groene AI). - Fixed
executable_pooluser-defined functions configured with<lifetime>not picking up changes to the underlying script. Previously, onlySYSTEM RELOAD FUNCTIONSwould re-read an edited script; periodic<lifetime>reloads kept executing the old version. #107087 (Groene AI). - Fix a
LOGICAL_ERRORexception (Cannot find input column ... on its position in inputs of expression actions DAG) for a correlated scalar subquery over a source projecting the same column identifier twice (e.g.SELECT number, *) whencorrelated_subqueries_default_join_kind = 'left'. #107112 (Groene AI). - Fixed a data race on the server-global trace collector between a worker thread starting its profiler and server shutdown. #107307 (Groene AI).
- 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 (Pablo Marcos). - Fixed the
CSVWithNamesandCSVWithNamesAndTypesheader having fewer columns than the data whenoutput_format_csv_serialize_tuple_into_separate_columnsis enabled (the default). The header (and the types row) now flattensTuplecolumns into their leaf fields with dotted names (e.g.t.a,t.b), so the header column count matches the data. A new settingoutput_format_csv_header_serialize_tuple_into_separate_columns(default1) controls this and can be set to0to restore the previous single-name header. #107371 (Groene AI). - Fixed reading
Icebergv3 tables whoseParquetdata files contain reserved row-lineage columns (such as_row_id); the nativeParquetreader no longer raisesICEBERG_SPECIFICATION_VIOLATIONfor reserved field IDs that are not part of the table schema. #107377 (Greg Maher). - Fixed a rare server abort during shutdown (
std::future_error:The associated promise has been destructed prior to the associated state becoming ready) caused by a scheduled task being dropped from a thread pool queue before it ran. #107383 (Groene AI). - Fix the
MaterializedPostgreSQLtable and database engines so that a single table or database can be replicated from a non-default PostgreSQL schema (materialized_postgresql_schema), including the case where tables with the same name exist in several schemas of the same database (previously they would share a publication and replication slot and cross-talk). #107425 (Alexey Milovidov). - Fix
MaterializedPostgreSQLstopping replication of an entire database (withLOGICAL_ERROR: Columns number mismatch) when a single replicated table’s structure changed while the server was down. Now only the affected table is skipped and can be recovered withDETACH/ATTACH. #107427 (Alexey Milovidov). BACKUPof aMaterializedPostgreSQLdatabase no longer hangs forever withTable ... were created or changed its definition during scanning, and now actually backs up the table data (delegated to the underlyingReplacingMergeTree), which can be restored as a standaloneReplacingMergeTree. #107433 (Alexey Milovidov).- Fixed a regression where setting
compatibility = '26.6'(which implicitly enables thehivepartition strategy) silently accepted{_partition_id}in S3/object storage table paths instead of raisingBAD_ARGUMENTS. #107437 (Lefteris). - Fixed a memory leak in the bundled
mongo-c-driverthat could occur when reading from MongoDB (for example, via a MongoDB dictionary or themongodbtable function) if a retryable read error was followed by a failed retry server selection. #107448 (Groene AI). - Fix an exception when inserting into an
Icebergtable whose metadata was created by an external engine and omits the optionalsnapshots,metadata-log, orsnapshot-logarrays. Such inserts now succeed instead of failing. #107473 (Shaohua Wang). - Fixed
DELETE FROM(lightweight delete) requiring theALTER UPDATEprivilege in addition toALTER DELETE. A user granted onlyALTER DELETEcan now runDELETE FROM, as documented. #107491 (Shaohua Wang). - Fixed
NOT_FOUND_COLUMN_IN_BLOCKwhen reading Hive-partitioned files withuse_hive_partitioning = 1and aWHERE/PREWHEREclause that filters a real (non-virtual) column while a Hive partition column is also selected. #107505 (Groene AI). - Fix a
LOGICAL_ERROR(Different order of columns in UNION subquery) when the old analyzer (enable_analyzer = 0) reads a subset of columns from a subquery whoseUNIONchildren areINTERSECT/EXCEPTset operations. #107511 (Groene AI). - Fix
NULLvalues being silently converted to empty strings when insertingArrow/ORCdata into aLowCardinality(Nullable(...))column. This was a regression introduced in 26.5. #107532 (Jimmy Aguilar Mena). - Fix a logical error (
Stream ... variant_discr ... is not found) that could occur when merging or reading aMergeTreepart produced by a mutation of a table with aDynamiccolumn. #107562 (Alexey Milovidov). - Fixed a logical error (
WhichDataType(const_type).isArray()) during primary-key analysis whenpointInPolygonis called with a constant polygon argument of a wrapper type such asVariantorDynamic(for example,pointInPolygon((x, y), if(c, [(0, 0), ...], NULL))). #107589 (Groene AI). - Fixed a logical error (
Last stored last_written_position in meta file ... is bigger than current last_written_pos) in theFileLogengine that could happen when a watched file was deleted and recreated reusing the same inode. #107617 (Groene AI). - Fix a rare server abort (
std::future_error:The associated promise has been destructed prior to the associated state becoming ready) during ZooKeeper client request processing, when an asynchronous Keeper request was dropped while being sent, for example under memory pressure. #107647 (Groene AI). - Fixed
RESTOREforReplicatedMergeTreetables so duplicate-content parts from a backup are preserved instead of being silently deduplicated. #107652 (Pablo Marcos). - Fix runtime join filter producing wrong results for
JSONcolumns. Closes #107646. #107663 (Pavel Kruglov). - 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 (Vladimir Cherkasov). - Quotas keyed by
normalized_query_hashnow account all resources (read_rows,read_bytes,result_rows,result_bytes,execution_time,written_bytes,errors) per query pattern, like the query-count counters, instead of accounting them against a single shared per-user bucket. #107681 (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 was constant-folded to aConstcolumn. #107719 (Groene AI). - Fix logical errors (
Bad cast) caused by inconsistent stripping ofLowCardinalitynested insideVariantandDynamiccolumns, for example inconcat,format, and primary key analysis. Closes #107598. #107773 (Pavel Kruglov). - Fixed a severe work-distribution skew with parallel replicas when the cluster contains inactive replicas (for example, stale entries left after autoscaling). Such replicas are no longer counted by the reading coordinator, so work is balanced across the online replicas instead of piling onto a single one. #107805 (Alexey Milovidov).
- Fix the
Not-ready Set is passed as the second argumentexception that could occur when building anINsubquery set during primary key analysis failed silently (for example, a subquery timeout withoverflow_mode = 'break'), leaving the set permanently unbuilt for the query pipeline. #107924 (Alexey Milovidov). - Fix a server crash in predicate pushdown (
enable_optimize_predicate_expression, legacy analyzer) when aUNIONsubquery appears inside aJOIN ... ONcondition. #107930 (Groene AI). - Fix spurious
CHECKSUM_DOESNT_MATCHandParquetread errors (and, for some formats, silently wrong results) when an S3 or S3-compatible (e.g. GCS) object is overwritten in place while being read. Such reads now fail with a clear, retryable error instead of returning data stitched from two object versions; controlled by the new settings3_validate_etag_on_read(on by default). #107934 (Shaohua Wang). - Fixed a
SELECTfailing withNOT_FOUND_COLUMN_IN_BLOCKon a table that has asetdata-skipping index when a row policy filters it using an always-true condition combined with a check on a non-indexed column. #107971 (Shaohua Wang). - Fixed executable user-defined function command parameter parsing so placeholders with empty or invalid names are not accepted as parameters. #107983 (Goutam Adwant).
- Fix performance regression for
Mapsubcolumns withPREWHERE. Closes #107912. Caused by #99200. #107988 (Pavel Kruglov). - Fix an out-of-bounds write when reading a
Variantcolumn from a malformedNativeblock whose discriminators reference a variant index that does not exist. #107991 (uwezkhan). - Fix wrong query results from incorrect primary key and partition pruning when
toStartOfDay,toStartOfISOYear,toDaysSinceYearZero,toRelativeSecondNum,toRelativeMinuteNum,toRelativeHourNum,toRelativeWeekNum,toRelativeDayNum,toMonthNumSinceEpoch, ortoYearNumSinceEpochis applied to aDate32key column containing dates outside the range the function can represent (in particular dates before1970-01-01). These functions report themselves as monotonic to the primary index, but previously wrapped around for such arguments, so the index could prune granules that actually contained matching rows; they now saturate at the bounds of their result type and stay monotonic over the wholeDate32range. #108018 (Nihal Z. Miaji). - Fix
accurateCastOrNullof aTuplewhose element isDynamic/Variant: a genuine sourceNULLwas treated as a conversion failure. For aNullabletarget element a sourceNULLnow stays an elementNULL(matching a plainTuple(Nullable(...))source); for a non-Nullabletarget element a sourceNULLnow nulls the whole tuple instead of producing the element default; parse/overflow failures still null the whole tuple. #108023 (Groene AI). Also fix a logical error when casting aDynamicorVariantcolumn nested inside aTupleto a non-Nullableelement type withaccurateCastOrNulloraccurateCastOrDefault. #108061 (Alexey Milovidov). - Fixed
numericIndexedVectorPointwiseMultiplyreturning an empty result when multiplying by an all-ones vector that has a different BSI (bit-sliced index) configuration. #108027 (Alexey Milovidov). - Fixed
toTime64andCAST(... AS Time64)not clamping out-of-range values to theTime64range insaturateandignoreoverflow modes, which could produce values that display identically but compare as different. #108028 (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).clickhouse-client --port 9440again automatically enables a secure (TLS) connection; this was broken by a refactoring that stopped passing the port to the secure-connection check. #108032 (Alexey Milovidov).- A transient error while refreshing data parts of a read-only table no longer permanently stops the background refresh task. #108034 (Alexey Milovidov).
- Fixed memory/CPU/mutation overload warnings in
system.warningslagging one asynchronous-metrics cycle behind (and being absent on the first cycle). #108035 (Alexey Milovidov). - The
mongodbtable function now acceptsoid_columnspassed as a named argument (e.g.oid_columns='_id'), instead of rejecting it withBAD_ARGUMENTS. #108039 (Alexey Milovidov). - Fix a
Bad cast from type DB::ColumnNullable to DB::ColumnVector<...>exception (logical error) 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 (Groene AI). - Fixed incorrect handling of zero-width assertions (
\b,^,$) in the regexp “match all” functionsextractAll,extractAllGroupsVertical,extractAllGroupsHorizontal,countMatchesandsplitByRegexp. For example,extractAll('new york is the greatest', '\b(\w)')now correctly returns the first letter of each word instead of every letter. #108047 (Alexey Milovidov). - Fixed
CREATE TABLE ... AS SELECTonAtomicdatabases leaving an empty table behind when the query fails — for example when the user has no access to a table referenced from a subquery. Previously a retry reported that the table already exists instead of the original error. The table is now created via a temporary table and becomes visible only after it has been fully populated. #108048 (Alexey Milovidov). - Allow querying a
range_hashedorcomplex_key_range_hasheddictionary that uses aDateTime64,Decimalor floating-point range with a matching argument todictGet/dictHas. Previously such queries failed withmust be convertible to Int64, and open-ended intervals ofDecimal/DateTime64ranges incorrectly returned the default value. #108052 (Alexey Milovidov). - Fixed an exception (
CANNOT_PARSE_TEXT) when loading a dictionary with a composite key whose key columns are not the first columns in the dictionary definition, with a localClickHousesource using an explicit query. Source columns are now matched to the dictionary structure by name instead of by position. #108053 (Alexey Milovidov). - Fixed the
valuestable function failing withARGUMENT_OUT_OF_BOUNDwhen a decimal literal that is not exactly representable in a narrow floating-point column (such as0.1for aFloat32column) is used, e.g.SELECT * FROM values('x Float32', 0.1). Such values are now accepted and converted to the nearest representable value, consistent withCASTandINSERT ... VALUES. #108055 (Alexey Milovidov). - Fixed a
LOGICAL_ERROR(No available columns) when executingSELECT count()(or other trivial queries) on a table where the user is grantedSELECTaccess only on anALIAScolumn. #108056 (Alexey Milovidov). - Fixed
mapFilter,mapSort(and its variants) andmapConcatdroppingLowCardinalityfrom the key and value types of aMap. PreviouslymapFilterover aMap(LowCardinality(String), String)column returnedMap(String, String), which could corrupt the metadata of a table created viaCREATE TABLE ... AS SELECTand makeCHECK TABLEfail. #108057 (Alexey Milovidov). - Fix incorrect results when using
hasTokenon text indexes with a tokenizer other thansplitByNonAlpha. #108066 (Robert Schulze). - Fixed a freeze of
SYSTEM RELOAD DICTIONARIES(andRELOAD DICTIONARY) when many MySQL dictionaries defined in XML shared a single connection pool viashare_connection. Such pools now honorconnection_pool_sizeandconnection_wait_timeout(default 5 seconds) from the configuration, matching dictionaries defined through named collections. #108083 (Alexey Milovidov). - Allow
EXISTS <dictionary>for a user that has only theSHOW DICTIONARIESprivilege on the dictionary (previously it requiredSHOW TABLES). #108084 (Alexey Milovidov). - Fixed
CREATE TABLE dst AS src SETTINGS ...(and similar variants withORDER BY/PARTITION BYbut without an explicitENGINE) silently dropping the source table’s engine, storage clauses (such as tableTTLand keys) and settings. The engine and the non-overridden storage clauses are now inherited from the source table, and the specified settings are merged on top of the source table’s settings. #108085 (Alexey Milovidov). - Fixed
INSERTintoMergeTreetables failing withfilesystem error: in rename: Permission deniedon filesystems backed by Windows (WSL, CIFS/SMB, Docker Desktop bind mounts), caused by the part writer leaving file descriptors open across the part-directory rename. #108089 (Alexey Milovidov). - Fixed a crash (null pointer dereference) when querying a
Hivetable without aWHEREclause, e.g.SELECT * FROM hive_table. #108094 (Alexey Milovidov). - 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 (Groene AI). - Fix
toStartOfIntervalanddateTruncreturning a rounded value instead of the start of the containing interval when the input has finer precision than the interval unit, e.g.toStartOfInterval(toDateTime64('2023-10-09 10:11:12.000999', 6), INTERVAL 1 millisecond)returned10:11:12.001instead of10:11:12.000. The overload with an explicit origin was affected too. Closes #103535. #108186 (Yarik Briukhovetskyi). - Hide sensitive information in the
view_querycolumn ofsystem.query_views_log. #108214 (Valerii Mordovskii). - Fixed a wedge on a
MergeTreetable attached with a legacyhypothesisskip index (a removed index type kept only forATTACHcompatibility). Previously a lightweightDELETE,OPTIMIZE, a plainINSERT, or a filteredSELECTon such a table failed withILLEGAL_INDEX(“Index of type ‘hypothesis’ is no longer supported”), and theDELETEmutation retried forever. The dead index is now treated as inert: it is carried forward untouched during merge/mutation, skipped on insert and query planning, and can still be dropped withALTER TABLE ... DROP INDEX. #108217 (Groene AI). - Fix the setting
type_json_allow_duplicated_key_with_literal_and_nested_objectnot working with typed paths inJSON. #108218 (Pavel Kruglov). - Fix a
LOGICAL_ERROR(Different list of shards in child plans) when running a query withmake_distributed_plan = 1over aMergeTreetable that has a normal/aggregate projection. #108256 (Groene AI). - Fixed
replaceRegexpOneandreplaceRegexpAllso.matches newline characters by default, consistently with other regular expression functions. #108265 (linjiayu1025-collab). - Fix a logical error when casting an
Array(Dynamic)orArray(Variant)toQBitwithaccurateCastOrNull, e.g.accurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)'). #108288 (Groene AI). 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 (Groene AI).- Fix lightweight
UPDATE/DELETEconditions being evaluated twice, which could lead to incorrect behavior for non-deterministic conditions and extra work for deterministic ones. Closes #86032. #108323 (ofeliacode). - Fix an exception in a predefined HTTP handler when a header whose
headers_regexpregular expression allows an empty value is absent from the request. #108324 (Vitaly Baranov). - Fix
arrayPartialSortwith a non-constant limit argument. #108327 (Vitaly Baranov). - Fixed a cancelled or
KILLedINSERTcontinuing to run for a long time while building a skip index (for example an unboundedset(0)index on a high-cardinality column). The index build now stops promptly when the query is cancelled. #108351 (Shaohua Wang). - Fixed a
SELECTfrom theprimestable function not responding to cancellation: with a largestep(orlimit) the query could keep running for a long time afterKILL QUERYor a timeout. It now stops promptly. #108353 (Shaohua Wang). - Fixed parsing of data-type names whose name contains the substring
INT(for example a function-like name such asquantileInterpolatedWeightedused in a data-type position). Such names were mistaken for MySQL integer types and had their first(...)argument group silently consumed as a display-width modifier, which could break the query formatting round-trip. #108354 (Groene AI). - Fixed an inconsistency where a malformed
ARRAY JOINfollowed by a comma and a parenthesized table list was misparsed as a cross join instead of being rejected. #108365 (Raúl Marín). - 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 (Raúl Marín). - Fix
CREATE OR REPLACEof a refreshable materialized view with aTOtarget: it was incorrectly rejected because the target table is already owned by the view being replaced. #108392 (Nikolay Degterinsky). - Fixed a server crash (
Received signal 4, illegal instruction) that could be triggered by a malformed or desynchronized native TCP protocol stream. The client-supplied initial address is now validated to be a numerichost:portbefore it is parsed, instead of letting a non-numeric port reach the trappedgetservbynamelibc function. #108410 (Groene AI). - Fixed a server crash during shutdown when shutting down a database throws an exception (for example when a table’s flush hits a ZooKeeper timeout). The rest of the shutdown sequence is no longer skipped, so system logs are flushed and their threads are joined before the server exits. #108417 (Groene AI).
- Fixed regular expression functions (
match,extract,extractAll,replaceRegexpOne,replaceRegexpAll, etc.) silently returning wrong results when the pattern contained a NUL (\0) byte. The NUL is now treated as an ordinary literal byte, consistent with RE2. #108427 (Alexey Milovidov). - Fixed
clickhouse-localreturning an empty reply to HTTPOPTIONSrequests when nohttp_options_responseis configured, which made the web UI (/play) show the connection as broken even though queries worked. #108428 (Alexey Milovidov). - Fix a
LOGICAL_ERROR(“Invalid action query tree node …”) exception when a distributed query both deduplicated structurally-identical duplicate-ALIAScolumns and referenced a table function with akey = valuenamed-collection argument (for exampleoss(s3_conn, filename = '...')). #108435 (Groene AI). - Fixed a server crash (
LOGICAL_ERROR: 'Unexpected exception in refresh scheduling') that could happen on startup when a coordinated refreshable materialized view in aReplicateddatabase was attached on a Keeper that does not support theMULTI_READfeature flag (for example after a Keeper downgrade). The view is now stopped gracefully instead of aborting the server. #108441 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKerror (e.g.Column _part not found) when selecting virtual columns from aMergeTreetable under parallel replicas, including viaSELECT *withasterisk_include_virtual_columns = 1. #108451 (Groene AI). 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 (Groene AI).- Restrict the model path of
catboostEvaluateto theuser_filesdirectory, like thefiletable function 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 (Groene AI). - The
hasColumnInTablefunction now requires theSHOW COLUMNSprivilege on the target table, the same grant required byDESCRIBEandSHOW CREATE TABLE. Previously any user could callhasColumnInTableto probe column names and test table and database existence without any access check. #108464 (Groene AI). - Fixed excessive memory allocation when deserializing crafted aggregate function states for
mannWhitneyUTest,rankCorr,largestTriangleThreeBuckets,quantileGK,sequenceMatch/sequenceCountandgroupArrayIntersect. A malformed state could declare a huge element count and make the server try to allocate tens of gigabytes from a few bytes of input; such states are now rejected withTOO_LARGE_ARRAY_SIZE. #108465 (Groene AI). - Validate the redirect target of an S3
301 Moved Permanentlyresponse againstremote_url_allow_hosts(RemoteHostFilter). Previously the AWS SDK 301 handling followed the attacker-supplied endpoint from the response (Locationheader or<Endpoint>element) without the host check, so a malicious or compromised S3-compatible server could redirect ClickHouse to an arbitrary host (SSRF). The 307 redirect path already performed this check; both paths are now consistent. #108466 (Groene AI). - Fixed a credential leak where the legacy
storage_aws_access_key_id,storage_aws_secret_access_key,storage_catalog_credential, andstorage_auth_headersettings of theDataLakeCatalogdatabase engine were shown in plaintext insystem.databases.engine_fullandSHOW CREATE DATABASE. They are now redacted as[HIDDEN]. #108470 (Groene AI). - 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 (Groene AI). - Fixed SQL injection in the MySQL wire protocol: the
SHOW TABLE STATUS LIKEargument and theSET <mysql_setting>value sent over the MySQL interface (port 9004) are now parsed and re-quoted instead of being concatenated verbatim into the rewritten query. Also fixedKILL QUERY <id>over the MySQL interface silently ignoring multi-digit connection ids. #108474 (Groene AI). - Sensitive values passed as HTTP query-string parameters (for example the
param_*query-parameter binding such asparam_secret_key/param_aws_secret_access_key, thepasswordparameter, or S3-stylesignatureparameters) are no longer written verbatim tosystem.text_logor OpenTelemetry spans. TheRequest URIlog line now redacts the values of parameters whose names look sensitive, replacing them with[HIDDEN]. #108475 (Groene AI). - Enforce the
http_forbid_headersconfiguration during schema inference for theurltable function andURLstorage engine. Previously a forbidden header was still sent over the network while inferring the schema (for example with theRegexpformat orDESCRIBE), and its response body could be reflected back in a parse error, leaking secrets. The header filter is now checked before any network access on the inference path, matching the existing behavior ofurlCluster. #108476 (Groene AI). - Fixed wrong results when using
SELECT ... SAMPLE ...together with the query condition cache (settinguse_query_condition_cache, enabled by default). #108488 (Groene AI). - Fixed a server crash (stack overflow) caused by deeply nested expressions such as
[[[ ... ]]]orarray(array( ... ))whenmax_parser_depthis set to a large value. #108493 (Raúl Marín). - Fixed the
RabbitMQtable engine hanging indefinitely onDROP TABLEor server shutdown when the broker closes the AMQP connection due to missed heartbeats without sending a TCP RST. All blocking event loop calls now have a 30-second timeout so shutdown always completes. #108497 (Aly Ayman). - Secondary queries executed as part of internal queries will now be logged as internal queries. #108506 (Miсhael Stetsyuk).
- The
ArrowFlighttable engine and thearrowFlighttable function now honor the<remote_url_allow_hosts>allow-list. Previously, the connection host and port were not validated, so a query could reach hosts not present in the allow-list. #108507 (Groene AI). - 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 (Groene AI). - Match
http_forbid_headerscase-insensitively. HTTP header names are case-insensitive, so forbiddingAuthorizationnow also blocksauthorization,AUTHORIZATION, and other case variants. Configuredheader_regexppatterns are now matched case-insensitively without needing an explicit(?i)flag. #108509 (Groene AI). - Fixed a server crash (segmentation fault) that could occur when a distributed query referenced a not-yet-materialized
MATERIALIZEDCTE as an external table and the remote source was created lazily. #108547 (Groene AI). - Fixed wrong results when the query condition cache (
use_query_condition_cache = 1) reused a skip-index-derived mark exclusion for a query that ran a different set of skip indexes, for example withuse_skip_indexes = 0,ignore_data_skipping_indices, or a differentuse_skip_indexes_for_disjunctionsmode. Skip-index-derived cache entries are now keyed by the effective set of skip indexes that ran. #108548 (Groene AI). - Fixed several bugs in
changeYear,changeMonth,changeDay,changeHour,changeMinuteandchangeSecondwithDateTime64arguments: the result column was created with the hardcoded default scale 3 instead of the argument’s scale, which led to aLOGICAL_ERROR(writeSlice expects same column types) when the result was passed toarrayPushBack/arrayPushFront/arrayConcat; nanosecond-precision (scale 9) inputs threwDECIMAL_OVERFLOW; and pre-epoch sub-second inputs returned the wrong calendar second. Also fixedtimeSlotsoverDateTime64ignoring the scale of the optionalSizeargument in its declared return type and returning wrong timestamps for the largest scale inSize. #108551 (Groene AI). #108681 (Takumi Hara). #108994 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKerror when a compound predicate is aliased inGROUP BYand referenced again, withenable_identifier_resolve_cacheenabled (the default). #108553 (Groene AI). - Fix a logical error (
Equal values are not contiguous within the range assumed to be sorted) when runningDISTINCTover aSTREAMread (SELECT DISTINCT ... FROM table STREAM). Read-in-order optimizations are no longer applied toSTREAMreads, which produce rows in commit order rather than sorting-key order. #108568 (Groene AI). - Fixed projections returning a column’s type default (e.g.
0) instead of its declaredDEFAULTvalue (e.g.-1) in two cases: when reading a column that was added withALTER TABLE ... ADD COLUMN ... DEFAULTafter the projection was created (reads from the base table were already correct), and after the column’sTTLexpired on a wide part. #108569 (Shaohua Wang). #109013 (Shaohua Wang). - Fixed a
ReadBuffer is canceled. Can't read from it.error that could occur when an upload to S3 (for example a backup) is retried after a transient read error. #108573 (Groene AI). - Fix
ATTACH PARTITION ... FROMrejecting tables whose primary keys are equivalent but declared differently (one explicitPRIMARY KEY, the other implicit fromORDER BY). #108590 (Jordi Orihuela). - Fixed direct read from the text index failing when multiple text indexes are partially materialized. Fixes #108530. #108607 (Anton Popov).
- 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 (Groene AI). - Fixed the
_etagvirtual column for theS3QueueandAzureQueuetable engines: it was declared but never populated, soSELECT _etagalways returned an empty string. It now returns the object ETag, like theS3engine and thes3table function. #108625 (Groene AI). - Fixed reading
Arrow,ArrowStreamand Arrow-basedORCfiles whose timestamp column carries a fixed numeric UTC offset (e.g.+05:30,-08:00,00:00) or the non-IANA markerfixedas its timezone, which previously failed withCannot load time zone ...(BAD_ARGUMENTS). #108633 (Groene AI). - Fixed an exception (
LOGICAL_ERROR: Join is supported only for pipelines with one output portorNOT_IMPLEMENTED: MergeJoinAlgorithm is not implemented for strictness Semi) whenjoin_algorithm = 'full_sorting_merge'was used for aSEMI/ANTIjoin, including the joins produced by decorrelating anEXISTScorrelated subquery.full_sorting_mergenow declines strictness/kind combinations it cannot execute, so the planner falls back to another enabled algorithm or reports that the join cannot be executed. #108658 (Groene AI). - Fixed a heap buffer overflow when building a text index with
positions = 1over many distinct short tokens. #108659 (Groene AI). - A query reading from or writing to S3 that is cancelled (e.g. by
KILL QUERY) while an S3 request is in flight is now reported as cancelled instead of with a misleading network/S3 error. In particular, a cancelled backup or restore to S3 now reportsBACKUP_CANCELLED/RESTORE_CANCELLEDinsystem.backups. #108673 (Julia Kartseva). - 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 (Groene AI). - Fixed a logical error (
Sort order of blocks violated) during a merge, and incorrect reads, when a non-nullableLowCardinalityelement of aNullable(Tuple(...))column is used as a subcolumn (for example as a sort key). #108679 (Groene AI). - Fix a possible crash (use-after-free) when
SYSTEM FLUSH DISTRIBUTEDruns concurrently withDROP TABLEof the sameDistributedtable. #108684 (Groene AI). - Fix a crash in Base64 decoding of the Azure account key, reachable via
azureBlobStorage(and related Azure table functions and storages) when the key is not valid Base64: a byte>= 0x80caused an out-of-bounds read, and any invalid byte caused undefined behaviour. Invalid keys are now rejected cleanly. #108716 (Groene AI). - 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 (Groene AI). - 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 an exception (
Cannot find sharding key column, and in debug and sanitizer builds a server abort) when aDistributedtable’s sharding key is an expression the analyzer const-folds, for exampleif(1, toInt32(id), toInt32(id) + 1), withoptimize_skip_unused_shards = 1. #108737 (Groene AI). - Fixed a logical error (
Bad cast from type DB::ColumnNullable to DB::ColumnString) and possible wrong results when usinggroup_by_use_nullswith aLowCardinalityconstant grouping key inGROUPING SETS/ROLLUP/CUBE. #108771 (Alexey Milovidov). - 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 (Groene AI). - Fixed a logical error (a server abort in debug and sanitizer builds) when an
INSERT ... SELECTthrough anAliastable, or into aTimeSeriestable, is cancelled without an exception, for example withtimeout_overflow_mode = 'break'. #108783 (Groene AI). #108796 (Shaohua Wang). - Fix a
Bad cast from type DB::ColumnSparse to DB::ColumnStringlogical error (a server abort in debug and sanitizer builds) whengroupConcatis applied to aTuplewhoseStringelement is stored sparse. #108790 (Groene AI). - Fix
TYPE_MISMATCHinmapFilter,mapSort,mapReverseSort,mapPartialSortandmapConcatwhen aMapvalue contains a nestedMapwithLowCardinality, e.g.mapFilter((k, v) -> 1, map('a'::LowCardinality(String), map('x'::LowCardinality(String), 'y'))). #108798 (Groene AI). - 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 (Gagan Dhakrey). - Fixed a bug where the
WITH TOTALSrow of aJOINcould contain default values (such as0) instead of the constant values coming from a constant subquery on one side of the join. The wrong result appeared only for some join orderings or with thequery_plan_join_swap_tablesetting. #108807 (Vladimir Cherkasov). - Fixed a segmentation fault (null-pointer dereference) that could occur when server shutdown ran concurrently with the shutdown of an
S3Queue/AzureQueuetable. #108810 (Miсhael Stetsyuk). - Fixed a startup abort (
Cannot allocate ThreadStack,EINVAL) on glibc builds running on CPUs with a large signal-stack size (for example Intel Sapphire Rapids / Granite Rapids with an AMX-aware kernel), where the signal alt-stack size was not rounded up to a multiple of the page size. #108813 (Groene AI). - Fix distributed queries occasionally failing with
UNEXPECTED_PACKET_FROM_SERVER(expected TablesStatusResponse, got ProfileInfo) when a connection that a previous cancelled query left out of sync was reused from the pool. #108854 (Alexey Milovidov). - Fixed a logical error (an exception in release builds, a server abort in debug and sanitizer builds) that could happen for a function call with more than one
LowCardinalityargument over a distributed table, for exampleconcatAssumeInjective((SELECT toLowCardinality('p')), s)used as aGROUP BYkey with theremotetable function. The messages wereDefault functions implementation for LowCardinality is supported only with a single LowCardinality argumentorExpected the argument ... to have N rows, but it has M. #108871 (Groene AI). - Fix
reinterpret(x, 'Decimal128(scale)')(andDecimal32/Decimal64/Decimal256/DateTime64targets) producing a result column whose internal scale was the source scale instead of the requested target scale when the source and target had the same physical type. The values were correct, but the column object was structurally inconsistent with its declared type. #108878 (Groene AI). - Fixed a
LOGICAL_ERROR(New empty part is about to materialize but the directory already exist) that could abort the server in debug and sanitizer builds when aDROP/DETACH/MOVE/REPLACE PARTITIONon aMergeTreetable ran after a previous such operation was interrupted (for example a rolled-back transaction or a crash) and left a staletmp_empty_<part>directory behind. The stale directory is now reclaimed instead of failing. #108879 (Groene AI). - Fixed ClickHouse Keeper returning incorrect
dataLength = 0in theStatofCreate2responses, and the ClickHouse ZooKeeper client not deserializing theStatofCreate2responses. #108909 (unintended). - Fixed
clickhouse-localrejecting an empty option value written adjacent to=(for example--format_csv_null_representation=''); it now behaves the same as--format_csv_null_representation ""andSET format_csv_null_representation = ''. #108910 (Vismay). - Fixed a
LOGICAL_ERROR(Inconsistent AST formatting) that aborted the server in debug and sanitizer builds when formatting aTupledata type that mixes named and unnamed elements (for exampleTuple(a UInt8, UInt16)). #108915 (Groene AI). - Fix a segmentation fault when merging
uniqExactaggregate states withGROUPING SETS,ROLLUPorCUBEandmax_threads > 1. #108928 (Raúl Marín). - Fixed possible wrong results or out-of-bounds reads when an
INSERTis rolled back after a mid-batch error (for example inBuffertables, asynchronous inserts, or theKafka/RabbitMQ/FileLogengines) while lazy column replication (enable_lazy_columns_replication) is in effect. #108935 (Groene AI). join_any_take_last_rowis now respected by all supported hash-based join paths, including joins that use automatic spilling to disk. #108936 (János Benjamin Antal).- Fixed a bug in the analyzer where
FINALon one table of aJOIN(e.g.FROM t1 FINAL JOIN t2) was incorrectly applied to the other joined tables as well, which could make such queries slower. #108979 (Vladimir Cherkasov). - Fix a
LOGICAL_ERROR(“Cannot find__grouping_setcolumn in header of MergingAggregatedTransform with grouping sets”, or “Chunk info was not set for chunk in MergingAggregatedTransform”) that could occur, with the analyzer disabled, for aUNION ALL/INTERSECT/EXCEPTwhere one branch usesGROUP BY GROUPING SETSwith parallel replicas and another branch usesFINAL. #109003 (Groene AI). - Fixed a
LOGICAL_ERRORin the automatic parallel replicas planner that could occur whenautomatic_parallel_replicas_modeis enabled together withparallel_replicas_min_number_of_rows_per_replicagreater than 0. #109011 (Groene AI). - Fixed an excessive memory allocation during schema inference of the
MsgPackformat: a corrupted input whose array/map/string/binary header declares a huge element count no longer drives a single multi-gigabyte allocation and is rejected as malformed input. This fixes an out-of-memory condition in release builds (and anallocation-size-too-bigabort under sanitizers). #109019 (Groene AI). - Fixed
use_client_time_zonebeing ignored forDateTime/DateTime64string literals interpreted on the server (asynchronousINSERT,SELECTliterals). The client now propagates its local time zone assession_timezonewhenuse_client_time_zoneis enabled, so server-side parsing matches the synchronousINSERTpath. #109051 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKerror whenquery_plan_optimize_lazy_finalis enabled together with aWHEREfilter partially pushed toPREWHERE(viaoptimize_move_to_prewhere_if_final). #109073 (Groene AI). - Fixed an error when using a qualified asterisk like
b.*in a query wherebis a table (or subquery/CTE) alias that shares its name with a non-compound column of another table. Such queries no longer fail and correctly select all columns ofb. #109078 (Vladimir Cherkasov). - Fix a
Block structure mismatch in JoinSteplogical error (a server abort in debug and sanitizer builds) when a correlated subquery is decorrelated into a join and the source relation carries a column name more than once, e.g.WITH t AS (SELECT number, * FROM numbers(3)) SELECT *, (SELECT t.number WHERE t.number >= 0) FROM twithcorrelated_subqueries_default_join_kind = 'right'. #109114 (Groene AI). - Fixed a hang where a query reading through the filesystem cache could keep waiting on an in-progress download after being cancelled with
KILL QUERY, and where dropping orSYSTEM STOP VIEW-ing a refreshable materialized view whose refresh was stuck in such a wait would block. #109116 (Murphy). - Fixed the
parallel_view_processingsetting being ignored when inserting into a table with materialized views — since 25.10, views always ran in parallel regardless of the setting. #109170 (Antonio Andelic). - Fixed a parser inconsistency where an
INSERTcolumn list accepted a qualified column matcher written ast.* LIKE '<pattern>'/t.* ILIKE '<pattern>'but rejected its canonicalt.COLUMNS('<regexp>')form, breaking the query format round-trip (and aborting the server in debug and sanitizer builds). #109176 (Groene AI). - Fixed non-monotonic
ProfileEventsincrements: theNetworkReceiveBytesandAIOWriteBytescounters could be incremented by a negative amount (wrapping around to a huge value) on a socket timeout or an AIO failure, andMemoryOvercommitWaitTimeMicrosecondswas measured with a non-monotonic clock. #109180 (Azat Khuzhin). - 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 (Nihal Z. Miaji). - Fixed a wrong result of correlated
EXISTSand scalar subqueries when the correlation appears only in the subquery projection together with a non-correlatedWHEREclause (the subquery could evaluate to false /NULLfor every row). Fixes #105760. #109186 (Dmitry Novik). - Fixed
CREATE USER ... HOST LIKE 'a', 'b'(and the equivalentALTER USER) silently keeping only the first pattern. All specifiedHOST LIKEpatterns are now stored in the user’s host allow-list. #109187 (Groene AI). - 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 via thecluster/remotetable functions, but a query through aDistributedengine table skipped it (and failed withINDEX_NOT_USEDunderforce_data_skipping_indices). #109188 (Groene AI). - Fixed a false
LOGICAL_ERROR(There was an error on <host>: Cannot obtain error message (probably it's a bug)) that could abort the server in debug and sanitizer builds when running a DDL query on aReplicateddatabase and its per-hostfinishedstatus node in Keeper had already been cleaned up. #109192 (Groene AI). - Fix
SAMPLEratios with an exponent whose magnitude overflowsInt32(e.g.SAMPLE 1e-3000000000) being silently treated asSAMPLE 1. #109197 (Raúl Marín). - Fix the access check for
SYSTEM PREWARM PRIMARY INDEX CACHE ... ON CLUSTER, which incorrectly required theSYSTEM PREWARM MARK CACHEprivilege instead ofSYSTEM PREWARM PRIMARY INDEX CACHE. #109198 (Raúl Marín). - Fixed
ALTERqueries failing forMergeTreetables created with a customdisksetting (SETTINGS disk = disk(...)). Fixes #63019. #109199 (Mikhail Artemenko). - Fixed a server crash when states of the aggregate functions
cramersV,cramersVBiasCorrected,contingencyortheilsUfrom a window context (OVER ()) and from a plain aggregation are combined through chained set operations (EXCEPT,INTERSECT) or nestedUNION ALLand then read, for example via the-Mergecombinator. #109200 (Groene AI). - Fix a wrong result for
ANY JOINwith a constantONcondition (e.g.t1 ANY INNER JOIN t2 ON 1): the query returned the full Cartesian product instead of theANYjoin result. #109207 (Vladimir Cherkasov). - 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 (Den Kalantaevskii). - Fix
SYSTEM DROP REPLICAandSYSTEM DROP DATABASE REPLICA ... FROM ZKPATHto reject empty or root-only ZooKeeper paths at parse time withBAD_ARGUMENTS, route auxiliary Keeper paths to the named Keeper, and canonicalize Keeper paths so the local self-protection checks cannot mis-target or bypass the intended replica. #109230 (Groene AI). - Fix S3 settings priority so a URL-scoped
<s3>endpoint block takes precedence over the top-level<s3>defaults. #109251 (Bharat Nallan). - Fixed a bug where column
DEFAULTvalues were not applied forINSERT INTO TABLE FUNCTION(for exampleremoteorfile) 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 (Groene AI). - Fix
CREATE TABLE ... AS SELECTfroms3Cluster(and other cluster table functions such asfileCluster/urlCluster) failing withNOT_FOUND_COLUMN_IN_BLOCKinside aReplicateddatabase. #109266 (Groene AI). - Fixed
SHOW TABLESandSELECT ... FROM system.tablesreturning different results for data lake catalog databases: tables that ClickHouse cannot read are now consistently hidden from both. #109273 (Smita Kulkarni). - Fixed a bug where merging a
MergeTreetable that has projections while theenable_block_number_columnorenable_block_offset_columnsetting is enabled produced projection parts containing a spurious_block_number/_block_offsetcolumn. The merged projection part then no longer matched the projection definition and the insert-produced projection parts, soCHECK TABLEandOPTIMIZE ... DRY RUNreported it as corrupted (CORRUPTED_DATA). #109284 (Groene AI). - Allow reading an Avro
arrayof two-field{key, value}records into a ClickHouseMapcolumn. This is the encoding Iceberg and Spark produce for aMAP<K, V>with a non-string key (Avro native maps only support string keys). Previously such a file could be read asArray(Tuple(key, value))but not asMap(K, V), which failed withType Map(...) is not compatible with Avro array. #109289 (Groene AI). - 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 (Groene AI). - Fixed a
LOGICAL_ERROR(Current component is empty) that could be raised by mutation operations such asKILL MUTATIONon aMergeTreetable that stores its metadata in Keeper, when theenforce_keeper_component_trackingserver setting is enabled. #109297 (Groene AI). - Fixed reading
ORCtimestamps beyond ~year 2262 into aDateTime64column with a scale coarser than 9. The nativeORCreader used to convert every timestamp through a fixedDateTime64(9)intermediate, which overflowsInt64at nanosecond scale and rejected such values withVALUE_IS_OUT_OF_RANGE_OF_DATA_TYPE, even when the requestedDateTime64scale (for exampleDateTime64(6), as produced by Iceberg) can represent the value. Timestamps are now read directly at the requested scale, anddate_time_overflow_behavioris honored when even the target scale cannot hold the value. #109302 (Groene AI). clickhouse-localacting as a server (afterSYSTEM START LISTEN HTTP) now serves HTTP connections using theTabSeparateddefault output format, matchingclickhouse-server, instead of the interactivePrettyCompactdefault. This fixes connecting toclickhouse-localover HTTP with drivers such asclickhouse-connect. The interactive terminal session still renders results asPrettyCompact. #109362 (Alexey Milovidov).- Fixed a transient
Code: 499 ... InvalidPart(S3_ERROR) failure on S3 multipart uploads. MinIO can briefly report a just-uploaded part as missing onCompleteMultipartUpload; this error is now retried like the already-handledNoSuchKey, bounded bys3_max_unexpected_write_error_retries. #109364 (Groene AI). - Fix
UNKNOWN_IDENTIFIERerror onALTER TABLE ... DROP COLUMNwhen another column has aDEFAULTorMATERIALIZEDexpression that defines and references an inline alias. #109374 (Alexey Milovidov). - Fix a data race (and resulting rare crash) in the parallel merge of
uniqExactaggregate states with two-level sets, which could occur withGROUPING SETS,ROLLUPandCUBE. #109389 (Groene AI). - Fixed an error (
NOT_FOUND_COLUMN_IN_BLOCK, orstd::bad_function_callin older versions) when runningCREATE TABLE ... ON CLUSTER ... AS SELECTreading aDistributedtable on a cluster with two or more shards. #109407 (Alexey Milovidov). - Fixed merges for tables with
TTL ... GROUP BY(rollup): parts that were already fully aggregated could be rescheduled for merging again and again indefinitely, and tables withMATERIALIZEDcolumns or enabled persistent virtual columns were handled incorrectly — such columns are now aggregated withany. Closes #105647. #109410 (Mikhail Artemenko). #109532 (Mikhail Artemenko). - Fixed
INwith a bare array column on the right argument silently returning a wrong (always-false) result or throwing an exception, so thatx IN arrbehaves likehas(arr, x). #109416 (Alexey Milovidov). - Fix
UNKNOWN_IDENTIFIERerrors onALTER TABLEoperations (RENAME/ADD/MODIFY COLUMN, andMATERIALIZE INDEXon a table with freshly inserted parts) forMergeTreetables with an implicit min-max index over the persistent virtual columns_block_number/_block_offset(enabled byadd_minmax_index_for_block_number_column/add_minmax_index_for_block_offset_column). #109428 (Groene AI). #110236 (Groene AI). - Fix a
LOGICAL_ERRORinarrayFoldover a non-constArray(LowCardinality(T))argument (for examplearrayFold((acc, x) -> acc + x, materialize([1, 2, 3]::Array(LowCardinality(Int64))), toInt64(0))), which failed withArguments of 'plus' have incorrect data types(a server abort in debug and sanitizer builds). #109462 (Groene AI). - Fixed
CHECK TABLEon aReplicatedMergeTreetable reporting a healthy part as broken when a transient, retryable ZooKeeper error (e.g. connection loss) occurred during the check; such errors are now surfaced as a retryable query error instead. #109465 (Alexey Milovidov). - Fix segfaults in
groupArrayLastMergeand thelargestTriangleThreeBucketsaggregate function: deserialization of aggregate function states is now validated, so a broken state does not lead to an out-of-bounds memory access. #109485 (Miсhael Stetsyuk). #109492 (Miсhael Stetsyuk). - Fixed the global
max_rows_in_join/max_bytes_in_joinlimit not being enforced for theparallel_hashjoin algorithm, where a query withjoin_overflow_mode = 'throw'could silently succeed instead of raisingSET_SIZE_LIMIT_EXCEEDED. #109488 (Hechem Selmi). - Fixed reading Paimon tables partitioned by a
BIGINTcolumn whose value does not fit intoInt32. Such partition values were truncated (for example9223372036854775807became-1), which produced a wrong partition path and failed with a filesystem error. #109510 (Groene AI). - 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 (Miсhael Stetsyuk).
- Fixed the MySQL
connect_timeout, read and write timeouts not taking effect: a connection attempt to an unresponsive MySQL server could hang for more than two minutes even withconnect_timeout = 1, because the sampling query profiler’s periodic signals kept resetting the MySQL client’s internal poll deadline. #109592 (Shaohua Wang). - Fixed a
LOGICAL_ERROR(creation_csn is not set while removal_csn is set to 1) that could be thrown when a non-transactionalTRUNCATEran concurrently with an uncommitted transaction that had inserted into the same table. Such aTRUNCATEno longer removes parts created by not-yet-committed transactions. #109598 (Tuan Pham Anh). - Fix
TYPE_MISMATCHerrors when readingParquetstruct columns whose physical nullability differs from the requested ClickHouse type: a non-nullableParquetgroup can now be read asNullable(Tuple(...)), and the nativeParquetreader can read a physically nullable struct (aParquetOPTIONALgroup) asNullable(Tuple(...)). #109615 (Groene AI). #109898 (Groene AI). - Fixed silent data loss when an
INSERT ... VALUESin a multi-query stream is followed by a trailing SQL comment (for exampleVALUES (1) -- comment) under the server-side inline insert parsing path (send_table_structure_on_insert_with_inline_data = 0). The trailing comment was scanned as row data past the terminating;, causing the following queries in the stream to be silently skipped. #109643 (Groene AI). - Fix a segfault when a query arrives in a narrow window during server shutdown after an error at startup. #109675 (Miсhael Stetsyuk).
- Fixed stale skip indices (
text,bloom_filter, etc.) and projections after materializing lightweight updates withALTER TABLE ... APPLY PATCHES. Previously the index and projection files that depend on a patch-updated column were left unchanged, so queries using them could return wrong results (e.g.hasTokenmissing an updated row, or a projection returning stale aggregates once the spent patch part was removed). #109709 (Groene AI). - 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 a
LOGICAL_ERRORwhen writing aLowCardinality(Time)column to theArrowformat withoutput_format_arrow_low_cardinality_as_dictionary = 1. #109730 (Groene AI). - Fix
ObjectStorageQueue/AzureQueue(and theazureBlobStoragetable function) silently skipping objects when the object storage returns an empty listing page together with a continuation token. Azure Blob Storage does this (e.g. when a listing crosses an internal partition boundary), and the async list iterator was treating the empty page as the end of the listing and dropping the token. It now follows the continuation token. #109761 (Gal Ben Moshe). - Fixed partition pruning returning no rows for Iceberg tables partitioned by a timestamp (
DateTime64) column. #109764 (Den Kalantaevskii). - Fix an
ILLEGAL_COLUMNexception in theconvfunction forFixedStringarguments; they are now correctly cast toString. Closes #109670. #109771 (hp). - The
getClientHTTPHeaderfunction now treats header names as case-insensitive, according to RFC 9110; in particular, theauthorizationheader is now filtered out regardless of case. Closes #103957. #109791 (Mikhail f. Shiryaev). - Fix
max_execution_time(withtimeout_overflow_mode = 'throw') sometimes never cancelling a query: when the internal timeout watcher was already waiting for a query with a later deadline, a query with an earlier deadline registered afterwards could be missed entirely, letting it run long past its time limit. #109792 (Shaohua Wang). - Fixed the file name of gzip-compressed Iceberg metadata files. ClickHouse wrote them as
v{N}.gzip.metadata.json(the HTTPContent-Encodingtoken), while the Iceberg spec expects thegzextensionv{N}.gz.metadata.json. As a result Spark and other Hadoop-catalog readers could not find the metadata written by ClickHouse. ClickHouse now writesv{N}.gz.metadata.jsonand still reads the legacygzipname for backward compatibility. #109812 (Groene AI). - Fixed
NOT_IMPLEMENTEDerror (“Method getDataAt is not supported for Nullable(String)”) that could be thrown by a join withenable_join_runtime_filters = 1(on by default since 26.2) when the build-side join key wasLowCardinality(Nullable(...))withNULLvalues and the runtime filter fell back to its bloom filter. #109824 (Groene AI). - External database engines (e.g.
PostgreSQL) no longer push down range comparisons (>=,>,<=,<) onUUIDcolumns. ClickHouse and external databases order UUIDs differently, so pushing these down silently dropped rows from the result; such predicates are now evaluated by ClickHouse instead. #109833 (Vismay). - Fixed a server crash when a lambda expression was passed where a higher-order function expects a concrete value (for example the accumulator of
arrayFold, as inarrayFold(lambda, arr, another_lambda)). Such queries are now rejected withILLEGAL_TYPE_OF_ARGUMENTinstead of crashing whenenable_analyzer = 0. #109840 (Groene AI). - Fixed the
icebergLocaltable function andIcebergLocalengine declaringazureinstead oflocalas their object storage type, which made them fail the disk type check (Disk type doesn't match) when used with a local disk viaSETTINGS disk = '...'. #109872 (Pedro Ferreira). - Fix reading Iceberg tables partitioned by the same source column more than once (for example
PARTITIONED BY (hours(ts), ts)). Such tables previously failed withCannot add column ...: column with this name already exists (ILLEGAL_COLUMN). #109895 (Groene AI). - Fix wrong query results caused by the primary key index incorrectly pruning granules for tables with a reversed (
DESC) key column when parts have no final mark (non-adaptive granularity,index_granularity_bytes = 0). #109901 (Nihal Z. Miaji). - Fixed
generateRandomStructureoccasionally producing an invalid structure string with two data types concatenated (for exampleDecimal32(7)IPv4) when type nesting exceeded the internal depth limit, which made the result unparseable. #109928 (Groene AI). - Fixed
NOT_IMPLEMENTEDerror (Method getDataAt is not supported for Nullable(String) in case if value is NULL) when atextindex is built onArray(LowCardinality(Nullable(String)))(includingNestedfields stored that way) and an indexed array contains aNULLelement.NULLarray elements are now skipped during index construction, matchingArray(Nullable(String)). #110055 (Groene AI). - Fix wrong results when a
minmaxskip index is built on aLowCardinality(Nullable(...))column:WHERE/PREWHERE/HAVING ... IS NULLpredicates pushed to storage previously pruned every granule and returned 0 rows even though the column containedNULLvalues. #110061 (Groene AI). - Fix
distinct_overflow_mode = 'break':DISTINCTnow returns the partial result accumulated up to the limit and stops reading the source, as documented. Previously the chunk that crossedmax_rows_in_distinct/max_bytes_in_distinctwas discarded (truncated or empty results) and the query kept reading and inserting into the hash set to the end of the input, which could end inMEMORY_LIMIT_EXCEEDED. #110075 (Sergey Kuznetsov). - Fixed a logical error
ChunkInfoRowNumbers does not existonOPTIMIZE TABLEof an Iceberg table containing a data file in a non-Parquet format (e.g.ORC) newer than all position delete files. #110107 (Alexey Milovidov). - Fix
max_bytes_in_distinctandmax_bytes_in_set: string keys are stored in an arena that was not counted by the limit checks, soDISTINCT/INover string keys could hold memory exceeding the byte limit by the whole key payload (unbounded in the key length). The limits now account for the arena, matching their documentation; queries with string keys close to a byte limit may now trip it earlier (correctly). #110120 (Sergey Kuznetsov). - Fix a
LOGICAL_ERROR(Bad cast from type ColumnLowCardinality to ColumnString) whenidentity(or a scalar subquery result) wraps a value containing a nestedLowCardinalityand the query usesWITH TOTALS/WITH ROLLUP. #110138 (Groene AI). - Fixed reading
Npyfiles with zero-sized inner dimensions: the number of materialized rows and the optimized and non-optimizedcountresults now agree. #110146 (Yanjun Qiu). - Fixed a quadratic-time blowup (and unresponsiveness to
max_execution_time) in aggregation in order when grouping by multiple keys whose sort order is only a prefix of the grouping key. #110159 (Alexey Milovidov). - Fix a logical error (
Unexpected number of columns in result sample block) when a filter containing a correlated subquery (for exampleexists((SELECT ...))) is optimized withconvert_query_to_cnforoptimize_and_compare_chain. #110187 (Alexey Milovidov). - Fixed an exception (
UNION mode UNION_DEFAULT must be normalized) when aDELETEorALTER UPDATEmutation used a set operation (UNION/UNION ALL/UNION DISTINCT/EXCEPT/INTERSECT) inside a subquery in itsWHEREcondition or in anUPDATEassignment. #110196 (Alexey Milovidov). - Fixed a
ReadBuffer is canceled. Can't read from it.logical error (server abort in debug/sanitizer builds) that could occur while reading a zip archive (e.g. duringRESTOREfrom a zip backup) after a prior read from the same archive failed mid-stream. #110197 (Groene AI). - Fixed slow server shutdown and unresponsive
KILL MUTATIONwhen a mutation withx IN (subquery)was building the subquery set during primary-key analysis; the set build is now cancelled promptly. #110198 (Alexey Milovidov). - Keeper now rejects the coordination settings
max_requests_batch_sizeandmax_requests_append_sizebeing set to0instead of getting stuck in an infinite append-entries loop in a multi-node setup. #110200 (Alexey Milovidov). - Fixed a
NOT_FOUND_COLUMN_IN_BLOCKerror when usingGROUP BY ALLover a tuple expression together withORDER BY. #110206 (Alexey Milovidov). - Fixed a
NOT_FOUND_COLUMN_IN_BLOCKerror onINSERTinto a table that has aCHECKconstraint referencing a subcolumn (such asx.nullof aNullablecolumn orarr.size0of anArray). #110208 (Alexey Milovidov). - 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 (Groene AI). - Fixed
system.tablesfor aDataLakeCatalog(Iceberg/Glue) database aborting the whole query, or silently dropping tables, when a single table’s metadata is unresolvable. Such a table now stays listed by name with default/NULL values for the columns that need the opened storage object (engine,total_rows, etc.), regardless ofdatabase_datalake_require_metadata_access. Direct access to the broken table still reports the error. #110242 (Groene AI). - 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 (Groene AI). - Fixed
INSERTinto a Microsoft Fabric / OneLakeDataLakeCatalogtable failing withIncorrectEndpointError(HTTP 400) by routing ADLS Gen2 (DFS) writes to the.dfsendpoint host instead of the.blobhost. Note: withremote_url_allow_hosts, both the.blob(read) and.dfs(write) Fabric hosts must be allow-listed forINSERT. #110290 (Mohammad Lareb Zafar). - Fixed a server abort when parsing certain PRQL queries (
SET dialect = 'prql'). A panic inside theprqlccompiler was aborting the process instead of being reported as a query error. #110316 (Groene AI). - Fix silently wrong query results when a projection part written before the projection’s column set changed (for example, after upgrading across versions that materialize an
ALIAScolumn’s source differently, or afterALTER TABLE ... MODIFY COLUMNre-points anALIAScolumn used by a projection) was read through the projection or merged: the missing column was filled with default values instead of the real data. Such parts are now read from the base table, and merges rebuild the projection from the base data. #110328 (Shaohua Wang). - Fixed
ORDER BY ... WITH FILLnot respectingmax_execution_timeand being slow to cancel when generating a large fill range (especially withINTERPOLATE). #110332 (Alexey Milovidov). - Fix a logical error (a server abort in debug/sanitizer builds) when a multi-command
ALTERsuch asUPDATE ..., DELETE ...was issued on an Iceberg table. Such mutations are now rejected with a clearNOT_IMPLEMENTEDerror. #110347 (Groene AI). - Fixed a parser bug where
COMMENTwas incorrectly consumed as an implicit alias when aSELECTquery ended directly after a bare table identifier (e.g.... FROM t COMMENT 'x'), causing a misleading syntax error instead of the comment being applied to the view/table. #110372 (Aditya Kumar). - 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 (Raúl Marín). - Fixed two cases where vector search could return fewer rows than expected:
vector_search_index_fetch_multipliervalues below 1.0 could truncate the computed fetch count to zero and produce an empty result (such values are now rejected), and the vector search optimization is now skipped forLIMIT ... WITH TIESqueries, because the optimization bounds the search to exactly N candidates and dropped rows tied with the N-th row. #110452 (Tamish Mhatre). #110453 (Tamish Mhatre). - Fix the logical error
Expected CommonSubplanReferenceStep to reference CommonSubplanStep, the errorSubplan cannot be used to build pipeline, and the logical errorTrying to extract chunk from ChunkBuffer before all inputs are finishedforIN (subquery)where the subquery contains a correlated subquery and the set is built during index analysis. #110491 (Alexey Milovidov). - Fix substitution of query parameters inside the definitions of a named
WINDOWclause. Previously, parameters there were silently kept unsubstituted, and an unsetIdentifierparameter could lead to the exceptionLogical error: '!part.empty()'duringEXPLAIN SYNTAX. #110506 (Alexey Milovidov). - Fixed server startup failure for
MergeTreetables on object storage disks when a leftovertxn_version.txt.tmpfile has broken disk-level metadata. #110519 (Alexey Milovidov). - Fix a logical error in the filesystem cache (
Expected file ... not to exist) that could occur when a background cache download failed with a non-filesystem error (for example while runningOPTIMIZEon an Iceberg table), leaving an empty orphan cache file behind. #110549 (Groene AI). - Fixed reading a corrupted
Native-format stream whoseDynamictype count orJSON/Objectpath count is close toSIZE_MAX: such malformed input is now rejected with a clearINCORRECT_DATAerror instead of an uncaughtstd::length_error. #110590 (Alexey Milovidov). - Fixed a server crash in the
MaterializedPostgreSQLdatabase engine that could happen when a table was detached (or its structure changed) while it was still queued for synchronization. #110596 (Alexey Milovidov). - Fixed
SET param_<name>in the client (and--param_<name>flags) misbehaving when the parameter name matches a builtin setting name such aslimit,offset,max_threads, orlog_comment. Depending on the colliding setting, the query failed withCANNOT_PARSE_QUOTED_STRING, the value was silently normalized (e.g.max_threads=0becameauto(N)), or a setting alias name was lost. Such a parameter also broke every subsequentSET param_*in the same session. #110597 (Raúl Marín). - Fix reading subcolumns of a column that has a
DEFAULTexpression and is not materialized in a part (e.g. afterALTER TABLE ADD COLUMNor duringALTER TABLE MATERIALIZE COLUMN): the subcolumn was filled with type default values instead of the evaluatedDEFAULTexpression, and the transposed vector distance functions (cosineDistanceTransposedand others) on suchQBitcolumns failed with theSIZES_OF_ARRAYS_DONT_MATCHerror. This closes #110634. #110636 (Alexey Milovidov). - Fixed a
LOGICAL_ERRORInvalid partition key size: 0that could fail anINSERTinto a partitionedMergeTreetable withnon_replicated_deduplication_windowenabled, when an async insert batch was only partially deduplicated (someinsert_deduplication_tokenvalues were duplicates and some were new). #110651 (Groene AI). - A background asynchronous insert flush now stops promptly when killed with
KILL QUERY; previously a flush of a large buffered payload kept parsing to the end and ignored the cancellation. #110652 (Shaohua Wang). - Fixed wrong results from
GROUP BYwithoptimize_aggregation_in_orderandDISTINCTwithoptimize_distinct_in_orderplaced over apartial_mergeJOIN. The read-in-order optimization was propagated through the partial-merge join, which re-sorts its left input by the join key and therefore does not preserve the left stream’s original order, so rows were grouped incorrectly. #110671 (Groene AI). - Fixed a signed integer overflow in
toStartOfIntervalwith an extremeMONTH,WEEK, orDAYinterval count onDate/Date32/DateTime64values. #110688 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKerror for queries with a subquery inFROMwhen parallel replicas run incustom_key_sampling/custom_key_rangemode. Such queries (e.g.SELECT * FROM (SELECT id, k, v FROM t WHERE id < 20) ORDER BY k) previously failed withNot found column __table2.id in block .... #110690 (Groene AI). - Fixed
readWKTrejecting WKT strings with leading whitespace (e.g.readWKT(' POINT(1 2)')), which are accepted by the typedreadWKTPoint/readWKTPolygon/… readers and by the WKT grammar. #110706 (Groene AI). - Fix a logical error (
Column ... already added for reading, a server abort in debug/sanitizer builds) when the same text-index predicate is used in bothPREWHEREandWHEREof a query over aMergetable on top of aDistributedtable. #110710 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKerror for the transposed distance functions overQBitcolumns (such ascosineDistanceTransposed) called with a scalar-subquery or constant reference vector when parallel replicas are enabled. This closes #110719. #110729 (Alexey Milovidov). - Fix a rare
LOGICAL_ERROR(Unexpected number of parts to remove from parts_queue; a server abort in debug/sanitizer builds) onReplicatedMergeTreewhen two partition operations (for example twoMOVE PARTITION/REPLACE PARTITIONqueries, or one racing a backgroundDROP_RANGE) cancelled the background part check over overlapping ranges at the same time. #110738 (Groene AI). - Fixed a
Hash is not set for serializationlogical error that could occur when a column with aQuantized(...)codec was wrapped inside another serialization, for example in aMergetable over sources whose same-named column has different types (merged into aVariant). #110776 (Groene AI). - Fix a server hang when multiplying a
median/quantileaggregate function state by a huge integer constant (e.g.medianState(x) * 18446744073709551615). The query became unresponsive to cancellation and could run indefinitely. #110779 (Groene AI). - Fix a server crash (integer division by zero) when a quota with a zero-length interval (for example
CREATE QUOTA q FOR INTERVAL 0 SECOND MAX queries = 1000) was consumed. A non-positive quota interval duration is now rejected at quota creation. #110846 (Pedro Ferreira). - Fixed
throwIf(notLike(col, pattern))(and otherthrowIfover a function) throwing unconditionally whencolisLowCardinality. The defaultLowCardinalityimplementation ranthrowIfon the whole dictionary, which always holds the reserved default value even when no row references it, so a non-zero value in that unused slot madethrowIfthrow for data that does not satisfy the condition. #110864 (Groene AI). - Propagate a query’s active roles (
SET ROLEor theroleparameter) to remote nodes on parallel-replica andDistributedreads over a cluster secured with an interserver secret; previously the remote nodes fell back to the user’s default roles, evaluating row policies inconsistently with the initiator. #110867 (Nikolay Degterinsky). - Fixed Iceberg tables producing duplicate field IDs after
ALTER TABLE ... ADD COLUMNwhen the initial schema contains nested fields (Tuple/Array/Map).last-column-idnow records the maximum assigned field ID including nested children, so a subsequently added column no longer reuses a nested field ID and reads no longer fail withICEBERG_SPECIFICATION_VIOLATION(Duplicate field id). #110884 (Groene AI). - Fixed a crash in FIPS builds when using an Ed25519 SSH key (
CREATE USER ... IDENTIFIED WITH ssh_key ... TYPE 'ssh-ed25519', or such a key inusers.xml). Ed25519 is not FIPS-approved; such keys are now rejected with a clearLIBSSH_ERRORerror. #110891 (Konstantin Bogdanov). - Fix the reduced-precision results of the transposed distance functions over
QBitcolumns (cosineDistanceTransposed,L2DistanceTransposed,dotProductTransposed). Values truncated toprecisionbit planes were reconstructed with the dropped bits zero-filled, which biased every reconstructed value towards zero and was degenerate at low precision: forQBit(BFloat16)at precision 1 only the sign bit survives, so every value reconstructed to±0.0and the distance was the same constant for every row, carrying no ranking information. Truncated values are now reconstructed to a bounded midpoint of the remaining precision cell (rawInt8codes to their cell centre; exact zeros and infinities are preserved), so a smallerprecisiontrades accuracy for speed without wildly biased results. Full-precision results are unchanged. This closes #110898. #110911 (Alexey Milovidov). - Fix a server crash (use-after-free) during graceful shutdown after Iceberg tables were queried from sessions that also used temporary tables. #110914 (Miсhael Stetsyuk).
- Fixed a
LOGICAL_ERROR: Cannot sum Bools(a server abort in debug/sanitizer builds) when mergingsumMap/sumMapWithOverflow/sumMapFilteredaggregate states withBoolvalues that were serialized in the old (version 0) state format. The same fix also corrects two silent wrong-result cases with version-0Boolstates: map keys of typeBoolwere not deduplicated across states, and zero-value compaction dropped the wrong entries. #110922 (Groene AI). - Fixed a crash when an aggregate function with the
-Tuplecombinator was used withRESPECT NULLSand produced an intermediate state (-State, distributed aggregation,WITH ROLLUP/WITH CUBE). The combined function was named after the wrong state variant, so its serializedAggregateFunctiontype re-resolved to an incompatible in-memory layout on a round-trip. #110930 (Groene AI). - Fix
PREWHERE(and row-level policies) on an Iceberg column that was renamed by schema evolution silently returning0rows for old data files. Such queries now return the correct rows, matchingWHERE. #110941 (Groene AI). - Fix a
LOGICAL_ERROR(LazyMaterializingTransform: Number of rows in lazy chunk N does not match number of offsets M) that could happen for vector search queries withvector_search_with_rescoring = 1combined with lazy materialization when several distances tie. #111003 (Groene AI). - Fixed reading
Arrow/ArrowStreamdata with empty nestedArray/Mapcolumns produced by Apache Arrow Java < 19.0.0 (bundled with Apache Spark), which were previously rejected with anINCORRECT_DATAerror about the offsets buffer being too small. #111101 (Raúl Marín). - Fix stale reads on
plain_rewritabledisks with the page cache enabled. #111105 (Mikhail Artemenko). - Fix
CANNOT_CONVERT_TYPEerror for constants ofVarianttype (includingGeometry) in distributed queries and queries with parallel replicas. #111136 (Nikita Fomichev). - Fix a bug where reading large files from HDFS could fail or read incorrectly when a single read request exceeded the
hdfsPread32-bit size limit (INT_MAX). #98470 (Arup Chauhan). - Fix incorrect use of the text index for equality comparisons with an empty needle. #108340 (Robert Schulze).
- Fixed a hang in
SYSTEM SYNC MERGESwith theManualmerge selector when a scheduled merge could not be placed into a full background pool. #108770 (Alexey Milovidov). - Fix
ATTACH TABLE ... AS REPLICATEDdiscarding committed data and resurrecting pre-mutation rows when a staletxn_version.txt.tmpfile was left on a data part. #108772 (Alexey Milovidov). - Fix a possible race condition in
ALTER TABLE ... MOVE PARTITION TO TABLEwith non-replicatedMergeTreetables that could produce intersecting data parts, because the commit of moved parts and block number allocation were not under the same lock. #108922 (Mikhail Artemenko). - Fix reading
Icebergtables written by Databricks UniForm, which writes a degenerate placeholder schema (with an empty field list) into manifest files. #108945 (Konstantin Vedernikov). - Fix a use-after-free when reading a non-partitioned
Hivetable with multiple threads. #109164 (Alexey Milovidov). - Fix the console log level not being reverted after server startup when
logger.startup_console_log_levelis set: the level was captured from the wrong configuration key, so the console stayed at the elevated startup level for the lifetime of the server. Closes #103472. #109858 (Garrett Thomas). - Fix snapshot-isolation anomalies in
plain_rewritabledisk metadata transactions. Fixes #92055. #110948 (Mikhail Artemenko). - Fix an abort (
front() called on an empty vector) inclickhouse-client --loginwhen the host was not passed as an explicit--hostargument, for example when it came from--connection, the configuration file, or theCLICKHOUSE_HOSTenvironment variable. Closes #103603. #110279 (Christoph Wurm). - Fix a logical error (
!part.empty()) when a lambda argument is a backtick-quoted identifier whose name contains a dot (for example__table1.). Such a query previously produced a handled exception in release builds and aborted the server in debug and sanitizer builds while formatting an error message. #108735 (Groene AI). - Fix a
LOGICAL_ERROR(No set is registered for key) inALTER TABLE ... DROP COLUMN,ALTER TABLE ... DELETE/UPDATEmutations, and lightweightDELETE FROM, on tables that have anALIAScolumn whose expression uses anINoperator (including through anotherALIAScolumn). #111039 (Pedro Ferreira). - 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. Closes #111031. #111049 (Groene AI). - Fixed a
LOGICAL_ERRORexception (ScatterExchangeStep should have one source shard, got 8) and duplicated rows when querying aMergetable overDistributedtables or views with the experimental settingmake_distributed_plan = 1. Closes #107946. #108401 (Groene AI). - Serialize a
Nullable(Tuple(...))column as a singleCSVfield instead of flattening it into separate columns. Previously a non-null value was written as severalCSVfields whileNULLwas a single\N, giving a row-dependent column count that brokeCSVWithNames/CSVWithNamesAndTypesheaders and round-trips. #108959 (Groene AI). - Fix a logical error (
KeyCondition uses PREWHERE output) in theParquetv3 reader when a format-level key condition references a column that is not read from theParquetfile. #109267 (Groene AI). - Fix wrong results for table-function reads with
FINALorSAMPLEunderserialize_query_plan = 1. Also fix the aggregation hash-table statistics cache key for table functions so different table functions no longer share the same preallocation entry. #109847 (Azat Khuzhin). - Fixed cleanup of a
BACKUP ... TO Memory(...)that fails before finalization: the failed backup was left registered, so its name could not be reused. #109947 (Julia Kartseva). - Fix extreme interval arithmetic for
WITH FILL STEPand theadd*/subtract*date/time interval functions: out-of-range deltas no longer rely on signed overflow, andWITH FILLwith a hugeYEARstep no longer stalls by running the calendar backward. #110158 (Groene AI). - 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 it themselves, such as Azure Key Vault. #110299 (Konstantin Bogdanov). - The lazy
FINALoptimization (query_plan_optimize_lazy_final, disabled by default) is no longer applied when the query reads in sorting-key order, because its replacement plan does not preserve that order and could return incorrectly ordered results. It is also no longer applied when aLIMITsmaller than the number of rows to read applies directly to the reading step, where the mandatory set-building pass defeats early termination. #110576 (Nikolai Kochetov). - Fixed
readWKTandreadWKTPointreturning uninitialized (scalar) or stale prior-row (vectorized) coordinates forPOINT EMPTY.POINT EMPTYis now rejected withCANNOT_PARSE_TEXT, since ClickHousePointis a fixedTuple(Float64, Float64)with no empty representation. #110692 (Groene AI). - Fix wrong timezone handling when materializing right-side columns in hash joins. Closes #111033. #111074 (Yarik Briukhovetskyi).
- Fixed wrong
count()results and dropped rows when aString(or narrowerFixedString) key or minmax skip index is filtered by a comparison with a widerFixedStringconstant, e.g.toFixedString('abc', 257) = string_col. Primary-key and minmax pruning built the range from the NUL-padded constant and wrongly skipped matching granules. #111106 (Groene AI). - Fixed asynchronous
Native-format inserts so one buffered entry that becomes incompatible afterALTER ... MODIFY COLUMNno longer causes the whole batch to fail. Closes #111064. #111108 (Mikhail f. Shiryaev). - 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 (Nikolay Degterinsky). - Fixed
INCOMPATIBLE_TYPE_OF_JOINfor 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 (Groene AI). - Fix the
formattable function returning no columns when the input data parses to zero rows (for example an empty JSON document or a GeoJSONFeatureCollectionwith no features). It now returns an empty result with the correct columns instead of throwingNOT_FOUND_COLUMN_IN_BLOCK. Closes #111390. #111428 (Groene AI).
Build/Testing/Packaging Improvement
- Sanitizer builds now capture the sanitizer report into the global buffer
sanitizer_report, so that the core dump analyzer can read it from the core dump. #109333 (Miсhael Stetsyuk). - Build
muslfrom source instead of using vendored binaries. #97452 (Konstantin Bogdanov). - Use SIMD
memcmp/memcpy/memmove/memset/bcmp/memmemimplementations from LLVM-libc. #107566 (Konstantin Bogdanov). Fix silentmemmovecorruption in-O0debug builds (-DDEBUG_O_LEVEL=0) on machines with AVX-512. #110904 (Konstantin Bogdanov). - Remove usages of the
curllibrary across the codebase and bundled third-party libraries. #108296 (Konstantin Bogdanov). - Updated
mariadb-connector-cto 3.4.9. #108328 (Konstantin Bogdanov). - Update
libsshto 0.12.0. #108329 (Konstantin Bogdanov). - Fix a hang on transaction
COMMITon macOS. #108375 (Raúl Marín). - Added a
COMPRESS_DEBUG_SECTIONSCMake option that compresses DWARF debug sections in object files (-gz), auto-enabled where the compiler supports it, to shrink Debug build directories; final binaries are left uncompressed, so runtime stack-trace symbolization is unaffected. #109306 (Murphy). The bundled LLVM toolchain is now built with zlib, so its clang supports-gz=zlib, and the missingclang++-21symlink was added. #109596 (Murphy). - Debug builds now compile the vendored Rust crates with reduced debug info (
debug = 1, cargo’slimitedlevel) and no incremental cache (REDUCE_RUST_DEBUG_INFO, on by default), shrinking Rust build artifacts (~12 → ~7 GB from scratch) and preventing unbounded cargo cache growth across rebuilds. Set-DREDUCE_RUST_DEBUG_INFO=OFFto restore full DWARF and incremental compilation. #109471 (Murphy). - Support the streaming distributed query exchange and
STREAMreads on macOS. #109769 (Raúl Marín). - Bump
libarchivefrom 3.8.7 to 3.8.8. #109874 (Robert Schulze). - Bump
c-aresfrom 1.34.6 to 1.34.8. #109905 (Robert Schulze). - Update
krb5to fix CVE-2026-40355 and CVE-2026-40356. #109910 (Robert Schulze). - Removed the
libpngthird-party dependency.FORMAT PNGnow uses a small built-in PNG encoder (backed by the bundled zlib) instead. #110051 (Alexey Milovidov). - Track raw C allocations (not going through
operator new) in the memory tracker on macOS by wrapping the jemalloc malloc zone, so memory limits are enforced for them. #110370 (Raúl Marín). - The
-distrolessDocker images forclickhouse-serverandclickhouse-keeperare now built from the shell-free production stage; previously they were built from the debug stage and included/busybox/sh. Closes #105677. #105678 (ashishch432). - Update
abseil-cppto LTS20260526.0. #108991 (Konstantin Bogdanov).
ClickHouse release 26.6, 2026-06-25. Presentation, Video
Backward Incompatible Change
- The change removes
allow_experimental_query_deduplicationfeature. The feature was experimental for a long time, has no tests and not going to be supported (initial tests were unstable and has been removed in #49579). #99398 (Igor Nikonov). - The XRay-based
SYSTEM INSTRUMENTfeature now usesargumentsinstead ofparameters: thesystem.instrumentation.parameterscolumn was renamed toarguments, and theSYSTEM INSTRUMENT ADD ... HANDLER PARAMETERS ...syntax was renamed toSYSTEM INSTRUMENT ADD ... HANDLER ARGUMENTS .... Queries or automation that use the old column or syntax must be updated to use the new names; the old names are no longer supported. #103854 (Pablo Marcos). - The setting
show_data_lake_catalogs_in_system_tableshas been renamed toshow_remote_databases_in_system_tablesand broadened: when its value is 0 (the default),MySQLandPostgreSQLdatabases are also hidden fromsystem.tables,system.columns, andsystem.completions, in addition to data lake catalogs. The old setting name is kept as an alias. #104416 (Pablo Marcos). - The default x86 build now targets x86-64-v3 (AVX2) instead of x86-64-v2 (SSE4.2). This requires a CPU with AVX2 support (Intel Haswell or later, AMD Excavator or later). If your CPU does not support AVX2, use the
amd64compatbuild which targets plain x86-64. #105019 (Raúl Marín). - Reject nested
Dynamic/Variantinmin/maxaggregates andminmaxindexes. Previously only top-levelDynamic/Variantwere checked. Closes #104747. #105468 (Pavel Kruglov). 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 (Raúl Marín).- Added granular control over query echoing in the CLI. The
--echooption now accepts an optional boolean value and works in both interactive and batch mode. New options--echo-formattedand--echo-query-idcontrol whether echoed queries are formatted and whether thequery_idis printed, respectively. The--hilite/--highlightoption now also controls highlighting of echoed queries. As a side effect,--echois now a boolean-value option, so a positional query directly after a bare--echois treated as its value; use--echo --query "..."or--echo=falseinstead. #106191 (Alexey Milovidov). - 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 (Groene AI). 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 — a data-loss footgun. It is now rejected withBAD_ARGUMENTSby default. To restore the previous silent-clear behavior, set the new settingallow_replace_partition_from_empty_source = 1, or setcompatibilityto26.5or lower; to explicitly drop destination data, useALTER TABLE ... DROP PARTITION. #104939 (Groene AI).- 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. Instances upgrading directly from a release that defaulted toold_separate_hashesshould first run withcompatible_double_hashesuntil the longest relevant deduplication window has elapsed before relying onnew_unified_hash. #107886 (Sema Checherinda).
New Feature
- Added support for continuous queries over
MergeTreetables, implemented via a series of snapshot reads. This is a first step toward general support for streaming queries. #105114 (Mikhail Artemenko). - 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 (Yarik Briukhovetskyi). - Add an embedded
/schemaweb UI toclickhouse-serverthat visualizes the dependency graph between tables, materialized views, refreshable materialized views, dictionaries, distributed tables and views. #105276 (Nikita Mikhaylov). - Added the
PNGoutput format support, allowing query output results to be directly rendered as PNG images. #74691 (Maksim Dergousov). - Added detection of the AI coding agent (Claude Code, Cursor, Codex, Gemini CLI, Goose, etc.) that invoked
clickhouse-clientorclickhouse-local, based on environment variables. The detected agent is reported in the newclient_agentcolumn ofsystem.query_log,system.query_thread_logandsystem.processes. #106619 (Alexey Milovidov). - 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). - Add the
GeoJSONinput format for reading GeoJSONFeatureCollectiondocuments, producing one row per feature withid(String),geometry(Geometry), andproperties(Nullable(JSON)) columns.Point,LineString,MultiLineString,Polygon, andMultiPolygongeometries are read into ClickHouse’s nativeGeometrytype.GeometryCollectionandMultiPoint, which theGeometrytype cannot represent, raise an exception by default, or can be stored asNULLvia theinput_format_geojson_unsupported_geometry_handlingsetting. Contributes to #91533. #98124 (Mark Needham). - 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 (Saarthak Gupta). clickhouse-localnow supportsSYSTEM START LISTENandSYSTEM STOP LISTENqueries, allowing it to be transformed into a server accepting TCP and HTTP connections. #101143 (Alexey Milovidov).- Added an interactive
helpcommand toclickhouse-clientandclickhouse-local. Typinghelp <name>(also/help,man,/man) shows the documentation of a function, table engine, data type, format, setting, or other component, rendered from Markdown in the terminal with syntax-highlighted SQL. When the word is ambiguous all matches are shown, and when it is not found, similar names are suggested. #108042 (Alexey Milovidov). - Support writing into Azure Data Lake Storage Gen2. #105406 (Konstantin Vedernikov).
- Adding
RowBinaryWithNamesAndTypesAndDefaultsformat to get better support for schema evolution. #105736 (Mark Zitnik). - Implement
ADD ENUM VALUESinALTER TABLEqueries to simplify appending new values to an existingEnumtype without the need to specify all currentEnumvalues again. #93830 (Ilya Golshtein). - 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.) SeeCREATE MATERIALIZED VIEWdocumentation. #104440 (Michael Kolupaev). - 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 (Yue Ni). - Added
ESCAPEsyntax that defines a custom escape character in aLIKEpattern, allowing you to treat%and_as literal characters instead of wildcards. #99774 (Ilya Yatsishin). - Add
materialize_projections_on_insertandmaterialize_projections_on_mergeMergeTreetable 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 (Christoph Wurm). - 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 (johnjing). - 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). - Add functions
arrayTopKandarrayBottomK: -arrayTopK(k, array)returns the K largest elements in descending order -arrayBottomK(k, array)returns the K smallest elements in ascending order. #104563 (Vitaly Baranov). - Added a new system table
system.iceberg_filesexposing per-file metadata forIcebergtables, with one row per data or delete file in each table’s current snapshot. This closes #98777. #104415 (Asya Shneerson). - Added
system.constraintstable that provides information about allCHECKandASSUMEconstraints across all tables, including constraint name, type, and expression. #105337 (Pedro Ferreira). - 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). - 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). - 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 (Jordi Villar). - 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 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 (Denny [DBA at Innervate]). - 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). - Add an optional
external_idcredential forS3role-based access. #106941 (Elian Gidoni). - Added a new
S3Queuesettingafter_processing_move_preserve_path. When enabled together withafter_processing='move'andafter_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 Shneerson). - Add
message_queue_disable_insertionserver setting to disable insertion from message queue engines (Kafka,RabbitMQ,NATS) into attached materialized views. Useful for read-only replica scenarios. #104911 (JIaQi Tang). - Added
LOCALTIMEandLOCALTIMESTAMP(SQL-standard / PostgreSQL syntax).LOCALTIMESTAMPis an alias fornow()(returnsDateTime);LOCALTIMEreturns the current time of day as aTimevalue. #106139 (Thomas Cabral). - 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). - 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 (Vinayak Joshi). - Added
min_byandmax_byaggregate aliases forargMinandargMax. #105712 (Joey Yu). These aliases are stupid, real engineers use the original ClickHouse names. - Added
REGEXP_SUBSTRas a case-insensitive alias ofregexpExtractfor Oracle/MySQL/Snowflake compatibility. #105122 (Alexey Milovidov). - Added
SESSION_USERas a case-insensitive alias ofcurrentUser()for PostgreSQL / SQL-standard compatibility. #106081 (Takumi Hara). - Support a trailing
NULL/NOT NULLmodifier inALTER TABLE ... ADD/MODIFY COLUMN, mirroringCREATE TABLE. #106150 (Takumi Hara). - You can now use
h3PolygonToCellsWithContainmentfunction from h3 to use their new algorithm which supports center-based, fully-contained, and overlapping containment modes. #104455 (Youssef Kadry). - Adds
IPV4_PREFIX_BITS and IPV6_PREFIX_BITSflags when Keying done byIP_ADDRESSorFORWARDED_IP_ADDRESS. #89270 (Aditya Chopra). formatReadableTimeDeltanow accepts anINTERVALexpression of type other thanMonthandYearas input. #64315 (Francisco J. Jurado Moreno).- 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 (Antonio Filipovic). - Add
output_format_float_precisionsetting to control the number of decimal digits in floating-point text output. #99721 (phulv94). - 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 (Ilya Yatsishin). - Add support for new HTTP handler configuration elements
<url_prefix>and<full_url_prefix>(match all paths under a base path, useful e.g. for Prometheus handlers), as well as<url_regexp>,<full_url_regexp>, and<headers_regexp>. The old<url>regex:...</url>form is now obsolete. #107492 (Vitaly Baranov). - Support
basicstatistics, a compact per-column statistic that stores numeric min/max, average string length, and NULL counts where applicable. #106048 (Han Fei). - Support TTL nodes in ClickHouse Keeper, opt-in via the
create_ttlfeature flag. #100397 (Konstantin Vedernikov). - Introduce a memory reservation feature for workloads. See the workload scheduling documentation. #82414 (Sergei Trifonov).
Experimental Feature
- 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 (Alexander Gololobov). 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 (Alexander Gololobov). - 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 (Alexander Gololobov). - Add
aiEmbedfunction for using LLM APIs to generate embeddings from within ClickHouse. #102922 (George Larionov). - Added an experimental Linux OOM canary: a sacrificial child process that the Linux OOM killer targets before the main server process. When enabled with
oom_canary_enable, it sheds memory pressure by purging allocator caches, cancelling queries, cancelling merges, and recording an event insystem.crash_log. The OOM response requires cgroup v2memory.eventsOOM-kill evidence. #101942 (Peng). - The web terminal interface at
/webterminalis now a production feature and is enabled by default. It is controlled by the newenable_webterminalserver setting; the formerallow_experimental_webterminalsetting is deprecated but still honored for backward compatibility. To disable the endpoint, setenable_webterminaltofalse. #106255 (Alexey Milovidov). - PromQL HTTP endpoints now support specifying the database and table via URL query parameters (
database=,table=, ortable=db.table). The previous implicitdefault.prometheustable fallback is removed: if neither the handler config nor the URL specifies a table, the handler now returnsThe time series table name is not set. To keep the old behavior, configure<table>default.prometheus</table>or passtable=...in the URL. #107553 (Vitaly Baranov). - Added support for the PromQL
histogram_quantilefunction inprometheusQueryandprometheusQueryRangetable functions. This enables computing quantiles over classic Prometheus histogram buckets identified by thelelabel. #103477 (Joe Smith). - 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 (Peng). - Added support for the AssemblyScript ABI for WebAssembly UDFs. You can try the AssemblyScript ABI without installing the toolchain locally by using the browser-based playground, which compiles AssemblyScript code and loads the resulting WebAssembly module into local ClickHouse. #104606 (Vladimir Cherkasov).
- Allow for attaching Prometheus handlers on the main HTTP port with an optional prefix. #104975 (James Cunningham).
- Added an experimental
MergeTreesettingpacked_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 (Raúl Marín). - Support
Buffersserialization for WebAssembly UDFs usingABI BUFFERED_V1, and addwebassembly_udf_enable_fuelas a persisted WASM UDF function setting. #105574 (Antonio Andelic). - Add an experimental
use_reader_executorsetting (default off) that routes reads through a new pipeline-basedReaderExecutorinstead of the legacy chain of read buffers. #106570 (Sema Checherinda). Added observability metrics for the experimentaluse_reader_executorread path, including a modeled read-cost KPI (ReaderExecutorModeledCostMsPerRequestedMiB). #106968 (Sema Checherinda). Introduced theChainedBuffersbuffer behind the experimentaluse_reader_executorread path, with aReaderExecutorChainedBufferBytesmetric. #107210 (Sema Checherinda). - 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 (Nikita Mikhaylov). Nullable(Tuple(...))is now Beta. Disabled by default, setenable_nullable_tuple_type = 1to use it. #107754 (Nihal Z. Miaji).
Performance Improvement
- Various changes to Keeper that make it around 2x faster overall (better batching, pipelining messages to leader, pipelining log appends). #101757 (Michael Kolupaev).
- Reduce per-query overhead for simple
SELECTqueries (parsing, analysis and planning). For example,SELECT count() FROM hitsfrom a single connection is roughly 50% faster. #104513 (Raúl Marín). - 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. Closes #65103. #91836 (Nihal Z. Miaji). - The default x86 build now targets x86-64-v3 (AVX2) instead of x86-64-v2 (SSE4.2). This requires a CPU with AVX2 support (Intel Haswell or later, AMD Excavator or later). If your CPU does not support AVX2, use the
amd64compatbuild which targets plain x86-64. #105019 (Raúl Marín). - Use
ipnsortanddriftsort(stable sorting) — C++ ports of the Rust standard library’s sort implementations — for the general-purpose comparison sorts. Speeds upORDER BYon non-numeric columns and stable sorts, and removes a worst case on reverse-sorted input. #106650 (Alexey Milovidov). - 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 (Nihal Z. Miaji). - Enable hash table prefetching for string key
GROUP BYqueries, improving high-cardinality string aggregation performance by ~8%. #101007 (Le Zhang). - 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 (Yuri Fedoseev). - Memory representation of
EnumDataTypewas optimized. Memory footprint of tables that haveEnumtype in it can improve up to 10x times forEnumcomponent. Operation time to retrieve name by value(number) is similar or faster. Search by name is slightly slower, but this access direction is less common. #95668 (Ilya Yatsishin). - Add identifier resolution caching to prevent duplicate identifier resolution during query analysis. #88043 (Max Justus Spransy).
- 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 (Dmitry Novik). - 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 (Dmitry Novik).
- 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 Khuzhin).
- Share the hash join’s
FixedHashMapas the join runtime filter on the probe side. When the build-side hash table is (or can be converted to) aFixedHashMap, it is published as the runtime filter and replaces theSet/BloomFilterthatBuildRuntimeFilterStepwould otherwise install. Controlled by the new settingjoin_runtime_filter_from_fixed_hash_table(defaulttrue). #105640 (Xiaozhe Yu). - Lazy application of selector and replication indexes in case of
JOINfollowed by a selectiveLIMITorTopNor anotherJOIN. To control the number of payload columns for enabling lazy selector indexes use the settingquery_plan_min_columns_for_join_lazy_indexing(0 means the optimization is disabled). To control theLIMITfor which the optimization is applied use the settingquery_plan_max_limit_for_join_lazy_indexing. #106566 (Hechem Selmi). - DP (dynamic programming) JOIN reordering is now allowed with parallel replicas. #105889 (Nikita Taranov).
- 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). - De-virtualize the emission of non-joined rows in RIGHT and FULL join by batching them. #105679 (Hechem Selmi).
- Support packed
keys32andkeys64methods inHashJoin. #107202 (Nikita Taranov). - Support packed
keys32andkeys64methods inSet. #107564 (Nikita Taranov). - More optimal handling of nullable columns in aggregation. #106015 (Nikita Taranov).
- Improve performance of
LIMIT BYqueries. #103349 (Nihal Z. Miaji). - 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 (Nihal Z. Miaji). - 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 (Nihal Z. Miaji). - 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 (Nihal Z. Miaji). - 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 (Nihal Z. Miaji). - Speed up sharded aggregation,
grace_hashjoin bucketing, and parallel window partitioning by replacing per-chunk column hashing with a kernel that uses hardware CRC32C. #106538 (Harikrishnan Prabakaran). - Optimize
L1Distance,L2Distance,L2SquaredDistance,LinfDistance, andcosineDistancefor array arguments with multi-target auto-vectorization on x86-64-v4/v3. For non-const array arguments, all of these exceptLpDistance, which usesstd::powwith a runtime exponent, can now use compiler-vectorized kernels. The existing AVX-512 and Sapphire RapidsBFloat16const-argument fast paths forL2DistanceandcosineDistanceare preserved. #101310 (Peng). - Improved performance of the
{Norm}DistanceanddotProductfunctions. #106007 (Nikita Taranov). - Improved performance of the
arrayNormfunction. #106211 (Nikita Taranov). - The performance of
dotProductimproved in some cases. #106210 (Nikita Taranov). - Improved performance of the AVX-512 const-left paths for
L2DistanceandcosineDistanceonArray(Float32),Array(Float64), andArray(BFloat16)when the array length is exactly divisible by the vectorized processing width. #104625 (Sergey Kuznetsov). - Enabled AVX-512 codegen for amd and better codegen for
arrayDistance. #106505 (Nikita Taranov). - Improved performance of the
L2DistanceTransposedandcosineDistanceTransposedfunctions for theQBitdata type. #106701 (Raufs Dunamalijevs). - 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 (Konstantin Bogdanov). - Improve performance of the
encrypt,decrypt, andhalfMD5functions by avoiding implicit per-row OpenSSL provider lookups in OpenSSL 3.x. #99105 (Konstantin Bogdanov). - Add SIMD implementation of
SHA1that hashes multiple inputs in parallel using AVX-512, improving throughput. #105459 (Joanna Hulboj). - Added an AArch64 ASIMD/NEON backend for the multi-buffer
MD5implementation. #105563 (Venkata Vineel ). - Squash source blocks before calculating projection during
MATERIALIZE PROJECTIONto reduce the number of temporary projection parts and merge overhead. ~3.4x speedup on a 50M-row table. #100047 (Amos Bird). - Reduced
INSERTlatency forMergeTreetables with skip indices onORDER BYcolumns by avoiding redundant column permutations during part writing (~17% on traces-shaped workloads). #101101 (Amos Bird). - Enabled Arrow’s SIMD code paths (NEON on ARM, SSE4.2/AVX2/AVX512 on x86) and used them to speed up decoding of
BYTE_STREAM_SPLIT-encoded ParquetFLOAT/DOUBLEcolumns. #106376 (Raúl Marín). - Improved insertion performance for
LowCardinalitycolumns withbloom_filterindexes. #106410 (Michael Jarrett). - Parallelize blob copies in
DiskObjectStorageTransaction::copyFileusing a per-disk thread pool. #105089 (Asya Shneerson). - Avoid reading file contents when using the
Oneinput format with file-like table functions such asfileands3. #105157 (Yue Ni). - Speed up
clickhousestartup on macOS by about 3x by not exporting dynamic symbols, which the dynamic linker would otherwise process on every launch. #107768 (Raúl Marín). - Speed up filesystem cache loading on startup by avoiding a redundant directory open per cache key. #107414 (Alexey Milovidov).
- Speed up filesystem cache loading on startup by letting directory-listing threads help load cache metadata once listing is finished, instead of leaving half the threads idle. #107416 (Alexey Milovidov).
- Reduced
clickhouseprocess startup overhead by updating the bundled WasmEdge library, which no longer generates a random hash secret in a global initializer at every startup. #107869 (Raúl Marín). - 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). Closes #106264. #106272 (Andy Zhao). - Skip index evaluation on
DateTime64types should consume lesser CPU in 26.6. #107707 (Shankar Iyer). - Improved performance of text index analysis in multi-token searches by optimizing handling of rare tokens. #98226 (Anton Popov).
- Use a cache for the posting-list compressed segments of the text index. #106299 (Anton Popov).
- Improved the performance of generic exclusion search for queries that select large consecutive ranges of the table. #93813 (Michael Jarrett).
S3clients with the same endpoint and bucket share a cache, avoiding duplicate region discovery. Closes #92482. #96802 (Andrey Zvonov).- If a query contains a
has(<constant array>, <expr>), the analyzer will transform the node to use a fasterinimplementation if it is feasible to do so. #97341 (Shankar Iyer). - When a new job is scheduled in
ThreadPool, wake the most recently idle worker thread (LIFO) instead of an arbitrary one. This reduces memory fragmentation from per-thread allocator caches. The order in which jobs are processed is not changed. #100177 (Alexey Milovidov). - Improved performance of approximate runtime filters and bloom filter indexes. #100201 (Christoph Viebig).
- Allow
ASOF JOINto use theparallel_hashjoin algorithm, parallelizing the build across distinct equality-key values. PreviouslyASOFwas unconditionally opted out ofparallel_hash. #105375 (Greg Maher). - Avoid reading unbounded inputs for
INTERSECTandEXCEPTqueries when an empty input makes the result known to be empty. #105393 (Yue Ni). - Add
constinitfor variousMemoryTrackerblockers. #105490 (Azat Khuzhin). - Improve performance of
bitmapContainsfor non-UInt64groupBitmapstates by avoiding repeatedrb_maxcalls during range checks. #105960 (Yue Ni). - Faster discontinuous queries for
LowCardinalitycolumns backed by a single dictionary. #103662 (Ivan Babrou). - Added a fast path for the
HashJoinprobe when the block has a single row. #106008 (Nikita Taranov). - Predicates from queries like
SELECT ... FROM view(SELECT ... FROM remote(...)) WHERE ...are now pushed into the query sent to the remote shard. The optimizationallow_push_predicate_ast_for_distributed_subquerieslacked a case for table functions. #105986 (Nikolai Kochetov). - Turn on
enable_join_transitive_predicatesby default. #103724 (Alexander Gololobov). - 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 (Anton Popov). - 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
MergeTreeread. #105445 (Yarik Briukhovetskyi). - 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 (Han Fei). - Added Keeper setting
nuraft_use_bg_thread_for_snapshot_io, enabled by default, to makeNuRaftread snapshot objects from a background thread instead of Raft worker threads. #106285 (Antonio Andelic). - Reduce peak memory usage when applying received snapshots in ClickHouse Keeper with
KeeperMemoryStorage. #105851 (Antonio Andelic). - Route LLVM/JIT allocations to a dedicated jemalloc arena. Reduces RSS fragmentation caused by interleaving long-lived JIT bookkeeping with short-lived query allocations. Adds new asynchronous metrics
jemalloc.jit_arena.active_bytes,jemalloc.jit_arena.dirty_bytes,CompiledExpressionCacheBytesMax, andCompiledExpressionCacheCountMaxfor observability.SYSTEM DROP COMPILED EXPRESSION CACHEnow also drops the underlying CHJIT instances and purges the JIT arena. #104113 (Raúl Marín). - Fix excessive memory reservation when reading sparse dictionary-encoded
Nullable(String)columns fromParquetwith the native V3 reader. #102805 (Francisco). - Fixed
CREATE TABLE ... CLONE AS (and REPLACE / ATTACH PARTITION ... FROM)on encrypted disks copying data instead of hardlinking it. #106731 (Nikita Mikhaylov). - 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 (Alexander Gololobov). - 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 (Nikita Mikhaylov).
- Remove duplicate calculations during query execution in more scenarios. #106113 (Yarik Briukhovetskyi).
- 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). - Improved the performance of case-insensitive substring search (
positionCaseInsensitiveUTF8,ILIKE,multiSearchAnyCaseInsensitiveUTF8, and related functions) by adding a NEON SIMD path on ARM and a wider AVX2 kernel on x86. #107882 (Raúl Marín). - Fixed a ~16% throughput regression of the
FPCfloating-point codec on ARM that was introduced when its predictor tables started usingVectorWithMemoryTracking. #108182 (Groene AI).
Improvement
- The background
MemoryWorkernow periodically updates the server’s hard memory limit based on the current memory usage and the amount of memory the kernel reports as available, so ClickHouse leaves room for other processes running on the same host. The formula is(resident memory + system MemAvailable) * max_server_memory_usage_to_ram_ratio. The samemax_server_memory_usage_to_ram_ratioserver setting controls both the startup cap and the dynamic adjustment; set it to0to disable both. To keep only the static startup/reload cap (the behavior of previous versions), set the new server settingmemory_worker_dynamic_hard_limitto0. #104964 (Alexey Milovidov). - Support C# PostgreSQL client in
PostgreSQLprotocol. This closes #18611. #80785 (Konstantin Vedernikov). - Mutations now use the analyzer. #98884 (Nikolai Kochetov).
- Added granular control over query echoing in the CLI. The
--echooption now accepts an optional boolean value and works in both interactive and batch mode. New options--echo-formattedand--echo-query-idcontrol whether echoed queries are formatted and whether thequery_idis printed, respectively. The--hilite/--highlightoption now also controls highlighting of echoed queries. As a side effect,--echois now a boolean-value option, so a positional query directly after a bare--echois treated as its value; use--echo --query "..."or--echo=falseinstead. #106191 (Alexey Milovidov). - Support schema evolution together with concurrent consistency checks for data lake catalogs. #106102 (Konstantin Vedernikov).
- Allow cache disk for datalake table engines. #102017 (RinChanNOW).
- 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 (Konstantin Vedernikov). - Update default of
S3(Azure)Queuesettingpersistent_processing_node_ttl_secondsfrom1 hourto6 hours(which stands for cleanup time due to service unclean restart etc). The previous default was fine for processing nodes ttl, but it is also used for bucket lock ttl, which can be hold for longer time, therefore 1 hour was not enough. #106838 (Kseniia Sumarokova). - Decreased the default size of the
Icebergmetadata cache from 1 GB to 128 MB. #106492 (Konstantin Vedernikov). - Propagate the
S3Queuestreaming taskquery_idto dependent table inserts. #106494 (Christoph Wurm). - Populate
used_storagesinsystem.query_logwith the storage engine name when querying tables viaDataLakeCatalog. #100706 (Melvyn Peignon). - You can check which ‘operation’ and what ‘summary’ Iceberg’s snapshots have. Useful for testing and debugging. #106246 (Den Kalantaevskii).
- Complete the final
S3multipart upload request asynchronously via the task tracker, so it can overlap with the last part upload instead of running serially in finalize. #105487 (Asya Shneerson). - Added four new
MergeTreetable 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 (Anton Popov). - Allow projections to override additional
MergeTreesettings (compression, part format, serialization) beyond justindex_granularity, with an allow-list of allowed settings and validation. #101170 (Amos Bird). - Add
current_projection,current_projection_progress,projections_completed, andprojections_remainingcolumns tosystem.mergesto expose projection merge progress. #102611 (Amos Bird). - 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 (Nikita Mikhaylov). - 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 (Raúl Marín). - Add a new keeper-only
system.keeper_snapshotstable with information about local ClickHouse Keeper snapshots. #105571 (Miсhael Stetsyuk). - Add a new keeper-only
system.keeper_changelogstable with information about local ClickHouse Keeper changelog (Raft log) files. #105617 (Miсhael Stetsyuk). - Add a keeper-only
system.keeper_clustertable. Contains one row per Raft cluster member as seen by the current Keeper. #105646 (Miсhael Stetsyuk). - Add more Keeper profile (server-side + client-side) events for watches. Closes #97703. #105336 (Konstantin Vedernikov).
- Added Keeper
coordination_settingsforNuRaftuncommitted log entry admission limiting and append-entries backward-probe throttling. #106108 (Antonio Andelic). - 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 (Bernard Lim). - Reduced cancellation latency for queries running over the PostgreSQL wire protocol:
KILL QUERYnow interrupts output serialization within a single chunk instead of waiting for the entire chunk to be sent to the client. #106535 (Roman Vasin). - Reduced cancellation latency for queries running over the MySQL wire protocol:
KILL QUERYnow interrupts output serialization within a single chunk instead of waiting for the entire chunk to be sent to the client. #107228 (Roman Vasin). - 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).- Send an exception to the client when TCP connection setup fails. #107317 (Nikolai Kochetov).
- Users can now insert
AvroFixedfields for 8-bit/16-bit/32-bit/64-bit integer variants. #98139 (Patrick Pichler). - 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 (Groene AI). - 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 (Alexey Bakharew). - 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 Talluri). - Populate the
ExecutableUserDefinedFunction*ProfileEventscounters forexecutable_poolUDFs. Per-call invocation count, wall and pool-wait time, child-process CPU and peak memory, and stdin/stdout bytes are now visible insystem.query_log.ProfileEvents. #105010 (Xu Jia) #105618 (Ilya Andreev). - 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 (Hanzi Jiang). - Added three Linux-only async metrics —
MemoryThreadStacksCount,MemoryThreadStacksVirtual, andMemoryThreadStacksResident— that report pthread stack memory separately from the rest of anonymous memory. Enabled viaasynchronous_metrics_enable_heavy_metrics. Requires Linux 5.17+ (prctl(PR_SET_VMA_ANON_NAME)) and readable/proc/self/smaps; otherwise the metrics are absent and the limitation is reported insystem.warnings. #106230 (Raúl Marín). - Expose the
MemoryThreadStacks*asynchronous metrics (resident/virtual size and count of thread stacks) on macOS. #107752 (Raúl Marín). - 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 the
--chimecommand-line option toclickhouse-client,clickhouse-local, and the embedded client. When a query finishes (on success or on error) after running for at least N seconds, the client writes the ASCIIBELcontrol character (\x07) to stderr. Terminals decide whether to make a sound or a visual flash based on the user’s preferences. Enabled by default with a 5-second threshold; pass--chime Nfor a custom threshold or--chime 0to disable. Closes #92718. #104545 (Groene AI). - In
clickhouse-client, when the terminal does not support bracketed paste, embedded newlines from a pasted multi-line query are now folded into the same edit buffer instead of switching to the continuation prompt for every line. The pasted query stays under a single prompt and the arrow keys navigate across its lines. This is a best-effort improvement that relies on the typical TTY-buffered paste behavior. #104299 (Alexey Milovidov). Now also works with syntax highlighting disabled (--highlight 0). #106665 (Alexey Milovidov). - Add MySQL-style runtime pager control for
clickhouse-client/clickhouse-local. #105706 (Azat Khuzhin). clickhouse-clientnow respects non-UTF-8 terminals: when the terminal character encoding is not UTF-8 (e.g. withLANG=C), thePrettyformats fall back to ASCII grid borders instead of printing Unicode box-drawing characters that would corrupt the terminal. #106213 (Alexey Milovidov).- Sanitize server-supplied display strings in
clickhouse-client’sHellopacket handling (server name, time zone, display name, password-rule patterns and messages) so a hostile server cannot inject bytes that the client renders verbatim, and cap their size to defend against unbounded allocation. #105243 (Raúl Marín). - The Web UI now displays the result as an image when a query uses an image output format such as
FORMAT PNG, instead of showing the raw bytes as a table. #107638 (Alexey Milovidov). - 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 (Ashrith Bandla). - The universal install script now also installs
clickhousectlinto~/.local/binon Linux and macOS, with achctlsymlink. SetCLICKHOUSE_ONLY=1to skip. #105399 (Alasdair Brown). - Fixed a spurious
Syntax error: Unterminated quoted stringthat could occur intermittently when installing ClickHouse viacurl https://clickhouse.com/ | shwhile aclickhousebinary already existed in the current directory. #106417 (Alexey Milovidov). - Fix the left panel height on the
play.htmlpage when the web terminal is open, so the terminal toggle button at the bottom stays visible. #105087 (Alexey Milovidov). - Avoid selecting the only query in the Web UI after running it. #105711 (Joey Yu).
- The Web SQL UI now expands the query editor when a query is at most 30% taller than the current editor height. #105713 (Joey Yu).
- In the Web UI, lay out the bottom menu icons (Web Terminal and GitHub) horizontally when the left panel is expanded, giving the list of databases and tables more vertical space. #106427 (Alexey Milovidov).
- In the Web UI (
play.html), pressingEscapenow deactivates the currently selected result-table cell. #107777 (Alexey Milovidov). - Improvements to the database panel in the Web SQL UI (Play): a tooltip on the database icon, a button to hide the panel, full-width clickable database/table names, and a fix for the panel width shifting when the scrollbar appears. #108013 (Alexey Milovidov).
- Add a server setting (
min_allocation_size_to_throw_on_memory_limit) to allow any allocation to throwMEMORY_LIMIT_EXCEEDED, this should help with preventing OOMs. #105265 (Azat Khuzhin). - Allow
NONEauthentication for SSH (prevents asking password forno_passwordusers). #105476 (Azat Khuzhin). - Reset the supplementary group list in
clickhouse subefore dropping privileges, matching the behavior of/bin/suandsudo. Previously the dropped process inherited the invoker’s supplementary groups. #105247 (Raúl Marín). - Add
BFloat16support for numeric predicate (isFinite,isNaN) functions. #105391 (Mohamed Hussain S). - Reduce memory usage of polygon dictionaries (
polygon_index_cell,polygon_index_each) and makesystem.dictionaries.bytes_allocatedcorrectly reflect the lookup index they build. #105431 (Raúl Marín). - 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). - 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 (János Benjamin Antal).
- ClickHouse throws a proper exception for attempts to use
table_readonlyfor replicated engines, with better exception handling for DDL queries (andDatabaseReplicated) related to this setting. #100950 (alesapin).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. Follow-up to #97652. #105109 (Alexey Milovidov). - Fixed refreshable materialized view refreshes that could fail with
UNKNOWN_TABLEafter the target table had been replaced (for example viaEXCHANGE TABLESor drop-and-recreate): the refresh now resolves the target table by name instead of relying on a stale UUID. #102724 (Seva Potapov). - Added a setting
wait_for_part_commit_in_dependent_materialized_views(defaultfalse). When a materialized view’sSELECTreads back from its own source table (for example via anINNER JOINto the source), the cascade could miss the row currently being inserted, because the inserted part is committed only after the dependent views run. Enabling this setting commits the part before the dependent views are triggered, so they observe the in-flight row, at the cost of less insert parallelism. #105943 (Elmi Ahmadov). - Do not swallow fatal errors (e.g.
MEMORY_LIMIT_EXCEEDED) intryDeserialize. #106808 (Azat Khuzhin). - Check
CREATE TEMPORARY TABLEgrant lazily inInverseDictionaryLookupPass. #107098 (Azat Khuzhin). - 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). - 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. Closes #106899. #107185 (Nihal Z. Miaji). - Preserve original error codes for exceptions wrapped in
arrow::Status. #107267 (Azat Khuzhin). - 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 (Maxim Orlovsky).
- 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 (Sema Checherinda). - Filesystem cache improvement: stop invalidated priority entries from pinning
KeyMetadata. Follow up to #106387. #107903 (Kseniia Sumarokova). FileCachemetrics improvement. #106116 (Kseniia Sumarokova).- 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).
- Fix a potential overflow in
roundUpToMultiplewhen computing filesystem cache boundary alignment for very large offsets. #92579 (Bharat Nallan). EXPLAIN SYNTAXnow formats operators as function calls consistently in explain output (for exampleplus(1, 2)instead of1 + 2). #94681 (Mohamed Abdelhalim ).- 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 (Mathuranath Metivier). - Improved error message for unresolved identifiers in queries without a
FROMclause to suggest adding one. #101769 (Yash ). - Add
EXPLAIN PIPELINEoption to compact repeated processor chains. #104662 (Yue Ni). - Fix a heap-buffer-overflow read in syntax-error message construction (
UTF8::computeWidthImplviaparseQuery.cpp) that occurred when the parser had backtracked past the first semicolon / end-of-stream token; release builds were splicing bytes from neighboring heap memory into the displayed error, ASan builds aborted. #105086 (Groene AI). - Make hive partition strategy a default under compatibility setting
file_like_engine_default_partition_strategy. #86746 (Kseniia Sumarokova). - Use a larger (8 MiB) thread stack on macOS to match the Linux default, fixing rare server crashes from stack overflow during JIT compilation. #107033 (Raúl Marín).
- The temporary storage size limit of
clickhouse-localis no longer hard-coded to 1 GiB. The default is raised to 1 TiB and can be configured with themax_temporary_data_on_disk_sizeserver setting. #106689 (Alexey Milovidov). - Add
read-checksumscommand toclickhouse-disks. It reads thechecksums.txtfile of aMergeTreeDataPartand prints it as a human-readable, tab-separated table. #106901 (Asya Shneerson). - Added a
read-bitmapcommand toclickhouse-disks. #107834 (murphy-4o). - Chdig: enable TLS for secure connections (previous leads to either “unknown setting
skip_verify” or “connection reset by peer”). #105864 (Azat Khuzhin). chdigv26.5.1. #105918 (Azat Khuzhin).chdigv26.6.1 -{asynchronous_,}metric_log, query patterns, heatmaps, logs/traces stored on disk (previously it can use >40GiB for 1 hour of traces). #107678 (Azat Khuzhin).- The server config (
programs/server/config.xml) now setskeep_alive_timeoutto 30 (formerly 10), aligning with the actual documented and implemented default. #107779 (Dan Checkoway). - The default for the server setting
disk_connections_rcvbufchanged from0(kernel TCP autotuning) to204800(200 KB), capping the per-socket TCP receive buffer for object-storage (S3/Azure/GCS) disk connections. #107859 (Sema Checherinda). - The
PREWHEREoptimizer now groups conjuncts that reference the same column set before estimating selectivity, so that conditions likea > 2500 AND a < 2502are evaluated together as a combined range rather than as two independent predicates, producing a more accurate selectivity estimate. #106337 (Han Fei). - Add silk fiber aware secure and plain socket implementations. #107680 (Miсhael Stetsyuk).
- Fixed a garbled error message (swapped arguments) and a typo in the
nestedfunction. #108031 (Alexey Milovidov). - Added a
sedcommand toclickhouse-disksthat applies a sed expression to a given path, in-place. #107131 (Asya Shneerson). - 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. #107428 (Alexey Milovidov).
Bug Fix (user-visible misbehavior in an official stable release)
- Make possible to drop detached parts with the
tryNsuffix. #58957 (János Benjamin Antal). - 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). - Fix a bug with
splitMultipartQuerythrowing an “Empty query” error for queries that end with comment after semicolon. #85491 (Yarik Briukhovetskyi). - Fix an exception with
ARRAY JOINs:Function writeSlice expects same column types for GenericArraySlice and GenericArraySinkwhich happens whenLowCardinalitynumeric types are used (issue #57243). #91784 (Jimmy Aguilar Mena). - Fix
NOT_FOUND_COLUMN_IN_BLOCKexception when usingLIMIT BYwith constant columns alongsideDISTINCTandORDER BYwith the new analyzer. #93195 (Ashrith Bandla). - Fix
NOT NULLcolumns being silently created asNullablewhendata_type_default_nullable = 1and the table is created in aReplicateddatabase or viaON CLUSTER. #97572 (xiaohuanlin). - Fixed HiveCatalog connection stability by adding automatic retry mechanism and reconnection logic for handling TTransportException errors when communicating with Hive Metastore. #98471 (Dmitriy Borisenko).
- Fixed
nestedfunction (used internally byARRAY JOIN) strippingLowCardinalityfrom column types, causingArray(LowCardinality(String))to becomeArray(String)in output. Closes #95582. #98974 (Yash ). - 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). - Fix logical error exception when reading Iceberg tables whose format version was upgraded by an external tool (e.g. Spark). #100407 (Alexey Milovidov).
- Functions
like,ilike,notLike,notILike, andmatchnow support constant haystack with non-constant needle (e.g.'foo' LIKE pattern_column), which previously threwILLEGAL_COLUMN. #100479 (Yash ). - Fixed wrong row count returned by a
MaterializedViewquery withquery_plan_enable_optimizations = 0when the view maps an integer column to aBoolcolumn. #100692 (Maksim Moisiuk). - 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 (Groene AI). - Fix race in RestCatalog. #101216 (Smita Kulkarni).
- Fix
NOT_FOUND_COLUMN_IN_BLOCKerror when selecting from a VIEW over a table with a normal projection. #101218 (Amos Bird). - Fix stale metadata in FileLog when a file is deleted and recreated. #101408 (Azat Khuzhin).
- 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 (Groene AI). - Fixed
FORMATclause being consumed byINSERTinstead of applying toEXPLAINoutput inEXPLAIN INSERT INTO ... SELECT ... FORMAT .... #101772 (Yash ). - 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 (Yash ). - Reject negative
Float64values (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. Closes #101825. #101842 (Groene AI). - 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 (Jimmy Aguilar Mena). - Fix inconsistent part metadata after mutations of columns with non-default serializations. #102817 (Eduard Karacharov).
- Fix updating metadata before executing mutation resolves #96806. #102882 (Smita Kulkarni).
- 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
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(...)). Closes #105356. #102942 (Nihal Z. Miaji). - Throw
INCORRECT_DATAinstead ofLOGICAL_ERRORwhen client-supplied data in the Native format is truncated or malformed. #102975 (János Benjamin Antal). - Added cancellation check to ObjectStorage read operation. Closes #98165. #103016 (Smita Kulkarni).
- Respect
input_format_binary_max_type_complexityin decoding aggregate function parameters. Closes #102903. #103026 (Pavel Kruglov). - Fix nullable inference for geo columns in Arrow-based Parquet reader. Closes #101845. #103032 (Pavel Kruglov).
- Fixed
recursiveRemoveLowCardinalityerasing custom geometry type names (e.g.LineStringvsRing,MultiLineStringvsPolygon), which caused misinterpretation of the geometry type. Closes #103207. #103041 (Joanna Hulboj). - 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 (Kirill Kopnev). - Fixed ClickHouse occasionally producing invalid GSSAPI tokens due to incorrect stripping of trailing null bytes. #103114 (Michael Jarrett).
- 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 (Peng). EXPLAIN SYNTAXexpands parameterized views. #103263 (Jordi Villar).- 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - Fixed a server abort when creating a table with an object-storage engine (
AzureBlobStorage,DeltaLakeAzure,S3,HDFS) using an unsupported number of arguments. The server now returns a cleanNUMBER_OF_ARGUMENTS_DOESNT_MATCHerror instead of aborting in debug/sanitizer builds. #103544 (Groene AI). - Fix a server crash in
JSONandDynamicdata type parameter parsing when the abstract syntax tree (AST) was structurally malformed (for example produced by the AST fuzzer): theequals(name, value)parameter expression could be left with fewer than two children, whichDataTypeObjectandDataTypeDynamicthen dereferenced without bounds checking. #103545 (Groene AI). - Fix logical errors in analyzer with column names collision in lambda used in prewhere. Closes #103584. #103627 (Pavel Kruglov).
- Fix sporadic
Logical error: 'Database <name> not found'fromDataLakeConfiguration::getCatalogwhen anIcebergengine table is loaded inside a regular database during async metadata loading. #103775 (Groene AI). - 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. Closes #74324. #103806 (Groene AI). - 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 (Groene AI). - 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. Closes #103333. #104119 (Groene AI). - 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 (DQ). - Fix a crash (
LOGICAL_ERROR“Columns are assumed to be of identical types, but they are different in Nullable” in debug builds, aColumnString::compareAtnull-pointer SIGSEGV in release builds) and a wrong result that could occur in queries usingdirectjoin_algorithmwith aMergeTreeright-side table when the lookup plan reordered columns during optimization. The right-side columns could land in wrong-named slots, so a filter or comparison on the join key saw a column of the wrong type. Surfaced by AST fuzzer as STID 2139-5111 and reported in #107272. #104174 (Groene AI). - Reject out-of-range integer partition ID for
Dateinstead of silent overflow orLOGICAL_ERRORonALTER. #104250 (Azat Khuzhin). - Disable
additional_table_filterswith parallel replicas and the analyzer without query plan serialization. Previously it could lead to incorrect results. #104296 (Azat Khuzhin). - 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. Closes #73633. #104327 (Groene AI). - 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. Closes #93132. Closes #102103. #104353 (Groene AI). - 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). - 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. Closes #82279. #104558 (Groene AI). - Fix a rare server abort during
MergeTreefamily table destruction. The abort could occur whenshutdownraised an exception before the background-job scheduler was fully stopped: a background task firing in that narrow window would dispatch a virtual call through a partially-destroyed storage object and hit__cxa_pure_virtual. #104561 (Groene AI). - Fix inconsistent result in
JSONcombined subcolumn with a type hint containing null value. #104584 (Pavel Kruglov). - Fix wrong results or missed projection when an aggregate projection contains multiple
sumIfaggregates with differentIN (...)conditions. #104765 (Jimmy Aguilar Mena). - Fix wrong row count from
arrayJoin()used insideJOIN ON: the result was multiplied by the array length an extra time. #104785 (Shaohua Wang). - Fix
deltaSumTimestampreturning wrong results for signed integer types crossing zero. Resolves #104750. #104830 (Konstantin Bogdanov). - Fix block structure mismatch in UnionStep after filter push-down with NULL constants. Closes #104821. #104853 (Pavel Kruglov).
- 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. Closes #104891. #104917 (Groene AI). - Fixed the
max_memory_usage_soft_limitwas not updated on-the-fly when the configuration changed. The soft memory limit was calculated once at startup and cached, so subsequent config reloads had no effect. After this fix, the limit is recalculated and applied immediately on every config reload, no Keeper restart required. #104940 (Kai Zhu). - Fix JIT symbol resolution on macOS so that sort, expression, and aggregate JIT compilation no longer fail with
CANNOT_COMPILE_CODE: Could not find symbol _<name>. #104946 (Alexei Fedotov). - Fix an exception (
Received signal 6 (abort)in vector hardening, observable asTuple::back()on an empty vector) when executing a query of the formSELECT ... FROM <Distributed table> WHERE/HAVING/GROUP BY ... (sharding_key_column IN tuple())withoptimize_skip_unused_shards_rewrite_inenabled under the new analyzer. #104966 (Alexey Milovidov). - Fix a
Logical error: 'Inconsistent AST formatting'server abort (STID 1941-1bfa) on queries likeCREATE TABLE t (c0 Int CODEC(not((not(materialize(1), materialize(2)))), ZSTD)) ENGINE = Memoryin debug / sanitiser builds. The formatter no longer emits redundant outer parens around a multi-argumenttuple(...)function call that appears insideCODEC/STATISTICS/BACKUP_NAMEargument lists (where the operator form(a, b)is disabled), keeping the format-parse-format round-trip stable. #104991 (Groene AI). - 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. Closes #104872. #105039 (Groene AI). - 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. Closes #101940, closes #102320. #105041 (Dmitry Novik). - Fix
countminstatisticsPREWHEREselectivity estimation forFloat32columns. Two bugs causedcountminstatistics to silently produce wrong estimates forFloat32columns:ConditionSelectivityEstimatorskipped statistics entirely when the column type (Float32) was narrower than the literal type (Float64), falling back to default selectivity and ignoring the sketch; andStatisticsCountMinSketch::estimateEqualhashed the first N bytes of aFieldobject, butFieldstoresFloat32asFloat64(NearestFieldType<Float32>=Float64), so the byte pattern used at query time differed from the actualFloat32bytes stored during build. #105047 (Han Fei). 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 (Groene AI).- Fixes a use-after-free in
runningAccumulatewhen called on a column whose aggregate function returns its own state (e.g.uniqStateOrDefaultState,sumStateOrDefaultState,uniqStateForEachState). #105085 (János Benjamin Antal). - Fixed a bug in the Web UI (
play.html): running a query while the cursor was past the only trailing;reported “empty query” instead of running the query. #105107 (Alexey Milovidov). - Fix
LOGICAL_ERROR: 'No user in current context, it's a bug'when aCREATE TABLE ... AS SELECTinside aReplicateddatabase reads fromsystem.current_rolesorsystem.enabled_roles. The query now succeeds and returns an empty result set in this internal DDL worker context. #105150 (Groene AI). - 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 (Groene AI). - 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 (Yarik Briukhovetskyi). - 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 (Groene AI). - Query can be executed successfully even if
FileCachefails to create some directory on disk for caching. #105250 (Den Kalantaevskii). - Fix server abort with
Assertion 'px != 0' failedinExtremesTransformwhen a query withextremes = 1hits an exception (for exampleMEMORY_LIMIT_EXCEEDED) while the transform is building its extremes columns from the first chunk. The client now receives the original exception instead of crashing the server. #105264 (Groene AI). LEFT ANTI JOINnow correctly returns the right-side join key column with default values for unmatched rows, instead of duplicating the left key value. Previously,SELECT a.x AS l, b.x AS r FROM a LEFT ANTI JOIN b ON a.x = b.xcould returnr = a.xfor the unmatched rows when it should return the default (0forInt32,''forString,NULLforNullable). Only the join key column was affected; non-key right columns were already defaulted correctly. The same bug appeared inRIGHT ANTI JOINwhenever the optimizer swapped sides. Closes #99959. #105278 (Groene AI).- Fix data loss in
clickhouse-localwhen started repeatedly with a non-default--default_database(for exampleclickhouse-local --path X -- --default_database=mydb): the lookup for the persisted database UUID was hardcoded tometadata/default, so each restart minted a fresh UUID and the previous run’s tables became invisible. Closes #101831. #105284 (Groene AI). - Fix a logical error
Mutation ofMemorytable produced incomplete outputraised when runningALTER TABLE <memory_table> APPLY PATCHESorALTER 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 (Groene AI). - Fix long-running queries with Unity Catalog by passing a
table_idparameter in the query request. #105303 (Konstantin Vedernikov). - Fix
CANNOT_CONVERT_TYPEforMergeoverMergeoverDistributedwithdistributed_group_by_no_merge=1. #105330 (Azat Khuzhin). - Fix
clickhouse localandclickhouse clientsilently ignoring--query/-qwhen a positional file argument was also given. Both forms now produceBAD_ARGUMENTSconsistently. #105334 (Raúl Marín). - Fix
REPLACE TEMPORARY TABLEsilently creating a new table when the target didn’t exist. It now throwsUNKNOWN_TABLE, matchingREPLACE TABLEsemantics. UseCREATE OR REPLACE TEMPORARY TABLEto keep the create-or-replace behavior. #105373 (Groene AI). - Fixed long-running reads (e.g.
INSERT ... SELECT) from aDataLakeCatalogdatabase withcatalog_type = 'glue'failing with anExpiredTokenerror once the STS session credentials captured at table-metadata load time crossed their expiry. The AWS STS credentials are now refreshed mid-query, so such reads continue past the token’s expiry. #105381 (Pratima Patel). - Fix logical error in negative
LIMIT BYin some cases when used withARRAY JOIN. #105403 (Nihal Z. Miaji). - 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 (Groene AI). - Fixed a possible server segfault in cluster table functions (
s3Cluster,urlCluster,fileCluster, …) when the planner produces aSELECTwith therecursive_withflag set but noWITHexpression. Closes #105370. #105433 (Groene AI). - Fix wrong result of
countDistinct/uniqExactonNullablecolumns whencount_distinct_optimization = 1(the NULL group was incorrectly counted). #105439 (Raúl Marín). - 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 (Raúl Marín).
- Validate
Dynamic/Varianttypes in windowPARTITION BY, it was not checked before whenallow_suspicious_types_in_group_byis disabled. Closes #105028. #105450 (Pavel Kruglov). - Fix
input_format_json_empty_as_defaultnot working in JSONStrings* formats. Closes #104913. #105453 (Pavel Kruglov). - Fix
NULLinsert intoVariantcolumn viaVALUESformat during expression parsing. Closes #104909. #105455 (Pavel Kruglov). - Fix
dictGetOrDefaultthrowingCANNOT_INSERT_NULL_IN_ORDINARY_COLUMNwhen the default argument is aNullableexpression andshort_circuit_function_evaluationis enabled with a mix of found and not-found dictionary keys. #105461 (Raúl Marín). - Fix silent value truncation in
Dynamiccolumns when theQuoted(Values) text reader falls back toStringfor incomplete inferred types likeMap(Array(Nothing), ...). Previously the fallback wrapped the raw field with naive'...'concatenation, so an inner single quote (always present for such fallbacks) prematurely terminated the quoted string and the rest of the value was lost. #105463 (Groene AI). - Fix SIGSEGV when reading
Dynamicsubcolumns from compressedMemorytable afterALTER. Closes #104901. #105464 (Pavel Kruglov). - Fix
toFloat64/toUInt32/toString/etc. onDynamicignoringcast_keep_nullable. Closes #104789. #105467 (Pavel Kruglov). - Include
skip_first_linesin schema cache key forWithNamesformats. Closes #104527. #105469 (Pavel Kruglov). - 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 (Groene AI). - Fix
NOT_FOUND_COLUMN_IN_BLOCKexception when combiningORDER BY ... WITH FILL INTERPOLATEandLIMIT N BYwith the analyzer enabled. Closes #103474. #105481 (Yakov Olkhovskiy). - Fix
toStartOfMillisecondandtoStartOfMicrosecondreturning a result off by nearly a second for negative (pre-epoch)DateTime64values, and fixUndefinedBehaviorSanitizersigned-integer-overflow intoStartOfSecond,toStartOfMillisecond, andtoStartOfMicrosecondforDateTime64inputs nearINT64_MIN. #105482 (Groene AI). - Add a new compatibility setting
analyzer_compatibility_prefer_alias_over_subcolumn(disabled by default). When enabled, the new analyzer prefers the alias-prefix interpretation overTuple-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 (Vladimir Cherkasov). - A vector search query executed with the index only optimization now returns the correct value for
L2Distance()if it is in theSELECTlist. The function was incorrectly returning the L2-squared distance value. Note that the vector search query was returning the correctly ranked results, only applications explicitly retrieving and interpreting theL2Distance()value would have seen the squared value. #105495 (Shankar Iyer). - Fixed a rare issue in new Kafka table engine where messages could be incorrectly handled during topic partition reassignment, potentially leading to skipped messages after offset rollback. #105500 (János Benjamin Antal).
- Fix an 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 (Groene AI). - Fix stdout/stdin compression not applied when format is explicitly specified. Closes #104441. #105528 (Pavel Kruglov).
- Fix SEGFAULT in
singleValueOrNulldeserialization forJSONtype. Closes #103630. #105535 (Pavel Kruglov). - Fix
clickhouse-format --backslashsilently droppingINSERTVALUESdata. Closes #103533. #105536 (Pavel Kruglov). - Fix
variant_throw_on_type_mismatch/dynamic_throw_on_type_mismatch=falsenot catching exceptions during function execution. Closes #103484. #105543 (Pavel Kruglov). - Fix ignoring
input_format_try_infer_datetimesduring insertion into shared data inJSON. Closes #103221. #105544 (Pavel Kruglov). - Fix
histogramproducing wrong results for small unsorted inputs. Closes #103109. #105548 (Pavel Kruglov). - Fix
DateTimewrapping around for out-of-range values inJSONExtractand text deserializations. Closes #103094. #105551 (Pavel Kruglov). - Fix usage of insertion table in table functions when
optimize_trivial_insert_selectis enabled. Closes #103083. #105555 (Pavel Kruglov). - Fix
CASEexpression returning theELSEbranch instead of the matchingTHENwhen both the expression and aWHENvalue wereNULL. #105556 (Raúl Marín). - Fixed a crash in
replxxcaused by hitting theFD_SETSIZElimitation ofselect(now replaced withpoll). Previously, with SSH or the web terminal enabled, this could crash the server. #105559 (Azat Khuzhin). - Materialize subcolumns in
executePartitionByExpressionbefore executing expression. Closes #103057. #105573 (Pavel Kruglov). - Fix
NOT_FOUND_COLUMN_IN_BLOCKexception whenTTLexpression references a subcolumn. #105578 (Pavel Kruglov). - 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 (Groene AI). - Fix
estimateCompressionRatiowindow function losing accumulated data between rows. Closes #101738. #105581 (Pavel Kruglov). - Fix crash when inserting tuples of different sizes in the same VALUES clause into a
Stringcolumn. Closes #101727. #105582 (Pavel Kruglov). - 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). - Fixes
NOT_IMPLEMENTEDerror ontoStringfromDateTimewith Timezone containingNULLvalue. Closes #103712. #105587 (Yarik Briukhovetskyi). - Fix OOB read in flattened
DynamiccolumnNativedeserialization. #105666 (Pavel Kruglov). - 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. Closes #105649. #105680 (Groene AI). - 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 (Groene AI). - 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. #104781. #105686 (Groene AI). - Fixed
singleValueOrNullMergereturning a concrete value instead ofNULLwhen merging a state that had already observed multiple distinct values. #105734 (Minh Vu). - Fix
Templateinput format error recovery after malformed rows. #105735 (Yue Ni). - Fix a crash in the
mongodbtable function, MongoDB storage and MongoDB dictionary source when the collection name is empty or contains NUL bytes. #105776 (Raúl Marín). - Fix
Keepersnapshot cleanup after failed writes so partial snapshots are cleaned up safely and failed writes can be retried without advancinglatest_snapshot_meta. #105779 (Antonio Andelic). - Fix
ALTER TABLE ... CLEAR COLUMNbeing rejected for explicitSummingMergeTreeandCoalescingMergeTreecolumns_to_sumcolumns. #105785 (Antonio Andelic). - Fixed an assertion in
DatabaseCatalog::tryGetDatabase(and resultingUNKNOWN_DATABASEerror in release builds) when creating a parameterized view whose database name is supplied via a query parameter, for exampleCREATE VIEW {db:Identifier}.v AS SELECT {p:UInt64}. Parameters in the DDL parts of theCREATEstatement are now substituted at create time, while parameters in the SELECT body remain available for substitution at view-call time. #105799 (Groene AI). - 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 (Groene AI). - 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 (Raúl Marín). - 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. Closes #105852. #105862 (Groene AI). - Fixed
ParquetandORCfilter pushdown forIN (subquery)predicates, allowing row-group/page/bloom-filter pruning to work forfile,url,s3, and object-storage reads. #105863 (Arsen Muk). - Fix read-in-order for
Mergetables (with a new analyzer). #105867 (Nikolai Kochetov). - Fixed Iceberg v2 merge-on-read position deletes returning wrong rows when a single delete file references multiple data files and several such delete files apply to the same data file. The streaming reader (
use_roaring_bitmap_iceberg_positional_deletes = 0) now filters delete-file rows byfile_pathin C++ instead of relying on Parquet row-group pruning, restoring the ascending-positions invariant. #105888 (Groene AI). - Fix
Cannot find columnerror for distributed queries withIN Array(...)filter for the new analyzer. #105894 (Nikolai Kochetov). - Fix a SIGSEGV in
ALTER TABLE ... MODIFY COLUMN ... Nullable(...)onMergeTreetables when a column withSTATISTICSis concurrently dropped by anotherALTER. Closes #105912. #105917 (Groene AI). - 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 (Rory Shanks).
- 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 (Pablo Marcos). - 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 (Vladimir Cherkasov).
- Fixed a possible crash due to a too-large string literal sent within the query. #105996 (Nikita Taranov).
- 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). - Fix
ALTER TABLEpartition operations silently failing forBoolpartition keys. Closes #101722. #106004 (Pavel Kruglov). - Fix
JSONExtractRawandJSONHasfor typedJSONpaths with default values. Closes #101721. #106005 (Pavel Kruglov). - Fix incorrect ’/‘-prefix addition on empty basepaths in data lake configurations. Closes #105989. #106013 (thewisenerd).
- 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 (Groene AI). - Fix
Keeperfailures during follower catch-up when the new request dispatcher response queue could fill before the response thread started. #106049 (Antonio Andelic). - 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 (Nikolai Kochetov). - 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).
- Fix
system.dictionariesreturning 0 rows with partialSHOW DICTIONARIESrevoke. #106105 (Pavel Kruglov). - 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 (Raúl Marín). - 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. Closes #106084. Closes #106124. Closes #106080. #106136 (Nihal Z. Miaji). - Fix support for using
WASMSQL UDFs inMATERIALIZED VIEWdefinitions. #106161 (Yue Ni). - 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 (Groene AI). - Fix clickhouse local’s
--query_idparameter to allow it to specify custom query id. #106205 (Yue Ni). - 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 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 ofappend_entriesrequests). #106220 (Michael Kolupaev). - Validate corrupted
DDSketchaggregate-function state (bin keys) on insertion instead of accepting malformed data. #106236 (Yarik Briukhovetskyi). - Fixed coordinator mode mismatch when subqueries override in-order settings. #106243 (Nikita Taranov).
- Fix
optimize_skip_unused_shardsdid not apply (andforce_optimize_skip_unused_shardsfalsely failing) when aDistributedtable is queried through aMergetable or themergetable function, with the predicate applied above it. #106250 (Nikolai Kochetov). - Fix
INTERPOLATE ()throwingINVALID_WITH_FILL_EXPRESSIONwhenORDER BYcolumns are aliased in theSELECTlist with the old analyzer. Closes #106248. #106252 (Yakov Olkhovskiy). - Fixed an abort when deserialising a malformed
AggregateFunction(uniqTheta, ...)state fromRowBinaryinput or a query parameter. The bad input is now rejected withCORRUPTED_DATAinstead of escaping as astd::exceptionand aborting the process viaabortOnFailedAssertion. #106260 (Groene AI). - 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 (Groene AI). - Fix
SLRUdowngrade failure rollback issue in26.1+. FixSystem/Datacache split priority withkeep_free_space_ratiofeature. #106286 (Kseniia Sumarokova). - Read the
nullsubcolumn as aJSONpath inNullable(JSON)instead of the null-map. Closes #106085. #106295 (Pavel Kruglov). - Fix
RestCatalog::emptyreturning the wrong result when an Iceberg REST catalog contains tables. #106301 (Lefteris). - 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 (Nikolai Kochetov). - 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 (Joanna Hulboj). - Fix a crash and a possible
NOT_FOUND_COLUMN_IN_BLOCKerror when constraint-based optimization (optimize_using_constraints) is used with correlated subqueries. #106349 (Raúl Marín). - Fixed an out-of-bounds read in
sipHash64Keyed,sipHash128KeyedandsipHash128ReferenceKeyedwhen hashing a column whose arrays are all empty and the key is not constant. #106355 (Raúl Marín). - 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 (Julia Kartseva). - 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 (Groene AI). - Fix
LOGICAL_ERRORexception during cache predownload when a remote S3 object is overwritten with shorter content between listing and reading. #106375 (Nikita Fomichev). - Fix memory usage growth in filesystem cache. #106387 (Kseniia Sumarokova).
- 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 (Raúl Marín). - Fixed backups failing with
FILE_DOESNT_EXISTwhen 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 (Julia Kartseva). - 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 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 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). - 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). - 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 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 (Vladimir Cherkasov). - 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 (Shaohua Wang). - Allows user to specify headers for
HTTPDictionaryusing named collections. #106459 (Jan Rada). - Fix a case where a worker thread could stay attached to a stale thread group after
CurrentThread::attachToGroupfailed part way through, causing later tasks on the same thread to fail withThread is already attached to a group. #106462 (Mikhail f. Shiryaev). - 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). - Malformed
Avroenum values are now validated and rejected with an error instead of causing an out-of-bounds read and abort when deserializing corruptedAvrodata. #106476 (Miсhael Stetsyuk). - 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 (Pedro Ferreira). - 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 (Vladimir Cherkasov). - 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 (Groene AI). - 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 (Nihal Z. Miaji). - 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 (Nihal Z. Miaji). - 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 (Groene AI). - 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 (Yarik Briukhovetskyi). - Fix exception
Mutation ofMemorytable produced incomplete outputraised when runningALTER TABLE <memory_table>commands that have no per-row data effect on aMemoryengine, namelyAPPLY PATCHES,APPLY DELETED MASK,MATERIALIZE STATISTICS,MATERIALIZE INDEX,MATERIALIZE PROJECTION, andREWRITE PARTS.Memorytables do not own those structures, so such commands are now treated as no-ops. #106621 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 crashing the server with a stack overflow. #106676 (Groene AI). - Fix server abort
Bad cast from type DB::ColumnNothing to DB::ColumnVector<char8_t>inFunctionIf::executeForConstAndNullableConditionwhen theif/multiIfcondition constant-folds toConst(Nullable(Nothing))(for example, an out-of-range subscript on an empty array, likearraySort(x -> x, [])[toNullable(1)]). #106678 (Groene AI). - 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 (Groene AI). - Make
FORMATapply to theEXPLAINoutput ofEXPLAIN ... INSERT ... SELECT ... FORMAT ...also whenSETTINGSprecede theFORMATor the output format isValues. Follow-up to #101772. #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). - Fix a race between destroying
INATSConsumerobjects and callingINATSConsumer::onMsgon them via callbacks in the NATS library. #106692 (Miсhael Stetsyuk). - Fixed
match,extract,extractAllandcountMatchesreturning wrong results for regular expressions containing hex or octal escapes. #106709 (ofeliacode). - 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 (Antonio Andelic). - Fix logical error in startup scripts in
SYSTEM RELOAD CONFIG. Additionally, load startup scripts onSYSTEM RELOAD CONFIG(currently private-only functionality). #106727 (Miсhael Stetsyuk). - 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 (Nikita Fomichev). - 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 (Raúl Marín). - 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 (Raúl Marín). - Reject
CREATE TABLE,ALTER TABLE ADD INDEX, andCREATE INDEXwithGRANULARITY 0for skipping indexes with a clearBAD_ARGUMENTSerror. Previously this triggered anInconsistent AST formattingexception in debug builds. #106783 (Groene AI). - Fixed Azure BACKUP/RESTORE ignoring endpoint settings for legacy-form
azure_blob_storagedisks. #106784 (Julia Kartseva). - Fixed a
Bad castexception while pruning parts byMinMaxstatistics when a key column isLowCardinalityand the predicate constant isLowCardinality(Nullable(...)). #106793 (Groene AI). - Fix inconsistent columns (that leads to
LOGICAL_ERRORlater) on exception (i.e.MEMORY_LIMIT_EXCEEDED) during parsing. #106802 (Azat Khuzhin). - Fix after configuring
keeper_server.http_control.secure_port, the server returned an HTTP response when making requests to HTTPS clients. #106822 (linjiayu1025-collab). - Fix logical error in
parseDateTimewith non-ASCII input bytes. #106856 (Pavel Kruglov). - Fix
SHOW CREATE ROW POLICYemittingrestrictive/permissivein lowercase instead of uppercase, inconsistent with other keywords. #106865 (Valery Petrov). - Fixes the case when parallel replicas wasn’t applied for view with
UNIONdue to empty table in theUNION. #106900 (Igor Nikonov). - Fix server crash (SIGSEGV) when reading truncated
Protobufdata withinput_format_allow_errors_num > 0. #106905 (Andrey Tsarevskiy | Андрей Царевский ). - Fix
THERE_IS_NO_COLUMNexception for distributed queries involvingoptimize_rewrite_aggregate_function_with_ifoptimization when the aggregate function argument requires a cast toNullabletype. #106908 (Yakov Olkhovskiy). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - Fix a server crash (null pointer dereference of
DB::IConnections) inRemoteQueryExecutorwhen a distributed query is cancelled right before it is sent to a shard. #106950 (Groene AI). - Fixed
elapsed_usalways being zero, andread_rows/read_bytesbeing undercounted, insystem.processors_profile_logandsystem.query_logfor asynchronous insert flush (AsyncInsertFlush) queries. #106982 (Christoph Wurm). - 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 (Groene AI). - Fix a logical error
conflicted_part_name.has_value()raised 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 (Groene AI). - Fixed an 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 (Groene AI). - 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 (Groene AI). - 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. Closes #87402. #107058 (Groene AI). - 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 (Groene AI). - Fixed a syntax error when a
FORMAT,SETTINGS, orINTO OUTFILEclause followsSHOW ROW POLICIESorSHOW MASKING POLICIES(e.g.SHOW ROW POLICIES FORMAT TabSeparated). #107061 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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. Closes: #106722. #107066 (Groene AI). - 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 (Nikita Fomichev). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - Fix spurious ZooKeeper session recreation on config reload. #107096 (Azat Khuzhin).
- Do not hold mutex across ZooKeeper reads in access entities refresh. #107097 (Azat Khuzhin).
- 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 (Groene AI). - 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 (Groene AI). - Fix a
Bad cast from type DB::IColumn const* to DB::ColumnNullable const*logical error 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Pablo Marcos). - Fixed a signed integer overflow in
quantileExactExclusive,quantilesExactExclusive,quantileExactInclusiveandquantilesExactInclusivethat could produce a wrong result forInt64inputs spanning a large range. #107154 (Groene AI). - 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 (Groene AI). - Make sure we don’t run startup scripts on config reload, as that is semantically wrong and unexpected by users - and has been known to be error-prone. #107187 (Miсhael Stetsyuk).
- Cap the max value for
queue_sizefor pre-reserve. #107205 (Elian Gidoni). - 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 (Nikolai Kochetov). - 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. Closes #106880. #107208 (Vladimir Cherkasov). - Fixed a possible null pointer dereference while resolving proxy configuration during late server shutdown. #107231 (Pedro Ferreira).
- Fix lightweight
UPDATEqueries with legacy parallel replicas enabled for non-replicatedMergeTreetables. #107246 (Groene AI). - Fixed a server abort (
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 crashing the server. #107279 (Groene AI). - Fix the stuck shutdown bug on server and local due to static thread pools keeping idle threads indefinitely if
max_*_thread_pool_free_size > 0. #107291 (Miсhael Stetsyuk). - Fix the
s3table function silently ignoring a lowercase positionalpartition_strategy(e.g.hive). #107297 (Julia Kartseva). - Fix
low_cardinality_allow_in_native_format=0handling in parallel blocks marshalling. #107319 (Azat Khuzhin). - 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 (Groene AI). - 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 (Antonio Andelic). - Fixed possible server stack overflow (crash) when reading a deeply nested schema or value in the
MsgPack,BSON,ORC,Parquet,JSON,DeltaLake,IcebergandPaimonformats. Such deeply nested input is now rejected with an exception. #107341 (Raúl Marín). - Fix a possible logical error in
SYSTEM SYNC DATABASE REPLICA ... STRICTand make theSTRICTmodifier actually take effect for database replicas. #107344 (Pedro Ferreira). - Fixes a server abort in debug/sanitizer builds when reading a
DeltaLaketable whose ClickHouse schema names a column that is absent from the Delta column mapping, for example after a column was renamed or dropped in the Delta log. The query now fails with a catchableINCORRECT_DATAerror instead. #107347 (Groene AI). - Fix
ORDER BY ... WITH FILLproducing extra rows when anORDER BYcolumn before the fill column uses aCOLLATEcollation. The rows are now grouped by the sorting prefix using that collation, matching the sort order. #107365 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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. #107388 (Alexey Milovidov). - 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 a
LOGICAL_ERROR(block.rows() == getRows()) raised on an asyncINSERTinto anAliastable whenuse_strict_insert_block_limitswas enabled. #107400 (Groene AI). - 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 (Groene AI). - 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 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 (Groene AI). - 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 an 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - Fixed stale AWS STS credentials when reading
DeltaLaketables overS3: the engine now keeps the freshly-credentialedS3client when refreshing its snapshot, so long-running reads no longer fail after the STS token’s TTL expires. The STS assume-role credentials provider now also honors credential refresh for anyS3access using STS. #107480 (Elmi Ahmadov). - 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 (Groene AI). - 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). - Query cancellation is now better tracked while waiting for the quorum in ReplicatedMergeTree. #107513 (Nikita Taranov).
- 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - 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 (Raúl Marín). - 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 (Groene AI). - 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 (Groene AI). - 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 (Groene AI). - Added missing bounds checks in Elf and DWARF parsing. #107579 (Michael Kolupaev).
- Added missing bounds checks in ORC reader. #107580 (Michael Kolupaev).
- Fixed an 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 (Groene AI). - Fix an unauthenticated memory-exhaustion denial of service on the MySQL protocol port. #107599 (Shaohua Wang).
- 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 (Groene AI). - Fixed two path-traversal issues in the replicated part fetch protocol that could let a malicious replica write files outside the part directory. #107606 (Antonio Andelic).
- Fixed ‘Account must be specified error’ when reading a Delta Lake table over Azure. #107620 (Smita Kulkarni).
- 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 (Groene AI). - Fix a server crash when reading a materialized view whose target is a
Distributedtable while the query runs withenable_analyzer = 0. #107653 (Groene AI). - 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). - 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 (Groene AI). - 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
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 (Groene AI). - Reading Arrow/ArrowStream data with empty
String/Binarycolumns produced by Apache Arrow Java < 19.0.0 (including Apache Spark) no longer throwsINCORRECT_DATA. #107764 (Raúl Marín). - Fixed a
BAD_GETexception (“Bad get: has String, requested UInt64”) fromcountmincolumn statistics estimation when a query compares a column against a literal of a different type that is not pre-coerced, such asnumeric_col IN (SELECT '5')orstring_col IN (SELECT 5). #107793 (Groene AI). - 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 an 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 (Groene AI). - Fix set skip index not pruning granules over
LowCardinalitycolumns. #107868 (Konstantin Bogdanov). - 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 (Sema Checherinda). - Fix incorrect results of
ORDER BYoverNullablecolumns with multiple sort keys on macOS (Apple Silicon), caused by a missing sign-extension in the JIT-compiled sort comparator. #107973 (Raúl Marín). - Fix performance regression when reading
Dynamiccolumns with multiple threads. Caused by #100730. Closes #107942. #107997 (Pavel Kruglov). - 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). - Fix a
Bad cast from type DB::ColumnSparse to DB::ColumnVector<char8_t>logical error when aLIKEquery reads from atextindex via the direct-read fallback path over a column stored sparse. #108068 (Groene AI). - Always run access cache batch-finished handlers, even on empty batch. #108124 (Azat Khuzhin).
- Fixed a
LOGICAL_ERROR(Column identifier is already registered) for some queries withUNION ALL. #100770 (Shaohua Wang). - Fixed a use-after-free of the workload storage mutex during server shutdown. #101447 (Tuan Pham Anh).
- Fixed a deadlock in
ALTER DATABASE MODIFY COMMENTwith theSharedcatalog. #103683 (Nikolay Degterinsky). - An empty Unicode-quoted identifier now raises a
SYNTAX_ERRORinstead ofCANNOT_PARSE_QUOTED_STRING. #104173 (leonard9893). - Preserve the original parameter types of
timeSeries*aggregate functions so thatAggregateFunctiontypes round-trip correctly across table reattach and parallel replicas. #104812 (Vitaly Baranov). - Fixed a
LOGICAL_ERRORfor a materialized CTE underserialize_query_planwith parallel replicas. #104896 (Igor Nikonov). - Fixed signed integer overflow in the
timeSeries*ToGridfunctions when the staleness (window) parameter is nearINT64_MAX. #105319 (Groene AI). - A
compatibilitysetting value no longer revertsapply_row_policy_after_finaltofalse, so row policies are always applied correctly withFINAL. #105637 (Yarik Briukhovetskyi). - Fixed
clickhouse chdig clientby honoringSETPGROUP/RESETIDS/SETSIGDEFin theposix_spawnstub. #105858 (Azat Khuzhin). - Fixed an exception during merge-tree sanity checks on projections when the merge/mutate executor was not initialized. #105919 (Mikhail Artemenko).
- During index analysis on projections, the
minmaxindex is now loaded from the projection itself rather than from the parent part, producing correct results. #105940 (Mikhail Artemenko). - Fixed an exception in
addMonotonicChainformaterialize(monotonic_chain(...)). #106050 (Nikolai Kochetov). - Fixed
RESTOREfailing on backups that includeMASKING POLICYdependents. #106086 (Julia Kartseva). - Fixed possible memory corruption when expanding SQL user-defined functions with
prefer_column_name_to_aliasenabled. #106121 (Nikolai Kochetov). - A dictionary using the bridge connection is now reloaded after a server restart, re-establishing the connection. Closes #106151. #106152 (Pedro Ferreira).
- Fixed the filesystem cache for
LocalObjectStorage. #106239 (Kseniia Sumarokova). - Fixed the lazy remote source for table functions with
use_delayed_remote_source. #106470 (Nikolay Degterinsky). - Fixed
timeSeriesLastToGridfor timestamps before the grid start and out-of-window timestamps. #106504 (Vitaly Baranov). #106577 (Vitaly Baranov). - Fixed a
LOGICAL_ERROR(Inconsistent AST formatting) on a function name containing query parameters. #106635 (Vitaly Baranov). - Fixed a logical error when a table is dropped before distributed plan task deserialization. #106944 (Alexander Gololobov).
- Use exact comparison for
NullableGROUP BYkeys. #107050 (Nikolai Kochetov). - Fixed a
LOGICAL_ERROR(Trying to get name of not a column) raised when a table-function argument was not a column expression (for example an unresolved*matcher frommultiIf/CASE). #107411 (Alexey Milovidov). - Fixed unbounded growth of the time-zone cache (
DateLUT) when many distinct invalid time-zone names are processed. #107464 (Alexey Milovidov). - Write the
part_logentry before reporting a plainMergeTreemutation as done. #107741 (Azat Khuzhin). arrayFoldnow sanity-checks its array argument against malformed input. #107932 (Michael Kolupaev).- Fixed a rare data race and possible use-after-free on the cached skip-index archive reader of a
MergeTreepart, which could happen when a query read skip indices while the part was being moved or renamed. #107995 (Raúl Marín). - Fix performance regression for
Mapsubcolumns withPREWHERE. #107988 (Pavel Kruglov). - Fix
parseDateTimeBestEffortwith a timezone throwingCANNOT_PARSE_DATETIMEon NULL rows oftoString(Nullable(DateTime64)). #108310 (Yarik Briukhovetskyi). - Fixed the
ArrowFlighttable function and engine rejecting a named collection that omits the optionaldatasetkey with aNo such key 'dataset'error. #108041 (Alexey Milovidov). - 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). - Fix
hasTokenwith a separator-containing needle silently returning results via a text index instead of raisingBAD_ARGUMENTS. #108189 (Jimmy Aguilar Mena). - 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 romanov). - Fixed a possible crash (null pointer dereference) when the
database/dboverride of a named collection passed toremote/remoteSecureis not a constant database name, e.g.remote(nc, database = (SELECT 1)). The query now fails with a clear error instead of crashing. #108271 (Groene AI). - Fixed refreshable materialized view getting stuck if the ZooKeeper connection is lost at the wrong moment. #108234 (Michael Kolupaev).
- Fix
Bad cast from type DB::ColumnVector<...> to DB::ColumnTuplewhen 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 (Groene AI). - Fix a
Bad cast from type DB::ColumnDynamic to DB::ColumnNullablelogical error when an explicit reference to aJOIN ... USINGkey whose common supertype isDynamicis passed to an aggregate function, for examplecount(t.key) IGNORE NULLS. #107289 (Groene AI). - 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. #107386 (Groene AI). - Fix a crash (SIGSEGV in release builds, type-mismatch assertion in debug builds) in
hasover aMapwith aDynamickey when the lookup argument isLowCardinality, e.g.has(map('a'::Dynamic, ...), toLowCardinality('b')). #107956 (Groene AI). - 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. #107648 (Groene AI). - 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). - 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 (Groene AI). - Fix
signed integer overflow(undefined behavior) indateDiffwithhourandminuteunits on extremeDateTime64values close to theInt64range limits. #108229 (Groene AI). - Fix
Too many marksfor a text index on an empty merged part. #106867 (Azat Khuzhin). - 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 (Groene AI). - Fix a server abort (
Logical errorinIColumn::insertFrom) when casting anArray(Dynamic)orArray(Variant)toQBitwithaccurateCastOrNull, e.g.accurateCastOrNull(CAST(range(114), 'Array(Dynamic)'), 'QBit(Float32, 114)'). #108288 (Groene AI). - Fixed a syntax error when an alias follows a subquery in
DESCRIBE TABLE (...) AS .... #100205 (Yarik Briukhovetskyi). getClientHTTPHeaderis now correctly treated as non-deterministic, so its result is no longer incorrectly reused by the query result cache. #108029 (Alexey Milovidov).
Build/Testing/Packaging Improvement
- Build
delta-kernel-rswith thedefault-engine-native-tlsfeature so that its own HTTP client (reqwest) can reuse the OpenSSL that ClickHouse already links in. This is only a partialnative-tlsenablement:object_storestill forcesreqwest/rustls-tls-native-roots, soreqwestends up with both thenative-tlsandrustlsbackends.delta-kernel-rsremains disabled under MSan for now becauseringis still compiled in viaobject_store(both transitively throughrustlsand directly for AWS request HMAC signing), and its hand-written assembly does not generate the symbols MSan requires (tracked upstream at arrow-rs-object-store#585). #96856 (Austin Bonander). - Add PGO (Profile-Guided Optimization) and BOLT (Binary Optimization and Layout Tool) post-link optimization for the
clickhousebinary. Profiles are collected from CI workloads and applied as a best-effort step during release builds — both stages fall back to non-optimized output if a profile is stale or incompatible. As of today, there are no benefits from PGO. #100938 (Alexey Milovidov). - Add
--storagemode toclickhouse keeper-benchthat benchmarksKeeperStoragein-process (no network, no raft, no state machine), using the samesetup/generatorconfig sections as the network mode. #103081 (Michael Kolupaev). - Fix build with
ENABLE_AWS_S3=OFF. #105390 (Yue Ni). - Update
mongo-cxx-driverto r4.3.0. #105522 (Konstantin Bogdanov). - Fix build against RapidJSON. #105674 (Ilya Golshtein).
- Speed up the build by removing transitive includes from widely-used base/ headers and stripping unused code from the vendored
Poco/Logger.h. #105702 (Raúl Marín). - Updated
libxml2from 2.15.1 to 2.15.3. #105985 (Konstantin Bogdanov). - Use
expat2.8.1 inside Poco. #105988 (Konstantin Bogdanov). - Bump
thrifttov0.23.0. #105993 (Konstantin Bogdanov). - Use
postgrestagREL_18_4. #105994 (Konstantin Bogdanov). - Upgrade
krb5to 1.22.2. #106076 (Konstantin Bogdanov). - Update bundled
curlto 8.20.0. #106077 (Konstantin Bogdanov). - Bumped
mariadb-connector-cto 3.1.29. All the ClickHouse-relevant patches preserved. #106287 (Nikita Mikhaylov). - Bump distroless base image digests for libssl3t64 CVE fixes. #106360 (Rahul Nair).
- Use
wasmtimev45.0.1. #106836 (Konstantin Bogdanov). - Bump
opensslto 3.5.7. #106844 (Konstantin Bogdanov). - Distroless Docker build now also updates the
:X.Y-distrolessand:X.Y.Z-distrolessfloating tags, not just the full-version tag. #106932 (Rahul Nair). - Disable unused
curlfeatures, such as NTLM auth, cookies, alt-svc, HSTS, DNS-over-HTTPS, netrc, MIME, AWS SigV4. #107226 (Konstantin Bogdanov). - Updated
NuRaftwith a fix for a snapshot-install livelock that occurred when snapshot IO ran on a background thread. Thenuraft_use_bg_thread_for_snapshot_ioKeeper setting remains disabled by default; CI now randomizes it to cover both modes. #107338 (Antonio Andelic). - Fix building
abseilwhen the ClickHouse checkout path contains a substring matching a header extension. #107349 (zhiqiang). - Determine the L2 cache size from
CPUIDon x86_64 instead of the glibc-specificsysconf(_SC_LEVEL2_CACHE_SIZE), which is not available under musl libc. #107469 (Konstantin Bogdanov). - Increase the stack size for musl builds to 8 MiB to support deeply-nested queries. #107470 (Konstantin Bogdanov).
- Derive the set of C library symbols localized in Rust static libraries from the actual reference libraries instead of a hand-maintained allowlist, so all compiler-rt builtins and platform libm functions are covered. #107571 (Raúl Marín).
- Switch the distroless server and keeper images to
gcr.io/distroless/base-nossl-debian13so they only ship the libraries ClickHouse actually links against and stop pulling in ones we statically link ourselves. #107837 (Rahul Nair). - Re-enable 50 stateless tests on macOS (
arm_darwin) that were stale-skipped, and usefsyncinstead ofF_FULLFSYNCfor directory syncing on macOS. #107887 (Raúl Marín).
ClickHouse release 26.5, 2026-05-21. Presentation, Video
Backward Incompatible Change
- Changed defaults of
date_time_input_formatandcast_string_to_date_time_modefrombasictobest_effort. Queries that previously failed to parse non-basic datetime strings (e.g.2024 April 4,Apr 15, 2020 10:30:00) may now succeed by default. To keep the old strict parsing behavior, set these settings tobasic(or usecompatibility). #89334 (Alexey Milovidov). - Tuple element name
nullis now forbidden because it conflicts with the subcolumn name used for Nullable null maps, causing ambiguous subcolumn resolution. #98377 (Alexey Milovidov). - Add a setting
dynamic_disk_allow_from_env,dynamic_disk_allow_from_zk,dynamic_disk_allow_includeto disallow usage offrom_env,from_zk,includein dynamic disks. Backward Incompatible Change because prohibits by default the behaviour which used to be allowed by default. #99138 (Kseniia Sumarokova). - You can no longer use the obsolete Arrow-based Parquet reader and writer. The native implementation will be used instead. #100949 (Alexey Milovidov).
SHOW CREATE TABLE tnow prefers the temporary table when both a permanent and a temporary table namedtexist and no database is specified, matching the existing behavior ofDESCRIBE TABLE. Additionally,DESCRIBE TEMPORARY TABLEsyntax is now supported. #100966 (Alexey Milovidov).- Reduced default
http_max_fieldsfrom 1,000,000 to 1,000 andhttp_max_field_name_sizefrom 128 KB to 4 KB to limit pre-authentication memory usage by HTTP connections. Addedhttp_max_request_header_sizeandhttp_headers_read_timeoutsettings. Users who rely on the previous higher limits can restore them via settings. #103285 (Sema Checherinda). - Added a
histogramsnested column tosystem.metric_logthat snapshots every registered histogram metric per row, with a newsystem_metric_log_show_zero_values_in_histogramssetting to control zero-value emission. Deprecates thesystem.histogram_metric_logtable. #103770 (Miсhael Stetsyuk). CASTtoDateTimeorDateTime64without an explicit time zone now preserves the time zone of its source argument (when the source is aDateTime/DateTime64with an explicit time zone), matching the behavior of thetoDateTime/toDateTime64functions. Closes #55072. #104433 (Alexey Milovidov).- Removed the
kqltable function. UseSET dialect = 'kusto'to run queries in the KQL dialect. #105101 (Alexey Milovidov). - The window functions
RANKandDENSE_RANKnow reject arguments and throwNUMBER_OF_ARGUMENTS_DOESNT_MATCH, in line with the SQL standard. Previously, queries such asRANK(x) OVER (ORDER BY id)were silently accepted with the argument ignored. To restore the previous lenient behavior, setallow_rank_dense_rank_arguments = 1. Closes #49526. #104324 (Groene AI).
New Feature
- Added a new setting
max_bytes_ratio_before_external_join, mirroringmax_bytes_ratio_before_external_group_byandmax_bytes_ratio_before_external_sort. It expresses the spill-to-disk threshold for hash joins as a fraction of available memory; combined with the absolutemax_bytes_before_external_join, the smaller resulting threshold applies. #103862 (Alexey Milovidov). Thenew max_bytes_ratio_before_external_joinsetting is now enabled by default at 0.5, mirroringmax_bytes_ratio_before_external_group_byandmax_bytes_ratio_before_external_sort. Hash joins automatically spill to grace hash join once the right-side data exceeds half of the available system memory (when memory limits are configured). #104285 (Alexey Milovidov). - Add table function
filesystem. It allows to represent directory structure as a table, to query files’ metadata and contents with SQL. Originally #42039 by @perst20. See #42039. See #50208. #53610 (Alexey Milovidov). - Allow passing bare function names to higher-order functions like
arrayMap,arrayFilter, etc. For example,arrayMap(negate, [1, 2, 3])is now equivalent toarrayMap(x -> negate(x), [1, 2, 3]). #101033 (Alexey Milovidov). - Add setting
send_table_structure_on_insert_with_inline_dataand--inline-insert-dataclient option to allow the server to parse inline INSERT data itself over the native protocol, avoiding the round-trip to receive table structure and improving performance for many small inserts. #101034 (Alexey Milovidov). - Add
tokenizeQueryandhighlightQueryfunctions for SQL query tokenization and syntax highlighting.tokenizeQueryreturns lexer tokens with byte offsets and token types;highlightQueryreturns parser-based syntax highlighting ranges with highlight categories (keyword, identifier, function, number, string, etc.). #101054 (Alexey Milovidov). - Add
url_basesetting to resolve relative URLs in theurltable function andURLtable engine, following RFC 3986 semantics. #101113 (Alexey Milovidov). - Support negative values in the
LIMIT BYclause to select rows from the end of each group instead of the beginning. For example,LIMIT -2 BY idreturns the last two rows perid. Negative offsets (LIMIT -1 OFFSET -1 BY id) and mixed signs (LIMIT -2 OFFSET 1 BY id) are supported as well. #103222 (Nihal Z. Miaji). - Support
json_valuefunction to output withtupleandarrayto improve performance of multiple json query. #78362 (kevinyhzou). Support multi-pathTuple/ArrayJSONPath argument inJSON_VALUE,JSON_EXISTS, andJSON_QUERY, by @KevinyhZou. #101102 (Alexey Milovidov). - A new
kafka_autodetect_client_rackparameter is introduced. If set, discover the Availability Zone via cloud facilities and propagate it as theclient.rackparameter oflibrdkafkato avoid cross-zone communications. #81323 (Ilya Golshtein). - Add
Readevent type tosystem.blob_storage_logfor tracking object storage read operations, controlled by new settingenable_blob_storage_log_for_read_operations. #96867 (Alexey Milovidov). - Users can now see ZooKeeper watches issued by
clickhouse-serverusing the newsystem.zookeeper_watchestable. #99277 (Den Kalantaevskii). - Added
Shardsprofile event that counts the number of shards involved in distributed queries, summed across all tables. #99470 (Alexey Milovidov). WASMUDFs can be declaredDETERMINISTICand become a subject of constant folding. #100005 (Vasily Chekalkin).- Add
parallel_replicas_prefer_local_replicasetting: when disabled, parallel replicas are selected purely by the load balancing algorithm, allowing evenmax_parallel_replicas = 1queries to be directed to another host. #100139 (Alexey Milovidov). - Add
{disk,storage,http}_connections_rcvbufand{disk,storage,http}_connections_sndbufserver settings to control TCP socket buffer sizes on outgoing HTTP connections, allowing operators to override kernel autotuning and cap per-connection memory usage. #100478 (Sema Checherinda). - Support
CREATE OR REPLACE MATERIALIZED VIEWwith the same atomic swap semantics asCREATE OR REPLACE TABLE. Works with inner tables,TOtables,POPULATE,REFRESH, andON CLUSTER. #100539 (DQ). - Add
s3_read_request_duration_microsecondsands3_read_request_byteshistogram metrics to observe S3 GET request connection lifetime and bytes consumed, visible insystem.histogram_metricsand the Prometheus endpoint. #102058 (Sema Checherinda). - Add
Paimon,PaimonS3,PaimonAzure,PaimonHDFS, andPaimonLocaltable engines with incremental read support backed by Keeper snapshot progress tracking. Incremental mode returns only new rows since the last committed snapshot. Targeted snapshot delta reads are available viapaimon_target_snapshot_id, and per-query snapshot caps viamax_consume_snapshots. Background metadata refresh is configurable withpaimon_metadata_refresh_interval_sec. Gated byallow_experimental_paimon_storage_engine. #102343 (XiaoBinMu). - Added a new Kafka table setting
kafka_map_virtual_columns_on_write. When enabled, columns named_key,_timestamp,_headers.nameand_headers.valuein the Kafka table schema are produced as the corresponding Kafka message key, timestamp and headers onINSERT, and are excluded from the message payload. #103243 (Alexey Milovidov). - Added
SYSTEM PAUSE VIEW [db.]nameandSYSTEM PAUSE VIEWSqueries for refreshable materialized views. UnlikeSYSTEM STOP VIEW,SYSTEM PAUSE VIEWdoes not interrupt the currently running refresh — the in-flight refresh is allowed to complete and only subsequent refreshes are prevented. Undone bySYSTEM START VIEWorSYSTEM START VIEWS, which now uniformly clear both the stopped and paused states. #103252 (Nikita Mikhaylov). - Added function
regexpPosition(with PostgreSQL-compatible aliasesregexpInstrandregexp_instr) that returns the byte position of the N-th regex match in a string. Supports start offset, return-after-match mode, regex flags, and capture-group selection. #104172 (Abhinav Agarwal). - New functions
isPrimeandisProbablePrimefor primality checks.isPrimereturns an exact result for unsigned integers up toUInt64.isProbablePrimealso supportsUInt128andUInt256; for those wider types,0means definitely composite and1means probably prime. The optional second argument ofisProbablePrime,rounds, controls the confidence (capped at256); the default of25rounds bounds the false-positive rate for a random composite below10^-15, andisProbablePrimeis cancellable. #104234 (Nihal Z. Miaji). #104639 (Alexey Milovidov). #104806 (Nihal Z. Miaji). clearand/clearnow clear the terminal in the clickhouse command-line tools instead of running as a mistaken query. #104318 (Tyler Hannan).- Allow the
filetable function to accept anArray(String)of paths inSELECTqueries. #104442 (Yue). - Add
deterministicandhigher_ordercolumns tosystem.functionstable. #104479 (Pedro Ferreira). - Add an optional encoding variant parameter to
bech32Encode(bech32/bech32m) and a raw decode mode tobech32Decodefor non-SegWit address encoding (e.g. Cosmos SDK, Injective, Osmosis). #98986 (Yash ). - You can now write data in
AvroConfluentformat, which was previously input-only. This enables producing Confluent Schema Registry-framed Avro messages directly from ClickHouse, for example when writing to Kafka. The schema is automatically registered with the registry. Use the newoutput_format_avro_confluent_subjectsetting to specify the subject name. #101935 (János Benjamin Antal). - Added the
prettyPrintJSONfunction to format a JSON string into a human-readable form. Useful for dashboards or reports where prettifying previously required an extra step on the client side. Closes #62523. #102594 (Dmitry Prokofyev). - Added
STRING_AGGas a case-insensitive alias ofgroupConcatfor PostgreSQL / SQL-standard compatibility. #105125 (Alexey Milovidov). - Individual subquery results can now be cached independently using
SETTINGS use_query_cache = trueon specific subqueries, without caching the entire outer query. A new settingquery_cache_for_subqueries = trueenables bulk propagation ofuse_query_cacheinto all subqueries. Note:use_query_cacheon the outer query no longer auto-propagates to subqueries. #99804 (Vincent Voyer). - Added lexer-based syntax highlighting to the query editor in the Web UI (
play.html), modelled afterclickhouse-clientcolors. #105105 (Alexey Milovidov).
Experimental Feature
- Added an experimental web terminal interface at
/webterminalthat provides an interactiveclickhouse-clientsession in the browser over WebSocket. Disabled by default; enable with theallow_experimental_webterminalserver setting. See it here. #100277 (Alexey Milovidov). #105191 (Alexey Milovidov). #105059 (Alexey Milovidov). - The
Kafka2engine (experimental, with Keeper-based offset storage) now supports directSELECTqueries and thekafka_commit_on_selectsetting. #100276 (Alexey Milovidov). WASMUDFs can now coerce more numeric types: smaller integers to wider integers (e.g.Int8toUInt64), and any integer to floating point (e.g.Int32toFloat32). #100435 (Vasily Chekalkin).- Support
LIKEfunction inDELETE FROM system.webassembly_modulesquery. #104397 (Vladimir Cherkasov). - Support geo types for
Iceberg. #103113 (Konstantin Vedernikov). - Add prepared statements functionality to ArrowFlight SQL server. #103047 (Yakov Olkhovskiy).
- Improved KQL parser (for the Kusto language support) robustness by preserving parser depth and backtracks counters across KQL parser stages, so parser limits are tracked consistently for complex KQL queries. #103528 (Yakov Olkhovskiy).
Performance Improvement
- Reuse the Parquet footer metadata cache when reading local Parquet files via the
filetable function orFiletable engine. Previously the cache was only consulted for object-storage backends. #104260 (Alexey Milovidov). - Push
ORDER BY ... LIMIT nthroughLEFT/RIGHTjoins when the sort key only references columns from the side preserved by the join, restricting how many rows the preserved-side input must produce before joining. Controlled by the new settingquery_plan_top_k_through_join(default enabled). #104268 (Alexey Milovidov). - Enable
use_top_k_dynamic_filteringanduse_skip_indexes_for_top_ksettings by default to improve performance ofORDER BY ... LIMIT Nqueries. #99537 (Alexey Milovidov). Restrictuse_top_k_dynamic_filteringto fixed-length sort columns by default, avoiding regressions onORDER BY <var-length-column> LIMIT Nqueries where the per-row threshold comparison cost exceeds the I/O savings. The previous behavior is available via the newuse_top_k_dynamic_filtering_for_variable_length_typessetting. #104216 (Alexey Milovidov). - Use the oversize-arena feature of
jemallocto reduce page faults. #103958 (Nikita Taranov). - Limit simultaneously active streams in
UNION ALLto reduce peak memory usage. #100176 (Alexey Milovidov). - Slightly optimize the userspace page cache. #100300 (Alexey Milovidov). Now the userspace page cache is always better than the OS page cache.
- Cold reads of object storage through the userspace page cache (
use_page_cache_for_object_storage = 1) are now significantly faster, because consecutive cache misses are coalesced into a single HTTP request instead of one request perpage_cache_block_sizeblock. #104230 (Alexey Milovidov). - Speed up the index analysis involving type casting and function application. Closes #55653. #100366 (Alexey Milovidov).
- Speed up huge queries on
Mergetables over a huge number of underlying tables. Closes #32465. #100369 (Alexey Milovidov). - Remove vtable from setting field types, reducing
Settingscopy size by ~28x and improving cache locality via typed-array layout for all settings types. #102269 (Raúl Marín). - Add
max_threads_min_free_memory_per_threadandmax_insert_threads_min_free_memory_per_threadsettings to automatically reduce query parallelism when the server is low on free memory. #100383 (Alexey Milovidov). - Reduce memory usage on low-memory systems (< 4 GiB). #100389 (Alexey Milovidov).
- Added
OptimizeTrivialGroupByLimitPass. For trivialSELECT ... FROM t GROUP BY k LIMIT nqueries (noHAVING,ORDER BY, or window functions), the analyzer now setsmax_rows_to_group_by = n + offsetwithgroup_by_overflow_mode = 'any', so aggregation stops oncendistinct keys have been produced instead of grouping the entire input. Controlled by the new settingoptimize_trivial_group_by_limit_query(enabled by default). #104473 (Amos Bird) (Alexey Milovidov). - Granule-level implicit min-max index for the
_part_offsetand_block_numbervirtual columns, including for projections. Enables fast pruning of granules based on virtual column predicates. #103952 (Mikhail Artemenko). #104746 (Mikhail Artemenko). #105137 (Mikhail Artemenko). - For the
prealloc_serializedfamily of aggregation methods, precompute per-row hashes during the batch-serialization pass and use them to (a) skip rehashing inemplaceKey/findKeyand (b) software-prefetch the next row’s bucket. Speeds up multi-key string/serialized aggregation by hiding hash-table cache-miss latency. #104475 (Amos Bird) (Alexey Milovidov). - Query condition cache for
Icebergtables. #102115 (Konstantin Vedernikov). - Optimize
cramersV,cramersVBiasCorrected,theilsU, andcontingencywhen used with window functions. Closes #83521. #93384 (Nihal Z. Miaji). - Added a query optimization that rewrites
tupleElement(dictGet('dict', ('a', 'b', 'c'), key), N)intodictGet('dict', 'a', key), avoiding fetching unnecessary dictionary attributes. Controlled by theoptimize_dictget_tuple_elementsetting (enabled by default). #100186 (Alexey Milovidov). - Enable buffering for sorting steps on the initiator for distributed queries with sorting. #100661 (Nikita Taranov).
- Performance improvement for
partial_mergeJOIN. #100945 (Artem Zuikov). - Slightly reduced memory over-allocation in
partial_mergeJOIN. #100963 (Artem Zuikov). - Optimize allocations/deallocations by caching sampling settings instead of traversing the entire memory-tracker hierarchy. #101267 (Azat Khuzhin).
- Reduce memory allocation overhead during S3 multipart uploads by preallocating internal tracking containers. #101799 (Gagan Dhakrey).
- Add software prefetch in hash join probe phase to reduce memory access latency for large hash tables, controlled by setting
enable_software_prefetch_in_join. #102444 (Xiaozhe Yu). - Optimize
MemoryTrackerlayout, improving its performance by ~25%. #103464 (Azat Khuzhin). - Rewrite
coalesce(a, b, ...) <op> constandifNull(a, b) <op> constpredicates before index analysis so per-column primary key and skip indexes on each argument can prune granules. Controlled by the new settingallow_key_condition_coalesce_rewrite(on by default). #103468 (Manuel). - Significantly improved query performance when reading Iceberg catalogs with large JSON metadata files by optimizing escaped slash processing. #103998 (Mohaidoss).
- Avoid index uncompressed cache overhead when the cache is disabled (server setting
index_uncompressed_cache_size = 0, which is the default). #104063 (Michael Kolupaev). - Fix
ORDER BY ... LIMITqueries with small limit reading excessive granules when combined with a non-selectiveWHEREfilter. Previously, any filter above an in-order read disabled the per-mark-range task split, so the pipeline could not cancel between granules and read the whole part for each stream. #104112 (Vladimir Cherkasov). - Fixed missing hash table sizes cache reuse after reordering JOIN sides. #104131 (Nikita Taranov).
- When
fsync_after_insertis enabled, fsync of part files is now performed in parallel using the IO thread pool, speeding up insert finalization on wide tables. The full ClickBenchhitsload is about 22% faster. #104137 (Alexey Milovidov). - Vectorise
find_first_symbols,find_first_not_symbols,find_last_symbols_or_null,find_last_not_symbols_or_null, andsplitIntoon AArch64 using NEON. Previously these helpers had a SIMD path only on x86 (SSE2 / SSE4.2) and fell through to a scalar loop on ARM. Speeds up TSV parsing by ~2x, URL functions andsplitByCharby ~1.3x on the ClickBenchhitsdataset; very dense JSON parsing (sub-16-byte field cadence) regresses slightly in line with the existing SSE2 trade-off. #104228 (Alexey Milovidov). - Reading data through a trivial
ALIAScolumn (e.g.some_alias['key']wheresome_alias ALIAS m) now goes through the same per-subcolumn read path as referencing the underlying column directly, restoring large I/O savings forMap,Array,TupleandNullablealiased columns. #104245 (Raúl Marín). - Reduced lock contention on the asynchronous remote-FS read path by making the per-query
AsyncReadCounterslockless. #104374 (Nikita Mikhaylov). - Slightly better query plan for projections in-order scan. #103723 (Mikhail Artemenko).
- Extend
optimizeUseNormalProjectionsto also handle a specific case where nothing was filtered but the projection’s sorting key can remove the sorting step from the query plan. #104680 (Mikhail Artemenko). - Allow
json.path[]syntax sugar and explicit type hints to work correctly on typedJSONpaths. #99179 (Pavel Kruglov). - Optimize
json.path[N].nested.path(which expands totupleElement(tupleElement(json.path[N], 'nested'), 'path')) intojson.path[].nested.path[N], which reads much less data. #99802 (Pavel Kruglov). - Optimize
SHOW TABLESaccess checks insystem.partsby hoisting database-level grant checks out of the per-table loop. #100860 (Shaohua Wang). - Remove a redundant per-table
SHOW TABLESaccess check in theSELECT name/SELECT database, namefast path ofsystem.tables. #100881 (Shaohua Wang). - Enable JIT compilation on macOS. #100947 (Alexey Milovidov).
- Skip deferring the row policy after
FINALwhen it depends only on sorting-key columns and is deterministic, and skip the correspondingPREWHEREdeferral that the row policy was forcing in that case. #102884 (Yarik Briukhovetskyi). - Added support for
hasAnyandhasAllas filter predicates in text indexes. #103266 (Anton Popov). - Route long-lived MergeTree heap state (per-part and per-table metadata) to a dedicated jemalloc arena, exposed via
jemalloc.mergetree_arena.*async metrics. Reduces default-arena fragmentation in steady-state and keeps per-part survivors from pinning otherwise-decayable pages. #104136 (Raúl Marín). - Improve ZooKeeper client timeout handling under heavy load when many requests are pipelined on a single session. The ZooKeeper client now uses a progress-based timeout: as long as any data is received from the server within
session_timeout_ms, the wait is extended. A hard cap of3 * session_timeout_msper request still bounds caller latency. Closes #100466. #104351 (Antonio Andelic). - Move per-event trace flags into a separate array and allocate them lazily, reducing the overhead of
ProfileEventstracing. #105030 (Azat Khuzhin). - Add
compareTrackAtforColumnDecimal, improving comparison performance forDecimalcolumns. #105110 (Artem Zuikov). - Added a SIMD implementation of
MD5(AVX2/AVX512) that hashes multiple inputs in parallel, improving throughput. #105161 (Joanna Hulboj).
Improvement
- Improve the help output for all ClickHouse applications:
--helpnow consistently returns exit code0, prints tostdout, and a top-levelclickhouse --helplists all subcommands. Adds a--no-sudooption forclickhouse start/restart(useful in Docker), and aclickhouse helpsubcommand. Continuation of #58244 from @qoega. #98148 (Alexey Milovidov). - The default of
input_format_column_name_matching_modeis changed frommatch_casetoauto. Input formats that match input column names against the table schema (JSONEachRow,CSVWithNames,JSONColumns,BSONEachRow,RowBinaryWithNames, etc.) now first try a case-sensitive match and fall back to case-insensitive matching when the case-sensitive match misses. The previous strict behavior is preserved undercompatibility. #104320 (Alexey Milovidov). - Added
STDDEVas a case-insensitive alias ofstddevSampfor PostgreSQL/SQL-standard compatibility. #105120 (Alexey Milovidov). - Added
array_to_stringas a case-insensitive alias ofarrayStringConcatfor PostgreSQL compatibility. #105121 (Alexey Milovidov). - Added
unnestas a case-insensitive alias ofarrayJoinfor PostgreSQL compatibility (function-call form). #105124 (Alexey Milovidov). - The progress bar in
clickhouse-clientnow shows temporary data on disk usage (e.g. for external sort, aggregation, or JOIN) next to RAM, including a per-host breakdown for distributed queries. #105190 (Alexey Milovidov). - Added
system.predicate_statistics_log, a new sampled log of predicate filter selectivity and MergeTree index-granule pruning per query. Disabled by default; enable via thepredicate_statistics_sample_rateserver setting. Needed for automatic index and projection recommendations. #98727 (Yarik Briukhovetskyi). - Allow skipping local shard with missing table when
skip_unavailable_shardsis enabled. #100141 (Alexey Milovidov). - Add startup warnings (visible in
system.warnings) when a Linux mdraid array is being resynchronized or is in a degraded state, as both can affect disk I/O performance or indicate disk failures. #100941 (Alexey Milovidov). - WASM UDFs now appear in
system.functionswith correctorigin(WasmUserDefined),syntax,arguments, andreturned_valuecolumns populated from their ClickHouse type metadata. Previously they were either missing or listed with the wrong origin as duplicates. #101053 (Vasily Chekalkin). - The
generate_seriestable function now supports negative step values for generating descending sequences, e.g.SELECT * FROM generate_series(99, 0, -1). #101056 (Alexey Milovidov). - Fix
Context has expiredexceptions raised by some functions (dotProduct,formatRow,structureToCapnProtoSchema/structureToProtobufSchema, user-defined functions) when used in deferred execution paths such asDEFAULT/MATERIALIZEDexpressions and table engine settings, by ensuring those functions hold a strong context where required. #101109 (Alexey Milovidov). - Fix spurious
Cache limits violatedlogical errors on priorities created with zero limits (such as the per-query filesystem cache priority used whenenable_filesystem_query_cache_limitis on). #101428 (Alexey Milovidov). - Auto-detect the region for
s3expressendpoints. #101520 (Pradeep Chhetri). - Support field ids for data files in
Icebergwrites. Closes #102322. #102362 (Konstantin Vedernikov). - The left panel in the web UI (
play.html) now scrolls independently, stays visible when the page is scrolled, and clicking a table scrolls to the query area. #102498 (Alexey Milovidov). - Allow opening the Play UI in a new tab via Ctrl/Cmd/Shift+click or middle-click on the ClickHouse logo in the left panel. #102501 (Alexey Milovidov).
- New metrics to track memory used by projection primary keys and projection index granularity across all tables. #102587 (Narasimha Pakeer).
- Apply
max_network_bandwidth_for_userandmax_network_bandwidth_for_all_usersto remote filesystem reads/writes. #103080 (Azat Khuzhin). - Improve the resilience of backups when Refreshable Materialized Views are constantly refreshed by making decisions based on the snapshotted tables’ state rather than a global one. #103384 (Nikita Mikhaylov).
SELECT * FROM system.databasesnow always lists data lake catalog databases regardless of theshow_data_lake_catalogs_in_system_tablessetting. Previously they were hidden by default, which was inconsistent withSHOW DATABASESthat always showed them. #103444 (Alsu Giliazova).- Align the default of the server setting
concurrent_threads_soft_limit_ratio_to_coresin code with the shippedconfig.xmlvalue (2), so the defaultmax_min_fairconcurrent threads scheduler caps query processing threads at 2x cores out of the box even when the shippedconfig.xmlis not used. #103446 (Alexey Milovidov). - Improved sanitizer robustness in parser and string-function edge cases by handling empty input in
getURLScheme, avoiding null-pointer arithmetic inLexer::nextTokenmax_query_sizechecks, and short-circuiting UTF-8 subsequence evaluation on empty haystacks before decoding. #103489 (Yakov Olkhovskiy). - Improved correctness of monotonicity inference for
divide(0, x)andintDiv(0, x): previously the functions were unconditionally reported as monotonic, but0 / xis non-monotonic on any range that includes 0 because0 / 0is undefined (NaN/Inffordivide, division-by-zero exception forintDiv). The false claim causedKeyCondition::applyMonotonicFunctionsChainToRangeto produce ranges withleft > right, which tripped aLOGICAL_ERRORInvalid binary search result in MergeTreeSetIndexin debug builds when anIN/NOT INexpression on the primary key wrapped the key individe(0, key)orintDiv(0, key). Release builds were unaffected — the assertion is gated by#ifndef NDEBUG. #103621 (Groene AI). - Replace the
HTTPConnectionPool*TCP{Rcv,Snd}BufBytes_{p50,p75,p90,p95}async metrics with a bucket-based histogramhttp_pool_tcp_buf_bytes(labelsgroup,direction) insystem.histogram_metrics. Per-group total async metrics are preserved. #103704 (Sema Checherinda). - The server settings
{disk,storage,http}_connections_{rcvbuf,sndbuf}are now reported as changeable without restart insystem.server_settings. Their values can be updated viaSYSTEM RELOAD CONFIG; the runtime application path was already in place since #100478. #103772 (Sema Checherinda). - Add support for resolved symbols (
Array(String)) inflameGraph. #103816 (Azat Khuzhin). - CLI client can now specify
<rainbow_parentheses>false</rainbow_parentheses>in its config in environments where terminal colors clash with the parentheses (similarly,clickhouse formatnow has--no_rainbow_parentheses). #103851 (Larry Snizek). - Fix
MultiVolnitskyUTF-8 case-insensitive search by rolling back partialputNGraminserts on failure and switching failed needles to fallback searchers, avoiding inconsistent state. #103864 (Yakov Olkhovskiy). - Implement
sched_getcpuviarseqTLS in glibc-compatibility musl. #104016 (Azat Khuzhin). - Replicated refreshable materialized view in APPEND mode will no longer refresh twice if connection to zookeeper was briefly lost during refresh. #104051 (Michael Kolupaev).
- Allow Distributed tables without an explicit column list to validate sharding keys against the inferred remote table structure. #104111 (Yue).
- Fix REST catalog with
Azureabfsspath. #104120 (Konstantin Vedernikov). - Honor
role_arnandrole_session_nameauth settings in the Keeper S3 snapshot client, allowing snapshot uploads to use STSAssumeRole-based authentication. #104140 (Alexey Milovidov). - Fix a memory leak when running queries with
MATERIALIZEDCTEs. #104153 (Alexey Milovidov). - Fix
lowerUTF8/upperUTF8exception when processing large non-ASCII data sets (e.g. during text-index builds) where the accumulated output buffer would exceed 2 GiB; reject excessively long single rows with a clear error. #104229 (Shaohua Wang). - Harden MergeTree column-statistics loading against transient I/O failures to prevent permanently disabling statistics-based optimizations for affected parts. #104372 (zoomxi).
INSERT INTO ... SELECT FROM input(...)no longer requires theCREATE TEMPORARY TABLEgrant. #104470 (Alexey Milovidov).- Added a new MergeTree setting
concurrent_part_removal_threshold_for_remote_disk(default16) that is used instead ofconcurrent_part_removal_thresholdwhen at least one part being removed is stored on a remote disk. The previous threshold of100could makeDROP TABLEand other part-removal operations on object storage backends stall for tens of seconds because removals were performed serially even though each one is a separate network round-trip. The new setting causes the parallel removal path to be entered much sooner on remote storage, while leaving local-disk behavior unchanged. #104676 (Groene AI). - New setting
defer_partition_pruning_after_final(default1) makes the 26.3-introduced behavior of skipping partition pruning underFINALopt-out. Set it to0to restore pre-26.3 partition pruning — substantially faster on event-log workloads where same-PK rows cannot span partitions.compatibility = '26.2'flips it to0automatically. #104705 (Nikita Fomichev). - Fix
intExp2returning wrong results for out-of-range inputs (shifts>= 64under JIT, and integers with magnitude exceedingINT_MAXon both code paths). #105054 (Raúl Marín). - Quote shell arguments built from CLI options and parsed input in
clickhouse installandclickhouse git-importso paths, user/group names, and commit hashes containing whitespace or shell metacharacters are handled correctly. #105232 (Raúl Marín). - The
Aliastable engine is now non-experimental and available without theallow_experimental_alias_table_enginesetting. #103488 (Alexey Milovidov). - Added
--queries-formatoption toclickhouse-benchmarkto choose between the default tab-escaped one-query-per-line input (tsv) and parsing standard input as a script of multiple queries separated by;(script). #99972 (Aleksandr Musorin). - The element-wise tuple operators
tuplePlus,tupleMinus,tupleMultiply,tupleDivide,tupleModulo,tupleIntDiv, andtupleIntDivOrZeroare now variadic and accept two or more tuples of the same size, applied element-wise as a left-fold. They previously accepted exactly two arguments only. #104659 (Aruj Bansal). - Added a new built-in web UI at
/processors-profilethat visualizes the pipeline of any pastSELECTquery as a heatmap, sourced fromsystem.query_logandsystem.processors_profile_log. Each processor is colored by itselapsed_usand shows per-processor stats (rows, bytes, wait times) on hover. #104614 (Nikita Mikhaylov). - Setting
query_plan_use_logical_join_step(and its aliasquery_plan_use_new_logical_join_step) is now obsolete and has no effect; the logical join step is always used. #104017 (Vladimir Cherkasov). - The
userinput onplay.htmland the other built-in web pages (dashboard.html,jemalloc.html,merges.html,binary.html,webterminal.html) is no longer pre-filled with the literal textdefault. It now shows auserplaceholder hint and is empty by default. When left empty, the page does not send auser=URL parameter (and the WebTerminal auth JSON omits theuserfield), so the server applies its usual fallback to thedefaultuser — and HTTP credentials supplied via other channels (X-ClickHouse-User, HTTP Basic, per-handler<handler><user>configuration) are no longer overridden. #105254 (Alexey Milovidov). ORCreader: decouple offset-based read (readBigAt) fromuse_prefetch, so EC-encoded data onHDFScan be read correctly even whenuse_prefetch = false(e.g. by Gluten). #103348 (zhanglistar).- Files downloaded from
play.htmlwith theCSVWithNamesformat now use the.csvfile extension. #103737 (JackFielding). - More input validation for the BigLake catalog. #105117 (Konstantin Vedernikov).
Bug Fix (user-visible misbehavior in an official stable release)
- Fix inconsistent formatting by remembering if an expression was parenthesized. #92340 (Alexey Milovidov).
- Fix accurate comparison between Decimal and Float types. #94293 (zoomxi).
- Allow positional arguments in distributed queries. #94359 (simonmichal).
- Fix assertion failure in
DatabaseCatalog::updateDependencieswhen dropping and recreating a materialized view with the same name; also fix view dependencies being silently lost duringRENAME TABLEorEXCHANGE TABLESwhen referential dependencies were empty. #98779 (Alexey Milovidov). - Fixed a server abort (assertion failure in
DatabaseCatalog::getTableImpl) that occurred when creating a table viaON CLUSTERwith a UUID identical to an existing database’s UUID. #98861 (xiaohuanlin). - Fixed usage of skip indexes on data read (with enabled setting
use_skip_indexes_on_data_read) and existing patch parts created by lightweight updates. #99543 (Alexey Milovidov). - Fix “Not-ready Set” exception when a filter with
IN (subquery)is moved to PREWHERE by the query optimizer. #100375 (Alexey Milovidov). - Fix “Cannot find column” error when combining
ADD COLUMNwithRENAME COLUMNin a singleALTER TABLEstatement. #100387 (Alexey Milovidov). - Fix views with mixed
UNIONandINTERSECT/EXCEPToperators returning wrong results afterDETACH/ATTACHor server restart. #100390 (Alexey Milovidov). - Fix “Trying to execute PLACEHOLDER action” exception that could occur during stress testing with the AST fuzzer when a correlated subquery appeared in an IN clause. #100398 (Alexey Milovidov).
- Fix logical error exception when inserting into an Iceberg table with a
Datecolumn partitioned byyear,month, ordaytransforms. #100404 (Alexey Milovidov). - Fix skip index being used with incompatible data after
ALTER TABLE MODIFY COLUMNchanges the column type, which could cause server crashes in sanitizer builds or incorrect query results. #100526 (Alexey Milovidov). - Fix credential leak in
query_logforpaimonCluster,paimonS3Cluster,paimonAzureCluster, anddeltaLakeS3table functions. #100529 (JIaQi Tang). - Fix
DROP TABLEon Kafka engine tables potentially hanging indefinitely due to a deadlock inrd_kafka_consumer_close. #100604 (Alexey Milovidov). - Replace the hardcoded
source_table_engineslist with runtime lookup viaStorageFactoryandDatabaseFactory. Addsource_access_typetoDatabaseFactory::EngineFeaturesso thatCREATE DATABASEwith source engines (PostgreSQL, MySQL, S3, etc.) requires the same source grants asCREATE TABLE. FixesGRANT TABLE ENGINE ON *failing withtable_engines_require_grant=false. Closes #71544. #100746 (pufit). - Fix server crash when reading from a table whose
ALIAScolumn contained a correlated subquery nested inside a function call (e.g.ALIAS toString(intDivOrZero(x, (SELECT ...)))).CREATE TABLEandALTER TABLEnow reject any subquery at any depth inDEFAULT/ALIAS/MATERIALIZEDcolumn expressions withTHERE_IS_NO_DEFAULT_VALUE. Previously, the shallow validation accepted nested subqueries, so the correlated case crashed at read time and the nested non-correlated case appeared to work but could lead to unexpected behavior; both are now rejected at DDL time. #100753 (Groene AI). - Fixed a server crash (
Logical error: Bad cast from type DB::FunctionNode to DB::ColumnNode) that could occur when using queries with correlated subqueries on tables that haveCONSTRAINT ... ASSUMEdefinitions, whenoptimize_substitute_columnsandconvert_query_to_cnfsettings are enabled. #100756 (Groene AI). - Fix an exception that could occur when inserting a row into a JSON column where the row introduced a new dynamic field alongside a typed field with an incompatible value, and the column was subsequently used as a GROUP BY key. #100758 (Jimmy Aguilar Mena).
- Fix workload IO scheduling being silently bypassed for S3/object-storage writes that go through the
DiskObjectStorageTransactionpath (used bys3_with_keeperdisks and explicitly whenuse_fake_transaction=false). Previously, INSERT writes into MergeTree tables on such disks ignoredCREATE RESOURCE/CREATE WORKLOADthrottling because the resource link was never injected intoWriteSettingsfor the transactional write path. #100777 (JIaQi Tang). - Fix shared schema-cache collision between
ProtobufandProtobufList: reading a message first asFORMAT Protobufand then asFORMAT ProtobufListcould fail becauseProtobufListforced the cached schema into its envelope form.ProtobufListnow falls back to the cached message type when no envelope schema is available. #100849 (Callum Cooper). - Fix heap-buffer-overflow in Rust CXX bridge due to
std::exceptionABI mismatch. #100931 (Azat Khuzhin). FunctionVariantAdaptornow throwsILLEGAL_TYPE_OF_ARGUMENTwhen allVariantalternatives are incompatible with a function, instead of silently returningNullable(Nothing). Previously, aWHERE function(variant_col)predicate where no alternative type was compatible would return 0 rows with no error, while the equivalentSELECTcontext already threw correctly. #100939 (Vasily Chekalkin).TRUNCATE ALL TABLESno longer fails when the database contains views. #100943 (Alexey Milovidov).- Fix the
optimize_rewrite_array_exists_to_hasoptimization to correctly handle type-incompatible cases (e.g. Date vs String) and re-enable it by default. #100944 (Alexey Milovidov). - Fix S3 settings priority so that
storage_configurationdisk settings override global<s3>section, and user/profile/query-level settings override both. #100975 (Alexey Milovidov). - Fix sparse serialization losing the sign of negative zero (-0.0) for BFloat16, Float32, and Float64 columns. #100983 (Takumi Hara).
- Fixed two bugs in the WKT geometry parser used when reading WKT-encoded GeoParquet and Arrow files:
MULTILINESTRINGgeometries were incorrectly parsed asPolygon(causing an exception for typed columns and silent data corruption for mixedGeometrycolumns), and a malformed WKT string with no type keyword triggered undefined behaviour instead of a clean error. #100997 (Vasily Chekalkin). - Fix
grouping/GROUPING SETSqueries on Distributed tables with a single shard that failed with “Method executeImpl is not supported for ‘grouping’ function”. #101030 (Alexey Milovidov). - Fix
LOGICAL_ERROR“Column identifier is already registered” in the planner that could occur when the same table expression was processed multiple times. #101048 (Alexey Milovidov). - Fix LOGICAL_ERROR exception “Column identifier is already registered” when
additional_result_filtersetting is used with UNION or EXCEPT queries. #101051 (Alexey Milovidov). - Fixed server crash (Logical error: Bad cast from ColumnVector to ColumnNullable) when using
* APPLYwith aggregate functions andgroup_by_use_nulls=1with GROUPING SETS, ROLLUP, or CUBE. #101062 (Groene AI). - Fix infinite loop when
input_format_csv_skip_first_linesorinput_format_tsv_skip_first_linesexceeds the number of lines in the file. #101111 (Alexey Milovidov). - Fix out-of-bounds access in lazy materialization optimization that could cause an exception in debug builds. #101144 (Alexey Milovidov).
- Fix type inference in recursive CTEs: column types are now iteratively widened via
getLeastSupertypeacross the non-recursive and recursive sides of theUNION ALLuntil convergence, preventing integer overflow in expressions likex + 1. #101155 (Alexey Milovidov). - Clamp MergeTree compress block size settings (max_compress_block_size, min_compress_block_size, marks_compress_block_size, primary_key_compress_block_size) to 256 MiB to prevent server crash when extreme values are set via CREATE TABLE SETTINGS. #101159 (Groene AI).
- Fix a LOGICAL_ERROR crash in
QueryAnalyzer::resolve()when a ROW POLICY uses a scalar subquery in itsUSINGclause (e.g.USING (SELECT 1)). Closes #100695. #101263 (Groene AI). - Fix undefined behavior in
MergeTreeDataPartWriterCompact::cancelwhen a stream allocation fails. #101292 (Alexey Milovidov). - Fixes a case where timezone was not included during the assignment in the ALTER statement. Closes #101328. Related https://github.com/ClickHouse/ClickHouse/pull/100647. #101403 (Yarik Briukhovetskyi).
- Fix server crash (LOGICAL_ERROR) for INSERT SELECT queries with ORDER BY ALL when the SELECT pipeline produces multiple streams. #101443 (Groene AI).
- Fix incorrect query results caused by join reordering pushing an INNER JOIN filter (referencing only the preserved side of an outer join) into the outer join’s ON clause. #101504 (Vladimir Cherkasov).
- Skip applying lazy materialization for plans with arrayJoin, which could lead to limit not being respected. Close #101608. #101644 (Vladimir Cherkasov).
- Fix incorrect JOIN query results when
mergeFilterIntoJoinConditionoptimization silently dropped a WHERE equality condition with mismatched types. #101652 (Xiaozhe Yu). - Fix the
errortest hint not working for syntax/parsing errors — previously-- { error SYNTAX_ERROR }on a malformed query would fail with “Expected server error” instead of matching the client-side parse error. #101675 (Groene AI). - Fix
INTO OUTFILE ... TRUNCATEnot actually using atomic rename — the write went directly to the original file instead of a temp file, so on query failure the original content was destroyed. Now the data is written to a temp file and renamed only on success. #101884 (Pablo Marcos). - Fixed an exception
Unsupported DeltaLake type: varchar(n)when reading Delta Lake tables whose schema contains varchar(n) or char(n) column types. These types are now mapped to String, consistent with how the Delta Lake protocol stores them as plain byte arrays in Parquet. #101973 (Flavio Malavazi). - Fix silent data loss when reading tar archives from S3 with
schema_inference_mode=unionand heterogeneous Parquet schemas — the Parquet metadata cache incorrectly reused the first file’s metadata for all subsequent files in the archive. #101990 (Ahaan Limaye). - Fix server crash (LOGICAL_ERROR) when executing ALTER TABLE UPDATE/DELETE on Iceberg tables when no prior SELECT or INSERT was done on the table in the same server lifetime. #102113 (Alexey Milovidov).
- Fix possible crash when an ALTER query executed on tables from in-memory database (e.g. temporary tables). #102360 (Den Kalantaevskii).
- Fixed
formatQueryproducing duplicate grants likeGRANT FILE ON *.*, FILE ON *.* TO xinstead ofGRANT FILE ON *.* TO xwhen formatting backward-compatible READ/WRITE grants on the same source. #102411 (Groene AI). - Fix lost parallelism for aggregation after read-in-order queries when
max_streams_to_max_threads_ratiois greater than 1. #102467 (Alexey Milovidov). - Fixed a crash (
LOGICAL_ERROR: Unknown virtual column) when selecting subcolumns (like.nullfor Nullable,.size0for Array, tuple elements, or map keys/values) from a Buffer table engine. #102470 (Groene AI). - Fix exception “Cannot fold actions for projection” in join reorder optimization when a LEFT/RIGHT JOIN with
join_use_nullsis combined with other joins involving more than two tables. #102516 (Alexey Milovidov). - Fixed silent overflow in scalar pointwise operations on numericIndexedVector (e.g.
numericIndexedVectorPointwiseAdd) when the scalar is out of range. Such inputs now raiseINCORRECT_DATAinstead of returning corrupted values. #102546 (FriendLey). - Fix inconsistent AST formatting for INSERT with SAMPLE and query-level OFFSET. Closes #102523. #102547 (zoomxi).
- Fix
LOGICAL_ERRORexception ingroupConcatwhen deserializing a malformed aggregate function state. #102558 (Christoph Wurm). - Now we do not accept garbage at the end of Time64 CSV values with
input_format_csv_use_default_on_bad_values=0. Closes #102490. #102596 (Yarik Briukhovetskyi). - Fix UNKNOWN_ELEMENT_OF_ENUM exception when inserting default value to JSON column with Enum typed paths. Closes #102359. #102687 (Pavel Kruglov).
- Fix columns_substreams.txt corruption during column rename in some cases. Closes #102259. #102689 (Pavel Kruglov).
- Fix inserting into Time data type during JSON parsing. Closes #102016. #102690 (Pavel Kruglov).
- Fix hex encoding of content sample in cached schema filenames. Closes #101904. #102703 (Pavel Kruglov).
- Fixed sort order violation (crash in debug, silent data corruption in release) during
SummingMergeTreemerge when theORDER BYkey is a hash expression over aFloat32column containing signaling NaN values. #102791 (Groene AI). - Make
DETACH DATABASE ... SYNCand other operations that callwaitDetachedTableNotInUsecancellable viaKILL QUERYand responsive to server shutdown, preventing indefinite hangs when a concurrent query holds a table reference. #102804 (Antonio Andelic). - Fixed possible incorrect result of
ANY RIGHT JOIN. #102893 (Nikita Taranov). - Fix S3 requests failing with
ios_base::clear: unspecified iostream_category errorinstead of being retried, caused by PocoBufferedStreamBuf::flushBuffernot handling short writes from the socket layer. #102894 (Sema Checherinda). - Fix
input('auto')table function failing via HTTP interface in INSERT SELECT queries. #102902 (Miсhael Stetsyuk). - Disable trivial LIMIT optimization with row policies/additional_table_filters (to allow parallel index analysis). #102921 (Azat Khuzhin).
- Hide secret key in
HMACSQL function. Fix #102927. #102997 (Mikhail f. Shiryaev). - Fix
MULTIPLE_EXPRESSIONS_FOR_ALIASexception raised on distributed queries that reference the samequantilecall multiple times (e.g. inSELECT,HAVING, andORDER BY) withoptimize_syntax_fuse_functionsenabled. #103014 (tanner-bruce). - Fixes a case found by CI where a not-ready set was passed when the filter depends on the left-side column. Closes #102966. #103029 (Yarik Briukhovetskyi).
- Fix castOrNull to JSON in some cases. Closes #101818. #103036 (Pavel Kruglov).
- Fix
SELECT DISTINCTsilently returning incomplete results when an aggregate projection matched the query and some parts of the table had no projection data (e.g. the projection was added on a table that already held data, andMATERIALIZE PROJECTIONwas not run). Closes #102951. #103052 (Nihal Z. Miaji). - Fix
TOO_FEW_ARGUMENTS_FOR_FUNCTIONexception when aWHEREpredicate such asAND(OR(A, A), A)collapses to a single top-level argument during common expression extraction in the analyzer. #103072 (Peng). - Fix a logical error
Function writeSlice expects same column types for GenericArraySlice and GenericArraySinkraised when evaluatingif/ifNullover tuples, maps, or arrays containing aQBitelement.ColumnQBit::structureEqualsincorrectly compared the inner tuple of oneQBitcolumn against the outer wrapper of the other, so structurally identicalQBitcolumns were reported as different. #103084 (Groene AI). - Make
DETACH DATABASEwithdatabase_atomic_wait_for_drop_and_detach_synchronouslyrespectKILL QUERYinstead of hanging indefinitely when a table reference is held. #103095 (Alexey Milovidov). - Fix segfault when deleting WASM module using non-identifier predicate (e.g.
WHERE 1=1). #103101 (Joe Redfern). - Fix backward compatibility break where old clients fail with
UNEXPECTED_PACKET_FROM_SERVERwhen inserting into a newer server viaremote()or distributed tables, caused by unconditionalsendProgressat the end ofprocessInsertQuery. #103148 (Sema Checherinda). - IN with non-constant tuple second argument must not CAST tuple elements down to the LHS type, this can overflow. Closes #103055. #103169 (Yarik Briukhovetskyi).
- Fix use-of-uninitialized-value in protocol function. #103187 (Pavel Kruglov).
- Fix
LOGICAL_ERROR(Bad cast … to ColumnLowCardinality) during MergeTree index analysis when aWHEREclause compares aLowCardinalitykey column with a constant cast to a type that contains nestedLowCardinality(for exampleVariant(LowCardinality(Date), String)). #103211 (Groene AI). - Fix
Logical error: 'index < bucket_count'in thetimeSeries*ToGridaggregate function family (e.g.timeSeriesResampleToGridWithStaleness,timeSeriesChangesToGrid,timeSeriesResetsToGrid,timeSeriesRateToGrid) when called with extreme timestamp parameters that would overflow signed 64-bit arithmetic in the bucket count computation. Also cap the total number of grid buckets at 16 million to prevent accidental large-memory allocation from adversarial inputs. #103223 (Groene AI). - Fix
Logical error: 'Port is already connected'exception during pipeline expansion in the lazyFINALpath forReplacingMergeTree. The bug affected queries withquery_plan_optimize_lazy_final = 1whenReadFromMergeTree::initializePipelineinserted internal transforms (e.g. aResize) that wired the sub-pipeline’s processors together, causingLazyUnorderedReadFromMergeTreeSource::expandPipelineto try to connect output ports that were already connected. #103230 (Groene AI). - Fix wrong results from
LIMIT BYandDISTINCTwhen the input is aUNION ALLof sorted subqueries. The query plan optimizer incorrectly treated such a union as globally sorted, causing extra rows to be returned. #103231 (Nihal Z. Miaji). - Fix possible crash during statistics calculation in Map type with lazy replication. Closes #102390. #103273 (Pavel Kruglov).
- Fix a data race for ClickHouse, MySQL, PostgreSQL and XDBC dictionary sources where
clone() constreads from andisModified() constwrites to the sameinvalidate_query_responsestring. #103277 (Miсhael Stetsyuk). - Fix incorrect monotonicity detection for
Date32. Closes #101265. #103283 (Yarik Briukhovetskyi). - Cap pre-auth TCP Hello packet strings to 64 KB and add
handshake_timeout_millisecondsserver setting to limit total handshake time, preventing unauthenticated clients from consuming excessive memory or holding threads indefinitely. #103284 (Sema Checherinda). - Fix Parquet ColumnIndex stats min_value > max_value for String columns. #103334 (Saurabh Kumar Ojha).
- Fix incorrect handling of NULL rows for
Nullable(Tuple(...))inputs inflattenTupleandtupleToNameValuePairs.flattenTuplenow preserves the outer null map so NULL rows stay NULL.tupleToNameValuePairsnow changes the result’s value type toNullable(T)when possible when the input isNullable(Tuple(...)), so NULL rows produce[('a', NULL), ('b', NULL)]instead of[('a', 0), ('b', 0)]. When the element type cannot be wrapped inNullable(e.g.Array), default values are used instead of NULL. Closes #103312. #103383 (Nihal Z. Miaji). - Check for malformed flattened Dynamic data in Native format. #103392 (Pavel Kruglov).
- Fix stale RPC causing replication stall after snapshot sync. #103406 (Seva Potapov).
- Fix a
LOGICAL_ERROR“Cannot pop N rows from X” that aborted the server (in debug / sanitizer builds) when reading a malformed BSON document containing a value whose BSON type is incompatible with the target column type inside aNullable(T)orArray(Nullable(T))column. The malformed row now produces a cleanILLEGAL_COLUMNexception as intended. #103418 (Groene AI). - Fix a server abort in
arrayFillandarrayReverseFillwhen applied to anArray(String)column whose first row is empty together with a constant-false lambda. The aggregate / sub-array loop underflowed asize_tindex toSIZE_MAX, which then caused an out-of-bounds read insideColumnString::doInsertManyFrom. Same bug family as #12263. #103424 (Groene AI). - Fixes ACCESS_DENIED / UNKNOWN_TABLE in downstream APPEND RMVs with SQL SECURITY DEFINER when an upstream REPLACE RMV’s EXCHANGE flips the target storage identity mid-resolution. #103427 (Alexander Gololobov).
- Populate
_timecolumn fromurltable function. #103437 (Nikita Taranov). - Fix potential out-of-bounds read in the
ALPcodec decompression path when processing malformed input with an invalid bit-width. #103457 (Raufs Dunamalijevs). - Fix a bug where
SYSTEM SYNC FILESYSTEM CACHE '<name>' ON CLUSTER ...could lose the cache name while formatting the query, causing remote nodes to sync all filesystem caches instead of only the requested cache. #103469 (Asish Kumar). - Fix processing of URL-encoded path in
deltaLakeAzure. Closes #103509. #103525 (Smita Kulkarni). - Fix heap-use-after-free in multiplying an
AggregateFunctionstate by an integer (e.g.quantilesExactState(...) * N). The exponentiation-by-squaring loop merged the state with itself, which is undefined when the aggregate function’smergereallocates its internal storage. Closes STID 0988-40af. #103536 (Groene AI). - Fixed a rare
LOGICAL_ERROR“Part X intersects previous part Y” raised duringReplicatedMergeTreetable startup when two empty unexpected parts on disk had overlapping but non-containing block ranges. The exception aborted the table-attach thread and prevented the table from coming up. #103537 (Groene AI). - Fix
Logical error: Incorrect mark rows for part ...(debug-only assertion) that was triggered by mutations onMergeTreetables with non-adaptive index granularity (index_granularity_bytes = 0) whose last data mark was incomplete (most reliably reproduced viaDETACH/ATTACHfollowed by a lightweightDELETE). #103538 (Groene AI). - Fix
clickhouse-localreturning 0 rows silently when reading from/procand/syspseudo-files via thefile()table function (e.g.SELECT * FROM file('/proc/cpuinfo', 'RawBLOB')). #103548 (Ashrith Bandla). - Fixed handling of the
max_string_lengthargument for theGenerateRandomtable engine. #103550 (Alex Kuleshov). - Fix masking nested credentials in logs. #103552 (Vitaly Baranov).
- Fix SVE detection using SVE instructions when unavailable. #103568 (Raúl Marín).
- Fix
GenerateRandomstorage args parsing. #103574 (Konstantin Bogdanov). - Fix infinite loop on
WITH FILLfor data starting with ±inf. #103580 (Konstantin Bogdanov). - Fix
JSONExtractinto aVarianttype silently truncating fractional JSON numbers. Previously,JSONExtract('{"x": 3.14}', 'x', 'Variant(Int64, Float64)')returnedInt64=3andJSONExtract('{"x": 3.14}', 'x', 'Variant(String, Int64)')returnedInt64=3, dropping the fractional part. The fractional value is now preserved losslessly: aFloat64/Decimalmember claims it when present, otherwise aStringmember captures the original JSON.Varianttypes containing only integer members (e.g.Variant(Int64, Int32)) and direct integer extraction (JSONExtract(json, 'Int64'),JSONExtractInt, etc.) are unchanged. #103620 (Groene AI). - Fix
SYSTEM INSTRUMENT REMOVEwithout arguments producingstd::bad_optional_access(error code 1001) instead ofSYNTAX_ERROR(error code 62). #103622 (Pablo Marcos). - Fix logical error / undefined behavior in
windowIDandtumblewindow view when called with a timezone string as the 3rd argument. #103641 (Alexey Milovidov). - S3 client logging now treats HTTP 400 responses that include a non-empty x-amz-bucket-region header (wrong SigV4 signing region) as an informational wrong-region case with a clearer log line instead of the generic error-style path. The STS web identity credentials provider is added to the S3 credentials chain only when web identity is configured, which reduces spurious warnings for deployments that do not use it. Closes #99140. #103673 (MeltonSmith).
- Fix
SYSTEM SYNC REPLICA <db>.<tbl> IF EXISTSto silently succeed when the database does not exist, matching the existing behaviour for a missing table and the precedent set byDROP TABLE IF EXISTS. Previously the query threwUNKNOWN_DATABASEdespiteIF EXISTS. Closes #103629. #103689 (Groene AI). - Fix logical error
Arguments of 'plus' have incorrect data typesthrown byFunctionBinaryArithmetic::executeImpl2when aMergeTreetable hadArray(LowCardinality(...))in its sort key and aWHEREclause usedplus/minusbetween that column and anArrayconstant of a different element type.KeyCondition::getMonotonicityForRangenow stripsLowCardinalityrecursively before invoking the inner numeric dispatch. #103701 (Groene AI). - Fix dynamic cache resize race in 26.1+. #103702 (Kseniia Sumarokova).
- Fixed an issue where text and bloom_filter skip indices on
ALIAScolumns whose expression contained a lambda with captured constants (e.g.arrayMap((k, v) -> concat(k, '=', v), mapKeys(m), mapValues(m)))were silently ignored. #103708 (Anton Popov). - Fix
positionandpositionCaseInsensitivewith astart_posclose toUINT64_MAXgetting stuck or causing a segmentation fault due to overflowing pointer arithmetic. #103766 (Raúl Marín). - Fixes undefined behavior while parsing dateTime with a double fractional part. #103773 (Yarik Briukhovetskyi).
- Fixed a data-correctness regression in 26.x where JIT-compiled
ifandmultiIfwith aDecimalresult type and a non-Decimal(integer or float) literal in one branch silently returned a value10^scaletoo small. The slow (non-JIT) path was unaffected. Workaround on affected versions:SET compile_expressions = 0. #103809 (Groene AI). - Fixes forwarding the tokenizer from the text index to supported functions. #103826 (Elmi Ahmadov).
- Fix wrong results from
numbers,generate_series, and similar range-honoring sources when theWHEREclause usesINorNOT INover a tuple whose elements deduplicate to a single key column (for example,WHERE tuple(number, number) NOT IN (tuple(1, 2))). Closes #103660. #103835 (Groene AI). - Keep the auto-spilling hash join’s actual memory peak under
max_bytes_before_external_join. Previously, statistics-driven preallocation, in-place hash table doubling, and unboundedGraceHashJoinin-memory buckets could each push the query past the configured cap and tripMEMORY_LIMIT_EXCEEDED. #103838 (Alexey Milovidov). - Fix a hang in
clickhouse-localshutdown when system logs (such astext_logorfilesystem_cache_log) are configured.SystemLogs::flushImplwas callingBaseDaemon::instance().flushTextLogs(), which throwsstd::bad_castoutsideclickhouse-serverand left the saving threads running untilpthread_cond_destroyblocked the destruction of the system log queues. #103874 (Alexey Milovidov). - Reject
MATERIALIZEDCTE queries whose body resolves to different inferred column types in different references with a clearTYPE_MISMATCHerror instead of crashing the server with aBad castLOGICAL_ERROR. This previously happened when the CTE body referenced identifiers from outer scope (for example an alias from the calling subquery’s projection) that were inlined as different constants per reference. #103879 (Groene AI). - Fix a use-of-uninitialized-value in the JOIN-conversion query plan optimizers (
tryConvertAnyOuterJoinToInnerJoin,tryConvertAnyJoinToSemiOrAntiJoin) when the filter on top of anANYOUTERJOINcontains a non-deterministic function such asrand,now, orrowNumberInAllBlocks. The optimizer no longer attempts to constant-fold such filters and leaves the JOIN unchanged, which also prevents incorrect conversions toINNER/SEMI/ANTI JOINthat could silently drop rows. #103880 (Groene AI). - Fix a use-after-free in
StorageKafka2that could crash the server when a Keeper session is replaced while the consumer is holding ephemeral topic-partition locks. #103890 (Groene AI). - Fixed a
LOGICAL_ERROR“Primary key type mismatch” thrown when joining anEmbeddedRocksDBtable viaJOIN ... USING (key)against a subquery whose key column has a different type (e.g.Nullable(UInt64),Int64,Decimal) than the storage’s primary key. The planner now declinesDirectKeyValueJoinon type mismatch and falls back toHashJoin, which handles the type conversion. #103928 (Groene AI). SET max_threads = DEFAULT(and the same formax_final_threadsandmax_parsing_threads) no longer loses the auto state. Previously, after resetting one of these settings,system.settingswould report the resolved core count (e.g.32) instead of'auto(32)', and the server would behave as if the value had been explicitly pinned. #103991 (Groene AI).- Fix
SIZES_OF_ARRAYS_DONT_MATCHwhen readingAggregateFunction(topK(N), String)columns whose persistedalpha_sizewas grown by a pre-25.12 deserialize+serialize cycle. #104002 (Raúl Marín). - Fixed SQL injection vulnerability in PostgreSQL, Cassandra and XDBC dictionary sources: string keys containing single quotes were escaped with
\'(backslash), which these backends treat as a literal backslash rather than an escape sequence, allowing arbitrary SQL to be injected into dictionary lookup queries.ExternalQueryBuildernow emits SQL-standard''escaping for those backends; ClickHouse and MySQL dictionary sources continue to use backslash escaping. #104009 (Shaohua Wang). - Fixed possible type mismatch in aggregation when a column type was altered to/from LowCardinality, and min-max projection wasn’t rebuilt. #104013 (Nikita Taranov).
- Fix infinite loop of query optimizations caused by not propagating prevention of unused column removal when merging expressions. #104083 (János Benjamin Antal).
- Fix
LOGICAL_ERRORinStreamingStorageRegistry::renameTablewhen batch-renaming streaming tables (S3Queue, Kafka, RabbitMQ) by using UUID-based identity tracking instead of name-based. #104101 (Nikita Taranov). - Fixed wrong results when a CTE constructed with
UNION ALLcontained aSELECT DISTINCTbranch and the outer query projected only a subset of the CTE’s columns. The new analyzer’sRemoveUnusedProjectionColumnsPasswas incorrectly removing the un-referenced column from the innerDISTINCTprojection, causing rows that should have remained distinct (same value in the projected column but different value in the dropped column) to collapse into one. #104114 (Groene AI). - Fix several edge case correctness issues in setting
optimize_inverse_dictionary_lookupwhere the optimization could silently drop rows or suppress exceptions. Closes #103270. Close #103085. #104133 (Nihal Z. Miaji). - Fix write out of bounds while deserializing
quantileTimingstate. #104141 (Alexey Milovidov). - Fix undefined behavior when an out-of-range
Float64value is converted to a wide integer type (UInt64,Int64,Int128,UInt128,Int256,UInt256). Previously, values equal toFloat64(numeric_limits<T>::max())(which rounds up to a value above the actual maximum) bypassed the bounds check and produced UB in the subsequent cast. This affected aggregate-function parameter parsing (topK,histogram,uniqUpTo,groupArrayInsertAt, etc.) and integer-typed settings viaSET <setting> = <Float64>. Closes #103817. #104154 (Groene AI). - Fix
LOGICAL_ERRORexception “Unexpected return type from comparison. ExpectedUInt8. GotConst(Nullable(UInt8))” when comparing a nestedTuple(Tuple(Nullable(...)))(or deeper nesting) with aStringliteral. The comparison’s return type is now correctly inferred asNullable(UInt8), matching the runtime behaviour. #104171 (Groene AI). - Fixed a server abort (
UndefinedBehaviorSanitizer: reference binding to null pointer, segfault in release builds) onSELECT ... FROM <ReplacingMergeTree(version, is_deleted)> FINAL PREWHERE is_deleted = <expr> AND <other column expr>whenquery_plan_optimize_lazy_final = 1. The lazy-FINAL non-intersecting reading step lost theis_deletedcolumn from its output header because prewhere consumed it as an input without re-exposing it as an output. The downstreamaddIsDeletedFilterstep then dereferenced a nullActionsDAG::Nodepointer. #104177 (Groene AI). - When calling system.failpoints table, it would use a failpoint, thus possibly disabling it. #104237 (Pedro Ferreira).
- Fix
MemorySanitizer: use-of-uninitialized-valueindetectLanguage*functions when the input contains a UTF-8 character ending exactly at the buffer boundary. #104257 (Raúl Marín). - Fix a logical error (
Bad cast from type DB::CachedObjectStorage to DB::S3ObjectStorage) that aborted argument parsing of data-lake table functions and engines (icebergS3,deltaLakeS3, etc.) when called withSETTINGS disk = '...'against a disk whose underlying object storage is wrapped by a decorator such as a filesystem cache. Closes #89300. #104258 (Groene AI). - Fix parsing of parenthesized subscript expressions on columns named
values, for example(values['a']), so they are no longer interpreted as SQL-standardVALUEStable expressions. #104312 (Desel72). - Fix a server abort/
LOGICAL_ERRORin the filesystem cache background eviction thread (SLRUFileCachePriority::collectEvictionInfo) that could fire whenkeep_free_space_size_ratioorkeep_free_space_elements_ratiowas high enough to trigger eviction while all cache entries had already been promoted to the SLRU protected queue (probationary empty). #104313 (Groene AI). - Fix exceptions (
NOT_FOUND_COLUMN_IN_BLOCK,LOGICAL_ERROR,AMBIGUOUS_COLUMN_NAME) when using projections with UNION ALL views, window functions, or alias-column name collisions. Regression from #88798. #104317 (Amos Bird). - Fixes a possible underflow in parsing postgres arrays. #104322 (Grant Holly).
- Functions that return a non-
Nullabletype (such asArray,Tuple, orMap) now acceptNullablearguments. Affected functions includeextractAll,extractAllGroups,extractAllGroupsHorizontal,extractAllGroupsVertical,extractGroups,splitByChar,splitByString,splitByRegexp,splitByWhitespace,splitByNonAlpha, andalphaTokens.NULLinput rows produce the default value of the result type (e.g. an empty array) instead of raising “Nested type is not allowed inside Nullable type”. #104326 (Alexey Milovidov). - Fix iceberg stats with partitioned table. This closes #104321. #104329 (Konstantin Vedernikov).
- Fix a fatal logical error at server startup on macOS (and similar jemalloc builds) where
Jemalloc::verifySetupincorrectly reported ajemalloc_enable_background_threadsmismatch because optionalbackground_thread/max_background_threadsmallctls are absent; verification is skipped when those mallctls are unavailable, andgetValueno longer leaves the output uninitialized on failure. Closes #102183. #104330 (SAYON DEEP). - Fix a correctness regression where
SELECTqueries withmax_rows_to_read_leafandread_overflow_mode_leaf = 'throw'could incorrectly throwTOO_MANY_ROWSeven when a skip index would have reduced the read below the leaf cap. The symmetric non-leaf settings (max_rows_to_read/read_overflow_mode) were already handled. #104331 (Groene AI). toUUID,toUUIDOrNull,toUUIDOrZero,toUUIDOrDefault,CASTtoUUIDandNullable(UUID),accurateCastOrNulltoUUID, and the input formats that parse a UUID from text (Avro,MsgPack,JSONExtract, …) now reject strings that have the right length but contain non-hexadecimal characters. Previously such inputs were silently turned into a fabricated UUID by walking off the end of the hex digit lookup table; nowtoUUIDthrowsCANNOT_PARSE_UUID, and theOr*variants returnNULL/ the zero UUID / the supplied default. #104370 (Groene AI).- Fix
Bad castLOGICAL_ERRORincaseWithExpression(and SQLCASE expr WHEN ... THEN ... ELSE ...) when the THEN-only supertype and the (THENs + ELSE) supertype land in differentColumnDecimalstorages — for example THEN values(UInt16, Int8)with an ELSE ofDecimal(9, 2). Closes #104335. #104378 (Groene AI). - Internal failures reported via
logExceptionBeforeStart(asynchronous insert flushes, materialized-view refreshes, parse errors raised during internal queries) now correctly increment theFailedInternalQuery,FailedInternalSelectQuery, andFailedInternalInsertQueryProfileEvents alongside the user-visibleFailedQuery,FailedSelectQuery, andFailedInsertQuerycounters. Previously these internal counters stayed at zero for failures occurring before query execution started, undercounting a major class of internal failures. #104399 (Groene AI). - Fix
Code: 36. BAD_ARGUMENTS Expected literal, got {name:Type}thrown when a query parameter is used inside thebase_backupsetting of aBACKUPorRESTOREstatement (e.g.BACKUP ... SETTINGS base_backup = S3({backup_name:String}, ...)). The regression was introduced in26.1.5by PR #99205. Closes #103324. #104413 (Groene AI). - Fix a server abort in
IcebergLocal/IcebergS3writes whenALTER TABLE ... DROP COLUMNis followed by anINSERTwithiceberg_metadata_staleness_msgreater than zero.ALTERnow invalidates the local Iceberg metadata files cache so subsequent reads and writes see the new schema. #104419 (Groene AI). - Fix
DROP ROLE,DROP USER,DROP SETTINGS PROFILE,DROP ROW POLICY,DROP QUOTAandDROP MASKING POLICYto remove references to the dropped entity from any other access entity that referenced it (e.g. a user’sDEFAULT ROLElist, a settings profile’sTOlist, a row policy’s grantees) and persist the cleanup to disk. Previously the in-memory state appeared correct becauseSHOW CREATEfilters unknown UUIDs, but the on-disk.sqlfiles retained danglingID('<dropped-uuid>')entries and the references were resurrected on the next server restart, surfacing asACCESS_ENTITY_NOT_FOUNDerrors during distributed query execution. #104427 (Groene AI). - Fixed a server abort triggered by
azureBlobStorage,AzureBlobStorage-engine, and DeltaLake-on-Azure with a connection string whoseBlobEndpointURL has an empty, non-numeric, or out-of-range port (e.g.BlobEndpoint=http://host:abc/). The server now returns a cleanBAD_ARGUMENTSerror instead of aborting in debug/sanitizer builds. #104460 (Groene AI). - Allow an unquoted identifier as the user name in the
remoteandremoteSecuretable functions, mirroring how the database and table arguments accept unquoted identifiers. Previously such a query failed with a misleading authentication error referring to thedefaultuser. #104465 (Alexey Milovidov). - Fixed
Logical error: Incorrect ASTSelectWithUnionQuery (modes: M, selects: N)triggered when a SQL user-defined function body contains a parenthesized innerUNION ALL(e.g.CREATE FUNCTION f AS x -> (SELECT 1 UNION ALL (SELECT 1 UNION ALL SELECT 1))). #104477 (Groene AI). - Fix
uniqThetaIntersectreturning the cardinality of the first argument instead of0when the second argument is an emptyuniqThetastate — for example the result ofuniqThetaMergeStateIf(s, predicate)when the predicate excludes every row. #104529 (Groene AI). - Fix
SHOW TABLESandsystem.tablessilently truncating the listing forDataLakeCatalogdatabases backed by Iceberg REST catalogs (iceberg-rest,onelake,biglake). When the catalog server paginates the list-tables or list-namespaces response (e.g. Microsoft Fabric / OneLake beyond ~50 tables per namespace), tables on later pages were silently invisible toSHOW TABLESandsystem.tables, even though they were queryable via directSELECT.RestCatalognow follows thenext-page-tokencontinuation token defined by the Iceberg REST OpenAPI spec, matching the existing behavior ofPaimonRestCatalogandUnityCatalog. #104531 (Groene AI). - The
inputtable function now infers its structure from the surroundingINSERTquery’sFORMATclause when that format has a fixed schema (LineAsString,RawBLOB,JSONAsString, etc.), so users no longer have to repeat the structure asinput('line String')for these formats. #104532. #104533 (Groene AI). - Updated datatype of fields in Iceberg history from
Int32toInt64. Closes #94176. #104579 (Smita Kulkarni). - Fixed
Inconsistent AST formattingLOGICAL_ERRORwhen parsing a function call where a lambda follows a comma, e.g.SELECT substring(x, `x` -> `x`). The parser used to silently merge the preceding arguments into the lambda’s left-hand side, producing a single-argument call that could not be re-parsed back to the same AST. It now preserves the function’s original arity. #104626 (Groene AI). CHECK TABLE tnow prefers aTEMPORARYtable over a permanent one with the same name when no database qualifier is given, matching the precedence already used bySHOW CREATE TABLE,DESCRIBE TABLE,OPTIMIZE TABLE, andALTER TABLE. PreviouslyCHECK TABLE tskipped temporary tables entirely, so it failed withUNKNOWN_TABLEon a temporaryLogorFiletable even though those engines supportCHECK. Follow-up to #100966. #104637 (Groene AI).- Fix Keeper termination and restart loop when
get /keeper/availability_zoneis sent withquorum_reads=trueto a Keeper without<placement>configured. #104663 (myeongjun). - Fix a TOCTOU data race in
FutureSetFromTuple::buildOrderedSetInplacethat results in a logical error. #104673 (Miсhael Stetsyuk). - Fix several functions returning different results for the same input depending on whether arguments arrived as columns or constants:
bitRotateLeft/bitRotateRight(boundary shift counts),length(FixedString)/concatWithSeparatorwithLowCardinality(Nullable)inputs,roundDownon NaN, andrightUTF8on invalid UTF-8. #104710 (Raúl Marín). - Fixed
anyHeavyreturning a non-heavy value when the most frequent value was the column default and the data lived across multipleMergeTreeparts (sparse-column read path). #104712 (Raúl Marín). - Fix several defects in setting-constraint handling:
MergeTreeSettingsconstraints declared on a setting’s canonical name could be bypassed by writing to an alias of that setting; thedisallowed_valuesconstraint check threw an exception on clamp paths (secondary queries,ON CLUSTERworkers,SQL SECURITY DEFINERviews) instead of silently dropping the change. #104737 (Raúl Marín). - Fix a
LOGICAL_ERRORexception (Metadata is not initialized) raised byOPTIMIZE TABLE,ALTER TABLE ... DELETE,ALTER TABLE ... ADD COLUMNand other ALTER variants on a lazily-attachedIceberg/IcebergLocal/DeltaLake/Huditable whose metadata had not been loaded yet (typical after a server restart, or after a previous metadata write failed and left a corrupted metadata file on disk). The operation now either proceeds normally if the metadata loads successfully, or surfaces the underlying load failure as a regular user-facing exception instead of aborting the server in debug / sanitizer builds. #104738 (Groene AI). - Fix segfault due to a use-after-free bug in
AvroConfluentRowInputFormat. #104751 (Miсhael Stetsyuk). - Scalar variants of
numericIndexedVectorPointwiseMultiply,numericIndexedVectorPointwiseDivide,numericIndexedVectorPointwiseEqual, andnumericIndexedVectorPointwiseNotEqualnow raiseINCORRECT_DATAwhen called with aUInt64scalar aboveInt64::max. #104784 (FriendLey). - Fix a bug where manually overriding a setting via its alias name (e.g.
SET enable_analyzer = 1instead ofSET allow_experimental_analyzer = 1) after applying acompatibilitysetting could cause that override to be reverted by a subsequent change of thecompatibilitysetting. #104829 (Raúl Marín). - Fix AWS logger being disabled after https://github.com/ClickHouse/ClickHouse/commit/0e8ad4355c9d. #104837 (Konstantin Bogdanov).
- Fix three more functions returning different results for the same input depending on whether arguments arrived as columns or constants:
transform(andcaseWithExpressionthrough it) with a constantDate/Date32/Enum/FixedStringdefault, comparison operators between aStringand a constantFixedString, andif/ifNull/nullIfwith aFixedStringbranch under a constant condition. #104858 (Raúl Marín). - Fix
Bad cast from type DB::ColumnConst to DB::ColumnNullableserver abort during partition pruning forMergeTreetables when the partition expression contains a function chain that collapses to a single constant value (such asfloor(NULL, toRelativeYearNum(...))). #104861 (Groene AI). - Fix a
ThreadSanitizerdata race in theContextDatacopy constructor:table_function_resultswas copied from the source object without acquiringtable_function_results_mutex, so a concurrentContext::executeTableFunctionwriter could race against the unsynchronized read in the copy constructor. #104879 (Groene AI). - Fix data part consistency checks for types with dynamic structure and detect corrupted columns_substreams.txt. Resubmit of https://github.com/ClickHouse/ClickHouse/pull/103858 with additional changes. #104888 (Pavel Kruglov).
- Fix race between DROP and UNDROP in DatabaseCatalog. #104915 (Azat Khuzhin).
- Fix filesystem cache dynamic resize with partially downloaded segments, including restore accounting after failed eviction. #104921 (Antonio Andelic).
DETACH TABLEon a temporary table (without theTEMPORARYkeyword) now correctly raisesSYNTAX_ERROR, matching the behavior ofDETACH TEMPORARY TABLE. Previously it silently set an internalis_detachedflag and returned without error. To remove a temporary table, useDROP TEMPORARY TABLEorDROP TABLE(the latter resolves the temporary table viaContext::ResolveExternal). Closes #103475. #104943 (Groene AI).- Make the
filesystemtable function honormax_memory_usage/max_server_memory_usagewhen loading file content. Previously, large or numerous parallel content reads could push past the limit without raisingMEMORY_LIMIT_EXCEEDEDand end up OOM-killed instead. #104956 (Alexey Milovidov). - Fixed a
LOGICAL_ERRORthrown when filteringsystem.detached_tablesbyuuid(e.g.SELECT count() FROM system.detached_tables WHERE uuid = '...'). The query now returns the expected result instead of aborting the server. #104979 (Groene AI). flattenTupleno longer raises aLOGICAL_ERRORwhen called on a tuple whose nested structure contains only emptyTuple()leaves (e.g.Tuple(c0 Array(Tuple()))orTuple(c0 Tuple())). Such inputs now produce a user-facingILLEGAL_TYPE_OF_ARGUMENTexception explaining that the flatten result would be an empty tuple. #104989 (Groene AI).- Fix a server abort and a silent-wrong-result bug when querying
loop(remote(...))(or anyloop()wrapping a storage that can defer aggregation) withGROUP BY. The outer planner used to addMergingAggregatedStepbased on the inner storage’s reported processing stage, butLoopSourcealways materialises its inner select withQueryProcessingStage::Completeand emits plain column chunks, soMergingAggregatedTransformtripped aLOGICAL_ERROR(Chunk info was not set for chunk in MergingAggregatedTransform) underenable_parallel_replicas = 1and silently dropped the outer aggregation otherwise. #105001 (Groene AI). clickhouse-benchmark --reconnect(bare, no value) was inadvertently broken in 25.4 by a change that turned--reconnectinto an integer option, requiring a value. The bare form now works again and is equivalent to--reconnect=1(reconnect on every query). #105006 (Groene AI).- Fixed malformed JSON output for column names ending with incomplete UTF-8 sequences. #105012 (Pablo Marcos).
- Fix silent data loss after
EXCHANGE TABLESorCREATE OR REPLACE TABLEof a materialized view’s source table. TheMV’s source-view dependency edge is now kept on the original name so it continues to fire on inserts. Regression introduced by #98779; restores the pre-regression behavior. #105029 (Sema Checherinda). - Fix
CANNOT_COMPILE_CODE Could not find symbol __fixunsdftiwhen JIT-compiling expressions that convert aFloattoUInt128, such astoUInt128(<Float64 expression>). The unsigned 128-bit float-to-int compiler-rt builtins were missing from the JIT symbol resolver. Closes #105031. #105048 (Raúl Marín). - Fix
clickhouse-localnot printing log messages from a failed query whensend_logs_levelis set. #105067 (Alexey Milovidov). - Fix incorrect results when the same parameterized view is referenced more than once in the same query with different argument values. Previously, the analyzer collapsed the calls into one, silently dropping all but the first filter. #105170 (Alexey Milovidov).
- Fix
TOTALSrow being rendered twice at the bottom of the result table in theplay.htmlweb UI. #103803 (Alexey Milovidov). - Reject non-finite vectors (
NaN,±Inf) during vector search (either as searched vectors or as reference vectors); they previously caused undefined behavior inusearch. #104079 (Groene AI). - PromQL: fix the aggregation operator for empty vectors. #104425 (Vitaly Baranov).
- PromQL: fix error handling in the Prometheus query API. #104741 (Vitaly Baranov).
- Fix a race in
MergeTreeTransaction::afterCommitwhere, after a connection loss between writing the commitCSNto ZooKeeper and finalizing the transaction, theCOMMITresponse could reach the client before the newcreation_csn/removal_csnbecame visible insystem.parts. #104708 (Tuan Pham Anh). - Fix exponential memory growth in the KQL parser when converting nested array indexing (
arr[arr[arr[...]]]). #105142 (Alexey Milovidov). - Fix incorrect results for
RIGHT ANY JOINwhen the right table has multiple rows per key and the output block is split due to size limits. Closes #99431. #102064 (Vladimir Cherkasov). - Check for stack overflow in
Avroreader during nested-type deserialization. #102417 (Pavel Kruglov). - Fix duplicate rows in
system.completionsforMergeTreesettings — each setting name appeared twice because bothgetMergeTreeSettingsandgetReplicatedMergeTreeSettingswere dumped despite having identical setting names. Closes #102013. #102015 (Groene AI). - Fix
StorageObjectStorageQueue(S3Queue,AzureQueue) blocking shutdown until partially-processed files were fully read from object storage. The source now aborts the read immediately on shutdown; deduplication ensures rows already streamed into the destination table before shutdown are not duplicated when the file is retried on next start. #103126 (Tuan Pham Anh). - Fix multi-block inserts to the
Aliastable engine withinsert_deduplication_tokenso that all blocks are kept. #103246 (Enric Calabuig). - Fix
JSONHasandJSONExtractBoolon nativeJSONcolumns returning the extracted value (cast toUInt8) instead of0/1. #103313 (zxuhan7). - Protect the
CustomSeparatedinput format against malformed or adversarial data that omitsformat_custom_row_after_delimiter. Header detection, schema inference, and variable-column rows previously accumulated fields unboundedly and could allocate many gigabytes of memory before failing. Reads now fail withINCORRECT_DATAonce a single row contains more than 1,000,000 fields. #103404 (Groene AI). - Fix
RESTOREof replicatedMergeTreetables so that restored part attachment usesbackup_restore_keeper_max_retriesinstead of the regular insert Keeper retry budget. #104610 (Pablo Marcos). - Fix wrong results from
WHERE p AND <LowCardinality(Nullable(int)) constant>onMergeTreetables. Previously such queries returned zero rows because part pruning derived aNULLdefault from theLowCardinality(Nullable(...))type and synthesized anotEquals(x, NULL)guard, pruning every part. #104767 (Groene AI). - Fix incorrect aggregation result when grouping by a non-injective function of a column that is also the partition key (e.g.
PARTITION BY awithGROUP BY intDiv(a, 2)ora % 2). Values from different partitions that mapped to the same group were not merged, producing duplicate group rows underallow_aggregate_partitions_independently = 1. #104869 (Nihal Z. Miaji). - Fix a race in
Keepersnapshot transfer where a snapshot could be removed or moved while it was being sent to a recovering follower. #104941 (Antonio Andelic). - Fix a silent wrong-result bug in
hilbertEncodeandmortonEncodewhere a non-constantTuplefirst argument (range mask) used row 0’s values to drive the bit-shift for every row. The functions now compute the per-row mask values, so the result no longer depends on the input being constant or on the block size. #104992 (Groene AI). - Fix
clickhouse-localsilently ignoring user-level configuration (profiles,users,quotas, access-control settings) when the configuration file is auto-discovered from./clickhouse-local.xml,~/.clickhouse-local/config.xml, or/etc/clickhouse-local/config.xml. Previously these settings were applied only when--config-filewas passed or./config.xmlexisted in the current directory; now all discovery paths behave consistently. #105008 (Groene AI). - Fix
BFloat16columns silently returning zero matches when compared against a string literal (e.g.WHERE bf16_col = '49.9'). #105042 (Raúl Marín). - Fix
CLEAR COLUMNand TTL handling during merges forSummingMergeTree,AggregatingMergeTree, andCoalescingMergeTreewhen merge-required columns are absent or expired. Closes #101953. #105203 (Antonio Andelic). - Fix a race between
DNSCacheUpdater::runandContext::reloadClusterConfigby adding an explicit null-guard forshared->clusters_configbefore dereferencing it. #105220 (Mikhail f. Shiryaev). - Fix
best_effortdate-time parsing fortoDateTime64withmsandnsprecision. #105233 (Kaviraj Kanagaraj). - Fix
OSIOWaitMicrosecondsreporting thread-lifetime I/O wait instead of per-query I/O wait. #105246 (Mikhail f. Shiryaev). Huditable engine now raisesINCORRECT_DATA(a regular query-level exception) instead ofLOGICAL_ERRORwhen a parquet file in the table directory does not match the Hudi[FileId]_[FileWriteToken]_[Timestamp].[extension]naming convention. Previously such file names caused an exception in debug builds. #105266 (Groene AI).- Fix deadlock in
ParallelFormattingOutputFormaton schedule failure: whenscheduleFormatterThreadForUnitWithNumberthrows (e.g.CANNOT_SCHEDULE_TASK), the unit was left inREADY_TO_FORMATwith no formatter thread to process it, leading to a hang. The schedule call is now wrapped intry/catchand any failure is routed throughonBackgroundExceptionso the collector exits cleanly. #105275 (Azat Khuzhin). - Fix silent data loss in
Distributedasync inserts when recovering from an abnormal shutdown: if the last.binfile in a saved batch was intact but a middle one was corrupted,DistributedAsyncInsertBatch::recoverBatchwould only validate the last file’s header and thensendBatchwould mark the entire batch — including the intact files — as broken, losing their rows. Each file’s header is now validated individually so only the actually broken file is moved tobroken/and the surviving rows reach the remote shard. #105281 (Groene AI). - Fix a regression in
clickhouse extract-from-config --try: when the config usedfrom_envattributes and had noinclude_fromelement (or had one pointing to a missing file), allfrom_envsubstitutions were silently dropped and returned empty strings. This broke the Docker entrypoint port discovery in 26.2.5. Closes #101704. #105283 (Groene AI). - Fix
INSERT INTOaSQLitetable failing with a SQLite syntax error when the inserted value is anEnum,JSON, orAggregateFunctionwhose text representation contains a single quote. Theoutput_format_values_escape_quote_with_quotesetting is now honored by the corresponding serializations (previously onlyStringandFixedStringhonored it). #105285 (Groene AI). - Fix
Code: 44. ILLEGAL_COLUMN: Cannot add column ...: column with this name already existsthrown by distributed queries withallow_push_predicate_ast_for_distributed_subqueries = 1(the default) when aGLOBAL INtuple is matched against a subquery whose projection contains duplicate column names, e.g.(x, y) GLOBAL IN (SELECT number, number FROM numbers(5)). #105290 (Groene AI). - Fix
reinterprettoArray(LowCardinality(...))returning a confusingNOT_IMPLEMENTEDerror at runtime; it now returnsILLEGAL_TYPE_OF_ARGUMENTduring type checking. #105301 (Raúl Marín). minMap/maxMap(array form) andminMappedArrays/maxMappedArraysnow treatNaNconsistently withORDER BY:NaNis treated as last (returned only when all values areNaN). Previously, results depended on the position ofNaNin the data due to IEEE 754 unordered comparison semantics, and disagreed with theMap-argument form ofminMap/maxMapthat was fixed in #100448. #105331 (Raúl Marín).- Fix a memory leak in the per-table
ColumnsDescriptioncache forMergeTree-family tables withNestedcolumns. Entries were never evicted acrossALTER ADD COLUMN/DROP COLUMNcycles whenshare_nested_offsets = 1(the default). #105376 (Groene AI). - Fix
BAD_ARGUMENTSexception “It’s a bug! Only integer types are supported by__bitWrapperFunc” thrown when aSELECTwith aTYPE set(N)skip index has aWHEREatom whose result type isFloat,BFloat16, or any other non-integer type (for exampleWHERE c0 + 0.1orWHERE log(c0)). The skip index now falls back to the regular filter path in that case. #105384 (Groene AI).
Build/Testing/Packaging Improvement
- Stop using the system
compiler-rtlibraries and headers. Closes #91475. #102857 (Konstantin Bogdanov). - Refresh the distroless Docker base image to fix OpenSSL CVEs in
libssl3t64. #103583 (Rahul Nair). - Reliably receive the GPG key during releases by chaining multiple Ubuntu keyservers, instead of timing out on
keyserver.ubuntu.com. #103834 (Mikhail f. Shiryaev). - Remove and forbid build-time
CMakechecks (check_*,try_compile,try_run). The compiler and toolchain are fixed, so feature detection at configure time is unnecessary and is now blocked project-wide; any version-specific behaviour must be gated onCMAKE_CXX_COMPILER_VERSIONexplicitly. #103980 (Alexey Milovidov). - Bump
libarchivefrom 3.8.6 to 3.8.7. #104047 (Robert Schulze). - Update
mongo-c-driverto 2.3.0. #104300 (Raúl Marín). - Update LLVM dependencies for 22.x. #104381 (Joshua Carp).
- Make the embedded-client and PTY descriptor classes build on macOS and FreeBSD by using portable POSIX
posix_openpt/grantpt/unlockptand removing Linux-only#ifguards. #104436 (Alexey Milovidov). - Upgrade
librdkafkato version 2.14.1. #105222 (János Benjamin Antal).
ClickHouse release 26.4, 2026-04-30. Presentation, Video
Backward Incompatible Change
- The
INoperator now uses exact value semantics forBooltype: only0and1values in the set matchBoolvalues. Previously, numeric values greater than255in theINset were incorrectly clamped to true when compared againstBool, soSELECT CAST(1, 'Bool') IN (256)returned 1. Now it correctly returns0. Closes #92980. #93115 (Ashrith Bandla). - The H3 library has been updated to v4, which improves the precision of length, area, and other metric calculations. This change is backward incompatible because the new results differ from previous ones. #100348 (Alexey Milovidov).
- Disallows using
SELECTas a bareword identifier in aWITHexpression list element. #101059 (Aruj Bansal). - This patch changes how the merge table will handle virtuals. If the underlying table contains
_tableor_database, these columns will be read from storage; otherwise, they will be filled after the read step using the expression step. #101742 (Mikhail Artemenko). - The
INoperator now rejects lossyDecimalconversions inside composite types (Tuple,Array,Map) as well, making its behavior consistent with top-level scalar comparisons. Previously, precision checks were enforced only for top-level scalar values: for example,CAST('33.3', 'Decimal64(1)') IN (33.33)correctly returned0, butCAST(['33.3'], 'Array(Decimal64(1))') IN ([33.33])incorrectly returned1because the lossy conversion happened inside anArray. Now both cases correctly return0. #101812 (Nihal Z. Miaji). - Reduced default
http_max_fieldsfrom 1,000,000 to 1,000 andhttp_max_field_name_sizefrom 128 KB to 4 KB to limit pre-authentication memory usage by HTTP connections. Addedhttp_max_request_header_sizeandhttp_headers_read_timeoutsettings. Users who rely on the previous higher limits can restore them via settings. #103285 (Sema Checherinda).
New Feature
- Add automatic spilling to hash and parallel hash joins by converting them to grace hash join when memory limit is reached. This behavior is controlled by
max_bytes_before_external_join. #97813 (János Benjamin Antal). - Add Arrow Flight SQL support. #91170 (Yakov Olkhovskiy).
- Add incremental read support for
Paimontable engines with Keeper-backed snapshot progress tracking, including targeted snapshot delta reads viapaimon_target_snapshot_id, and extend test coverage for type mapping, partition pruning, and incremental read scenarios. #93655 (XiaoBinMu). - The
stemfunction is now non-experimental (previously, settingallow_experimental_nlp_functionshad to be enabled). #102399 (Jimmy Aguilar Mena). You can now stem all the words/tokens in columnsString,FixedString,Array([Fixed]String),Nullable,LowCardinalityandConsteasily with thestemfunction. #99137 (Jimmy Aguilar Mena). - Implement new behavior of
max_insert_block_size_rows,max_insert_block_size_bytes,min_insert_block_size_rows,min_insert_block_size_bytesin squashing under compatibility settinguse_strict_insert_block_limits. #94207 (Kirill Kopnev). - Add function
arrayAutocorrelation(arr [, max_lag])that computes the normalized autocorrelation of a numeric array for each lag. Supports integer, float, and decimal array types. #94776 (Wenyu Chen). - A SQL function
obfuscateQuery. Closes #98010. #98305 (Xuewei Wang). - Add support for Map and JSON/Object types as dictionary attributes. Now dictionaries can store and retrieve complex types including Map(String, String), Map(String, Array(String)), JSON, and Nullable(JSON) types in both FLAT and HASHED layouts. #98627 (yanglongwei).
- Added two new MergeTree settings —
replicated_fetches_min_part_levelandreplicated_fetches_min_part_level_timeout_seconds— that allow replicas to skip fetching freshly-inserted (unmerged) parts from peers, reducing replication overhead during heavy ingestion. #98625 (tanner-bruce). - Add MergeTree skip index support for JSON columns using JSONAllPaths with bloom_filter, tokenbf_v1, ngrambf_v1, and text (inverted) index types, enabling granule skipping based on the set of JSON paths present in each granule. #98886 (Pavel Kruglov).
- The
printffunction now supports non-constant format strings, allowing different format patterns per row based on column values. #98991 (Yash ). - Add a new projection index,
commit_order, that reorganizes data in insertion order. #99004 (Mikhail Artemenko). - Add
highlightfunction that wraps occurrences of search terms in a text string with HTML tags (default<em>/</em>). Supports ASCII case-insensitive matching, automatic merging of overlapping matches, and custom open/close tags. #99131 (Peng). - Implement quotas by normalized query hash to protect public ClickHouse services from abuse. 1. Support
NORMALIZED_QUERY_HASHas a quota key type - separate quota buckets per unique normalized query, soCREATE QUOTA q KEYED BY normalized_query_hashtracks each distinct query independently. 2. SupportQUERIES_PER_NORMALIZED_HASHas a quota resource type — limits max executions of any single normalized query within an interval, soMAX queries_per_normalized_hash = 100prevents any one query pattern from running more than 100 times. #99586 (Alexey Milovidov). - Users can now write join queries using the
NATURAL JOINsyntax, which automatically matches on all columns sharing the same name and deduplicates those columns in the result. #99840 (Peter Nguyen). - Support
SET TIME ZONE 'tz'as alias forSET session_timezone. #99883 (phulv94). - Added support for parameterized queries in the Web UI (
play.html): query parameters like{name:Type}are detected and input fields are shown for filling in their values. #100041 (Alexey Milovidov). - Support SQL standard
VALUESclause as a table expression inFROM, e.g.SELECT * FROM (VALUES (1, 'a'), (2, 'b')) AS t(id, val). #100143 (Desel72). - Add PostgreSQL-compatible units to the
EXTRACToperator:EPOCH,DOW,DOY,ISODOW,ISOYEAR,WEEK,CENTURY,DECADE,MILLENNIUM. Also fixEXTRACT(WEEK FROM date)which previously threw an error. #100274 (Alexey Milovidov). - Added support for SQL-standard compound interval literals with
TOrange qualifiers, e.g.INTERVAL '1:30' HOUR TO MINUTE. Internally decomposed into sums of intervals. #100453 (Desel72). - Add asynchronous metrics for kernel TCP receive and transmit buffer memory (
sk_rmem_alloc,sk_wmem_alloc) of HTTP connection pool sockets, reported as p50/p75/p90/p95 percentiles and totals per connection group. #100575 (Sema Checherinda). - Added a jemalloc profiling web UI for ClickHouse Keeper, available at
/jemallocon the HTTP control port. #100606 (murphy-4o). - Implement command
SYSTEM FLUSH OBJECT STORAGE QUEUE db.table PATH 'x'for ordered and unordered modes. #100709 (Bharat Nallan). - Added function
JSONAllValuesthat returns all values from aJSONcolumn asArray(String), with values serialized in text representation and ordered by their path names. Added support of text index forJSONAllValuesexpression onJSONcolumns. When a text index is created onJSONAllValues(json_column), it is automatically used to filter queries onJSONsubcolumns (e.g.,json_column.key1 = 'value'). #100730 (Anton Popov). - Adds a new setting
input_format_column_name_matching_modewhich allows different case sensitivities for input formats. #99346 (manerone). - Add
watchcommand toclickhouse-keeper-clientwith watch support inget,exists, andlscommands. #100834 (Den Kalantaevskii). - Added
getChildrenRecursive(ListRecursive) request to ClickHouse Keeper andlsrcommand toclickhouse-keeper-client. This closes #99916. #100998 (Konstantin Vedernikov). - Add new function
arrayTransposetaking a two-dimensional array (matrix) and transposing it:SELECT arrayTranspose([[1, 2, 3], [4, 5, 6]]). #101214 (Vitaly Baranov). auto_statistics_types mergetreesetting defaults to'minmax, uniq'— minmax and uniq statistics are created automatically for all suitable columns in new tables -materialize_statistics_on_insertdefaults to false — statistics are now built during merges rather than at insert time, reducing insert overhead. useSET materialize_statistics_on_insert = 1to restore the old behavior. #101275 (Han Fei).- Add
prefer_dependency_replicarefresh setting for materialized view dependency chains to reduce missing data from cross-replica replication lag. #101591 (Seva Potapov). - Adds a
hasPhrase(aliasmatchPhrase) function for phrase search (continuous sequences of tokens). Search is brute-force, i.e. not supported by the text index yet. #101997 (Elmi Ahmadov). - Add
s3_read_request_duration_microsecondsands3_read_request_byteshistogram metrics to observe S3 GET request connection lifetime and bytes consumed, visible insystem.histogram_metricsand the Prometheus endpoint. #102058 (Sema Checherinda). DateandDate32values can now be added toTimeandTime64values using the+operator, producing aDateTimeorDateTime64result. For example,SELECT toDate('2024-01-15') + toTime('14:30:25')returns2024-01-15 14:30:25. The result is computed in the session timezone, and out-of-range results are handled according to thedate_time_overflow_behaviorsetting. Closes #95914. #102421 (Nihal Z. Miaji).- The text index is now GA and stays enabled regardless of the
compatibilitysetting, preventing unexpected disabling during backup restores or when running in compatibility mode. #101518 (Nikita Fomichev).
Experimental Feature
- Add
ALTER TABLE ... EXECUTE remove_orphan_filesfor Iceberg tables to identify and remove unreferenced files from object storage. #99127 (murphy-4o). - Add
query_plan_optimize_join_order_randomizesetting that randomizes statistics used for join reordering, useful for testing. #100643 (Vladimir Cherkasov). - Add AI function support to ClickHouse, allowing users to call OpenAI and Anthropic endpoints using SQL.
aiGenerateis included as the first such function. #100831 (George Larionov). - Add AI functions:
aiClassify,aiExtract, andaiTranslatefor utilizing LLM APIs in ClickHouse. #100832 (George Larionov). - Added
system.histogram_metric_log, a new system table that periodically snapshots all histogram metrics (e.g. S3/Azure latencies, keeper request processing stages durations). Also, thevaluecolumn ofsystem.histogram_metricschanges toFloat64as it’s more flexible and compatible with the Prometheus data model. #103046 (Miсhael Stetsyuk). The table structure is likely to be changed in future releases.
Performance Improvement
- ClickHouse is now able to prune entire data parts in SELECT queries based on min/max statistics. #94140 (zoomxi).
- Reduce lock contention during readonly operations on ReplicatedMergeTree tables with finished mutations. #95771 (Eduard Karacharov).
- Respect
optimize_read_in_orderwhen reading projections. Closes #89453. #95885 (Andrey Zvonov). - Small set of improvements in Hash Join and Concurrent Hash Join. #96663 (Yarik Briukhovetskyi).
- Optimize
DISTINCTtransform by disablingLowCardinalitycolumns optimization when input data is almost distinct. #97113 (Nihal Z. Miaji). - Performance optimization for
LIKEqueries from #97723. Now these queries can use text indices. #98149 (Elmi Ahmadov). - Vectorized math functions (
exp,log,sigmoid,tanh) are now accelerated on AArch64 (using NEON/SVE) and on FreeBSD/Darwin, where they previously used a slower scalar fallback. #98230 (Raúl Marín). - Queries filtering on
MergeTreeprimary key columns with regexp alternations over literal strings, such as^(abc-1|abc-2), can now use primary key pruning when the alternatives share a common prefix. #98988 (Yash ). - Generalize
ORDER BY ... LIMITtop-k dynamic filtering to supportNullable,String, andCOLLATEtypes. #99033 (murphy-4o). - Speedup hash join on
Int32andInt64keys with small range by using a direct-index hash table. #99275 (Hechem Selmi). - Faster discontinuous queries for
LowCardinalitycolumns with a single dictionary. #99285 (Ivan Babrou). - Speed up
var*Stableandstddev*Stablefunctions forFloat64columns by devirtualizing the inner loop. Note: this enables compiler optimizations (FMA/registers) that alter floating-point results at the ULP level. #99460 (Riyane El Qoqui). - Use optimised Firedancer base58 encode for inputs of 32/64 bytes (automatic for
base58Encode). Allow using optimised base58 decode if decoded result is 32/64 bytes (explicit withbase58Decode('...', 32)or alike). #99461 (Joanna Hulboj). - Enable linker section-based optimizations (
-ffunction-sections,-fdata-sections,--icf=all) to reduce binary size and improve instruction cache utilization. #99474 (Alexey Milovidov). - Fix negative scaling for short queries with aggregation on machines with many cores. When a query reads few marks, the pipeline no longer expands to
max_threadsafter aggregation, avoiding overhead from mostly-empty streams. #99493 (Alexey Milovidov). - Improve the performance of queries with parallel replicas by correctly selecting the reading task size. #99801 (Nikita Taranov).
- Allow prefetching when reading a remote file through the userspace page cache. #99919 (Alexey Milovidov).
- Avoid unnecessary computation of String
.sizesubcolumn during subcolumns enumeration. #99941 (Pavel Kruglov). - Make clickhouse-client’s progress bar less jittery when working from a hotel with clusters with a very large number of replicas. #100145 (Alexey Milovidov).
- Start
MemoryWorkerinclickhouse-localwhen page cache is enabled, so that the userspace page cache can be actually used. #100306 (Alexey Milovidov). - Optimize queries by pushing the
LIMITclause down into theUNION ALL. #100364 (Alexey Milovidov). - Add JIT compilation support for
StringandFixedStringcolumn comparisons inORDER BY, improving merge-phase sort performance by 6–17% for string-heavy sort keys. Co-authored with @lgbo-ustc. #100577 (Raúl Marín). - When
read_in_order_use_virtual_rowis enabled together with the newread_in_order_use_virtual_row_per_blocksetting, virtual row boundary information is now emitted after each block read fromMergeTree, allowing the merge to reprioritize sources mid-stream for parts whose data is fully filtered out byWHERE/PREWHERE/JOIN. Close #99945. #100603 (Vladimir Cherkasov). - Faster Float-to-String conversion for large integer values by extending the
itoafast path with dragonbox-compatible rounding. #100649 (Raúl Marín). - Replace
dragonboxwithzmijfor 1.5x-3x faster Float-to-String conversion. #100650 (Raúl Marín). - Faster
Int128/UInt128to string conversion by replacing software division with Barrett reduction and unrolling the conversion loop. #100671 (Raúl Marín). - Avoid spawning redundant threads in
uniqExactparallel merge. #100686 (Jiebin Sun). - Add batch parallel merge for
uniqExact. #100687 (Jiebin Sun). - Better parallelization of queries with simple views (with underlying
MergeTreetable) executed with parallel replicas. #100815 (Igor Nikonov). - Implements support of parallel replicas over simple views (including eligible
UNION ALLviews overMergeTreetables) whenparallel_replicas_allow_view_over_mergetree=1. This allows to parallelize view’s outer query instead of inner one which increases query parallelization across nodes. #100958 (Igor Nikonov). - Optimise reading in order of the primary key for
full_sorting_mergewhen filters withINare present in the query plan. #101261 (Nikita Taranov). - Optimization allocations/deallocations by caching sampling settings instead of traverse all memory tracker hierarchy. #101267 (Azat Khuzhin).
- Fix significant INSERT performance regression when
deduplicate_insert = 'enable'(default since 26.2) by deferring data hash computation from squashing to the sink and using batch column hashing viaupdateHashWithValueRange, reducing overhead from ~2.5s to ~0.5s for 5M rows with 22 columns. #101494 (Sema Checherinda). - Reduce profiled lock overhead by using
try_lockto avoid timing uncontended acquisitions and removing hold-time measurement. #101502 (Antonio Andelic). - Replace hand-written AVX-512 intrinsics in
arrayDotProductwith platform-independent auto-vectorizable loops, adding AVX2 and ARM NEON support. #101571 (Peng). - Improve performance in
INSERT VALUESforMap,Array, andTuplecolumns when values are passed as escaped strings (e.g.'{\'key\':1}'), avoiding unnecessary fallback to the SQL expression parser. #102119 (Joanna Hulboj). - Fixed excessive
RabbitMQtable engine CPU usage. #102711 (Jaap Elst). - The JOIN order optimizer now infers transitive equi-join predicates from existing join conditions. For example, given
A.x = B.x AND B.x = C.x, the equivalenceA.x = C.xis recognized, allowing the optimizer to consider direct joins between transitively-connected tables. This can improve plan quality for star and snowflake schemas where dimension tables connect through a shared fact table. The feature is controlled by the newenable_join_transitive_predicatessetting (off by default). #98479 (Alexander Gololobov). - Optimize
TRUNCATE DATABASE TABLES LIKEby pre-cancelling merges in parallel. #98597 (Shaohua Wang). - Add monotonicity support for multiply, enabling primary key pruning for
key * constantexpressions. #98983 (Amos Bird). - Cache dictionaries no longer take an exclusive lock in
hasKeys; this reduces lock contention by using a shared lock for cache reads. #100796 (liuguangliang). - Inline VIEW subquery in the query tree to allow more optimisations to be applied to the VIEW. #100830 (Dmitry Novik).
- Optimize cache loading on server startup. #101500 (Kseniia Sumarokova).
- Implement lazy column materialization for ReplacingMergeTree with FINAL in case the predicate is selective enough. #101647 (Nikolai Kochetov).
- Re-enable the
optimize_rewrite_array_exists_to_hasoptimization (off by default since 23.10). It rewritesarrayExists(x -> x = elem, arr)into the much fasterhas(arr, elem)and now correctly skips the rewrite when the array element type andelemare not compatible forhas(e.g.DatevsString), so previously breaking queries continue to work. Closes #71431. #100944 (Alexey Milovidov).
Improvement
- Improved EXPLAIN PLAN pretty=1 output: print top-level query output columns, show join relation labels/symbols with estimated result rows and locality, and include per-step output columns for join/source steps. The changes cover Information Deficit part from #98117. #99462 (Kirill Kopnev).
- Add MergeTree table setting
share_nested_offsets(defaulttrue). When set tofalse, Array columns with dotted names (e.g.n.a,n.b) are treated as independent columns instead of sharing offset files and validating equal array sizes as part of legacyNestedsemantics. #98416 (Amos Bird). - Users can now specify multiple authentication methods in users.xml/yaml configuration (in SQL it was always possible). #91998 (Flip-Liquid).
- Auto reload Raft inter-node connections which are using TLS. #93455 (Evgeny).
- Extend
cast_keep_nullableto work with Dynamic/JSON types. When set, casting NULL from types that can be Nullable will return NULL, otherwise NULL will throwCANNOT_INSERT_NULL_IN_ORDINARY_COLUMNerror. #96504 (Seva Potapov). - Reduced the memory footprint from the internal data structures (
ISerializationobjects) by introducing an object pool. #96563 (Nikita Mikhaylov). - Add support of
passwordandidentityfields to keeper-client XML config. #96800 (Grigorii Sokolik). - Improve
Icebergwrites for the unity catalog. #98162 (Konstantin Vedernikov). - Add setting
finalize_projection_parts_synchronouslyto allow synchronous finalization of projection parts during INSERT, reducing peak memory usage for tables with many projections while preserving existing async behavior by default. #98228 (Amos Bird). - Add
projections_duration_mscolumn tosystem.part_logthat records per-projection merge/rebuild duration in milliseconds. #98292 (Amos Bird). - Improve canceling queries using ExpressionTransform and NumbersRangedSource by KILL QUERY and cancel query (Ctrl+C) in clickhouse-client. #98908 (Roman Vasin).
- Replace the hardcoded
source_table_engineslist with a runtime lookup viaStorageFactory::getAllStorages(). This adds access checks for some missing table engines and closes #71544. #98984 (pufit). - Add a setting to control type mismatch behavior for Variant and Dynamic (throw or return null). #99085 (Bharat Nallan).
- Improve
Icebergand Spark compatibility: fix inconsistent path handling caused by mixed usage of storage paths and metadata paths; enforce thatIcebergtables write down a table location that is either a URL or an absolute path; add a fallback for counting file sizes inAzurebecause some ClickHouse readers don’t support byte counting after traversal; handleversion-hint.txtin a manner compatible with Spark; introduce type-level abstractions that make it harder to mix up path types in the future; add tests forAzureandLocalthat verify cross-engine interoperability without intermediate uploading/downloading; fix usage of position deletes, which previously relied on path inference heuristics where that approach is inappropriate. #99163 (Daniil Ivanik). #100420 (Daniil Ivanik). - Fix possible race condition in
IPartitionStrategy::cached_resultintroduced in https://github.com/ClickHouse/ClickHouse/pull/92844. #99400 (Arthur Passos). - Users can now write ClickHouse Interval datatypes in the Arrow Format. #99519 (Peter Nguyen).
- Adds native support for importing and exporting
UUIDdata types inArrowandParquetformats. Users can now directly query and transfer UUID data between ClickHouse and other data tools without requiring manual string conversions or workarounds. Automated logical inference for top-level UUIDs, and support for explicit schema hint for nested UUIDs. #99521 (Ivan). - Support
7zarchives on object storage. Closes #70968. #99600 (Alexey Milovidov). - Add
ObjectStorageListedObjects,ObjectStorageGlobFilteredObjects,ObjectStoragePredicateFilteredObjects, andObjectStorageReadObjectsProfileEvents for introspection of object storage (S3,Azure, etc.) file listing and reading pipeline. #99778 (Sema Checherinda). - Fix
mergetable function failing withUNKNOWN_IDENTIFIERerror when querying columns not present in all underlying distributed/remote tables. #99833 (Alexey Milovidov). - Now we include commit time in total mutation execution time metric for ReplicatedMergeTree. It was lost after #96376. #99936 (alesapin).
- Add a write-ahead log for blob objects pending removal in
MetadataStorageFromDisk, improving durability and consistency between metadata and remote object storage when objects are deleted. #100019 (Maksim Kita). - Disable AI SQL generation (
??command) in the embedded client (SSH and WebSocket protocols) to prevent access to the server’s environment variables. #100290 (Alexey Milovidov). - Change the interface for Iceberg inserts with the catalog. Deprecate settings:
storage_catalog_type,storage_aws_access_key_id, etc. #100334 (Konstantin Vedernikov). - Render tabs as 4 spaces when pasting into clickhouse-client. Closes #100405. #100416 (Raúl Marín).
- Avoid scanning the whole remote data lake catalog for “Maybe you meant …” table hints when
show_data_lake_catalogs_in_system_tablesis disabled. #100452 (Alsu Giliazova). - Apply
distributed_index_analysis_min_indexes_bytes_to_activateafter partition pruning. #100477 (Azat Khuzhin). - Fix assertion failure in Parquet bloom filter push down when using empty IN/NOT IN clauses. #100543 (zoomxi).
- MinMax column statistics now store the minimum and maximum values as Field (typed) instead of Float64. The serialized format includes the column type name alongside the values. The statistics file version is bumped to V2; files written by older versions require re-materialization (ALTER TABLE … MATERIALIZE STATISTICS ALL). fix #53140. #100605 (Han Fei).
- Update
cppkafkato include fix for Consumer close deadlock. #100612 (Azat Khuzhin). - Object information used for parsing data files in Iceberg now contains the number of file rows and file size in bytes parsed from manifest file. #100645 (Daniil Ivanik).
- Add
use_separate_cache_arenaconfiguration parameter to be able to control separation of the cache memory arena. #100664 (Seva Potapov). - Adds native support for importing Apache Arrow’s
StringViewandBinaryViewdata types into ClickHouseStringcolumns, improving compatibility for Arrow-based ingestion. #100762 (Ivan). - A few Keeper server settings are now hot-reloaded if config file is changed at runtime: max_requests_batch_size, max_requests_batch_bytes_size, max_request_size, quorum_reads. #100773 (Michael Kolupaev).
- Increment profile events
MemoryAllocatedWithoutCheck/MemoryAllocatedWithoutCheckBytesin release build. #100899 (Pavel Kruglov). - Cgroupv2 memory tracking now excludes
slab_reclaimablefrom kernel memory, giving a more accurate measure of non-reclaimable memory usage. #100901 (Antonio Andelic). use_partition_pruning = 0now also disablesMinMaxindex pruning and count optimization on partition key columns, in addition to disabling pruning based on partition keys. #100904 (Nihal Z. Miaji).pretty=1inEXPLAIN [PLAN]now prints expressions in a human readable format. #100927 (Kirill Kopnev).accurateCastOrNullandaccurateCastOrDefaultnow supportTupletarget types, including nestedTupleswithNullableelements. Previously these functions rejectedTupletargets becauseTuplecould not be insideNullable. Closes #100820. #100942 (Nihal Z. Miaji).- Fix chart duplication in Play UI when switching between light and dark themes. #101058 (Alexey Milovidov).
- Update chdig to v26.3.1 (perfetto UI, sparklines to summary for CPU/Memory/Merges/Queries), system.warnings, regexp search in logs). #101092 (Azat Khuzhin). Update chdig to v26.4.3 (perfetto improvements, fixes for sharing via pastila.nl, flamegraph diffs, change settings in realtime). #103145 (Azat Khuzhin).
- You can now have a trailing comma in the
WITHclause before aSELECTquery. #101093 (Aruj Bansal). - Add
compress_per_column_in_compact_partsMergeTree setting to control how compressed blocks are organized within Compact parts. Whentrue(default, preserving current behavior), each column starts a new compressed block, allowing selective decompression. Whenfalse, all columns within a granule are packed into the same compressed block, improving compression ratio and read performance for workloads that always read all columns. #101114 (Amos Bird). - Show table info balloon in Play UI only when hovering over the table name, not the entire row. #101118 (Alexey Milovidov).
- Add engine-specific icons and improve table list UX in the Play UI sidebar. #101134 (Alexey Milovidov).
- Support
Nullable(Tuple)forArrow,ArrowStream,ORC, legacyParquetformats. #101272 (Nihal Z. Miaji). - Display TOTALS row as a table footer in the web UI (play.html). #101286 (Alexey Milovidov).
- Support multi-query mode in the web UI (
play.html): run multiple queries at once with parallel execution ofSELECT-like queries and per-query result display. #101290 (Alexey Milovidov). - Fix column resize in play.html web UI after the result table was refactored into a web component. #101295 (Alexey Milovidov).
- Add ability limit amount of jemalloc profile flushes on MEMORY_LIMIT_EXCEEDED per time interval. #101396 (Azat Khuzhin).
- Added keeper settings
nuraft_streaming_mode(by defaultfalse),nuraft_max_log_gap_in_stream,nuraft_max_bytes_in_flight_in_stream. Closes #90743. #101427 (Kseniia Sumarokova). - Added
CGroupMemoryUsedWithoutPageCacheasync metric that reports cgroup memory usage excluding both the kernel OS page cache and the ClickHouse userspace page cache, mirroringMemoryResidentWithoutPageCache. Also clarified theCGroupMemoryUsedmetric description. #101513 (Francesco Ciocchetti). - Add parser-level syntactic sugar for the SQL standard
OVERLAYfunction syntax. Theoverlayfunction already exists; this adds support for the keyword-based form usingPLACING,FROM, andFORas separators. #101681 (Desel72). - Added column alias
INDEX_LENGTHto system tableinformation_schema.tables, analogous to existing uppercase aliases in this table. #101705 (Robert Schulze). - System table
information_schema.tablesnow ignores inactive table parts. This makes the shown table size values more realistic. #101706 (Robert Schulze). - The
ngramsfunction now rejects invalid ngram lengths. Example:SELECT ngrams('abc', 0)now returns an error. #101922 (Robert Schulze). - A follow-up for #91820 and #90837: filter unsupported algorithms from the error message; run FIPS-specific tests in FIPS builds. #102067 (Mikhail f. Shiryaev).
- Limit cell height to three lines in the Web UI (
play.html), with expandable cells on click. #102154 (Alexey Milovidov). - Added new option that allows to force (virtual/path) style for S3 endpoints. Resolves #82019; #76007 Continue of https://github.com/ClickHouse/ClickHouse/pull/83168. #102378 (Konstantin Vedernikov).
- The
restore_replace_external_engines_to_nullsetting now also skips restoring databases with external engines (e.g.DataLakeCatalog,MySQL,PostgreSQL,S3) instead of failing or initiating external connections. #102400 (Nikita Fomichev). - Add text index analysis support for the
hasPhrasefunction via theHINTmode. #102438 (Elmi Ahmadov). - Treat STATISTICS as read-only in ColumnDependency to fix LOGICAL_ERROR during MATERIALIZE STATISTICS ALL. #102627 (Konstantin Bogdanov).
- Create and populate
system.asynchronous_metric_login keeper-as-server mode. #102664 (Miсhael Stetsyuk). - Add
default_system_log_flush_policy.skip_alias_columnsconfig option to allow omitting ALIAS columns from system log tables, fixing S3-backed system logs that reject ALIAS columns. #102669 (Miсhael Stetsyuk). - Don’t enable auto statistics for system tables. They rarely have chance to use them. #102862 (Han Fei).
- Support
arraytokenizer for the LIKE optimization. #102880 (Elmi Ahmadov). - Send MemoryAllocatedWithoutCheck even in release builds. #103064 (Azat Khuzhin).
- Expose per-thread untracked_memory in system.stack_trace. #103065 (Azat Khuzhin).
Bug Fix (user-visible misbehavior in an official stable release)
- Fix
Block structure mismatch in streamerror caused by unnecessary columns returned from Lazy materialization. Fixes #95191. #96682 (Nikolai Kochetov). - Fix a logical error with data masking policy query with
ON CLUSTER. #97594 (Bharat Nallan). - Fix a bug when using Unity catalog on top of GCS. #98456 (Melvyn Peignon).
DataLakeCatalognow respects the server’shttp_forbid_headersconfiguration when validating theauth_headersetting. #98827 (Michael Anastasakis).- Fix N+1
HeadObjectcalls for S3 brace-expansion globs. #99219 (Konstantin Bogdanov). - Validate setting changes in create queries when the engine itself also supports settings. #99279 (János Benjamin Antal).
- Fixed
ALTER TABLE UPDATE/DELETEfailing withMissing columnserror when a table has a MATERIALIZED column whose expression depends on an EPHEMERAL column. #99281 (Yash ). - Credentials in JDBC, ODBC, and NATS connection strings are now masked in query logs and
SHOW CREATEoutput, preventing accidental exposure of sensitive information. For URI-style connection strings (e.g.{scheme}://{user}:{password}@{host}), only the password portion is masked while the rest remains visible for easier debugging. Thenats_tokensetting is now also masked. #99344 (János Benjamin Antal). - Fix parseDateTimeBestEffort incorrectly parsing words starting with month prefixes in DD-month-YYYY format. Closes #99345. #99350 (Pavel Kruglov).
- Fix ignoring of TABLE_UUID_MISMATCH for non analyzer. #99380 (Azat Khuzhin).
- Fix a bug where explicit settings sent alongside
compatibilityin the same request could be silently ignored when their value matched the server default. #99402 (Raufs Dunamalijevs). - Fixes cases where numbers with leading zeros in hive partitioning path were causing errors. Fixes #98801. #99458 (Yarik Briukhovetskyi).
- Fix heap-use-after-free when a table is dropped concurrently with a running read query (19 occurrences in CI over the last 90 days). #99483 (Alexey Milovidov).
- Fixed a bug in Keeper where a read request could get stuck (causing session to time out) if a different unrelated session on the same server was closed at just the wrong moment. #99484 (Michael Kolupaev).
- Validate column structure before applying patches. #99531 (Seva Potapov).
- Fix vertical merge
rows_sourcesassertion failure whenSYSTEM STOP/START MERGEStoggles rapidly during merge of table withDynamiccolumns. #99532 (Alexey Milovidov). - Fix incorrect partition pruning for
toWeek()that caused queries withWHERE toWeek(date, mode) = Nto return empty results for weeks 49-52 on tables partitioned bytoYYYYMM(date). #99542 (Takumi Hara). - Fix exception in functions operating on ColumnReplicated with unreferenced rows produced by JOIN. #99564 (Hechem Selmi).
- Fix
CLEAR COLUMNnot rebuilding projections and not reevaluation materialized columns that depend on the cleared column, which could cause exceptions or data corruption during subsequent merges. #99565 (Desel72). - Fixed an exception (
Bad get: has Tuple, actual type String) inConditionSelectivityEstimatorwhen a query uses IN with a single scalar query parameter (e.g.WHERE col IN ({p:String})) on a table that has column statistics anduse_statisticsis enabled. #99614 (Ilya Yatsishin). - Part with unknown projections should not be marked as lost forever. #99623 (Sema Checherinda).
- Fix a rare logical error exception during vertical merge when
SYSTEM STOP MERGESandSYSTEM START MERGESare executed concurrently. #99628 (Desel72). - Fix dangling reference in injectRequiredColumns causing crash during merge. #99679 (Tuan Pham Anh).
- Fix undefined behavior in Avro format reader when reading numeric values that overflow the target column type. Now queries fail on overflows instead of silently producing incorrect values. #99697 (asyablue22).
- Fix parsing of shell-style quotes in arguments for the
executabletable function. #99794 (Nikita Semenov). - Fix false-positive abort in
NativeReaderwhen deserializing a Native format stream with a row-count mismatch: changed fromLOGICAL_ERRORtoINCORRECT_DATAso the error is handled as a data error rather than triggeringabort()in sanitizer/debug builds. #99822 (Rahul Nair). - Fix process abort in
Tuplecolumn deserialization when the serialization kind in the binary stream isDETACHED. #99823 (Rahul Nair). - Fix false
LOGICAL_ERRORexception during filesystem cache dynamic resize due to a race condition in SLRU sub-queue promotion. #99850 (Alexey Milovidov). - Fix async insert queries reporting zero
written_rows,read_rows, andresult_rowsinquery_logand client output. #99879 (Sema Checherinda). - Fix exception “Bad cast from type X to Y” in
KILL QUERYwhen the internal query against system tables returns columns wrapped inColumnConst. #99881 (Alexey Milovidov). - Fix logical error with correlated subquery within untuple argument. #99917 (Vladimir Cherkasov).
- Fixes an exception when calling
right,rightUTF8, or other substring functions with a length of INT64_MIN (-9223372036854775808), which previously caused undefined behavior due to integer overflow. The functions now correctly report an ARGUMENT_OUT_OF_BOUND error. #99934 (Jimmy Aguilar Mena). - Now ClickHouse should properly handle spark-style tables (where we have full absolute path for each file or relative path to common table path). Fixes #92348. #99935 (alesapin).
- Fix “Inconsistent AST formatting” exception for
ALTER TABLE ... MODIFY QUERYwith nested subqueries containingSETTINGSwhen theALTERitself also hasSETTINGS. #99938 (Nikita Mikhaylov). - Revert #97114 “Move join step row estimation before check for 1 child” due to suspected performance regression. #99957 (Alexander Gololobov).
- Fixes a bug where ClickHouse could skip files if the
Content-Lengthheader was missing in their HEAD request response (for example, because of decompressive transcoding in GCS). #99971 (Yarik Briukhovetskyi). - Fix assertion failure (exception in debug builds, incorrect results in release builds) when multiplying
NumericIndexedVectoraggregate states by an even integer constant, caused by self-XOR on aliased Roaring bitmaps inpointwiseAddInplace. #99976 (Desel72). - Prevent
Unexpected return typeexception in legacy filter pushdown through chainedJOIN USINGwhen key types change after join conversions. #99999 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception “Unexpected node type for table expression … Actual IDENTIFIER” when a scalar subquery is used inside an unresolved table function argument, e.g.SELECT * FROM remote('localhost', view(SELECT 2 AS x), concat(x, (SELECT 1))). #100014 (Alexey Milovidov). - Fixed
INSERTwithVALUESfailing when the data was followed by a trailing SQL comment (--or/* */) on the next line. The comment is now skipped instead of being parsed as another row. #100016 (Pratima Patel). - Fix exception in
arrayRemovewhen comparing tuples with NULL components. #100017 (Alexey Milovidov). - Fix cross-user data leak in
system.asynchronous_inserts: any user withSELECTon the table could see pending async insert entries belonging to other users. Entries are now filtered by the current user, unless the user has theSHOW_USERSprivilege. #100024 (Shaohua Wang). - Fixes case where Time64 to UInt64 cast could clamp values to 24 hours. #100025 (Yarik Briukhovetskyi).
- Fix local server crash when CREATE DICTIONARY has a definition with list value containing non-existing function. #100036 (Yakov Olkhovskiy).
- Fix
CSV,MsgPackformat not being able to parseNullable(Tuple)properly. Closes #99753. #100038 (Nihal Z. Miaji). - Fix
CREATE VIEWfailing withUNKNOWN_IDENTIFIERwhen using a WITH function-expression alias (e.g.tuple(...)) as the right-hand side ofIN. #100042 (Peng). - Fix timeseries aggregate functions (e.g.
timeSeriesResampleToGridWithStaleness) failing withILLEGAL_TYPE_OF_ARGUMENTwhen used withinitializeAggregationorAggregatingMergeTreeunder parallel replicas. #100053 (Alexey Milovidov). - Make correctly processing negative values inside NumericIndexedVectorDataBSI. #100086 (Daniil Ivanik).
- Fix
accurateCastOrDefaultandto*OrDefaultfunctions not preserving Const column type for constant inputs. #100132 (Alexey Milovidov). - Omitted query parameters with
LowCardinality(Nullable(T))type now correctly default to NULL, same asNullable(T). #100144 (Denys Melnyk). - Fix use-of-uninitialized-value in StringSearcher.h. #100225 (Konstantin Bogdanov).
- Allow cancellation of scalar subqueries and other analysis-time pipelines via Ctrl+C. Previously, pressing Ctrl+C during a long-running scalar subquery had no effect until the subquery completed. Also fix the progress bar and JSON statistics to correctly report rows read during scalar subquery execution, both in
clickhouse-clientandclickhouse-local. Co-authored with @YjyJeff. #100230 (Raúl Marín). - Fixed a
LOGICAL_ERRORexception in queries involvingDynamiccolumns with cross joins and runtime filters, caused byColumnVariant::filtersharing variant column pointers instead of cloning them in thehasOnlyNullsoptimization path. Closes https://github.com/ClickHouse/ClickHouse/pull/100147. #100234 (Pavel Kruglov). - Fixed array of variant bug which may reinterpret data type upon calling
arrayFirst/arrayLastfunction. For example, previouslyArray(Variant(Date, Bool))is converted toBoolwhen the actual underlying variant type isDate. #100255 (timothygk). - A few minor changes to functions: h3 functions now validate boundaries better; readWKB checks the size limits (a new setting,
max_wkb_geometry_elements); random generator functions limit the maximum iterations in their computations. A follow-up for #93543. #100270 (Alexey Milovidov). - Fixed an issue where cutURLParameter could incorrectly skip parameters when they appeared as substrings of other parameters. #100280 (Nikita Semenov).
- Fix exception when Iceberg metadata file path setting contains a null byte. #100283 (Alexey Milovidov).
- Fixed the quadratic number of run queries when
distributed_index_analysisis used with predicates containingINsubqueries. #100287 (Anton Popov). - Fix “Block structure mismatch” exception when using
GROUP BY ... WITH TOTALS HAVINGcombined withUNION DISTINCTand nullable expressions. #100293 (Alexey Milovidov). - Fix LOGICAL_ERROR exception in
estimateCompressionRatiowhenblock_size_bytesparameter is extremely large. #100298 (Alexey Milovidov). - Fix “Inconsistent AST formatting” exception in debug builds when using
GROUP BY CUBE(...) WITH ROLLUPor similar combinations. #100376 (Alexey Milovidov). - Fix exception when creating a view with column aliases and
SELECT *orEXCEPT/INTERSECTqueries. #100386 (Alexey Milovidov). - Fix
DROP TABLEhanging indefinitely on Kafka engine tables when consumers are stuck in a rebalance after a heartbeat error. #100388 (Alexey Milovidov). - Fix
ReadBuffer is canceled. Can't read from it.exception in backup/restore operations using zip archives. #100400 (Alexey Milovidov). - Fix
TOO_MANY_ROWSexception forSELECT count()queries withmax_rows_to_read/force_primary_keywhen data is split across multiple parts with non-aligned granule boundaries. #100408 (Alexey Milovidov). - Fix
system.completionsto correctly filter databases, tables, and columns by access rights in all grant combinations: per-table, per-db, and per-column revoke. #100432 (Shaohua Wang). - Fix SEGFAULT in NuRaft due to race condition. #100444 (Pablo Marcos).
min/max/argMin/argMaxnow treat NaN consistently withORDER BY: NaN is always skipped (returned only when all values are NaN). Previously, results depended on NaN position in the data due to IEEE 754 unordered comparison semantics. #100448 (Raúl Marín).- Fixed a copy-paste bug where
delta_lake_snapshot_end_versionset withoutdelta_lake_snapshot_start_versionwas silently ignored instead of producing aBAD_ARGUMENTSerror. #100454 (Mohammad Lareb Zafar). StorageRabbitMQ::shutdownis not idempotent (it unconditionally accesses weak pointers and then destroys the corresponding shared pointers), but is now called twice: once inStreamingStorageRegistryand then inDatabaseCatalog. This fix makes the method idempotent and adds defensive null checks. #100455 (Miсhael Stetsyuk).- Fix
LOGICAL_ERRORexception when usingaccurateCastOrNullwithQBittarget type. #100470 (Raufs Dunamalijevs). - Fix LOGICAL_ERROR exception “Stream … not found” when inserting into a table with nested
Array(JSON)columns in wide parts withoptimize_on_insert=0. #100475 (Pavel Kruglov). - Validate file entry paths in backup metadata to reject path traversal, absolute paths, and empty names during
RESTORE. #100483 (Pablo Marcos). - Fix
LIMIT m OFFSET n WITH TIESsyntax not working. This syntax is equivalent toLIMIT n, m WITH TIESwhich already worked. #100491 (Nihal Z. Miaji). - Fix exception “No set is registered for key” when using
INwithNullable(Tuple)columns that have named fields andLowCardinalityelements. #100523 (Alexey Milovidov). - Fix heap-buffer-overflow in usearch
sorted_buffer_gt::insert()that could crash or silently corrupt memory during vector similarity search. #100537 (Dustin Healy). - Fix
EXECUTE ASignoringFORMATandINTO OUTFILEclauses specified in the query. #100538 (pufit). - Fix inconsistent AST formatting for SAMPLE with query-level OFFSET. Closes #100576. #100579 (Pavel Kruglov).
- Fix polaris catalog with azure. Since 25.12 this catalog with azure started to add bucket at the beginning of the path. For example
abfss://polaris-polaris@<some_url>.windows.net/polaris-polaris/<other-path>instead ofabfss://polaris-polaris@<some_url>.windows.net/<other-path>. This PR cuts bucket in the path. #100583 (Konstantin Vedernikov). - Fix type mismatch exception in transform when default column is const on some blocks. Closes #100574. #100616 (Pavel Kruglov).
- Fixes NOT_FOUND_COLUMN_IN_BLOCK cases where the projection SELECT part has columns that do not exist in the original SELECT part of the query. Closes #100194. #100623 (Yarik Briukhovetskyi).
- Validate Npy format shape dimensions against file size and overflow limits to prevent denial of service from crafted
.npyfiles with unreasonably large dimensions. Also reject empty shapes and cap per-row memory to 2 GiB. #100625 (Raúl Marín). - Fix
session_timezonebeing ignored when parsingDateTimevalues during async inserts (TCP) and all inserts over HTTP. #100647 (Sema Checherinda). - Allow passing sharding key to
cluster()andclusterAllReplicas()table functions when using a table function as the source (e.g.cluster('name', view(...), sharding_key)). #100665 (Sergey Veletskiy). - Fix server crash (assertion failure) when using parametric aggregate functions with Array combinator and NULL arguments, such as
quantileIfArrayArray(0.5)([[NULL]], [[1]]). #100679 (nerve-bot). - Fix exception when computing common supertype for empty and non-empty tuples with
use_variant_as_common_typeenabled. #100699 (Antonio Andelic). - Server no longer fails to start when an Azure blob storage disk is configured but the endpoint is temporarily unreachable (e.g. DNS failure). #100701 (Raúl Marín).
- Fix undefined behavior in
positiveModulowhen the unsigned divisor does not fit in the signed result type. #100705 (Raúl Marín). - Fix server crash (logical error “Unexpected return type from __topKFilter”) when
use_top_k_dynamic_filteringis enabled and theORDER BYcolumn hasDynamicorVarianttype. #100742 (Groene AI). - Fix server crash when using
has()function with PREWHERE/WHERE on a Tuple key containing LowCardinality elements. #100760 (Groene AI). - Fix
file_offset_of_buffer_end <= getFileSize()assertion failure (exception in debug builds) when reading fromLogorStripeLogtables on S3 object storage with concurrent writes. #100763 (Alexey Milovidov). - Fix an exception in the statistics selectivity estimator when a WHERE clause contains a function expression (e.g. toDecimal64(col, 3)) on a table with statistics enabled. The estimator now skips such predicates instead of attempting an invalid type cast. #100764 (Han Fei).
- Fixes a rare case where join with reordering can produce a wrong result. #100790 (Yarik Briukhovetskyi).
- Fix incorrect
AggregateFunctionargument types in optimized trivial count, which causedNUMBER_OF_ARGUMENTS_DOESNT_MATCHexception when querying expressions likecount(v0 + v1)on distributed tables. #100794 (YjyJeff). - Some catalogs can show some secrets in the
SETTINGSsection ofselect * from system.databasesquery result. This PR prevents such behavior. #100800 (Konstantin Vedernikov). - Fix undefined behavior (signed integer overflow) in
toStartOfIntervalwhen using Week, Quarter, or Year intervals with an origin argument and extreme interval values. #100817 (Raúl Marín). - Fix
If,Distinct,DistinctIf,IfStateaggregate function combinators withTuplereturn type and one or moreNullableargument not being able to read older serialized states after introduction ofNullable(Tuple). Closes #98917. #100826 (Nihal Z. Miaji). - Fix segfault in s3Cluster and distributed queries due to connection pool use-after-free. #100837 (Konstantin Bogdanov).
- Fix null pointer dereference segfault when loading dictionaries during server shutdown.
Context::getUserDefinedSQLObjectsStorage(dereferencesuser_defined_sql_objects_storage) is called by dictionary threads concurrently with the main thread callingContext::shutdown(setsuser_defined_sql_objects_storageto null). We need to make sure we disable future updates in the dictionaries loader, kill the currently running dictionary queries and join the dictionary loading threads - all before runningContext::shutdown. Similar to what we do with normal queries. #100839 (Miсhael Stetsyuk). - Fix buffer overflow in
ULIDStringToDateTimewhen input contains non-ASCII bytes. #100843 (Konstantin Bogdanov). - Fix crash (
LOGICAL_ERROR) when querying aMergetable (ormerge()table function) that wraps multiple tables including aDistributedtable, withdistributed_group_by_no_merge=1enabled. #100859 (Groene AI). - Cast_keep_nullable when enabled will not throw when casting dynamic null to variant. #100864 (Seva Potapov).
- Fix
clickhouse-keeper-clientget,exists, andlscommands printing duplicatewatch_iderror messages to stdout instead of stderr. #100893 (Mohammad Lareb Zafar). - Fix exception in
intDiv/intDivOrZeroon arrays of nullable tuples, e.g.SELECT intDiv([divide((1, 2), ... AND NULL)], 2). #100895 (Raúl Marín). - Evaluate engine arguments for
StorageAliasbefore storing the definition, so that expressions likecurrentDatabase()are resolved to literals before being saved to the database. #100902 (Nikolay Degterinsky). - Fix
processAndOptimizeTextIndexFunctionswhenquery_plan_merge_expressions = 0, whereExpressionStepis directly aboveReadFromMergeTree. Fixes #100879. #100909 (Jimmy Aguilar Mena). - Update replxx to include fix for out-of-bounds access in do_complete_line. #100925 (Azat Khuzhin).
- Fix wrong results when JOIN with shard-by-PK optimization uses query condition cache and some parts are filtered out by cached conditions. #100926 (Groene AI).
- Fix
divideandintDivreturningILLEGAL_DIVISIONwhen used in filter expressions during index analysis in some cases. #100928 (Nihal Z. Miaji). - Fixed “Target table doesn’t exist” errors for materialized views with inner tables during async startup, caused by incorrect startup dependency ordering. #100946 (Nikolay Degterinsky).
- Fix undefined behavior (signed integer overflow) in parseDateTimeBestEffort when parsing datetime strings with more than 18 fractional-second digits. #100948 (Vasily Chekalkin).
- Fixed a crash when using a text search index with an
INclause containing a tuple subquery, e.g.WHERE (id, str) IN (SELECT (id, str) FROM ...), or when the number of columns in the subquery does not match the tuple on the left side ofIN. #100959 (Anton Popov). - Fixed crash when building a polygon dictionary from a
MergeTreetable that uses sparse columns serialization. #100964 (Anton Popov). - Fix logical error “Invalid action query tree node” when using
INTERSECT ALL/UNION ALLwith constant-folded expressions. #100977 (Alexey Milovidov). - Fix
sumCountOrDefaultaggregate function with one or moreNullableargument not being able to read older serialized states after introduction ofNullable(Tuple). Closes #100882. #101021 (Nihal Z. Miaji). - Fix crash (
Logical error: isConst/isSparse/isReplicated assertTypeEquality) in merge algorithms when lazy column replication (enable_lazy_columns_replication) producesColumnReplicatedcolumns that flow into merge-sort pipelines with late-arriving inputs. #101036 (Groene AI). - Fix incorrect
UNKNOWN_IDENTIFIERerror when the same alias is used for multiple expressions inSELECT; the correctMULTIPLE_EXPRESSIONS_FOR_ALIASerror is now reported. #101040 (Alexey Milovidov). - Fix ALIAS columns with
DateTime/DateTime64types not applying timezone conversion when the declared timezone differs from the expression timezone. #101043 (Alexey Milovidov). - Fix row policies not being recorded in
query_logfor views, subqueries, andINSERT ... SELECT. Even though row policies were applied during query planning, they were not propagated from sub-planners to the parent planner for logging. Row policies (for logging only) are now kept inQueryAccessInfoso that both planners and sub-planners can populate them. #101044 (Narasimha Pakeer). - Fix exception in
DirectJoinMergeTreeEntitywhen pipeline blocks containColumnConstcolumns that are merged with regular columns. #101046 (Alexey Milovidov). - Fix spurious space in CTE column alias formatting (
WITH t (a, b)→WITH t(a, b)). #101049 (Alexey Milovidov). - Fix
remote/clustertable functions failing with nested table functions likemergewhen the analyzer is enabled. #101055 (Alexey Milovidov). - Fix
OFFSETbeing applied twice in distributed queries whenprefer_localhost_replica=1, producing fewer rows than expected. #101071 (Nihal Z. Miaji). - Fix crash when using the
Regexpformat with an invalid regular expression informat_regexpsetting. #101074 (Nihal Z. Miaji). - Fix “Illegal type Decimal64 of start parameter” error for timeseries aggregate functions when using
serialize_query_plan=1with parallel replicas. #101083 (Groene AI). - Fix exception in
optimizeLazyMaterializationwhen a projection with PREWHERE is used withORDER BY ... LIMIT. #101115 (Anton Popov). - Fix server crash (SIGABRT) when using aggregate functions with the internal-only
Nullcombinator (e.g.sumNull,avgNull) andaggregate_functions_null_for_empty = 1setting enabled. #101147 (Groene AI). - Fix a use-after-free in the filesystem cache write path that could cause reads from freed memory when logging completed file segments (detected by MemorySanitizer in BuzzHouse). #101161 (Groene AI).
- Fix server crash with “Trying to attach external table to a ready set without explicit elements” when distributed index analysis encounters a GLOBAL IN predicate whose set was built without explicit elements. #101178 (Groene AI).
- Fix
MAX/MINaggregate functions onDecimalcolumns returning incorrect results when JIT compilation is enabled (after the compilation threshold is reached). #101203 (Raúl Marín). - Fix
minmax_count_projectionand trivialCOUNT(*)optimizations being permanently disabled after a lightweight delete, even after all parts with a mask of lightweight delete were merged away. #101212 (Anton Popov). - Fix a case which can lead to
Having zero bytes, ...logical error from cache arising from a remote object being overwritten in betweenlistandreadwhich previously resulted in a stale object metadata. #101219 (Kseniia Sumarokova). - Fix server crash (LOGICAL_ERROR: Bad cast from ColumnVector to ColumnLowCardinality) when querying a MergeTree table with
ORDER BY CAST(lc_column, 'Type')wherelc_columnhas a LowCardinality type. #101220 (Groene AI). - Fix cleanup of stale processing nodes in
S3Queue. #101230 (Kseniia Sumarokova). - Fix UB in mergeTreeAnalyzeIndexes() in case of invalid optimizations argument. #101253 (Azat Khuzhin).
- Fix
Logical error: 'partitions_count > 0'exception when performing consecutiveALTER TABLE UPDATEon a partitioned Iceberg table. #101278 (Desel72). - Fix wrong query results when a large integer constant (e.g. 256, 2147483648) is used as a boolean predicate in a WHERE clause with AND on MergeTree tables. For example,
SELECT count() FROM t WHERE (2147483648 > b) AND 2147483648would incorrectly return 0 instead of matching all rows. #101287 (Groene AI). - Fix insert-select from delta lake cluster with replicated merge tree. #101299 (Konstantin Vedernikov).
- Fixed crash with “Logical error: Reading from materialized CTE before materialization” when a scalar subquery references a chain of dependent materialized CTEs. #101305 (Groene AI).
- Fix data race on
storage_idinIStorage::getDependentViewsByColumn. #101385 (Nikolay Degterinsky). - Fix BACKUP FROM SNAPSHOT AST formatting and cloning. #101405 (Pablo Marcos).
- Fix LOGICAL_ERROR crash “Current component is empty” when querying
system.part_moves_between_shardswithenforce_keeper_component_trackingenabled. #101462 (Groene AI). - Fix segmentation fault in DataTypeDynamic::create() when the fuzzer generates a malformed Dynamic type AST. #101464 (Groene AI).
- Throw an error when
delta_lake_snapshot_versionor CDF version settings are used without DeltaKernel enabled, instead of silently returning wrong data. #101489 (Desel72). - Fix
NOT_FOUND_COLUMN_IN_BLOCKexception when using ARRAY JOIN with JOIN USING andanalyzer_compatibility_join_using_top_level_identifiersetting enabled. Close #101240. #101507 (Vladimir Cherkasov). - Fix Iceberg INSERT retry loop failing when the table was created with
iceberg_metadata_file_pathand the target metadata version already exists. #101548 (Groene AI). - Strip Nullable from result column in arrayIntersect and related functions to avoid serialization/deserialization mismatch. #101569 (George Larionov).
- Fix server crash (LOGICAL_ERROR) when SELECT-ing from a materialized view backed by an IcebergLocal table engine. #101577 (Groene AI).
- Fix incorrect error message when calling
intExp10with NaN argument — it saidintExp2instead ofintExp10. #101582 (Krishna Chaitanya). - Fix
allow_statistics=0not blockingALTER TABLE ADD STATISTICSandALTER TABLE DROP STATISTICSafter refactoring in #100288. #101585 (Krishna Chaitanya). - Fix
KeeperMapCREATE TABLEfailing with “Cannot create metadata for table” when leftover ZooKeeper nodes from a pre-25.1 partial drop are missing thedrop_lock_versionnode. #101623 (Antonio Andelic). - Fix possible logical error during reading Map subcolumns. Closes #100769. Closes #101336. #101641 (Pavel Kruglov).
- Fix exact subcolumn match priority over prefix match in
getSubcolumnDatato avoid possible crash. Closes #101271. #101645 (Pavel Kruglov). - Fix crash (LOGICAL_ERROR: “ColumnUnique can’t contain null values”) when comparing a
LowCardinalitycolumn with aVariantNULL constant whileuse_variant_default_implementation_for_comparisonsis disabled. #101690 (Groene AI). - What: Added empty-stream guard to Bzip2ReadBuffer so it returns EOF instead of throwing UNEXPECTED_END_OF_FILE when the inner stream is empty. #101691 (ClickGap AI Bot).
- What: Fixed the inverted description text for the
alterablecolumn insystem.s3_queue_settingsandsystem.azure_queue_settings— swapped0and1meanings to match the actual code behavior. #101703 (ClickGap AI Bot). - Fix positiveModulo(tuple, number) incorrectly dispatching to division instead of modulo. #101709 (ClickGap AI Bot).
- Fixes a crash when
thread_pool_sizeis configured on a cache-wrapped disk. Previously,FileCacheSettings::loadFromConfig()rejectedthread_pool_sizeas an unknown setting, preventing the server from starting. The setting is a validIDiskparameter that controls the number of threads used for disk-to-disk copy operations during background part moves. #101712 (Francisco). - Fix
RANGE_HASHEDdictionary creation silently accepting a non-existentMAXrange attribute and using the wrong type configuration when min and max range attributes had different types. The bug was a copy-paste error inbuildRangeConfigurationthat looked upmin_attr_nameinstead ofmax_attr_namefor the max attribute. #101732 (Yakov Olkhovskiy). - Fix use-after-free crash in CPU lease scheduler when the wait timer outlives the worker thread whose
ProfileEvents::Countersit references. #101761 (Antonio Andelic). - Fixes bug in arrayLevenshteinDistanceWeighted and arraySimilarity functions. Closes #101725. #101767 (Mikhail f. Shiryaev).
- Fix Prometheus Query API ignoring POST form bodies. #101794 (James Cunningham).
- Fix exception escaping from S3
Client::~Clientdestructor causing server termination. #101798 (Gagan Dhakrey). - Fix use-after-scope in parallel deserialization of
Objecttype dynamic paths, which could cause crashes when reading tables with many dynamic paths. #101823 (Antonio Andelic). - Fixed incorrect output in function
formatDateTimewith formatter%Wwith certain (non-default) formatting settings. #101847 (Robert Schulze). - Fix
shouldPatchFunctionfalse negative inSYSTEM INSTRUMENT ADDwhen the search string first appears inside a template argument of the demangled symbol name. #101885 (Pablo Marcos). - Fix UDF registry loss when ZooKeeper session expires during periodic refresh — all user-defined functions could become unavailable until a full refresh succeeds. #101891 (Nikita Fomichev).
- Fixed
system.codecsdescription forAES_256_GCM_SIVto reportAES-256instead ofAES-128. #101917 (Jimmy Aguilar Mena). - Fix using wrong extremes in min-max index created on JSON column leading to wrong query result. Closes #101700. #101918 (Pavel Kruglov).
- The
splitByStringtokenizer now rejects empty separator strings. #101928 (Robert Schulze). - Fix
materialize_skip_indexes_on_merge=falsenot suppressing text (full-text) indexes during merge. Previously, only non-text skip indexes (minmax, set, bloom_filter) were suppressed; text indexes continued to be built, wasting CPU and I/O. #101932 (Groene AI). - The
sparseGramstokenizer generated longer tokens than the provided max length (this was due to a hard-coded+2in the implementation). #101934 (Elmi Ahmadov). - Fix SIGSEGV in
MergeTreeDataPartWriterWide::cancelwhen a stream constructor throws duringaddStreams, leaving a null entry incolumn_streams. #101936 (Antonio Andelic). - Fixes an exception when querying Merge or Distributed tables with a full-text index and combined filter conditions that mix
has*Tokenswith LIKE, whilequery_plan_direct_read_from_text_indexis enabled. #101939 (Jimmy Aguilar Mena). - Fix undefined behaviour when parsing native protocol query packets with invalid
QueryProcessingStagevalues. #101972 (Raúl Marín). - Close TCP connection when an exception occurs during initial query parsing to prevent reading garbage from a desynchronized stream. #101989 (Raúl Marín).
- Fix SLRU race bug in filesystem cache 26.1+, which can lead to space reservation logical error. In debug build it can also lead to failed assert:
'Previous state is Evicting, but expected state to be Active while setting Evicting flag for 2c1e3484ecdc6b78a8978fa5b17c5097:0:339 (state: Evicting)'.. #101991 (Kseniia Sumarokova). - Fix exception when casting a string with trailing data to empty
Tuple()type. #102011 (Alexey Milovidov). - Fixes incorrect row ordering in queries that use ORDER BY with the grace_hash join algorithm. Affected queries could return results in the wrong order, producing silently incorrect output. #102036 (János Benjamin Antal).
- Fixes a LOGICAL ERROR (Unexpected size of index type) that could occur in RIGHT JOIN and FULL JOIN queries when the
max_bytes_in_joinsetting was configured. #102042 (Jimmy Aguilar Mena). - Fixes cases where Time with negative values was returning wrong result on comparison with DateTime. Closes #101670. #102056 (Yarik Briukhovetskyi).
- Fix crash in UDF refresh caused by
ZooKeeperRetriesControlretrying on a stale (expired) ZooKeeper session without renewing it. #102059 (Nikita Fomichev). - Fix missing spaces when formatting unlock snapshot. close https://github.com/clickhouse/clickhouse/issues/101723. #102063 (Han Fei).
- Fix crash (SIGSEGV) when querying a view with a WHERE clause and the inner query produces columns with different types than the view metadata (e.g. Nullable from LEFT JOIN with
join_use_nulls). #102085 (Miсhael Stetsyuk). - Fix
VectorSimilarityIndexCacheentries never being evicted after part removal due to mismatched cache keys. #102152 (Seva Potapov). - NACK broken messages when using rabbitmq storage. #102157 (Seva Potapov).
- Fix logical error when parsing incorrect empty tuple string. #102289 (Nihal Z. Miaji).
- Fix incorrect aggregation results (duplicate rows) when using
optimize_aggregation_in_order=1with GROUP BY columns ordered differently from the table’s sorting key. #102299 (Groene AI). - Fix crash in
IcebergLocalALTER TABLE ... UPDATEwhen using Avro format, caused byLowCardinality/Nullablewrapper types not being unwrapped before serialization. #102337 (Desel72). - Fixed a segmentation fault in mutations on materialized columns without an expression. Closes #102185. #102342 (zoomxi).
- Coalescing merge tree fix for array type. This closes #89509. #102384 (Konstantin Vedernikov).
- Fix segfault (or LOGICAL_ERROR in debug builds) when reading Parquet files with bloom filter push down enabled and WHERE clause equality/inequality conditions. The crash occurred due to an out-of-bounds memory access in the Parquet prefetcher’s bloom filter data retrieval, and could also cause non-deterministic wrong query results. #102385 (Groene AI).
- Fix
LOGICAL_ERRORabort during SLRU filesystem cache dynamic resize caused by shared eviction statistics across sub-queues and incorrect recovery path for failed candidates. #102396 (Antonio Andelic). - Fix failure to initialize on a fresh replica Alias tables without a target table in the Database Replicated. Closes #101320. #102397 (Nikolay Degterinsky).
- Fix out-of-bounds read in string search functions (
countSubstrings,position, etc.) when searching for a needle consisting entirely of null bytes. #102401 (Raúl Marín). - Full text index settings (
enable_full_text_index,allow_experimental_full_text_index,use_skip_indexes_on_data_read) are no longer disabled when thecompatibilitysetting points to a version older than 26.1. Previously this could preventSharedDatabaseCatalogfrom creating tables with text indexes. #102422 (Nikita Fomichev). - Fix out of bounds read in
printfwith trailing%. #102472 (Raúl Marín). - Fixes a chassert exception
ReadBuffer is canceledin debug builds in AsynchronousMetrics, caused by rewind not resetting the buffer cancellation flag. #102524 (Yuri Fedoseev). - Fixed
hasToken/hasTokenOrNullwith separator-only needles (e.g.'()','!!!') on columns with a text index: previously the index silently skipped all granules instead of throwingBAD_ARGUMENTS(forhasToken) or returningNULL(forhasTokenOrNull). #102544 (Jimmy Aguilar Mena). - Fix OOMs on huge multi requests in the keeper. For OpenTelemetry tracing, we unconditionally allocate >1 KiB for OpenTelemetry spans in
ZooKeeperRequestobjects - meaning, for really huge multi requests, we try to allocate >10 GiB extra memory. To fix this, we now keep shared data in static memory and usestd::unique_ptroverstd::optionalinZooKeeperOpentelemetrySpans. #102586 (Miсhael Stetsyuk). - Fix
NamedCollectionCurrentMetric being inflated byCREATE NAMED COLLECTION IF NOT EXISTSon existing collections, and not being initialized for collections loaded from config or SQL storage at startup. Closes #102507. #102598 (Pablo Marcos). - Fix exception in
getStructureOfRemoteTablewhen local shard returns empty columns due to concurrent DDL. #102604 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception when multiple concurrentCREATE TABLE IF NOT EXISTSqueries target the sameS3Queuetable on a Shared database. #102610 (Nikita Taranov). - Fix LOGICAL_ERROR crash “Unexpected number of rows in column subchunk” in native Parquet V3 reader when reading nullable columns with a WHERE filter. #102628 (Groene AI).
- Fix
AzureWriteMicrosecondsprofile event description saying “read” instead of “write”. #102639 (Miсhael Stetsyuk). - Bug with row policy that gives ‘Not found column in block’ exception in some special cases. #102648 (Yarik Briukhovetskyi).
- Fixed a server exception in ClusterDiscovery when a static cluster (defined in config) temporarily had no live nodes. #102661 (Kseniia Sumarokova).
- Fix wrong date data type inference in case of overflow after timezone adjustment. Closes #102601. #102674 (Pavel Kruglov).
- Fix
SYSTEM WAIT VIEWhanging forever when the refreshable materialized view is dropped while the wait is in progress. #102681 (Nikolay Degterinsky). - Fix CASE with Dynamic expression returning ELSE for all rows. Closes #102511. #102684 (Pavel Kruglov).
- Fix flattened Dynamic type serialization with binary encoded data types. Closes #101911. #102692 (Pavel Kruglov).
- Fix format_schema_source=‘query’ silently ignoring multi-row results. Closes #101905. #102698 (Pavel Kruglov).
- Report actual exit code via SSH client instead of mapping all errors to
1. Closes #101741. #102700 (Konstantin Bogdanov). - Fix losing HTTP headers for dynamic/predefined query handlers. Closes #101846. #102706 (Konstantin Bogdanov).
- Apply Poisson sampling correction to collapsed jemalloc heap profiles to match jeprof output. Previously the collapsed format underestimated actual allocation sizes by not accounting for the sampling probability. #102759 (Antonio Andelic).
- Fix the crash in the function
hasPhrasewith aNULLargument. #102802 (Nikita Taranov). - Fix server crash (SIGSEGV) when reading Avro files with recursive schemas containing cyclic symbolic type references. Now such schemas are detected and rejected with a clear error message instead of crashing. #102853 (Groene AI).
- Fix server crash (LOGICAL_ERROR assertion) when a function on a
Variantcolumn hits a memory limit or other non-type-conversion exception during result casting inFunctionVariantAdaptor. The exception is now propagated correctly instead of being misclassified as an internal error. #102855 (Groene AI). - Fix server crash in debug/sanitizer builds when
std::length_erroris thrown during schema inference (e.g., from extremeinput_format_msgpack_number_of_columnsvalues or malformed input data). #102859 (Groene AI). - Make null representation in serialization of replicated and sparse columns respect settings (e.g. format_tsv_null_representation). #102888 (Hechem Selmi).
- Backported in #103499: Fix S3 requests failing with
ios_base::clear: unspecified iostream_category errorinstead of being retried, caused by PocoBufferedStreamBuf::flushBuffernot handling short writes from the socket layer. #102894 (Sema Checherinda). - Fix
minmax_count_projectionand trivialCOUNT(*)optimizations being permanently disabled after a lightweight delete, even after all parts with a mask of lightweight delete were merged away. #102900 (Anton Popov). - Fix random crashes in jemalloc due to LTO. #102913 (Azat Khuzhin).
- Optimize row policy OR-chains to IN in the new analyzer. #102915 (Azat Khuzhin).
- Fix jemalloc metadata corruption caused by page cache freeing with wrong alignment that may lead to crashes. #102918 (Azat Khuzhin).
- Plain INSERTs without materialized views no longer request excessive ConcurrencyControl slots and threads (
max_threadsinstead ofmax_insert_threads), preventing CC slot starvation and thread count blowup on clusters with high INSERT throughput. #102961 (Sema Checherinda). - Reintroduce ArrowMemoryPool to allow throwing MEMORY_LIMIT_EXCEEDED to avoid kernel OOM. #102999 (Azat Khuzhin).
- Fix
cast_string_to_date_time_modebeing ignored forCASTtoNullable(DateTime). Closes #101840. #103035 (Pavel Kruglov). - Added support for
ALIAScolumns in text index direct read optimization. #103037 (Anton Popov). - Backported in #103454: Fix
SELECT DISTINCTsilently returning incomplete results when an aggregate projection matched the query and some parts of the table had no projection data (e.g. the projection was added on a table that already held data, andMATERIALIZE PROJECTIONwas not run). Closes #102951. #103052 (Nihal Z. Miaji). - Fix wrong results returned by
WHERE x AND toNullable(N)onMergeTreetables whenNis an integer wider thanUInt8(e.g.256,65535,2147483648, or any negative integer). The filter incorrectly discarded all rows becausesplitFilterNodeForAllowedInputsused aNULLzero when converting theNullableremainder of a reducedANDto boolean, turning the comparison intoNULLunder three-valued logic. #103077 (Groene AI). - Fixed incorrect argument type reported in error messages of string search functions (e.g.
locate,position) when arguments are passed in swapped order (locate(needle, haystack)withfunction_locate_has_mysql_compatible_argument_order = 1). #103102 (Alex Kuleshov). - Fix waitForPause hanging indefinitely when disableFailPoint is called with no thread paused at the failpoint. #103119 (Shaohua Wang).
- Cap pre-auth TCP Hello packet strings to 64 KB and add
handshake_timeout_millisecondsserver setting to limit total handshake time, preventing unauthenticated clients from consuming excessive memory or holding threads indefinitely. #103284 (Sema Checherinda). - Fix Parquet ColumnIndex stats min_value > max_value for String columns. #103334 (Saurabh Kumar Ojha).
- Check for malformed flattened Dynamic data in Native format. #103392 (Pavel Kruglov).
- Populate
_timecolumn fromurltable function. #103437 (Nikita Taranov). - Fix SVE detection using SVE instructions when unavailable. #103568 (Raúl Marín).
Build/Testing/Packaging Improvement
- Libstemmer (Snowball) dependency now uses newer version v3.0.1. #99256 (Jimmy Aguilar Mena).
- Randomize settings in clickhouse-test:
use_skip_indexes_for_top_k,use_top_k_dynamic_filtering,query_plan_max_limit_for_top_k_optimization. #91782 (Nikita Fomichev). - Implement a stress test for functions, checking the soundness of their various properties. #93543 (Michael Kolupaev).
- Provide own CMake configuration for
llvm-projectinstead of importing upstream one. #97453 (Konstantin Bogdanov). - Randomize more
optimize_*settings in the test infrastructure to improve coverage of query optimization passes. #97547 (Alexey Milovidov). - Use Rust toolchain nightly-2026-03-22. #98602 (Konstantin Bogdanov).
- Use
wasmtimev42.0.1. #98603 (Konstantin Bogdanov). - Use
llvm-project22.1.1. #98882 (Konstantin Bogdanov). - Replace
SANITIZE_COVERAGE(custom sanitizer callbacks, symbol-level granularity) with LLVM source-based coverage (WITH_COVERAGE,-fprofile-instr-generate -fcoverage-mapping) for the nightly per-test coverage pipeline. The server now reads its own coverage mapping from ELF sections at startup and collects(file, line_start, line_end)tuples per test via a newSYSTEM SET COVERAGE TEST 'name'command. Test selection in targeted CI checks uses line-range queries against a newchecks_coverage_linesCIDB table and ranks candidate tests by how many changed diff lines they cover. #99513 (Nikita Fomichev). - Fix llvm-libc link error with -O0 build. #100023 (Zheguang Zhao).
- Fixed two error messages on container startup in case the configuration did not contain the
logger.logandlogger.errorlogsettings (e.g. when all log messages are supposed to go to STDOUT/STDERR). #100239 (Simon). - Prefer
ld64.lldover Apple’sld(cctools-port ld64) for macOS builds. This should significantly reduce Darwin link times, as cctools-port’s ld64 is very slow with-ffunction-sectionsand-dead_strip. Falls back toldifld64.lldis not available. #100275 (Alexey Milovidov). - Tests to ensure that directories do not register any secrets (REST + Glue). #100307 (Konstantin Vedernikov).
- Repeat recently modified tests with different randomized settings. #100385 (Alexey Milovidov).
- Track
#embedfile dependencies in CMake and enable ccache depend mode for correct rebuilds. #100411 (Alexey Milovidov). - Add correctness tests for TPC-H queries. #100580 (Raufs Dunamalijevs).
- Use
aws-sdk-cpp1.11.771. #100582 (Konstantin Bogdanov). - Allow performance test XMLs to reference external SQL query files and settings via file attribute. #100747 (Raufs Dunamalijevs).
- Fix compilation with
-march=x86-64-v4by adding missingTargetSpecific.hinclude inLowerUpperImpl.h. #100932 (Alexey Milovidov). - Fix build on gentoo by adding —no-default-config to cxxflags. #100973 (Isak Ellmer).
- Added
utils/auto-bisect/— a shell-based bisection framework that downloads pre-built CI binaries and runs a user-supplied test script to find the first commit that introduced a regression, without requiring a local build. #100989 (Nikita Fomichev). - Disable ThinLTO by default in CMake so that local developer builds no longer implicitly enable it. CI release builds are unaffected since they explicitly pass
-DENABLE_THINLTO=1. #101041 (Alexey Milovidov). - Add TPC-DS SF1 benchmark to performance tests. #101209 (Raufs Dunamalijevs).
- Added stateless tests for MergeTree lightweight deletes covering:
has_lightweight_deleteflag lifecycle,COUNT(*)correctness withoptimize_trivial_count_query,MATERIALIZED/DEFAULTcolumn integrity,ReplicatedMergeTreeflag recovery,read_in_orderwith deleted rows, multiple delete/merge cycles,_row_existscolumn hiding, predicate variety, andALTER DELETERBAC enforcement. #101792 (Nikita Fomichev). - Distroless Docker images are now published with ubuntu and alpine variants for tagged releases. #101941 (Rahul Nair).
- Stack traces now show clean bare relative paths (e.g.
src/Common/Exception.cpp) instead of paths polluted with the build directory (e.g../ci/tmp/fast_build/./src/Common/Exception.cpp). #102000 (Raúl Marín). - Add a CI style check that rejects files larger than 5 MB committed to the repository, with a whitelist for existing legitimate test data. Remove unused 14 MB
zookeeper_log.parquet. #102080 (Raúl Marín). - Remove ~400 unused
#includedirectives from headers to reduce compilation times. #102585 (Raúl Marín). - Use
wasmtimev43.0.1. #102603 (Konstantin Bogdanov). - Use
openssl3.5.6. #102606 (Konstantin Bogdanov). - Use
xz5.8.3. #102607 (Konstantin Bogdanov). - Upgrade distroless Docker image base from Debian 12 (glibc 2.36, OpenSSL 3.0) to Debian 13 (glibc 2.41, OpenSSL 3.5), reducing CVE surface to zero reachable vulnerabilities. #101678 (Rahul Nair).
ClickHouse release 26.3 LTS, 2026-03-26. Presentation, Video
Backward Incompatible Change
- Downgrading after upgrading may cause data loss. Propagate data types serialization versions to nested data types. For example, String serialization version
with_size_streampreviously was applied only on top-level String columns and Tuple elements. Now it’s applied to any String type inside any nested type likeArray/Map/Variant/JSON/etc. This behaviour is controlled by MergeTree settingpropagate_types_serialization_versions_to_nested_typesthat is now enabled by default. After this change, newly created data parts cannot be read by older versions, but old parts can be read on new version with no problems. Upgrade is safe, but downgrade is not — if you need to roll back after upgrading to 26.3, data written by 26.3 in columns with nested types will be unreadable! See #101429 for details. #94859 (Pavel Kruglov). - Remove the
hypothesisskip index type. It was an obscure, experimental feature with limited practical use. Creating tables withINDEX ... TYPE hypothesiswill now produce an error. #96874 (Alexey Milovidov). - Remove the experimental
detectProgrammingLanguagefunction. #99567 (Alexey Milovidov). - Fix
NOToperator precedence to match the SQL standard:NOTnow binds looser thanIS NULL,BETWEEN,LIKE, and arithmetic operators. For example,NOT (x) IS NULLis now parsed asNOT (x IS NULL)instead of(NOT x) IS NULL. This may change the result of queries that relied on the previous (non-standard) behavior. #97680 (Alexey Milovidov). - Corrects the metadata of normal projections so that projections with multi-column sorting keys are properly recognized. Builds on top of #90429. #91352 (Amos Bird).
- Fixed skip index files not respecting replace_long_file_name_to_hash setting, causing “File name too long” errors and broken index reads for indices with long names. Skip index filenames are now hashed when they exceed max_file_name_length, similar to column files. This is backward compatible (new servers read old parts), but downgrading (or old servers during a rolling upgrade) may cause long-named indices to be ignored. #97128 (Raúl Marín).
- Turn on async insert by default. ClickHouse will be batching all small inserts by default now. This setting is set under compatibility. If you set
compatibility=<version less than 26.2>then default value would be the previous one,false. You can turn off/on async inserts at several levels: in the config in users profiles, for the session, for the query, or for the MergeTree table. #97590 (Sema Checherinda). - Change the default value of
mysql_datatypes_support_levelfrom empty todecimal,datetime64,date2Date32, enabling proper mapping of MySQLDATEtoDate32,DECIMAL/NUMERICtoDecimal, andDATETIME/TIMESTAMPwith precision toDateTime64by default. Previously, MySQLDATEcolumns were mapped toDatewhich cannot represent dates before 1970-01-01, causing data corruption. #97716 (Alexey Milovidov). - Accept array of part names instead of regexp for
mergeTreeAnalyzeIndexes{,UUID}since regexp is slow (Experimental feature). #98474 (Azat Khuzhin). - Change default
stderr_reactionfromthrowtolog_lastfor executable UDFs. UDFs that write warnings to stderr no longer fail when exit code is 0. Exit code exceptions now include stderr content. #99232 (Xu Jia).
New Feature
- Added bucketed serialization for Map columns in MergeTree (
map_serialization_version = 'with_buckets'). Keys are split into hash-based buckets so that reading a single key (m['key']) only reads one bucket instead of the entire column, providing 2-49x speedup for single-key lookups depending on map size. The number of buckets and the bucketing strategy can be controlled by new MergeTree settings:map_serialization_version,max_buckets_in_map,map_buckets_strategy,map_buckets_coefficient, andmap_buckets_min_avg_size. #99200 (Pavel Kruglov). - Support materialized CTE. Allow evaluating CTEs only once during query execution and store their results in temporary tables. Closes #53449. #94849 (Dmitry Novik).
- Allow certain SQL-standard functions without parentheses for compatibility, such as
NOW. Closes #52102. #95949 (Aly Kafoury). - You can now use the natural sort key function as
naturalSortKey(s). #90322 (Nazarii Piontko). - You can now use native JSON/Object input for JSONExtract functions. Closes #88370. #96711 (Fisnik Kastrati).
- If a query parameter has
Nullabletype and is not specified, we will assume that its value isNULL. #93869 (Vikash Kumar). - Support auxiliary ZooKeeper for
Replicateddatabase. #95590 (RinChanNOW). - Support
hasfunction for JSON type to check path existence, similar to Map. #96927 (DQ). - Added the
mergeTreeTextIndex(database, table, index)table function, which allows reading data directly from a text index. This function can be used for introspection or for performing aggregations on top of text index data. #97003 (Anton Popov). - Add
table_readonlyMergeTree setting to mark tables as read-only, preventing inserts and modifications. #97652 (Alexey Milovidov). - Add new setting
use_partition_pruningand aliasuse_partition_key. Set it tofalseto disable partition pruning based on the partition key. #97888 (Nihal Z. Miaji). - Implements
ALTER TABLE ... EXECUTE expire_snapshots('<timestamp>')for Iceberg tables. #97904 (murphy-4o). #99130 - Allow each
type=httpentry in<protocols>to specify a custom<handlers>key pointing to a separate<http_handlers_*>config section, enabling different HTTP routing rules per port. #98414 (Amos Bird). - Add
pretty=1option toEXPLAINfor tree-style indented output andcompact=1to collapseExpressionsteps, making query plans more readable. #98500 (Kirill Kopnev). - Add
restore_access_entities_with_current_grantsserver setting. When enabled, restored users/roles from backups have their grants limited to what the restoring user is allowed to grant (same semantics asGRANT CURRENT GRANTS), instead of failing withACCESS_DENIED. #98795 (pufit). - Add
caseFoldUTF8andremoveDiacriticsUTF8functions for Unicode case folding and diacritical mark removal. #98973 (George Larionov). - Add
normalizeUTF8NFKCCasefoldstring function for NFKC_Casefold Unicode normalization, which combines NFKC normalization with case folding. #99276 (George Larionov). - Add
unicode_wordtokenizer for full-text indexes and thetokensfunction. It splits text using Unicode word boundary rules: ASCII words are formed with connector characters (underscore, colon, dot, single quote), while non-ASCII Unicode characters become single-character tokens. Note: 26.3 accepts this tokenizer only under the nameunicode_word; it was renamed toasciiCJKin 26.4. #99357 (Amos Bird). - Added
max_skip_unavailable_shards_numandmax_skip_unavailable_shards_ratiosettings to limit how many shards can be silently skipped whenskip_unavailable_shardsis enabled. If the number or ratio of unavailable shards exceeds the configured threshold, an exception is thrown instead of returning silently incomplete results. #99369 (Alexey Milovidov). - Users can now use
SOMEkeyword for subquery expressions. It behaves identically toANY. #99842 (Artem Kytkin). - Add
output_format_trim_fixed_stringsetting to strip trailing null bytes fromFixedStringvalues in text output formats. #97558 (NeedmeFordev). - Support parenthesized table join expressions in FROM clause, e.g.
SELECT * FROM (t1 CROSS JOIN t2). #97650 (Alexey Milovidov). - Implement function
toDaysInMonth: it returns the number of days in the month of the specified date. #99227 (Vitaly Baranov).
Experimental Feature
- Add experimental support for WebAssembly-based user-defined functions (UDFs), allowing custom function logic to be implemented in WebAssembly and executed within ClickHouse. Special thanks to Alexey Smirnov for contributing the Wasmtime backend support. #88747 (Vladimir Cherkasov). Incremental improvements for WASM UDF support. #99373 (Vasily Chekalkin).
- Add support for external SQL dialects using
polyglotlibrary. #99496 (Alexey Milovidov). - Add
ALPfloating-point compression codec (without ALP_rd fallback for non-compressible doubles). #91362 (Nazarii Piontko). - Add experimental lazy type hints for
JSONcolumns. When enabled viaallow_experimental_json_lazy_type_hints,ALTER TABLE ... MODIFY COLUMN json JSON(path TypeName)that only adds or modifies type hints completes instantly as a metadata-only operation, without rewriting historical data. Type hints are applied at query time for old parts and materialized during INSERTs and background merges. #97412 (tanner-bruce). - Enable parallel reads from YTsaurus table engine. #97343 (MikhailBurdukov).
Performance Improvement
- Improve the performance of data lakes. In previous versions, reading from object storage didn’t resize the pipeline to the number of processing threads. This gives orders of magnitude improvements (~40x) on multi-core machines. #99548 (Alexey Milovidov).
- Now, the relationship between
enable_parallel_replicasandautomatic_parallel_replicas_modeis as follows. A query can use parallel replicas only ifenable_parallel_replicas > 0. Additionally, ifautomatic_parallel_replicas_mode=1, the decision whether to use parallel replicas is made during planning based on the previously collected statistics. Ifautomatic_parallel_replicas_mode=0, parallel replicas will be used for all supported queries regardless of any statistics. One notable exemption is distributed insert-select with parallel replicas: in this case, queries will always be executed as ifautomatic_parallel_replicas_mode=0. #97517 (Nikita Taranov). - Allow partition pruning when the predicate contains any comparison operator (
=,<,>,!=) and the partition key is wrapped in a deterministic function chain (e.g.PARTITION BY xand predicates likecityHash64(x) % 5 > 2,toYYYYMM(x) < 2026,toYYYYMM(x) = 2026, ortoYYYYMM(x) != 2026will all use the partition key for pruning). Closes #28800. #98432 (Nihal Z. Miaji). - Allow read-in-order optimization and primary-key pruning when the
CASTtarget type isNullableand the conversion is monotonic; for example, withPRIMARY KEY x, ClickHouse can use read-in-order optimization forORDER BY x::Nullable(UInt64)and can apply primary-key pruning for predicates such asWHERE x::Nullable(UInt64) > 500000. #98482 (Nihal Z. Miaji). - Allow index pruning and filter pushdown when an integral column is compared with a float literal; for example, predicates like
WHERE x < 10.5can now use the primary key for pruning, and filters such asprime < 1e9ornumber < 1e5are now pushed down for theprimes()andnumbers()table functions instead of causing unbounded execution. Closes #85167. #98516 (Nihal Z. Miaji). - Added a new SLRU cache for Parquet metadata to improve read performance by removing the need to re-download files just to read metadata. #98140 (Grant Holly).
- Support swapping sides of ANTI, SEMI and FULL joins based on optimizer statistics. #97498 (Hechem Selmi).
- Optimize granules skipping for
pointInPolygonfor large polygons and fixpointInPolygonindex analysis throwing during primary key pruning. #91633 (Nihal Z. Miaji). - Improve performance of
levenshteinDistancefunction. #94543 (Joanna Hulboj). - Optimize batch decimal type conversions by avoiding per-element function calls. #95923 (Konstantin Bogdanov).
- Iceberg tables now support asynchronous metadata prefetching via
iceberg_metadata_async_prefetch_period_mstable setting, which periodically pre-populates the metadata cache. Additionally, theiceberg_metadata_staleness_msquery setting allows SELECT queries to use cached metadata if it is fresher than the specified staleness, eliminating calls to the Iceberg catalog during request processing. #96191 (Arsen Muk). S3Queueordered mode uses S3 ListObjectsV2 StartAfter to avoid re-listing full prefix history, reducing ListObjects calls. #96370 (Venkata Vineel ).- Lower memory usage for inserts deduplication. In general the original block is needed for deduplication, but for sync insert we could omit it and save the memory for good. #96661 (Sema Checherinda).
- Use an arch-specific value for cache line size instead of a hardcoded value of 64. #97357 (Nikita Taranov).
- Slightly optimized reading from the text index dictionary, improving the overall performance of text index analysis. #97519 (Anton Popov).
- Speed up
LZ4decompression of 16 byte blocks in ARM. #97774 (Raúl Marín). - Refactor tokenization to a new high-performance interface, replacing the old iterator-style API to support SIMD and stateful tokenizers. Part of #90268. #97871 (Amos Bird).
- Improved performance of text index analysis for queries with combined conditions involving both indexed and non-indexed columns. Previously, early exit optimization during index analysis was incorrectly disabled in such cases. #98096 (Anton Popov).
- Improve the performance of queries with constant expressions that generate very long arrays or maps. #98287 (Alexey Milovidov).
- Fix key condition analysis for
DateTime64primary keys compared with integer constants, which previously resulted in no granule pruning. #98410 (Amos Bird). - The setting
optimize_syntax_fuse_functionsis enabled by default. #98424 (Alexey Milovidov). - Optimize
avgWeightedaggregate function by using local accumulators instead of per-row store-forwarding through aggregate state, improving performance by up to 27% for Nullable inputs. #98793 (Antonio Andelic). - Improves performance and reduces memory usage for parallel window functions in certain scenarios, and for
arrayFoldworkloads with large arrays. This can also reduce page-fault pressure and improve stability under tight memory limits for affected queries. #98892 (filimonov). - Improve performance of sorted merges. #99013 (Artem Zuikov).
- Optimize
INTERSECT ALLandEXCEPT ALL. #99097 (Raufs Dunamalijevs). - Support the
read_in_order_use_virtual_rowoptimization for reverse-order reads. #99198 (Vladimir Cherkasov). - Reduce cache contention in
RIGHTandFULLJOINs by checking if JoinUsedFlags is set before writing. #99274 (Hechem Selmi). - Optimize
PrefetchingHelper::calcPrefetchLookAheadby replacing floating-point math with pure integer arithmetic, improving instruction cache layout and reducing cycle overhead during aggregation loops. #99327 (Riyane El Qoqui). - Reduce memory consumption of Keeper by replacing
absl::flat_hash_setwithCompactChildrenSetfor storing node children. The new container stores 0–1 children inline without heap allocation, which covers the majority of Keeper nodes. This reducesKeeperMemNodesize from 144 to 128 bytes. #99860 (Antonio Andelic). - Aggregate projections are now correctly supported in views. Fixes #32753. #88798 (Amos Bird).
- Support OUTER to INNER join conversion optimization with
join_use_nulls. Closes #90978. #95968 (Vladimir Cherkasov). - Improve subcolumns reading by correct sizes calculation before reading. It reduces memory usage and speeds up the subcolumns reading. #96251 (Pavel Kruglov).
- Make mark, uncompressed and page caches to use separate jemalloc arena to avoid memory fragmentation when short lived allocations, i.e., for queries and requests are mixed with longer lived allocations for caches. #96812 (Seva Potapov). #98812. #99021
- Tables with
DELETE TTLrules can now use the vertical merge algorithm. #97332 (murphy-4o). - Apply data skipping indexes during distributed index analysis. #97767 (Azat Khuzhin).
- Marks of secondary indexes are now prewarmed when the
prewarm_mark_cachesetting is enabled (loaded into the index mark cache during data part fetches and table startup). #97772 (Anton Popov). - Reduced locking during access control. #97894 (Nikita Taranov).
- When apply_row_policy_after_final or apply_prewhere_after_final is enabled, compound AND conditions in row policies and PREWHERE are now decomposed to extract sorting-key atoms for primary key index analysis. Previously, if a deferred filter contained a mix of sorting-key and non-sorting-key predicates (e.g. x > 1 AND y != ‘foo’), the entire expression was excluded from index analysis. Now sorting-key atoms (like x > 1) are extracted and used for granule pruning, even from nested AND expressions. #98513 (Yarik Briukhovetskyi).
- Reduce lock contention in MergeTreeBackgroundExecutor by making task resources release without acquiring the lock. Closes #93620. #98604 (Dmitry Novik).
- Fix excessive memory usage (~514 MiB) during format auto-detection when reading non-Arrow data (e.g. JSON from
urlorfilewithout explicit format), caused by the ArrowStream reader misinterpreting the first bytes as a huge metadata length. #98893 (Konstantin Bogdanov).
Improvement
- Makes it possible to parse GeoParquet files that contain different Geo type in the same column. #97851 (Mark Needham).
- Introduce
tokensForLikePatternSQL function that tokenizes LIKE patterns while respecting wildcard semantics:%and_are treated as wildcards, escaped wildcards (\%,\_) are treated as literals, and tokens adjacent to unescaped wildcards are discarded. #97872 (Amos Bird). - Add a
{_schema_hash}placeholder for the S3 table engine that inserts a hash of the table’s column definitions into the S3 path. #98265 (Miсhael Stetsyuk). SymbolIndex,addressToSymbol,system.symbols, andbuildIdnow work on macOS by parsing Mach-O symbol tables. #99014 (Alexey Milovidov).- The
system.stack_tracetable now works on macOS, allowing introspection of all server thread stack traces. #98982 (Alexey Milovidov). - Add per-server LDAP config option
<follow_referrals>(defaultfalse) to control whether the LDAP client follows referrals. Disabling referral chasing avoids timeouts and hangs when searching from an Active Directory domain-root base DN. Referral-related log messages are moved fromwarntotrace. #96765 (paf91). - We now track any data skipping indices that were used during query execution in the query_log table in a new column named
skip_indices. Fixes #78676. Original author @pheepa. #87862 (Grant Holly). - ACCESS_DENIED hints no longer reveal column names unless the user can show all required columns; database/table names remain visible in the hint. #91067 (filimonov).
- Add a dedicated cleanup thread for MergeTree to prevent cleanup delays under heavy merge load. This resolves #86181. #91574 (Amos Bird).
- Reload cluster config if IPs of local server’s hostname changed, instead of IPs of any host. Fixes #81215, #70156 and #65268. #93726 (Zhigao Hong).
- Allow optimize_aggregators_of_group_by_keys to correctly optimize aggregate functions in GROUPING SETS queries. #93935 (Xiaozhe Yu).
- Keeper-bench: report errors in metrics and generate json metrics file for —input-request-log mode. #95748 (Mohammad Lareb Zafar).
- Add new clause ROLE to CREATE USER. #97074 (Vitaly Baranov).
- You can now set internal_replication settings for a cluster created by the Replicated database. #97228 (Pervakov Grigorii).
- New setting
allow_nullable_tuple_in_extracted_subcolumnscontrols whether extractedTuple(...)subcolumns fromTuple,Variant,DynamicandJSONare returned asNullable(Tuple(...))(NULLfor missing rows) or asTuple(...)(default tuple values for missing rows). Disabled by default, this setting can only be changed by restarting the server. #97299 (Nihal Z. Miaji). - Add information about deferred filters as a separate item to EXPLAIN query output (when using Row Policies/PREWHERE with FINAL). Related: #91065. #97374 (Yarik Briukhovetskyi).
- Enable
type_json_allow_duplicated_key_with_literal_and_nested_objectby default. It allows to avoid errors about duplicated keys during parsing of JSONs like{"a" : 42, "a" : {"b" : 42}}that can be formatted by ClickHouse from original JSON data{"a" : 42, "a.b" : 42}. #97423 (Pavel Kruglov). - Keeper improvement:
find_super_nodesis a very useful command for debugging unexpected growth in the node count in Keeper. Unfortunately, if there are multiple super nodes, it’s almost impossible to find more than one, because the command gets stuck forever traversing the children of the first encountered super node. This PR forbids traversing the children of super nodes. #97819 (pufit). - Initial completion support for
clickhouse-keeper-client. #97828 (Konstantin Bogdanov). - Flush async logging buffers in case of crash. #97836 (Azat Khuzhin).
- Enable the impersonate feature by default (see EXECUTE AS target_user). #97870 (Vitaly Baranov).
- Improve canceling queries with SQLite table engine by KILL QUERY and cancel query (Ctrl+C) in clickhouse-client. #97944 (Roman Vasin).
- Add server setting
jemalloc_profiler_sampling_rateto control jemalloc’slg_prof_sampleand expose it asjemalloc.prof.lg_sampleasynchronous metric. #97945 (Antonio Andelic). - Support weights in concurrent bounded queue implementation. #97962 (Daniil Ivanik).
- Add sslmode to the allowed keys for PostgreSQL dictionary sources. Previously, sslmode was not in the dictionary_allowed_keys allowlist in PostgreSQLDictionarySource.cpp, making it impossible to configure SSL mode for PostgreSQL dictionary connections. This prevented dictionaries from connecting to PostgreSQL servers that require SSL (e.g., AWS RDS, which enforces SSL by default), as the connection would fail TLS negotiation and the server would reject the unencrypted fallback. #98014 (mcalfin).
- Show a clear “no such file” error when passing a non-existent file path to
clickhouseorclickhouse-local, instead of a confusing generic message. #98048 (Raúl Marín). - Text indexes can now be built on top of
Nullable([Fixed]String)andArray(Nullable([Fixed]String))columns. #98118 (Jimmy Aguilar Mena). - Avoid dropping named collections that are dependencies of dictionary sources. #98127 (Pablo Marcos).
- Enable
grace_hashjoin algorithm for queries with totals. #98144 (János Benjamin Antal). - Cancel background merges early in DROP DATABASE for ordinary shared merge tree. #98161 (Shaohua Wang).
- Improve canceling queries with MongoDB and MySQL by KILL QUERY and cancel query (Ctrl+C) in clickhouse-client. #98187 (Roman Vasin).
- Remove NetlinkMetricsProvider and use procfs exclusively for per-thread taskstats metric collection. Netlink-based collection is problematic in containerized environments and has worse tail latency under contention. #98229 (Amos Bird).
- Refactor Iceberg manifest file handling to fix issues with manifest file caching. #98231 (Daniil Ivanik).
- Now we take into account cases where the sorting key of the table can be an expression like
toDate(time), and can make the decisions about not-deferring expressions like this if they are part of filters. #98237 (Yarik Briukhovetskyi). - Add a new
MaxAllocatedEphemeralLockSequentialNumbermetric for the maximum sequential number allocated for ephemeral lock znodes in ZooKeeper. #98243 (Miсhael Stetsyuk). - Update clickstack to version 2.20.0. #98252 (Aaron Knudtson).
- Added a new profile event
KeeperRequestTotalWithSubrequeststhat counts each subrequest within a multi-request individually, providing better visibility into the actual Keeper workload. The existingKeeperRequestTotalevent continues to count each multi-request as a single request. #98348 (Antonio Andelic). SYSTEM RELOAD DICTIONARIESnow reloads dictionaries in topological order so that dictionaries sourcing from other dictionaries see fresh data after reload. #98356 (Alexey Milovidov).- Restart the statistics cache after changing the MergeTree setting. #98520 (Han Fei).
- Only “alive” replicas (that are connectable) participate in distributed index analysis. #98521 (Azat Khuzhin).
- Add a setting
access_control_improvements.disallow_config_defined_profiles_for_sql_defined_users(disabled/allowed by default) that disallows using config-defined settings profiles (except for thedefaultprofile) for SQL-defined users. #98662 (Alexander Tokmakov). - Cap the number of nodes used in the automatic parallel replicas heuristic to the actual number of nodes in the cluster (instead of only the
max_parallel_replicassetting). #98668 (Nikita Taranov). - Implement hedged requests and asynchronous reading for distributed index analysis. #98724 (Azat Khuzhin).
- Deserialization of binary
AggregateFunctionstates now requires consuming the full input. If extra redundant trailing bytes are present, ClickHouse throws an exception instead of accepting malformed state data. #98786 (Nihal Z. Miaji). - Make TRUNCATE DATABASE respond to query cancellation. #98828 (Shaohua Wang).
- Improve
keeper-benchwith request pipelining, warmup period, per-operation stats, reproducible seeds, and better error handling. #98906 (Antonio Andelic). - Support SAMPLE clause in distributed index analysis. #98931 (Azat Khuzhin).
- Show chart title in dashboard even when query returns empty result or encounters an error. #98975 (Yash ).
- Analyzer error messages no longer dump all columns of a table (which could produce 150KB+ exceptions). Column lists are now capped at 10 entries. #99002 (Yash ).
- Properly return column stats from sub-queries with joins so that parent query can use them for join reordering. #99096 (Alexander Gololobov).
- Mark ZooKeeper session as expired immediately when finalization starts, instead of waiting for the send thread to exit. This allows other threads to establish a new session without delay. #99102 (Raúl Marín).
- Use more math functions from LLVM-libc:
exp,exp2,expm1,fabs,fabsl,floor,fmodl,log,log2,logf,pow,scalbn,scalbnl,copysignl,nan,nanf,nanl, and theexplogxfshared constants. #99118 (Konstantin Bogdanov). - Reduce memory usage and fix potential duplicate output in
system.jemalloc_profile_textcollapsed format. #99121 (Antonio Andelic). - Add
is_subrequestcolumn tosystem.aggregated_zookeeper_logto separate standalone requests from sub-requests inside Multi/MultiRead requests. Previously, sub-requests were aggregated into the same buckets as standalone requests, and since each sub-operation was logged with the total multi-request duration, the average latency became misleading. Sub-requests now have zero latency. #99169 (Miсhael Stetsyuk). - Allow
ALTER TABLE MODIFY COLUMN x TTL ...command without specifying column type. #99208 (Nikolay Degterinsky). - Skip stale Keeper requests for sessions that have already disconnected, avoiding unnecessary Raft round-trips. The number of tracked finished sessions is capped by the
max_finished_sessions_cache_sizecoordination setting. #99246 (Antonio Andelic). - Support text index built on
mapValues(map)withINoperator. #99286 (Anton Popov). - Shell-like completion support in clickhouse keeper-client (handle completions of arguments in quotes, i.e.
'foo ba', handle escaped arguments, i.e.foo\ ba, makelsprint quoted nodes, if they have whitespaces). #99312 (Azat Khuzhin). - Prevent Keeper
mntrcommand from getting stuck because of lock contention. #99472 (Antonio Andelic). - Reduce lock contention in Keeper dispatcher by invoking callbacks and dispatching read requests outside mutex scope, and add profiled lock guards for observability. #99751 (Antonio Andelic).
- Tolerate missing padding at the end of the last block of parquet files. #99857 (Seva Potapov).
Bug Fix (user-visible misbehavior in an official stable release)
- Fixes how an Alias table target is saved as a DDL dependency when not fully qualified: it’s now saved with the Alias table database instead of the session database. #95175 (Enric Calabuig).
- Fix wrong result or exception during reading subcolumns of ALIAS columns. #95408 (Pavel Kruglov).
- Fix missing column when non-standard identifier alias in JOIN with old analyzer. Fixes #25594, #47288 and #53263. #95679 (Zhigao Hong).
- Fixes a crash in Kusto dialect functions
bin(),bin_at(),extract(), andindexof()when empty arguments are provided. #95736 (NeedmeFordev). - Forbids mounting local_object_storage (which is used by datalakes above local filesystem and maybe by LocalDisk) anywhere apart from user_files_path in clickhouse-client. #96201 (Daniil Ivanik).
- In
DeltaLaketable engine fix logical race on snapshot version change, remove redundant heavy snapshot reloads. #96226 (Kseniia Sumarokova). - Fix logical error on attaching a part in MergeTree if there were several chained renames between detaching and attaching. #96351 (Alexey Milovidov).
- Fix a bug where explicit settings sent alongside
compatibilityin the same request could be silently ignored when their value matched the server default. #97078 (Raufs Dunamalijevs). - Fix the client reporting
NETWORK_ERRORinstead of the actual parsing error (with the correct row number) when an INSERT with parallel parsing encounters invalid data. #97339 (Alexey Milovidov). - Fix
sumCountaggregate function not being able to read older serialized states after introduction ofNullable(Tuple). Closes #97370. #97502 (Nihal Z. Miaji). - Fix exception in tuple comparison involving
Nothingtype elements (e.g., comparing withNULLtuple elements) when used withGROUPING SETSandORDER BY. #97509 (Alexey Milovidov). - Fix non-deterministic
uncompressed_hashcomputation for Compact MergeTree parts when multiple compression codecs are used, which could cause incorrect deduplication behavior. #97522 (Alexey Milovidov). - Fix logical error about missing stream during INSERT SELECT with JSON and buckets in shared data. Closes #97331. #97523 (Pavel Kruglov).
- Fix
MEMORY_LIMIT_EXCEEDEDexceptions being incorrectly reported asCORRUPTED_DATAduring SummingMergeTree and CoalescingMergeTree merges. #97537 (János Benjamin Antal). - Fix “Context has expired” exception for correlated subqueries containing table functions like
url(). #97544 (Alexey Milovidov). - Fix exceptions and incorrect behavior in
optimize_syntax_fuse_functionswith aggregate projections, Date types, and column name preservation. #97545 (Alexey Milovidov). - Remove incorrect
replaceRegexpOnetoextractquery rewrite that produced wrong results when the regexp didn’t match; also fix exception whenreplaceRegexpOneis used withGROUP BY ... WITH CUBEandgroup_by_use_nulls=1. #97546 (Alexey Milovidov). - Fix
DROP DATABASEwithdatabase_atomic_wait_for_drop_and_detach_synchronouslyhanging indefinitely when the query is killed. #97586 (Alexey Milovidov). - Fix
KILL QUERYnot being able to terminate queries stuck inWITH FILLgeneration, dictionary loading viadictGet, orALTER DELETEwithmutations_sync=1onReplicatedMergeTree. #97589 (Alexey Milovidov). - The
looptable function was callinginner_storage->read()directly, bypassing the interpreter layer where row policies, column-level grants, and other security checks are applied. This allowed a user restricted by row policies to read all rows vialoop(table)even when a direct SELECT returned zero rows. #97682 (pufit). - Fixes incorrect partition pruning in cases of using pre-epoch DateTime64 with
toDate()function. #97746 (Yarik Briukhovetskyi). - After this patch,
hasPartitionIdwill return false if another partition with a higher partition ID exists in the data part set. #97748 (Mikhail Artemenko). - Fix possible crashes during reading of empty granules in advanced shared data in JSON. Closes #97563. #97778 (Pavel Kruglov).
- Fix
Cannot schedule a fileLOGICAL_ERRORonINSERTintoDistributeddue to race betweenDROPandINSERT. #97822 (Azat Khuzhin). - Fixed ClickHouse server crash/assert in call to
mapContainsKey/mapContainsKeyLikewithtokenbf_v1skip index. #97826 (Shankar Iyer). - Fix LOGICAL_ERROR exceptions caused by
LowCardinalityinside compound types (Variant,Dynamic,Tuple) inconcatWithSeparator,format,INsubqueries,GLOBAL IN, and joins with runtime filters. #97831 (Raúl Marín). - Fix
LOGICAL_ERRORexceptionChunk info was not set for chunk in MergingAggregatedTransformwhen usingARRAY JOINwithmerge()table function over multiple Distributed tables combined withGROUP BY. #97838 (Raúl Marín). - Fix server crash (
std::terminate) caused by an uncaught exception in the HTTP connection pool destructor when the connection group hard limit is reached under high concurrency. The exceptionHTTP_CONNECTION_LIMIT_REACHEDcould escape~PooledConnectionwhen recycling a connection back to the pool, leading toSIGABRT. #97850 (Antonio Andelic). - Fix incorrect result when
grace_hashalgorithm is used with non-equi joins and left block cannot be processed completely because of the size constraints on the join result. #97866 (János Benjamin Antal). - Fix performance inefficiency in DeltaLake metadata scanning introduced in #96686. #97880 (Kseniia Sumarokova).
- Fix data race in ZooKeeper client between sendThread and receiveThread. #97887 (Pablo Marcos).
- Fixes a bug where it was not possible to use CTE with distributed insert selects. Continuation of https://github.com/ClickHouse/ClickHouse/pull/87789. Closes #95837. #97889 (Yarik Briukhovetskyi).
- Fix exception from
CachedOnDiskReadBufferFromFile::readBigAt. Closes #97325. #97890 (Kseniia Sumarokova). - Fix
LOGICAL_ERRORexception inAliasengine with materialized columns due to column mismatch. Closes #97907. #97921 (Kai Zhu). - Fix Keeper data loss after restart when using Azure Blob Storage with
s3_plainmetadata for log storage. #97987 (Antonio Andelic). - Fix JIT miscompilation of
signfunction for integer types wider thanInt8— values outside the -128..127 range could produce incorrect sign. #98012 (Alexey Milovidov). - Fixed
DUPLICATE_COLUMNexception and silent NULLs when reading Delta Lake tables that use column mapping “name” mode with struct fields whose names contain dots (e.g.STRUCT<`a.foo`: STRING, `b.foo`: STRING>). #98013 (Caio Ishizaka Costa). - Fix mutation after lightweight update and secondary indices. #98044 (Raúl Marín).
- Fix incorrect result of FINAL queries when mixing primary key and non primary key skip indexes. #98097 (Raúl Marín).
- Enforce READ ON FILE checks for scalar file() and DESCRIBE TABLE file(). #98115 (Nikolay Degterinsky).
- Fixes a crash where querying files with a glob pattern (e.g.,
file('dir/**', 'LineAsString')) would throw an unhandled filesystem exception (STD_EXCEPTION) if the directory contained a dangling symlink. Dangling symlinks are now silently skipped, and the query returns results from all valid files. #98143 (Mark Andreev). - Fix segfault in query plan optimization when converting outer join to inner join with
arrayJoinin filter expression. #98147 (Alexey Milovidov). - Fix
ProtobufListformat not working with Kafka engine due to read state not being reset between messages. #98151 (Alexey Milovidov). - Fix logical error with analyzer_compatibility_join_using_top_level_identifier and ARRAY JOIN, closes #98164. #98179 (Vladimir Cherkasov).
- Set
Watchcomponent for watch responses inaggregated_zookeeper_loginstead of leaving it empty. #98202 (Antonio Andelic). - If the partition key columns are not covered by the sorting key, then partition pruning could incorrectly skip partitions containing rows that should “win” during FINAL deduplication. #98242 (Yarik Briukhovetskyi).
- Fix logical error “Bad cast from type DB::ColumnConst to DB::ColumnArray” in
kql_array_sort_asc/kql_array_sort_descwhen called with constant array arguments. #98251 (Alexey Milovidov). - Fix out-of-bounds access in
ColumnConst::getExtremesthat could cause a crash whenextremes = 1is enabled. #98263 (Alexey Milovidov). - Fix potential deadlock when two concurrent
MOVE PARTITIONoperations work with the same pair of tables in opposite directions. #98264 (Alexey Milovidov). - HTTP server now returns an error message in the response body for 400 Bad Request responses caused by malformed headers, instead of an empty body. #98268 (Alexey Milovidov).
- Fix wrong results with distributed index analysis (experimental feature) and query condition cache. #98269 (Azat Khuzhin).
- Fixed LOGICAL_ERROR exception “Invalid binary search result in
MergeTreeSetIndex” triggered bytoDateconversion on key columns with data crossing the 65535 boundary. #98276 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception when a RIGHT JOIN wrapped in a CROSS JOIN is swapped by thequery_plan_join_swap_tableoptimization in the legacy join step code path. #98279 (Alexey Milovidov). - Validate corrupted data during
DDSketchdeserialization to prevent segfaults, exceptions, infinite loops, and OOM when reading corruptedquantilesDDaggregate function states. #98284 (Alexey Milovidov). - Fix LOGICAL_ERROR “Trying to execute PLACEHOLDER action” when correlated columns from outer queries are referenced inside lambda functions such as
arrayMap. #98285 (Alexey Milovidov). - Fix logical error exception in
caseWithExpressionwhenCASEexpression involvesmaterialize(NULL)or otherNullable(Nothing)arguments. #98290 (Alexey Milovidov). - Fix bad cast exception when filtering
_tablevirtual column inmergetable function. #98291 (Alexey Milovidov). - Fix sporadic deduplication failure where re-inserts were incorrectly deduplicated due to inconsistent cleanup ordering between
blocks/anddeduplication_hashes/ZooKeeper directories. #98293 (Alexey Milovidov). - Fix exception when
ORDER BY ... WITH FILLis used together withLIMIT BY. #98361 (Alexey Milovidov). - Fix silent data corruption when inserting a Parquet/Arrow
Datecolumn into anEnumcolumn — now properly rejects the incompatible type conversion instead of storing invalid enum values. #98364 (Alexey Milovidov). - Fix exception when reading an Arrow file with
Arraycolumn into a table withNestedcolumn. #98365 (Alexey Milovidov). - Fix
MATERIALIZE INDEXandMATERIALIZE PROJECTIONmutations getting stuck when the index or projection is dropped before the mutation finishes. #98369 (Alexey Milovidov). - Fix exception when reading from
Nullable(Tuple(...))where a Tuple element name collides with the Nullablenullsubcolumn. #98372 (Alexey Milovidov). - Fix exception “Column … query tree node does not have valid source node” when joining a
Mergetable (wrapping aDistributedtable) with another table. #98376 (Alexey Milovidov). - Fix incorrect Parquet
BooltoFixedStringconversion in native V3 reader that produced raw bytes instead of string representation. #98378 (Alexey Milovidov). - Fix
tryGetColumnDescriptionto filter subcolumns by parent column kind, consistent with other column lookup methods. #98391 (Alexey Milovidov). - Accept base64 credentials without padding in HTTP Basic Auth. Some HTTP clients omit trailing
=padding in theAuthorization: Basicheader, which previously caused authentication failures. #98392 (Amos Bird). - Fix incorrect partition pruning results after merging parts with
Nullablepartition key columns, caused by wrong min-max index bounds. #98405 (Amos Bird). - Fix rare exception in the pipeline executor, that could manifest as a
Received signal 6(only in debug builds), when pipeline expansion races with query cancellation. #98428 (Alexey Milovidov). - Fix exception “Column identifier is already registered” when
count_distinct_optimizationis used with aQUALIFYclause. #98433 (Alexey Milovidov). - Fix exception “cannot be inside Nullable type” when using
IN/NOT INwithLowCardinalitycolumn arguments (e.g.a NOT IN (b)whereaisLowCardinality(String)). #98443 (Alexey Milovidov). - Fix “Pipeline stuck” exception in
full_sorting_mergejoins caused by a deadlock inPingPongProcessorwhen theFilterBySetOnTheFlyoptimization created a circular dependency withMergeJoinTransform. #98454 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception “Projection cannot increase the number of rows in a block” when merging parts with TTL that deletes all rows and an aggregate projection with a constantGROUP BYkey. #98458 (Alexey Milovidov). - Fix logical error exception when
CROSS JOINis used together withINNER JOIN USING. #98459 (Alexey Milovidov). - Fix null pointer dereference in
dictGetOrDefaultwhen the key argument isNullable. #98460 (Alexey Milovidov). - Fix exception in
DISTINCTqueries when using aggregate projections andmaterializecausesLowCardinalitytype differences between the query and the projection. #98462 (Alexey Milovidov). - Fix LOGICAL_ERROR exception when
arrayJoinis used in a filter expression with OUTER JOIN andjoin_use_nullsenabled. #98464 (Alexey Milovidov). - Fix logical error exception “Replica decided to read in WithOrder mode, not in ReverseOrder” when using parallel replicas with
optimize_aggregation_in_order. #98467 (Alexey Milovidov). - Fixed ClickHouse Keeper disconnecting Java ZooKeeper clients after
addWatchrequest. The Java client expects a 4-byteErrorResponsebody in theaddWatchresponse, but Keeper was sending an empty body, causingEOFExceptionand session disconnect. This broke Apache Curator’sCuratorCacheand any Java application using persistent watches. Fixes #98079. #98499 (Antonio Andelic). - Fix
zk_followersandzk_synced_followersKeeper metrics not decreasing when a follower goes down. Add newzk_learnersandzk_synced_non_voting_followersmetrics to themntrfour-letter-word command. Fixes #54173. #98504 (Antonio Andelic). - Fix a LOGICAL_ERROR exception in
renameAndCommitEmptyPartsthat could occur whenTRUNCATE TABLEruns concurrently withOPTIMIZE TABLEusing MergeTree transactions. #98508 (Alexey Milovidov). - Fixed Keeper’s secure raft port ignoring
cipherListanddhParamsFilefromopenSSLconfiguration, always using defaults instead of user-specified values. Close #51188. #98509 (Antonio Andelic). - Fixed misleading Keeper log messages like “Receiving request for session X took 9963 ms” where the reported time was actually spent waiting idle in
poll()between heartbeats, not performing the operation itself. Fixes #79026. #98510 (Antonio Andelic). - Fix unexpected result with read_in_order_use_virtual_row and monotonic functions, close #97837. #98514 (Vladimir Cherkasov).
- Fix
LOGICAL_ERROR: Not-ready Set is passed as the second argument for function 'in'when usingPREWHEREwithINsubquery on MergeTree tables. #98522 (Alexey Milovidov). - Fix Keeper TCP connections preventing graceful server shutdown by not responding to shutdown signal. #98525 (Alexey Milovidov).
- Fix exception “Sorting column wasn’t found in the ActionsDAG’s outputs” when
query_plan_convert_join_to_inis enabled withquery_plan_merge_expressions = 0. #98526 (Alexey Milovidov). - Fix MongoDB dictionary source failing with named collections. Closes #97840. #98528 (Pablo Marcos).
- Fixed LOGICAL_ERROR when Identifier is empty after parameter substitution. #98530 (Pervakov Grigorii).
- Fix pipeline deadlock when using
sort_overflow_mode = 'break'together with window functions. #98543 (Alexey Milovidov). - Fix column rollback in Buffer engine during handling an exception during appending a new block. Old logic could lead to corrupted in-memory state of columns. #98551 (Pavel Kruglov).
- Fixed exception
Bad cast from type ColumnConst to ColumnDynamicin null-safe comparison (<=>/IS NOT DISTINCT FROM) with constDynamicorVariantcolumns andNULL. Also fixedIS DISTINCT FROMwithDynamic/VariantvsNULLalways incorrectly returning 0. #98553 (Alexey Milovidov). - Fixed usage of the text index with other skip indexes. Previously, logical errors such as “Trying to get non-existing mark” could be thrown when a query filter utilized a text index and other regular skip indexes simultaneously. #98555 (Anton Popov).
- Fix logical error “TABLE_FUNCTION is not allowed in expression context” when a table function with an alias appears multiple times in the same query scope (e.g. in both
PREWHEREandQUALIFYclauses). #98557 (Alexey Milovidov). - Fix distributed index analysis with expressions (not just columns) in PK (leads to zero filtering of redundant granules on remote replicas). #98561 (Azat Khuzhin).
- Disallow dropping column when its subcolumns are used in other columns default/alias expressions and use analyzer for default expressions on alter drop column. #98569 (Nikita Mikhaylov).
- Fix S3 requests being incorrectly retried on non-retryable errors (including
HTTP_CONNECTION_LIMIT_REACHED) in the HTTP client. #98598 (Sema Checherinda). - Fixes a decimal overflow when partition pruning with DateTime64. #98628 (Yarik Briukhovetskyi).
- Fix two bugs in JIT expression compilation: a copy-paste error in
nativeCasttype checking that made integer-to-integer and float-to-float cast branches unreachable, and incorrectnullptrTargetMachine passed to LLVMPassBuilderpreventing target-specific optimization passes from being registered. #98660 (Alexey Milovidov). - Fix RBAC bypass that allowed users to DESCRIBE any table via
remote(),remoteSecure(),cluster(), orclusterAllReplicas()pointed at localhost, without requiringSHOW_COLUMNSprivilege. #98669 (pufit). - Fix
BAD_GETexception and incorrect query results when a non-boolean expression (e.g.sin(col)) is used in both WHERE and SELECT with a JOIN, due to filter push-down optimization corrupting shared DAG nodes. #98681 (Alexey Milovidov). - Fix LOGICAL_ERROR “Replica decided to read in Default mode, not in WithOrder” when using
read_in_order_through_joinwith parallel replicas. #98685 (Alexey Milovidov). - Fix exception “Bad cast from type
DB::TableFunctionNodetoDB::QueryNode” when usinginputtable function as an argument ofremote. #98694 (Alexey Milovidov). - Fix outdated data parts resurrection caused by incorrectly cleaning up empty covering parts. #98698 (Shaohua Wang).
- Fix exception in
LogicalExpressionOptimizerPasswhen a boolean function in anequalscomparison returns aVarianttype. #98712 (Alexey Milovidov). - Fix
parseDateTimeBestEffortincorrectly parsing words starting with month/weekday prefixes. Closes #97965. #98742 (Pavel Kruglov). - Fix
UNKNOWN_IDENTIFIERexception when queryingmerge()table function orMergeengine over tables with JSON columns that have different parameters (e.g. differentSKIPfields) and ALIAS columns referencing JSON sub-paths, with the new analyzer enabled. Closes #97812. #98753 (Pavel Kruglov). - Fix
optimize_skip_unused_shardsoptimization with the analyzer in caseDistributedstorage is used in aView. #98754 (Nikolai Kochetov). - Fix tuple subcolumn access by name (e.g.
SELECT x.aforTuple(a UUID, b Int32)) for external tables passed via--externalinclickhouse-client. Closes #96925. #98755 (Pavel Kruglov). - Fix
reverseUTF8exception on invalid (truncated) UTF-8 input. #98770 (Alexey Milovidov). - Fix detecting set skip index usefulness with OR with false (i.e. or(x, 0)) predicate. #98776 (Azat Khuzhin).
- Fix a
LOGICAL_ERRORexception (Block structure mismatch inremoveUnusedColumns) that could occur withFINAL+PREWHERE+ constantWHEREexpression + column-independent aggregates likecount(). #98778 (Alexey Milovidov). - Make
system.trace_logentries for ClickHouse dictionaries’ auto-reloads have non-empty query IDs. #98784 (Miсhael Stetsyuk). - Fixes a crash where we could de-reference a null pointer in system tables created between the time when we snapshot the tables in the
IDatabaseTablesIterator::table()call and the tables changing in another thread during later iteration. #98792 (Grant Holly). - Fix
SYSTEM START REPLICATED VIEWnot waking up the refresh task. #98797 (Pablo Marcos). - Fix exception “Inconsistent table names” when using
view()table function containing JOINs inside another JOIN (only with old analyzer). #98809 (Alexey Milovidov). - Fix adjusting RLIMIT_SIGPENDING (via pending_signals). #98829 (Azat Khuzhin).
- Fix exception when composing
loopwith cluster table functions. #98860 (Konstantin Bogdanov). - LEFT ANTI JOIN with multiple join key columns returned wrong results when
enable_join_runtime_filters=1(which is default). #98871 (Alexander Gololobov). - Fix
WITH FILL STALENESSproducing extra filled rows when data is read in multiple chunks (e.g., with smallindex_granularity). #98895 (Alexey Milovidov). - Fix “RPNBuilderFunctionTreeNode has A arguments, attempted to get argument at index B” LOGICAL_ERROR. #98900 (Azat Khuzhin).
- Fix memory tracking drift caused by failed allocations not being rolled back,
nallocx(0)undefined behavior, and off-by-one in global peak tracking. Extend tracking to coverio_uringring buffers. #98915 (Antonio Andelic). - Forbid attaching to local data lake tables outside user paths, not only creating them. #98936 (Daniil Ivanik).
- Fix a race condition that could cause a “ReadBuffer is canceled” exception in queries using
urlClusteror similar cluster table functions. #98955 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception in financial functions (financialNetPresentValue,financialInternalRateOfReturn, etc.) whenBFloat16type arguments are passed. #98958 (Alexey Milovidov). - Fix skip indexes (and primary key conditions) not being applied for ALIAS columns when query plan expression merging is disabled (query_plan_merge_expressions = 0 or query_plan_enable_optimizations = 0). #98960 (Peng).
- Increment
InsertQueryProfileEvent for async inserts. Closes #98626. #98962 (Narasimha Pakeer). - Fix exception “Inconsistent KeyCondition behavior” in debug builds when primary key contains NaN float values, by making
accurateLessandaccurateEqualshandle NaN consistently with ClickHouse sort order. Closes #98075. #98964 (Alexey Milovidov). - SummingMergeTree no longer sums Bool (and other domain type) columns. Bool values are kept as-is instead of being arithmetically summed. #98976 (Yash ).
- Fixes an exception Scalar doesn’t exist that occurred when querying a remote shard with
optimize_const_name_sizeset andenable_scalar_subquery_optimization= 0. Large constants replaced with__getScalarreferences in the remote query were not being sent to the shard, causing the query to fail. #98979 (andriibeee). - Fix
NOT_FOUND_COLUMN_IN_BLOCKfor some queries withGROUP BYand expressions that include inverse dictionary lookup,Date/DateTimeconversion comparisons, and tuple comparisons. Closes #98888. #98980 (Nihal Z. Miaji). - Fixed undefined behavior (null pointer dereference) when altering a version/sign/is_deleted column to
EPHEMERALorALIASin MergeTree engines. Such alterations are now properly rejected. #98985 (Alexey Milovidov). - Fixed an issue where
system.grantsomitted the regular expression parameters forURLandS3grants in theaccess_objectcolumn. #98987 (DQ). - Fixed Iceberg BigLake reads: ADC credentials are now forwarded to the GCS S3 client (fixing 403 errors), OAuth2 credentials are URL-encoded before sending (fixing auth failures for tokens with special characters), and namespace traversal no longer aborts on BigLake HTTP 400 responses. #98998 (Nikita Fomichev).
- Fixed
clickhouse-clientfailing to switch timezone whenTZenvironment variable uses POSIX file path syntax (e.g.TZ=:/etc/localtime). #99000 (Yash ). - Fix incorrect or less pruning when
startsWith,LIKE,NOT LIKEused withFixedStringcolumn. Additionally,FixedStringtoStringcast function can now prune granules when wrapped around key column. Closes #98940. #99001 (Nihal Z. Miaji). - Fixed
windowFunnelwithstrict_deduplicationreturning incorrect level when a duplicate event was encountered. #99003 (Yash ). - Fixes a bug where EXISTS would ignore LIMIT and OFFSET clauses in subqueries, causing incorrect results when the subquery returned no rows due to an offset or a zero limit. Closes #88722. #99005 (andriibeee).
- Fix “Block structure mismatch” exception when filter push-down optimization encounters an AND expression that short-circuits to a constant with
GROUPING SETS. #99010 (Alexey Milovidov). - Fix exception when reading patch parts (lightweight updates) without
_part_offsetcolumn in the query plan. #99023 (Alexey Milovidov). - A query like
SELECT * FROM table WHERE pk_id = ''wherepk_idis the primary key and ofStringtype will now correctly use the primary key index for filtering granules. #99027 (Shankar Iyer). - Fix
DEPENDENCIES_NOT_FOUNDexception in Kafka engine when materialized view is detached while the background thread is streaming data. #99028 (Alexey Milovidov). - Fix exception when creating a table with an
EPHEMERALcolumn that has the same name as a virtual column (e.g.,_part_offset). #99031 (Alexey Milovidov). - Fix misleading “inflate failed: buffer error” when reading non-existent compressed files via
url()table function with glob patterns. Now returns empty result as expected whenhttp_skip_not_found_url_for_globsis enabled. #99034 (Alexey Milovidov). - Fix server crash (std::terminate) when executing
ALTER TABLE ... DROP PARTon a patch part after a schema change (e.g. ADD COLUMN). The crash was caused by missing system columns (_part) in the empty coverage part metadata, leading to an uncaught exception inside a NOEXCEPT_SCOPE. #99036 (Peng). - ClickHouse server process could crash if there was a memory limit exceeded exception thrown during a cached disk read. That is now fixed. #99042 (Shankar Iyer).
- Fix
LOGICAL_ERRORwhen querying a table that has both a ROW POLICY and an ALIAS column usingdictGet. The issue was caused by premature access to the table expression during ALIAS column resolution in the new analyzer. #99065 (Peng). - Fix out of bounds error when user tries to query only virtual columns from Iceberg table with Avro format for data. It’s super rare scenario so not marking it as critical. Fixes #88238. #99080 (alesapin).
- Fix segfault in recursive CTE with
remote()+view(). #99081 (Konstantin Bogdanov). - Skip unnecessary extra index analysis when read-in-order optimization is applied. #99084 (Vladimir Cherkasov).
- Fixed a crash triggered by a memory limit exception thrown during patch part application. #99086 (Anton Popov).
- Fix debug assertion in
DDLWorkercaused by stalefirst_failed_task_nameafter a ZooKeeper entry is deleted during reinitialization recovery. #99099 (Antonio Andelic). - Fixed rebuild of text indexes on merges with TTL. #99107 (Anton Popov).
- Fix crash in
ALTER TABLE ... REMOVE SETTINGSquery for Iceberg table engine. Fixes #86330. #99108 (alesapin). - Fixes a bug in
query_plan_convert_any_join_to_semi_or_anti_joinoptimization, returning an incorrect result for unmatched rows. Related: https://github.com/ClickHouse/ClickHouse/pull/95995. #99112 (Yarik Briukhovetskyi). - Fix LOGICAL_ERROR exception in
ASTColumnsExceptTransformer::transform. #99119 (Pablo Marcos). - Fix RBAC bypass that allowed users to obtain table structure via
DESCRIBE TABLEorCREATE TABLE ASon table functions (mysql(),postgresql(),sqlite(),arrowFlight(),jdbc(),odbc(), etc.) without the required source access privileges. For functions that infer schema from remote servers, this also allowed triggering outbound connections (SSRF) without authorization. #99122 (pufit). - Fix Keeper crash (segfault in NuRaft) during dynamic reconfiguration and leadership transfer. #99133 (JIaQi Tang).
- Fix crash on usage of Buffer table with SAMPLE when destination does not support it. #99141 (Kseniia Sumarokova).
- Fix LOGICAL_ERROR due to patch parts column order mismatch. #99164 (Pablo Marcos).
- Fix very rare crash when Iceberg table contains files of mixed format (ORC and Parquet). Fixes #88126. #99168 (alesapin).
- Fix max_execution_time not being applied for backup/restore. #99205 (Kseniia Sumarokova).
- Fix
insert_deduplication_tokenbeing silently ignored forINSERT SELECTqueries withoutORDER BY ALL. Previously, deduplication was disabled entirely for unsortedINSERT SELECT, even when an explicit user token was provided. Now, providinginsert_deduplication_tokenis sufficient to enable deduplication regardless ofORDER BY ALL. #99206 (Desel72). - Fix excessive access checks during
InverseDictionaryLookupPassoptimization by checkingCREATE_TEMPORARY_TABLEgrant once before the pass instead of for every visited node. #99210 (Mikhail Artemenko). - Fix
clickhouse format --obfuscateproducing invalid SQL by obfuscating skip index types, compression codec names, database engine names, and dictionary layout/source definitions. #99260 (Raúl Marín). - Fixed a bug where, in some cases, comparing between Time[64] and DateTime[64] types was confusing; now, in cases like this, Time[64] values are promoted to DateTime[64] by adding the
1970-01-01as a date part. #99267 (Yarik Briukhovetskyi). - Clamp settings constraints in DDL worker for distributed DDL queries. #99317 (Pablo Marcos).
- Fix minor issues with TOTP authentication: the
--one-time-passwordCLI option with empty password, validation of<digits>and<period>configuration values. #99322 (Vladimir Cherkasov). - Fix logical error
unordered_map::at: key not foundin Avro output format when serializingEnum8/Enum16columns with values not present in the enum definition. #99332 (Desel72). - Fix CHECK TABLE with sparse serialization inside Tuple with Dynamic. Closes #96588. #99351 (Pavel Kruglov).
- Fixed too strict validation of text index preprocessor. #99359 (Anton Popov).
- Fix compatibility when upgrading replicated tables with implicit minmax indices from 25.10 to newer versions. #99392 (Raúl Marín).
- Removed support for negated functions (
notEquals,notLike,notIn) in text index analysis. These functions could never skip any granules, so analyzing the index for them only added overhead without any benefit. #99393 (Anton Popov). - Fix
optimize_skip_unused_shardswith a new analyzer for the case when aDistributedtable was used inside an IN subquery. #99436 (Nikolai Kochetov). - Fix heap-use-after-free in
INTERSECT/EXCEPTwhen the query produces duplicate column names. #99471 (Alexey Milovidov). - Fix logical error in
ALTER TABLE ... DROP PARTwhen a typed query parameter is used for the part name. #99489 (Alexey Milovidov). - Fixed
NOT_FOUND_COLUMN_IN_BLOCKexception when a text index predicate (e.g.hasAllTokens) is referenced in bothSELECTandWHEREclauses via an alias. #99504 (Anton Popov). - Fix incorrect results when using
hasAllTokenswith OR across columns that have separate text indexes. #99505 (Anton Popov). - Initialize page cache in
clickhouse-localso thatpage_cache_max_sizesetting takes effect. #99510 (Alexey Milovidov). - Fixed rare incorrect marking of a data part as broken and detaching it after
DETACH/ATTACH TABLEquery. #99529 (Anton Popov). - Fix
std::length_errorexception when querying empty system tables with Pretty format via HTTP interface. #99541 (Alexey Milovidov). - Fix
LOGICAL_ERRORwhen usingALTER TABLE ADD COLUMNto create anEPHEMERALcolumn with the same name as a virtual column (e.g._part_offset). #99549 (Alexey Milovidov). - Fix
VectorSimilarityIndexCacheentries never being evicted after part removal due to mismatched cache keys. #99575 (Seva Potapov). - Forbid reading Google credentials from a local file. This setting is insecure because it allows reading other credentials if the file path is known. #99584 (Konstantin Vedernikov).
- Fix performance degradation in the analyzer. Prune unused columns from ARRAY JOIN. #99587 (Dmitry Novik).
- Fixed reading of text index in table with existing lightweight deletes and row policies. #99661 (Anton Popov).
- Fix nullptr dereference in Parquet reader when filter-in-decoder path encounters filtered-out pages. Closes #99676. #99677 (Alexey Milovidov).
- Fix incorrect seek in AsynchronousReadBufferFromFileDescriptor with O_DIRECT. Closes #99358. #99678 (Pavel Kruglov).
- Fixed heap-buffer-overflow in
CompressionCodecT64and process abort inCompressionCodecMultiplewhen decompressing malformed compressed data. Both issues were found by new libFuzzer targets. The codecs now throw an exception instead of crashing. #99680 (Rahul). - Delay processing until server has finished loading all the tables. #99700 (Seva Potapov).
- Fix MySQL dictionary source bypassing
RemoteHostFilterfor inline DDL params. #99720 (Shaohua Wang). - Fix logical error when iterating over data lake tables in
system.tables. #99739 (Konstantin Vedernikov). - Fixed analysis of predicates with the
INfunction by text index with the preprocessor. Fixed the collision of searched tokens in the text index, which could lead to incorrect results. #99755 (Anton Popov). - Fix infinite loop when reading
Npyformat files with negative shape dimensions. #99812 (Desel72). - Fix global-buffer-overflow in
CRC32function onFixedStringarguments when evaluated with zero rows during query plan header computation. #99835 (Alexey Milovidov). - Fix crash (null pointer dereference) when executing
ALTER TABLE ... MODIFY COLUMN ... COMMENTon Iceberg tables. #99838 (Desel72). - Fix
aggregate_functions_null_for_emptysetting to work with aggregate functions returning non-Nullable types such asArrayorMap(e.g.,groupArray,sumMap). #99839 (Alexey Milovidov). - Fix LOGICAL_ERROR exception in
midpointfunction when called with mixed signed/unsigned integer types. #99867 (Alexey Milovidov). - Fix “Block structure mismatch” exception in queries with HAVING clause where the filter expression contains both an aggregate wrapped in a NULL-producing function and
materialize(0). #99915 (Alexey Milovidov). - Fix assertion failure in
sipHash128Keyed(and similar keyed hash functions) when the data argument is a Map with array keys or other nested array types. #99921 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception “Not-ready Set” inINfunction during query plan optimization withconvertAnyJoinToSemiOrAntiJoin. #99939 (Alexey Milovidov).
Build/Testing/Packaging Improvement
- Reduce compilation time by removing heavy header includes and moving expensive template instantiations out of headers. #97893 (Raúl Marín).
- Reduce compile time of arithmetic functions and related headers by shrinking template dispatch matrices and removing heavy includes. #98204 (Raúl Marín).
- Use
mongo-c-driver2.2.2. #98304 (Konstantin Bogdanov). - Use
postgresREL_18_3. #98306 (Konstantin Bogdanov). - Enable jemalloc allocator for UBSan builds to avoid RSS accumulation from glibc malloc’s poor memory reclamation behavior. #98444 (Alexey Milovidov).
- Use Rust v0 symbol mangling and strip internal symbols from PRQL library to reduce symbol name bloat from parser combinator libraries. #98446 (Alexey Milovidov).
- Add TPC-H benchmark suite and TPC-DS README to
tests/benchmarks. #98495 (Raufs Dunamalijevs). - Add correctness tests for all 99 TPC-DS queries. #99204 (Raufs Dunamalijevs).
- Add integration test reproducing DDL CREATE TABLE + ALTER with offline replica bug (#44070), marked as expected failure. #99259 (Raufs Dunamalijevs).
- Integrate jemalloc with
je_prefix and remove usage of linker’s —wrap. #99342 (Azat Khuzhin).
ClickHouse release 26.2, 2026-02-26. Presentation, Video
Backward Incompatible Change
- Deduplication is turned ON for all inserts by default. It was OFF before for async inserts and for MV’s, but it was ON for sync inserts. The goal is to have the same defaults for both ways of inserts. If you have deduplication explicitly disabled on your cluster, you have to explicitly set
deduplicate_insert='backward_compatible_choice'to keep the old behavior. The same withdeduplicate_blocks_in_dependent_materialized_views. #95970 (Sema Checherinda). - Improved storage format of statistics. All statistics are now stored in a single file. #93414 (Anton Popov). If you didn’t explicitly enable table statistics, you can ignore this item.
- Limit S3(Azure)Queue in-memory metadata. System tables are renamed from
azure_queuetoazure_queue_metadata_cacheandsystem.s3queuetos3queue_metadata_cache. #95809 (Kseniia Sumarokova). - Previously, applying a function to a
Variantcolumn silently returned NULLs when a variant sub-type was incompatible with the function; now it throws an exception, which may break queries that relied on the silent NULL behavior. #95811 (Bharat Nallan). DATEcolumns from PostgreSQL are now inferred asDate32in ClickHouse (in previous versions they were inferred asDate, which led to overflow of the values outside of a narrow range). Allow insertingDate32values back to PostgreSQL. Closes #73084. #95999 (Alexey Milovidov).- The semantics of the
do_not_merge_across_partitions_select_finalsetting were made more obvious. Previously, the feature could be automatically enabled when the setting was not explicitly set in the configs. It caused confusion repeatedly and, unfortunately, led to some issues in production. Now, the rules are simpler:do_not_merge_across_partitions_select_final=1enables the functionality unconditionally. Ifdo_not_merge_across_partitions_select_final=0, then automatic is used only if the new settingenable_automatic_decision_for_merging_across_partitions_for_final=1and not used otherwise. To preserve the old behaviour as much as possible, the defaults were set todo_not_merge_across_partitions_select_final=0andenable_automatic_decision_for_merging_across_partitions_for_final=1. #96110 (Nikita Taranov). - When creating an S3 table with explicitly specified columns, ClickHouse now validates that those column names actually exist in the remote file’s schema. Queries that previously worked with mismatched column names will now fail at table creation time. This closes #96089. #96194 (Konstantin Vedernikov).
- Forbid using subqueries in ORDER BY and other table key expressions. #96847 (Alexey Milovidov).
- Enable
apply_row_policy_after_finalby default. Initially, whenoptimize_move_to_prewhere_if_final=0, both ROW POLICY and PREWHERE respect FINAL and were applied after FINAL. This was broken by #87303, which ignored theoptimize_move_to_prewhere_if_finalfor the ROW POLICY filter. To fix this, this PR enables the settingapply_row_policy_after_finalintroduced in #91065. Withapply_row_policy_after_finalenabled, ROW POLICY would continue to respect FINAL by default, as previously. This PR is an incompatible change because it changes the behaviour foroptimize_move_to_prewhere_if_final=1. Now, to get the ROW POLICY applied before FINAL,apply_row_policy_after_finalshould be used instead ofoptimize_move_to_prewhere_if_final. #97279 (Nikolai Kochetov). - The
Datetype is now serialized as Arrow’s nativedate32type in Arrow/ArrowStream formats, instead ofuint16. Tools like PyArrow will now correctly see the column as a date type. The old behavior can be restored with theoutput_format_arrow_date_as_uint16setting. Reading old Arrow files that useduint16forDatecolumns is still supported. #96860 (Alexey Milovidov).
New Feature
- Users can now use ClickStack (an observability UI) directly from ClickHouse, useful for debugging and local development. #96597 (Aaron Knudtson).
- Support time-based one-time password (TOTP) as an authentication method. #71273 (Vladimir Cherkasov).
- Add
lazy_load_tablesdatabase setting. When enabled, tables are not loaded during database startup — a lightweightStorageTableProxyis created instead and the real table engine is materialized on first access. #96283 (xiaohuanlin). - Added
input_format_max_block_wait_mssetting to emit data blocks by timeout and allowed processing of remaining data when an HTTP connection is closed unexpectedly. #94509 (Mostafa Mohamed Salah). - Google BigLake catalog integration. This closes #95339. #97104 (Konstantin Vedernikov).
- Added system table
system.tokenizerswhich shows all available tokenizers. #96753 (Robert Schulze). - Add new system table
system.user_defined_functionsto monitor UDF loading status and configuration. #90340 (Xu Jia). - Add
system.jemalloc_statstable exposing jemalloc memory allocator statistics (viamalloc_stats_print) for diagnosing memory usage on servers built with jemalloc. Also add a/jemalloc.htmlHTTP endpoint on the ClickHouse HTTP interface for interactive visualization of these statistics. #97077 (Antonio Andelic). - Added
system.jemalloc_profile_texttable for reading and analyzing jemalloc heap profiles. The output format is controlled by thejemalloc_profile_text_output_formatsetting (raw, symbolized, or collapsed; default collapsed). Inline frame resolution is controlled byjemalloc_profile_text_symbolize_with_inline(when enabled, inline frames are included at the cost of slower symbolization; when disabled, they are skipped for faster output). For the collapsed format,jemalloc_profile_text_collapsed_use_countcontrols whether stacks are weighted by live allocation count (true) or live bytes (false, default). This enables easier memory profiling and flame graph visualization of jemalloc heap profiles. Fixes #93248. #97218 (Antonio Andelic). - Add the
default_dictionary_databasesetting, which lets ClickHouse resolve external dictionaries referenced without a database qualifier in a specified default database. This simplifies migration from XML-defined global dictionaries to SQL-defined per-database dictionaries—allowing existing dictionary queries (e.g. dictGet(‘name’, …)) to continue working without modification. #91412 (Dmitrii Plotnikov). - Support auxiliary zookeeper for
DatabaseReplicated. #91683 (RinChanNOW). - Implement new table function
primesand new system tablesystem.primesthat contains prime numbers in ascending order. Closes #90839. #92776 (Nihal Z. Miaji). - Async inserts support parallel quorum. The inserted data is replicated to the quorum. If duplicates are found, query waits until previously inserted data is replicated as well. #93356 (Sema Checherinda).
- Added functions
colorOKLABToSRGB,colorSRGBToOKLABto convert value from sRGB to OKLAB and vice versa. #93361 (Pranav Tiwari). - A new
deduplicate_insertsetting which overridesinsert_deduplicateandasync_insert_deduplicate. #94413 (Sema Checherinda). - Server setting
insert_deduplication_versionmakes it possible to migrate on unified deduplication hash. #95409 (Sema Checherinda). - Add
xxh3_128hashing function. #96055 (Raúl Marín). - Added
OPTIMIZE <table> DRY RUN PARTS <part names>query to simulate merges without committing the result part. It may be useful for testing purposes: verifying merge correctness in the new version, deterministically reproducing merge-related bugs, and reliably benchmarking merge performance. #96122 (Anton Popov). - Add a new check enabled by default via setting
check_named_collection_dependenciesto avoid dropping named collections used by tables. #96181 (Pablo Marcos). - Added
system.fail_pointsto inspect existing failpoints in the server and whether they are enabled or not. This is going to help automate testing. #96762 (Pedro Ferreira). - Add role-based access to Glue catalog. Use settings
aws_role_arnand, optionally,aws_role_session_name. #90825 (Antonio Andelic). - Added a setting
add_minmax_index_for_temporal_columnsthat, when enabled, automatically creates minmax indexes for allDate,Date32,Time,Time64,DateTime, andDateTime64columns. #93355 (Michael Jarrett). - Support for extended table aliases for JOINs (queries like
SELECT * FROM (SELECT 1) AS t(a) JOIN (SELECT 1) AS u(b) ON a = b). Closes #95131. #95331 (Yarik Briukhovetskyi). - Added support for
ALTER TABLE RENAME COLUMNfor Iceberg tables. Previously onlyADD COLUMN, DROP COLUMN, and MODIFY COLUMNwere supported. #97455 (murphy-4o).
Experimental Feature
- The text index is now GA. #96794 (Robert Schulze).
- The
QBitdata type for quantized bit-packed vector storage (used for approximate nearest-neighbor search) is now generally available and no longer requires enabling an experimental setting. #95358 (Raufs Dunamalijevs). - Vector search in ClickHouse can now use replicas in the cluster to distribute the load and search of vector index parts. This enables ClickHouse to support large vector indexes that exceed the memory capacity of a single VM. #95876 (Shankar Iyer).
- Add server-side AST fuzzer controlled by
ast_fuzzer_runsandast_fuzzer_any_querysettings. When enabled, the server runs randomized mutations of each query after its normal execution, discarding the results. #97568 (Alexey Milovidov). - Add
iiffunction to the experimental KQL dialect. #94790 (happyso). - Schema inference now respects
allow_experimental_nullable_tuple_type. When enabled, it allows inferred tuple types to beNullable(Tuple(...)), so missing nested objects can becomeNULLinstead of a tuple ofNULLelements. #95525 (Nihal Z. Miaji). - The
use_statistics_cachesetting is now enabled by default, so column statistics are cached in memory to speed up query optimization without needing to reload them from each part. #95950 (Han Fei).
Performance Improvement
- Allow any deterministic expression in Primary Key to be used for data skipping (e.g.
ORDER BY cityHash64(user_id)/ORDER BY length(user_id)). For deterministic expressions, ClickHouse can apply the expression to query constants and use the result in the primary key index for predicates like=,IN, andhas. If the expression is also injective (e.g.ORDER BY hex(p)orORDER BY reverse(tuple(reverse(p), hex(p)))), we can effectively use the index for the negated forms:!=,NOT IN, andNOT has. Closes #10685. Closes #82161. #92952 (Nihal Z. Miaji). - Improved storage format of statistics. All statistics are now stored in a single file. #93414 (Anton Popov).
- Allow parallelized read for remote table engines/functions in the filesystem cache. #71781 (Kseniia Sumarokova).
- Allow using userspace page cache with local files and object storage table functions. #77874 (Michael Kolupaev).
- Avoid unnecessary memcpy in userspace page cache. #77884 (Michael Kolupaev).
- The default for
concurrent_threads_scheduleris nowmax_min_fairinstead offair_round_robin. This improves fairness under high load by prioritizing queries with fewer allocated slots, so short-running queries aren’t penalized by long-running ones. #95300 (Sergei Trifonov). - If a
FINALquery used primary key condition for filtering followed by skip indexes for other conditions, thePrimaryKeyExpandprocessing step will now only check the initial shortlisted primary key ranges for intersection. #94903 (Shankar Iyer). - When using parallel replicas with table functions like
s3(...), queries with a single subquery wrapping the table function are now automatically parallelized across replicas, whereas previously only direct table function references were parallelized. Closes #92264. #96332 (phulv94). - Enable splitting data and system files in cache into separate segments. #87834 (MikhailBurdukov).
- Speed up some hash join operations by implementing dynamic dispatch for
ColumnVector::replicate. #79573 (Raúl Marín). - Performance improvement for parallel hash join in cases of complex predicates. Previously, we were processing non-joined rows in one thread, which is suboptimal the idea of the optimization is to parallelize the processing of the non-joined rows across multiple threads. Can be toggled by the
parallel_non_joined_rows_processingsetting. Enabled by default. #92068 (Yarik Briukhovetskyi). - Slightly optimize parsing of JSON type. #93614 (Pavel Kruglov).
- Improve memory footprint of AST. Optimization makes sense as fields are not used when highlighting is not used and there is no VALUES parsing. #93974 (Ilya Yatsishin).
- Optimize memory consumption of named Tuple AST objects. Place column names as strings in tuple object instead of having them in generic AST literal nodes. #94704 (Ilya Yatsishin).
- Devirtualization is improved with additional linker options. #94737 (Nikita Taranov).
- Improve clone replica performance for ReplicatedMergeTree tables with many parts by batching ZooKeeper requests. #94847 (c-end).
- When read step already has PREWHERE filters a new filter couldn’t be added. This change postpones PREWHERE optimization until after JOIN runtime filter optimization so that runtime filters can be also pushed to PREWHERE. #95838 (Alexander Gololobov).
- Speedup
T64codec compression by using dynamic dispatch on x86. #95881 (Raúl Marín). - Speed up
uniqover numeric types by batching inserts when possible (not null, not -If, no GROUP BY, no IPv6 or String). #95904 (Raúl Marín). - Low-level optimizations for Keeper:
ZooKeeper::observeOperationshas been found to account for >20% of the ZooKeeper receive thread CPU consumption. This change addresses that by: 1. ForAggregatedZooKeeperLog::stats, useCityHash64instead ofSipHashwhich is >10x faster. 2. ForCoordination::ErrorCounter, usestd::array<std::atomic<UInt32>, N>instead ofstd::unordered_mapandstd::mutex. #95962 (Miсhael Stetsyuk). - Remove 64-byte alignment for ProfileEvents::Counter to save memory. #96097 (Azat Khuzhin).
- Memory optimization: trim size of
CachedOnDiskReadBufferFromFilestructure 50x. #96098 (Azat Khuzhin). - Don’t copy old data on hash table resizing if it’s empty. #96180 (Raúl Marín).
- Support JOIN runtime filters for
RIGHT OUTERJOINs. #96183 (Hechem Selmi). - The optimization
enable_join_runtime_filtersis now the default. #89314 (Alexey Milovidov). - Previously, text index direct read optimization was applied only when all parts had a materialized text index. This PR adds partial support: if some parts have a materialized text index, those parts will use it, while parts without a materialized text index will fall back to executing the original filter expression. #96411 (Anton Popov).
- Added
minmaxsecondary indexes on time columns andbloom_filterindexes onquery_id/initial_query_idcolumns to system log tables for faster filtering. #96712 (Alexey Milovidov). - Lazy materialization optimization is now applied to all branches of a
UNION ALLquery, not just the first one. Queries that combine multiple sorted and limited reads from differentMergeTreetables viaUNION ALLwill now benefit from deferred column reading on every branch, reducing I/O. #96832 (Federico Ginosa). - Optimize minmax skip index computation during INSERT by removing an unnecessary data copy and enabling vectorized min/max calculation for numeric columns. #97392 (Raúl Marín).
- Storage
DeltaLakenow takescount()result from delta lake metadata and shows correct table stats in system.tables (total bytes/rows). #96190 (Kseniia Sumarokova). - The unused columns are removed also from the reading step in case of reading from a MergeTree. It is especially useful when a filter is pushed down into
PREWHERE. #89982 (János Benjamin Antal). - Improved processing
SHOW TABLESquery by fetching only names of tables and improved getLightweightTablesIterator to return structure containing only table names. resolves #93835. #94467 (Smita Kulkarni). - Improve
assumeNotNull,coalesce,ifNullto enable primary key and skip index pruning for range predicates when key columns are wrapped in these functions. Closes #94689. #94754 (Nihal Z. Miaji). - Add with_data & with_stat extension to getChildren Keeper request. This allows fetching not only the list of children, but also their
statand/ordatain a single operation. #94826 (Nikolay Degterinsky). - The index analysis is done only once (in most cases) regardless of whether we end up executing a local plan or a plan with parallel replicas. #94854 (Nikita Taranov).
- Allow to enable distributed index analysis based on amount of parts (
distributed_index_analysis_min_parts_to_activate) and indexes size (distributed_index_analysis_min_indexes_size_to_activate). #95216 (Azat Khuzhin). - Enable PREWHERE optimization for Iceberg tables. #95476 (Konstantin Vedernikov).
- Reduce the memory footprint of some AST classes. #95514 (Raúl Marín).
- Limit the number of pipeline streams generated with
split_intersecting_parts_ranges_into_layersenabled. Helps to avoid excessive memory consumption. #96478 (Nikita Taranov). - Implement equivalent sets optimization for multiple joins. Queries with multiple consecutive
INNER JOINoperations now benefit from improved filter pushdown optimization. When tables are joined on equivalent columns (e.g.,t1 JOIN t2 ON t1.id = t2.id JOIN t3 ON t2.id = t3.id WHERE t1.id > 10), filters applied to any table in the chain are automatically pushed down to all tables. Close #96550. #96596 (Vladimir Cherkasov). - Optimize delta lake metadata scan. Uses changes from delta-kernel PR https://github.com/delta-io/delta-kernel-rs/pull/1827. #96686 (Kseniia Sumarokova).
- In Replicated database, don’t update the cached cluster for every dummy query. #96897 (Tuan Pham Anh).
- Use the primary key index when filtering with
startsWithUTF8if the prefix contains only ASCII characters. #97055 (vkcku).
Improvement
- Add OpenTelemetry tracing for Keeper requests. #91332 (Miсhael Stetsyuk).
- New configuration options:
logger.startup_console_level&logger.shutdown_console_levelto allow for overriding the console log level during the startup & shutdown of ClickHouse respectively. #95919 (Garrett Thomas). - Respect command-line overrides when reloading configuration. Closes #80294. #80295 (Alexey Milovidov).
- Allow key-value overrides for named collection parameters in
mongodbtable function. #89616 (vanchaklar). - The read-in-order optimization for Iceberg tables now works with complex sorting functions like
icebergBucketandicebergTruncate, not just simple column references. #90256 (Konstantin Vedernikov). - Add a new column named parts_postpone_reasons in system.mutations to improve diagnostics, which shows the parts postpone reasons. #92206 (Shaohua Wang).
- Track changes in the number of rows to read (due to inserts/deletes or query condition cache usage) in
DataflowStatisticsCache. #93636 (Nikita Taranov). - Support SYSTEM RESET DDL WORKER [ON CLUSTER] query. It requests to reset the state of DDLWorker in its main thread. It is helpful to refresh the replica active when host IDs are updated. #93780 (Tuan Pham Anh).
- Support
mutation_idsinsystem.part_logfor event type ofMUTATE_PARTandMUTATE_PART_START. #93811 (Shaohua Wang). - Background operations (Mutate, Merge) can now be configured independently via ‘background’ profile. Previously such operations shared settings with regular queries via ‘default’ profile. #93905 (Arsen Muk).
- Add more information to
system.crash_log. #94112 #95857 (Miсhael Stetsyuk). - Added new
QueryNonInternalmetric to track the number of executing non-internal queries. This metric is exposed asClickHouseMetrics_QueryNonInternaland helps operators monitor query concurrency against themax_concurrent_querieslimit, which only applies to non-internal queries. #94284 (Ashwath Singh). - Support input bytes statistics collection for columns from compact parts in
RuntimeDataflowStatisticsCacheUpdater. #94626 (Nikita Taranov). - Add a check for Keeper misconfiguration leading to cluster assembly failures. Closes #60932. #94682 (Konstantin Bogdanov).
- Improve JSON prefixes deserialization during part loading. #94848 (Pavel Kruglov).
- Refactor the write using full INSERT pipeline, which triggers materialized views on the target table. #94890 (Kai Zhu).
- Use vector similarity search plan optimizations only if the index exists for the search column. #94998 (Eduard Karacharov).
- Check for the total memory limit before the user authentication and throw
(total) memory limit exceededif the total limit is more than allowed. #95003 (Nikolai Kochetov). - Added the
throw_on_unmatched_row_policiesconfiguration option which, when enabled, throws an exception if a user queries a table that has row policies but none of them apply to that user — preventing the ambiguous behavior of returning all rows due to access control misconfiguration. #95014 (Vitaly Baranov). - Dynamic update s3 access tokens in long queries with unity catalog. This closes #93981. #95069 (Konstantin Vedernikov).
- Disable jemalloc’s dirty page decay if ClickHouse is under sustained memory pressure for
memory_worker_decay_adjustment_period_msmilliseconds. Enable jemalloc’s dirty page decay back if ClickHouse is working under normal conditions for same amount of time. #95145 (Antonio Andelic). - S3Queue auxiliary Zookeeper support using
keeper_pathsetting from s3Queue. #95203 (Diego Nieto). - Respect
max_parts_to_merge_at_oncein TTL drop part merges. #95315 (Kseniia Sumarokova). - Add
connection_addressandconnection_portto query_log to reflect physical connection (addressandportare replaced when connected through proxy and auth_use_forwarded_address=1). #95471 (Yakov Olkhovskiy). - Fix incorrect memory accounting for the query conditions cache. The key problem was that it didn’t take into account the cache key that composed of several strings (like part_name, the table id and the whole SQL condition). #95478 (Nikita Mikhaylov).
- Server started with the embedded configuration will allow to manipulate users and grants, saving them to the
accessdirectory, as the regular configuration does. This improves testing. Also enabled all access_control_improvements in the embedded config and in clickhouse-local. #95481 (Alexey Milovidov). - Improved S3 authentication error messages to include a hint to check credentials when access is denied. #95648 (Gerald Latkovic).
- Enable statistics cache and set the update period of cache to 300s. #95841 (Han Fei).
- Add component name to
system.aggregated_zookeeper_log. #95882 (Antonio Andelic). - Skip object storage reads when querying
DeltaLaketables fromsystem.tables. #95899 (Antonio Andelic). - Enable
enable_max_bytes_limit_for_min_age_to_force_mergeby default if thecompatibilitysetting is26.2or higher. #95917 (Christoph Wurm). - Delta Lake is now available on macOS. Closes #95979. #95985 (Alexey Milovidov).
- In previous versions, when combining conflicting ALTER expressions with UPDATE and RENAME COLUMN, a logical error was thrown instead of a proper exception. Closes #70678. #96022 (Alexey Milovidov).
- Improve the help output for all ClickHouse applications and add a —no-sudo option with a few fixes. This is a continuation of #58244 from Ilya Yatsishin. #96025 (Alexey Milovidov).
- Add
distanceCosinealias forcosineDistancebecause all other distance functions already have alias of this form. #96065 (Raufs Dunamalijevs). - Add support for the
with_dataKeeper extension to improve table fetching in Database Replicated. #96090 (Nikolay Degterinsky). - Update chdig to v26.2.1 (new features and MacOS support). #96113 (Azat Khuzhin).
- Improve filter pushdown for
numbersandprimes. ClickHouse can now derive conservative value bounds fromWHEREconditions when exact bounds cannot be derived, and restrict sequence generation accordingly (for example, forWHERE number % 5 < 2 AND number > 100 AND number < 300, ClickHouse will only generate numbers between 100 and 300, then apply the predicate), avoiding unbounded scans. Closes #84853. Closes #93913. #96115 (Nihal Z. Miaji). - The formatter previously wrapped SELECT in parentheses when a
COMMENTclause was present to disambiguate parsing. Instead, outputCOMMENTbeforeAS SELECT, which eliminates the ambiguity without parentheses. #96293 (Alexey Milovidov). - The
allow_impersonate_userconfig setting is now located inside theaccess_control_improvementssection rather than being a standalone server setting. #96451 (Vitaly Baranov). - Make
core_dump.size_limitconfiguration setting hot-reloadable, to avoid having to restart servers for configuration changes to take place. #96524 (Miсhael Stetsyuk). - Improves CPU and real-time profiler interoperability with socket timeouts. #96601 (Sergei Trifonov).
- Prevent the resurrection of dropped data if ADD COLUMN is run quickly after the DROP COLUMN mutation. #96713 (Alexey Milovidov).
- Change
function_idtype insystem.instrumentationfrom LowCardinality(Int32) to Int32. #96726 (Copilot). - Synchronous waiting for mutations will respect query cancellation and time limits. #96756 (Alexey Milovidov).
- Added system command
SYSTEM RELOAD DELTA KERNEL TRACING <level>to be able to change delta-kernel logging, which can be useful for debugging. #96763 (Kseniia Sumarokova). - Filtering by IP address family, i.e.
dns_allow_resolve_names_to_ipv4/ipv6settings, are applied even if DNS cache is disabled. #96810 (c-end). - Better jemalloc introspection. #96840 (Azat Khuzhin).
- Fix
/playWeb UI throwingQUERY_CACHE_USED_WITH_SYSTEM_TABLEwhen querying system tables. #96869 (Alexey Milovidov). - Improve Web UI: change favicon to indicate running query state; display errors from auxiliary queries (loading databases and tables) instead of silently ignoring them. Closes #85055. #96883 (Alexey Milovidov).
- Make the left panel in
/playUI clickable to toggle the database list. #96884 (Alexey Milovidov). DROP DATABASEnow drops tables in reverse dependency order, improving crash-safety when the database contains tables with loading dependencies (e.g.Distributedtables usingjoinGet). #97057 (Alexey Milovidov).- Bump yaml-cpp to prevent skipping invalid YAML. #97333 (Azat Khuzhin).
- Show a loading indicator in the
play.htmlsidebar while tables are being fetched. #97531 (Alexey Milovidov). - Add a copy-to-clipboard button for raw query results in the built-in web UI (play.html). #97532 (Alexey Milovidov).
- Fix query obfuscator (
clickhouse-format --obfuscate) to produce parseable SQL in more cases. #97584 (Alexey Milovidov).
Bug Fix (user-visible misbehavior in an official stable release)
- After metadata-only ALTERs, such as extending the elements of Enums, the optimization of aggregation with projection may end up producing an exception. #84143 (Alexey Milovidov).
- Materialized views now use the database where they were created as execution context, meaning that: - it is possible to omit explicit database qualification on names referred in view’s select query - if no explicit database qualification is given, the same database where the materialized view was created is assumed. #88193 (Dmitry Kovalev).
- Fix query parameter substitution in CREATE USER authentication methods when using ON CLUSTER. Query parameters in authentication methods (e.g., password) were not being replaced, causing UNKNOWN_QUERY_PARAMETER errors on remote nodes. #92777 (xiaohuanlin).
- Fixed inconsistencies in text index analysis for
has,mapContainsKey, andmapContainsValuefunctions. Previously, queries using these functions could return different results depending on whether the expression was evaluated with or without a text index. #93578 (Anton Popov). - Fix crash when attaching a table to a
MaterializedPostgreSQLdatabase ifdropReplicationSlotthrows during stack unwinding. #96871 (Alexey Milovidov). - Backups could crash the server if you do many concurrent backups clashing over the same files. #93659 (Alexey Milovidov).
- Fixes queries with parallel replicas and JOIN with non-MT table. Closes #92056. #93902 (Igor Nikonov).
- Fixes an issue when Iceberg columns with dot in names returned NULL as values. #94335 (Mikhail Koviazin).
- Fixed handling of UTF8 strings in
stringJaccardIndexUTF8and improve performance. #94613 (Joanna Hulboj). - Fix possible overflows in
WITH FILL STALENESS(that leads to UB or/and endless loops). Fix possible endless loop due to big jumps. Add old analyzer support (mostly for stress tests). #94663 (Azat Khuzhin). - Fix possible hung distributed queries when hostnames resolve to multiple addresses and a remote replica freezes. #94726 (c-end).
- Fix invalid result on joining multiple table expressions, when leftmost table expression is a
-Clustertable function. Resolves #89996. #94748 (Konstantin Bogdanov). - Fix incorrect primary key and skip index pruning for predicates involving
toWeek,toYearWeek,toStartOfWeek,toLastDayOfWeek, andtoDayOfWeek, and fix exceptions in some of these functions for valid queries withLowCardinality(String). #94816 (Nihal Z. Miaji). - Remove unnecessary skip permissions check in
ATTACHqueries for a view with SQL Security. This prevents potential privilege escalation when a user attaches a view with a definer without validating required access. #94865 (pufit). - Fixes a crash during
ReplicatedMergeTreestartup caused by concurrent removal ofdelete_tmp_*directories. #94892 (myeongjun). - Fix
INSERTinto Iceberg tables with materialized views losing deduplication information, which caused an exception. #94938 (Daniil Ivanik). - Fix a bug where
SYSTEM DROP QUERY CACHE TAG 'TAGNAME' ON CLUSTER <CLUSTERNAME>would drop the full cache on the cluster. #94978 (Rory Crispin). - Preserve constant index granularity (use_const_adaptive_granularity) after Vertical merges (v2 with a fix for Nested, and in general). #95013 (Azat Khuzhin).
- Fixes race in filesystem cache in version 26.1 after [ClickHouse/ClickHouse#82764](https://github.com/ClickHouse/ClickHouse/pull/82764). #95042 (Kseniia Sumarokova).
- Fix postgresql() table function canceling by KILL QUERY and cancel query (Ctrl+C) in clickhouse-client. #95136 (Roman Vasin).
- Fixed type inference for qualified columns from source tables when multiple joins are used with
USINGclause. Previously, subsequent joins incorrectly updated types of underlying source columns to a common supertype even when the column was not involved in that join (e.g., inSELECT t2.a FROM t1 LEFT JOIN t2 USING (a) LEFT JOIN t3 USING (a), thet2.acolumn is only used by the first join, so its type should be the supertype oft1.aandt2.a, excludingt3.a). This could lead to logical errors or crashes when functions expected different column types than what actually appeared in the execution plan. #95157 (Vladimir Cherkasov). - Make column transform only once during getting content of manifest .avro list and files. #95164 (Daniil Ivanik).
- Fix incorrect calculation of JSON column sizes that could lead to excessive memory usage or wrong column statistics. #95207 (Azat Khuzhin).
- Fixed inaccurate memory accounting when applying large patch parts after lightweight updates. Previously, applying large patches could cause excessive memory usage and result in the server process being killed by the OOM killer. #95231 (Anton Popov).
- Fix undefined behavior that could cause incorrect results or an exception when a distributed query with
max_parallel_replicasfell back to a local replica during index analysis. #95263 (Azat Khuzhin). - Fix aggregation of sparse columns for
sumand timeseries whengroup_by_overflow_modeis set toany. #95301 (Mikhail Koviazin). - Fix a reliability issue in
plain_rewritabledisk policy where a network error mid-way through unlinking a metadata file could leave the storage in an inconsistent state. #95302 (Mikhail Artemenko). - Replace Date with Date32 for iceberg. #95322 (Konstantin Vedernikov).
- The password argument of the
redistable function now will be masked in the logs and system tables (e.g.:query_log). #95325 (János Benjamin Antal). - Fix a bug where tables could be dropped or altered while a distributed query was still executing against them, potentially causing exceptions or incorrect results. #95356 (Azat Khuzhin).
- Fix a logical error in some cases when negative
LIMIT/OFFSETis used in distributed queries. #95357 (Nihal Z. Miaji). - Fix a bug where clickhouse-client would ask for password twice when connecting using ssh. #95372 (Isak Ellmer).
- Fix a data race in storage S3(Azure)Queue. #95385 (Kseniia Sumarokova).
- Fix the prewhere filter error caused by lambda expressions in prewhere. #95395 (Xiaozhe Yu).
- Fix
optimize_syntax_fuse_functionsto not rewritesum/count/avgintosumCount()when the aggregate argument isNullable. Closes #95390. #95441 (Nihal Z. Miaji). - Avoid possible crash for distributed queries in case of cancellation. #95466 (Aleksandr Musorin).
- Fix deduplication for streaming from S3(Azure)Queue engine. #95467 (Kseniia Sumarokova).
- Fix updating row policies assigned to the initial user in distributed queries. #95469 (Vitaly Baranov).
- Fix check for encrypted disks over plain_rewritable (Fixes possible
It is not possible to register multiple plain-rewritable disks with the same object storage prefix). #95470 (Azat Khuzhin). - The
mergeTreeProjectiontable function was missing an access check, allowing users without SELECT permission on a table (but with permissions for table functions) to read data from its projections. This fix adds the same access check thatmergeTreeIndexandmergeTreeAnalyzeIndexesalready have. #95480 (Alexey Milovidov). - Fix possible logical error during reading of size subcolumn from dynamic subcolumns of Dynamic/JSON types. #95573 (Pavel Kruglov).
- Fix regression in (experimental) zero‑copy replication introduced by #94262 where shared parts could be deleted before other replicas finished fetching them. #95597 (filimonov).
- Fix crash during
tupleElementapplied to arrays of JSON. Closes #95581. #95647 (Pavel Kruglov). - Fix logical error exception when using a matcher (
*) inside a lambda function within a VALUES clause in a JOIN with USING. Close #93675. #95661 (Vladimir Cherkasov). - Fixed
There was an error: Cannot obtain error messagelogical error when waiting for a distributed DDL and dropping the Replicated database concurrently. Fixes #95539. #95664 (Alexander Tokmakov). - Fix
INfunction returning incorrect results withNULLvalues whentransform_null_inis enabled. Closes #65776. #95674 (Nihal Z. Miaji). - Correctly handle LowCardinality Nullable types in
CASTwhen the settingcast_keep_nullableis enabled. Closes #95670. #95747 (Alexey Milovidov). - Fix squashing partitioned delta lake data. #95773 (Kseniia Sumarokova).
- Fix race condition for Nullable join column in runtime filters. #95775 (Hechem Selmi).
- Fix possible logical error in query with matcher (
*,table.*) andanalyzer_compatibility_join_using_top_level_identifierwhenUSINGcolumn has different types in tables and select list. Close #90477. #95808 (Vladimir Cherkasov). - Fix memory safety bugs in parallel thread pool operations (backups, aggregation, distributed queries) that could cause exceptions when an error occurred during task scheduling. #95818 (Raúl Marín).
- Fixes a crash on the DROP WORKLOAD while running concurrently with queries using the workload being dropped. #95856 (Alexey Milovidov).
- Fix slow performance when querying system tables with a user that has limited grants on many databases. Closes #89371. #95874 (pufit).
- Fix executing tupleElement on JSON with nested paths, previously it could lead to wrong query result. #95907 (Pavel Kruglov).
- Fixed a
NOT_SUPPORTEDerror that could occur when using thedirectjoin algorithm with an empty MergeTree table. #95935 (Vladimir Cherkasov). - Fix the client not suggesting and auto-completing alias names for settings, closes #92190. #95945 (phulv94).
- Fix event_date in system.asynchronous_metric_log. #95947 (Raúl Marín).
- Fix skipping paths in JSON data type. Previously with
JSON(SKIP path)all JSON keys with prefixpathwere skipped, even keys like"pathpath", so it could lead to data loss for these paths during insert. Now it’s fixed and only key"path"is skipped. #95948 (Pavel Kruglov). - Part with unknown projections should not be marked as lost forever. #95952 (Mikhail Artemenko).
- Fix empty string becoming
NULLinJointable withNullable(String)key. Closes #71414. #96002 (Alexey Milovidov). - Now the PostgreSQL engine can correctly read
BOOLEAN[]. Closes #72754. #96006 (Alexey Milovidov). - Fix the
ProtobufListformat for the case of reading from an empty file. Closes #70059. #96007 (Alexey Milovidov). - Fix
ProtobufListformat producing ghost record for empty tables. Closes #72596. #96010 (Alexey Milovidov). - Fix
iffunction type mismatch betweenUInt64andInt32in an unusual case of distributed queries and PREWHERE, with type inference. Closes #70017. #96012 (Alexey Milovidov). - Fix
JITcompiled queries involvingBooltypes. #96013 (Alexey Milovidov). - Fix logical error when reading UUID column from SQLite TEXT column. Closes #71263. #96016 (Alexey Milovidov).
- Fix SQLite engine type conversion for
DateTime,Date,UUID, and other types. Closes #73481. #96017 (Alexey Milovidov). FixedStringvalues were escaped incorrectly in queries to external databases, SQLite and PostgreSQL. Closes #73519. Co-authored with @jh0x. #96019 (Alexey Milovidov).- Fix assertion failure in WindowTransform with a large PRECEDING offset. Closes #75852. #96026 (Alexey Milovidov).
- Fix a bug with possible data corruption when concurrent async inserts are using the same parameter names but contain different values. #96035 (Seva Potapov).
- Fix period for global profilers (controlled by
global_profiler_real_time_period_nsandglobal_profiler_cpu_time_period_ns). Instead of set value, a truncated value was used, causing profiler to wakeup more than intended. #96048 (Antonio Andelic). - Earlier if reference data file inside iceberg manifest file for position delete was present in an entry but was null, we didn’t get correct bounds for a corresponding data files. This PR fixes this bug. #96061 (Daniil Ivanik).
- Fix revoking default roles. #96103 (Vitaly Baranov).
- Fix use-after-free in the index analysis in a rare combination of disabled
use_primary_keyand a very large number of disjunctions of conditions that use the index. #96112 (Alexey Milovidov). - Fix a regression with the
Gorillacodec when an explicitly specified size does not correspond to the data type size, and the buffer size is too small. In previous versions, it threw an exception on decompression. Closes #78253. #96118 (Alexey Milovidov). - Avoid a deadlock in dictionaries loaded when one dictionary references a Merge table that references it recursively. Closes #78360. #96120 (Alexey Milovidov).
- Fix use-of-uninitialized-value in
formatDateTimewith non-fixed-width formatters, such as MySQL and JODA-style. #96133 (Alexey Milovidov). - The combination of settings
use_const_adaptive_granularityandindex_granularity_bytes(which means “non-adaptive granularity”) led to a miscalculation of the number of rows to read and an exception. #96143 (Alexey Milovidov). - Running an invalid ALTER UPDATE mutation on object storage file-like tables, such as S3 and Azure, could lead to a nullptr dereference. Closes #92994. #96162 (Alexey Milovidov).
- Fix
AccessRights::containsreturning incorrect results with partial revokes. #96170 (pufit). - Fix query condition cache hash collision for CTE folded constants, which could lead to a wrong query result. Closes #96060. #96172 (Alexey Milovidov).
- Fix possible deadlock in ProcessList. It can happen because of possible lock inversion if memory overcommit tracker triggers when we are adding task to cancellation checker. #96182 (Antonio Andelic).
- Fixed a bug where queries involving outer joins (LEFT, RIGHT, or FULL) combined with multiple INNER JOINs could return incorrect results due to illegal join reordering. When an outer join’s ON condition referenced columns from multiple previously joined tables, the optimizer failed to account for all table dependencies and could reorder the joins incorrectly, producing missing rows. Close #95972. #96193 (Vladimir Cherkasov).
- When a table has no statistics defined, ClickHouse shouldn’t try to load them. This avoids some overhead (100+ms) for checking if the statistics files exist. (issue #96068). #96233 (Han Fei).
- Fix
optimize_syntax_fuse_functionsto not rewritesum/count/avgintosumCount()when the aggregate argument isLowCardinality(Nullable). Closes #95390. #96239 (Nihal Z. Miaji). - Fix incorrect partition pruning for
not INandnot hasfunction in some cases. #96241 (Nihal Z. Miaji). - Fix
stack-use-after-scopein the vector similarity index. #96259 (Alexey Milovidov). - Fix test runner not recognizing error hint comments when a query is preceded by a SQL comment. #96336 (Yakov Olkhovskiy).
- Fix logical error in KeyCondition when a table has a nullable primary key, and the query uses the
coalescefunction, which has its first argument constant. #96340 (Alexey Milovidov). - The interaction of
GROUPING SETS,group_by_use_nulls, and theTupledata type withLowCardinalityinside it, could produce an unexpected block structure in the query pipeline, which led to a logical error. This appeared after the introduction ofNullableTuples. #96358 (Alexey Milovidov). - It was possible to create a table with an empty expression
()as an index, which led to an invalid memory access. #96363 (Alexey Milovidov). - Fixed crash in old analyzer if JOIN and duplicated aliases. #96405 (Ilya Golshtein).
- Fix
Nested columns sizes are inconsistent with local_discriminatorserror due to a wrong in-place filtering optimization for Variant columns. #96410 (Alexey Milovidov). - Fix
CREATE TABLE ... CLONE AS ...ignoring full qualifier of source table. #96415 (Hasyimi Bahrudin). - Fix
mysqltable function canceling by KILL QUERY and cancel query (Ctrl+C) in clickhouse-client. #96437 (Roman Vasin). - Fixes livelock in the cancellation checker thread for queries with high
max_execution_timevalues. #96450 (Sergei Trifonov). - Fix a logical error in some cases when fractional
LIMIT/OFFSETis used in distributed queries. #96475 (Nihal Z. Miaji). - Fix null pointer dereference in certain expressions with lambda functions. #96479 (Alexey Milovidov).
- Fix incorrect results when
LowCardinalitycolumns are converted toNullable. #96483 (Nihal Z. Miaji). - Fix a crash when creating an Iceberg table with an
ORDER BYclause referencing a non-existent column or using a positional argument. Closes #93280. #96484 (Konstantin Vedernikov). - Fix runtime filter exception for Tuple columns with Nullable subfields. #96509 (Alexey Milovidov).
- Fix
LOGICAL_ERRORexception in Parquet V3 native reader whenPREWHEREfilter column contains non-boolean UInt8 values. #96594 (Alexey Milovidov). - Fix implicit index regeneration in replicated tables during metadata changes. #96600 (Raúl Marín).
- Fixes a datarace on DROP WORKLOAD. #96614 (Sergei Trifonov).
- Fix a bug in Iceberg table writes where partitioned inserts could produce incorrect data distribution across partition files. #96620 (Konstantin Vedernikov).
- Fixed
heap-use-after-freeinCREATE TABLEwith constraints. #96669 (Nikita Taranov). - Validate witness version in bech32 to avoid buffer overflow. #96671 (Raúl Marín).
- Fix
system.tablesreturning errors when a Data Lake REST catalog is created with an invalidauth_headersetting. #96680 (Han Fei). - Fix
min(timestamp)returning epoch (1970-01-01) via_minmax_count_projectionafter TTL merge when all rows in a block are filtered out. #96703 (Raquel Barbadillo). - Improve validation of the
iceberg_metadata_file_pathsetting to prevent path traversal and ensure the specified metadata file is within the table directory. #96754 (Daniil Ivanik). - Fix crash in
ifNullwithVariantargument used inGROUP BY. #96790 (Alexey Milovidov). - Fixed cache key collisions between tables with
table_disk=1setting. #96818 (Raufs Dunamalijevs). - Fix MemoryWorker’s purging thread being stuck because of a race condition. #96819 (Antonio Andelic).
- Don’t log data with credentials in iceberg catalogs. #96831 (Konstantin Vedernikov).
- Fix exit status of clickhouse-client after server error. #96841 (Vitaly Baranov).
- Queries with CROSS JOINs and enabled parallel replicas could return incorrect result. Fixes #74337. #96848 (Igor Nikonov).
- Fixed
ALTER TABLE DROP COLUMNqueries failing after a lightweight update was previously performed on the same column. #96861 (Anton Popov). - Fix stack overflow (crash) when creating archive-based backups (
.zip,.tzst) to aplain_rewritableobject storage disk. #96872 (Alexey Milovidov). - Fix server crash when backup fails due to full disk or other I/O errors on the destination filesystem. #96873 (Alexey Milovidov).
- Fix
EXCEPT ALLandINTERSECT ALLignoring row multiplicities and behaving like theirDISTINCTcounterparts. #96876 (Alexey Milovidov). - Fix
std::terminateexception inindexOfAssumeSortedwhen called with incompatible types (e.g.,IPv4array with integer search value). #96877 (Alexey Milovidov). - Fix exception
Bad cast from type DB::ColumnNullable to DB::ColumnStringwhen using window functions withgroup_by_use_nulls = 1and CUBE/ROLLUP/GROUPING SETS. #96878 (Alexey Milovidov). - Fix incorrect results when JIT-compiled expressions convert
DateTimetoDateTime64(e.g., inCASE/if/multiIfwith mixed DateTime types). The value was reinterpreted instead of properly scaled, producing wrong timestamps after expression compilation kicked in. #96879 (Alexey Milovidov). - Fix logical error exception in
CoalescingMergeTreewhen a skip index expression produces a constant column (e.g.,bloom_filteronifNotFinite(1, c0)for an integer column). #96880 (Alexey Milovidov). - Fix wrong port number in error message when accidentally connecting with HTTP to the TLS-enabled native protocol port. #96881 (Alexey Milovidov).
- Fix per-subquery
SETTINGSnot being applied to table functions likefilein CTEs and subqueries. #96882 (Alexey Milovidov). - Fix memory leak of BIO objects when reading X509 certificates. #96885 (Alexey Milovidov).
- Fix
LOGICAL_ERRORexception in query analyzer when a lambda expression is passed where a concrete value is expected (e.g., as the accumulator argument ofarrayFold). #96892 (Alexey Milovidov). - Fix
ColumnNullable is not compatible with originalexception when casting complex nested types (Array of Nullable Tuple containing Map with Nullable Enum values). #96924 (Alexey Milovidov). - Fix a race condition in sharded
HASHEDdictionary parallel loading that could occasionally cause some rows to not be loaded. #96953 (Alexey Milovidov). - Fix a race condition between
REPLACE PARTITIONand background mutations that could result in both old and new data being visible after the replace. #96955 (Alexey Milovidov). - Fix
arrayJoinfunction producing duplicate rows when used with INNER JOIN and WHERE clause, caused by the partial predicate push-down optimization incorrectly pushing filters containingarrayJoinbelow a JOIN. #96989 (Alexey Milovidov). - Fix crash (SEGFAULT) in
clearCachescaused byBlockIO::operator=not movingquery_metadata_cache, leading to premature destruction of cached storage snapshots and use-after-free ofMergeTreeDatastorage. #96995 (Alexey Milovidov). - Fix assertion failure in
IfTransformStringsToEnumPasswhen theifortransformfunction returnsNullable(String)(e.g. withGROUP BY ... WITH CUBEandgroup_by_use_nulls = true). #97002 (Alexey Milovidov). - Fix incorrect data written during
INSERT ... SELECTwithUNION ALLandJOIN, where constant string columns could receive wrong values after block squashing. #97019 (Hasyimi Bahrudin). - Fix
assert_castexception (or silent data corruption in release builds) when building column statistics afterALTER TABLE MODIFY COLUMNchanges the column type. #97027 (Alexey Milovidov). - Fix reads of uninitialized memory in Azure Blob Storage, SSH protocol, and Arrow Flight interfaces. #97053 (Alexey Milovidov).
- Fix cases where indexes were affecting the result for queries with row policy/PREWHERE and FINAL. #97076 (Yarik Briukhovetskyi).
- Fix remaining race condition between
REPLACE PARTITIONand background mutations inMergeTreetables that could cause old data to reappear. #97105 (Alexey Milovidov). - Fix implicit indices with alias columns and do full validation before creating them. #97115 (Raúl Marín).
- Fix logical error in
FunctionVariantAdaptorwith functions requiring const arguments likearrayROCAUC. #97116 (Bharat Nallan). - Fix stuck mutations when
PartCheckThreadre-enqueues aGET_PARTfor an already-mutated part, leaving phantom entries inparts_to_do. #97162 (Alexey Milovidov). - Fix query plan row count estimation for subqueries with
ORDER BY ... LIMIT, which could cause the optimizer to choose a suboptimal join order. #97193 (Alexander Gololobov). - Fix
LOGICAL_ERRORexception inFunctionVariantAdaptorwhen a function operating on Variant columns returnsNothingtype, which can happen with empty arrays inUNION ALLqueries. #97213 (Alexey Milovidov). - Fix a data race during S3 multipart copy operations (e.g., during
BACKUP/RESTOREto S3) that could cause exceptions under concurrent access. #97227 (Azat Khuzhin). - Fix
LOGICAL_ERRORexception whenarrayJoininWHEREclause references columns from both sides of aJOIN. #97239 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception when reading.sizesubcolumn of a sparseNullable(String)in a Tuple with PREWHERE. #97264 (Alexey Milovidov). - Fix exception “Number of rows in lazy chunk does not match number of offsets” in
LazyMaterializingTransformwhen reading from tables with non-adaptive index granularity (index_granularity_bytes = 0) usingORDER BY ... LIMIT. #97270 (Alexey Milovidov). - Fix
SYSTEM RESTART REPLICAlosing table from database when table re-creation fails with a non-ZooKeeper exception (e.g. memory limit), causing metadata digest mismatches inDatabaseReplicated. #97276 (Alexey Milovidov). - Field
readonlyinsystem.merge_tree_settingsnow properly reflects that certain merge tree settings (e.g.index_granularity) are unconditionally readonly. #97277 (Robert Schulze). - Fix a crash during
count()optimization onMergeTreetables when the storage snapshot was created without data. #97281 (Pablo Marcos). - Fix a possible crash when resolving function names from debug information for stack traces. #97294 (Azat Khuzhin).
- Fix logical error with analyzer_compatibility_join_using_top_level_identifier and ALIAS columns. Close #96228. #97297 (Vladimir Cherkasov).
- Fix
LOGICAL_ERRORexception inapplyOrderwhen using text-indexed columns withQUALIFYclause. #97313 (Alexey Milovidov). - System table
system.functionsnow shows for internal functionscategories = 'Internal'instead ofcategories = ''. #97315 (Robert Schulze). - Query with RIGHT JOIN chain and enabled parallel replicas can produce incorrect result. Fixes #74341. #97316 (Igor Nikonov).
- Fix spurious
TABLE_UUID_MISMATCHerrors that could occur with refreshable materialized views and other scenarios where tables are renamed. #97323 (Azat Khuzhin). - Fix segfault in
StorageKeeperMapbackup due to use-after-free of dangling storage pointer in lazy backup batch. #97336 (Alexey Milovidov). - Fix the
existsfunction with a scalar subquery inside anALTER UPDATE/DELETEwhenmutations_execute_subqueries_on_initiatoris enabled. The scalar subquery was incorrectly evaluated, which could lead to an error or a corrupt mutation command that made the table unloadable on the next server restart. #97347 (Kirill Kopnev). - Fix logical exception
Unexpected return type from equals. Expected Nullable(UInt8). Got Const(LowCardinality(Nullable(UInt8)))when comparing NULL with a Variant column containing LowCardinality types. #97379 (Alexey Milovidov). - Fix a possible race condition when
EXCHANGE TABLESis executed in parallel with the sharded query cache enabled. #97411 (Konstantin Vedernikov). - Fix
LOGICAL_ERRORexception in Array-to-QBitconversion whennullable_sourcefrom an outerTuplewrapper replaces the converted array column with a mismatched column type. Closes #97389. #97413 (Alexey Milovidov). - Fix AST formatting roundtrip inconsistency for aliased tuple literals inside parentheses, e.g.,
(('a', 'b') AS x)was incorrectly reformatted astuple(('a', 'b') AS x). #97418 (Alexey Milovidov). - Fix an exception during asynchronous inserts with deduplication when a parsing failure produced an empty block with zero rows. #97460 (Sema Checherinda).
- Fix exception “Number of rows in lazy chunk does not match number of offsets” in
LazyMaterializingTransformwhen reading from tables with non-adaptive index granularity (index_granularity_bytes = 0) usingORDER BY ... LIMIT. #97482 (Alexey Milovidov). - Fix insert iceberg settings. Add alias for the
allow_experimental_insert_into_icebergsetting. #97483 (Konstantin Vedernikov). - Fix
ACCESS_DENIEDfor users withoutCREATE TEMPORARY TABLEpermission whenoptimize_inverse_dictionary_lookupoptimization rewritesdictGet(...)predicates. ClickHouse now skips the rewrite and executes the original expression. Closes #97269. #97484 (Nihal Z. Miaji). - Fix assertion failure (exception in debug/sanitizer builds) in
SetandMergeTreeIndexSetwhen processing columns with inner sparse subcolumns (e.g.,Tuplecolumns from MergeTree parts with different sparse serialization profiles). #97493 (Alexey Milovidov). - Fix a possible use after free in StorageKafka2. #97520 (Bharat Nallan).
- Fix
INTO OUTFILEwithTRUNCATEandinto_outfile_create_parent_directoriessetting when the output path contains directories. #97549 (Alexey Milovidov). - Fix
BAD_ARGUMENTSerror when querying tables with lambda expressions inside ALIAS columns through themerge()table function with the analyzer enabled. #97551 (Alexey Milovidov). - Fix
system.zookeeper_infoexception when Keeper zxid is 0. #97553 (Alexey Milovidov). - Fix a possible logical error in
ip_triedictionary when key type is not String. #97555 (Bharat Nallan). - Fix REST catalog OAuth authentication not working for the base
RestCatalog(it only worked for derived catalogs likeOneLakeCatalog). This broke the default REST catalog after BigLake catalog was introduced. #97561 (Konstantin Vedernikov). - Geometry functions (
perimeterSpherical,areaSpherical, etc.) now accept individual geometry subtypes (Polygon,Ring,Point, etc.) in addition to theGeometryvariant type. #97571 (Alexey Milovidov). - Fix
LOGICAL_ERRORexception when usingisNull/isNotNullon subcolumns ofNullable(Tuple(... Nullable(T) ...))types. Closes #97224. #97582 (Alexey Milovidov). - Fix null pointer dereference when applying patch parts during lightweight updates. #97583 (Alexey Milovidov).
BaseSettings::readBinarypasses the index fromaccessor.findtofield_infos[]without checking for the not-found sentinel value (i.e.,-1), which may cause astd::vectorout-of-bounds access. The issue was caught thanks to libcxx hardening. This probably happened during query plan deserialization when a newer server sends a setting unknown to an older server. The string-based read method already handles this correctly;readBinarywas missing the same check. #97585 (Miсhael Stetsyuk).- Fix incorrect query results for
UNION ALLqueries where one branch had a constant-false predicate — the branch would incorrectly read data instead of returning nothing. #97620 (Bharat Nallan). - Fix
IN (col)with a single column reference failing withUNSUPPORTED_METHODerror. #97646 (Alexey Milovidov). - Fix logical error exception during
GROUP BY ... WITH ROLLUP/CUBEwhen keys includeLowCardinality(Nullable(...))insideNullable(Tuple(...)). #97647 (Alexey Milovidov). - Fix AST formatting inconsistency for
NOT (1, 1, 1)that could causeLOGICAL_ERRORin debug builds. #97653 (Alexey Milovidov). - Fix
keeper-converterexception when encountering empty ZooKeeper transaction log files. #97673 (Alexey Milovidov).
Build/Testing/Packaging Improvement
- ClickHouse can be built with clang-23 (master). #95578 (Alexey Milovidov).
- Fix force
is_localto false whenbind_hostis configured and replace with integration test. Follow-up for #74741. #93109 #96018 (Zhigao Hong). - Stress tests: fix stress and upgrade tests in CI. ignore
no-{build}tags. add compatibility randomization. #94693 (Nikita Fomichev). - Publish parser_memory_profiler binary from build. Tool can be used to analyze AST memory consumption. #95826 (Ilya Yatsishin).
- Add
--symbolizeflag forparser_memory_profilertool that produces.heap.symfiles with resolved symbols in results. #96477 (Ilya Yatsishin). - Pin third-party Docker images in integration tests to specific versions. #96500 (Alexey Milovidov).
- Restore the possibility to link
OpenSSLdynamically. This is not recommended and not used by any production builds, but the option still exists for enthusiasts on the Internet. #96506 (Govind R Nair). - Reduce
magic_enumrange from [-100, 1000] to default [-128, 127] by using a per-type specialization forCoordination::OpNum, improving build time. #96632 (Alexey Milovidov). - Remove unnecessary C++ templates from Function classes to reduce build times. #96646 (Alexey Milovidov).
- Move
StorageSystemLicensesgeneration to configure time to improve build parallelism. #96697 (Alexey Milovidov). - Parallelize license scanning. #96727 (Raúl Marín).
- Add stateless functional test for SSH protocol support. #96996 (Alexey Milovidov).
- Add Kafka 3.9.0 to the stateless functional test infrastructure, enabling direct testing of Kafka and Kafka2 table engines using ClickHouse Keeper as ZooKeeper. Six new stateless tests cover basic produce/consume, virtual columns, INSERT, multiple formats, broken message handling, and Keeper-based offset storage. #96997 (Alexey Milovidov).
- Add a CI workflow to build PGO+BOLT optimized clang toolchain. #96991 (Alexey Milovidov).
- Use the PGO-optimized LLVM/Clang build in CI, which should give 20..30% build speed improvement. #97031 (Alexey Milovidov).
- Replace math functions from glibc with llvm-libc implementations. #90151 (Konstantin Bogdanov).
- Update Boost from 1.83 to 1.90, fixing a
devectorassertion failure in debug builds. #97037 (Alexey Milovidov). - Update
postgresto REL_18_1. #95189 (Konstantin Bogdanov). - Use
libexpat2.7.3. #95218 (Konstantin Bogdanov). - Use
OpenSSL3.5.5. #95345 (Konstantin Bogdanov). - Use
simdjsonv4.2.4. #97129 (Konstantin Bogdanov). - Use
libarchive3.8.5. #97131 (Konstantin Bogdanov). - Use
fast_floatv8.2.3. #97133 (Konstantin Bogdanov). - Use
abseil-cpp20260107.1,s2geometryto v0.13.1. #97134 (Konstantin Bogdanov). - Bump
libxml2to 2.15.1. #95574 (Robert Schulze). - Upgraded 7 Tier-3 integration test Docker images from EOL or removed base images to current supported versions. #97314 (Rahul).
- Add TPC-DS benchmark queries. #97349 (Raufs Dunamalijevs).
- Replace individual x86 instruction-set cmake options (
ENABLE_SSSE3,ENABLE_AVX2,NO_SSE3_OR_HIGHER,ARCH_NATIVE, etc.) with a single numericX86_ARCH_LEVELoption (1/2/3/4), matching the standard x86-64 microarchitecture levels already used by the runtime dispatch system. #97354 (Raúl Marín). - Avoid instantiating
division_by_nullable=truetemplate variants for non-division operations inFunctionBinaryArithmetic, reducing compilation time and binary size. #97496 (Raúl Marín). - Reduce the include footprint of
Exception.hby removing it from high-fan-out headers liketypeid_cast.h,assert_cast.h,Context_fwd.h,IDataType.h, and various Column headers. #97497 (Raúl Marín). - Always use bundled
compiler-rtheaders (sanitizer and XRay interfaces) instead of the host compiler’s headers, and buildcompiler-rtlibraries from source by default. #97499 (Raúl Marín). - Avoid including boost/multiprecision headers in
wide_integer_impl.hon platforms with adequatelong double, improving build time. #96633 (Alexey Milovidov). - Implement LLVM Code Coverage job and enable it initially for master branch. #90952 (Alexey Bakharew).
- Enable fast libcxx hardening for release builds. This is mostly needed for out-of-bounds checks. Given performance tests results, no noticeable performance impact is expected. #94757 (Miсhael Stetsyuk).
ClickHouse release 26.1, 2026-01-29. Presentation, Video
Backward Incompatible Change
- Fix inconsistent formatting caused by an incorrect substitution of aliases in the formatter. This closes #82833. This closes #82832. This closes #68296. This change is potentially backward incompatible: when the analyzer is disabled, certain CREATE VIEW queries with IN referencing an alias cannot be processed. To prevent the incompatibility, enable the analyzer (it is enabled by default since 24.3). #82838 (Alexey Milovidov).
- Codecs
DEFLATE_QPLandZSTD_QATwere removed. Users are advised to convert existing data compressed withDEFLATE_QPLorZSTD_QATto another codec before upgrade. Note that in order to use the codecs, settingsenable_deflate_qpl_codecandenable_zstd_qat_codechad to be enabled. #92150 (Robert Schulze). - Improve UDF debugging by enabling stderr capture in
system.query_log.exception. Previously, UDF stderr was only logged to files and not exposed in query logs, making debugging impossible. Now stderr triggers exceptions by default and is fully accumulated (up to 1MB) before throwing, so complete Python tracebacks and error messages appear insystem.query_log.exceptionfor effective troubleshooting. #92209 (Xu Jia). - Empty column list in
JOIN USING ()clause is now considered a syntax error. Previously it was supposed to beINVALID_JOIN_ON_EXPRESSIONduring query execution. In some cases such as joining withJoinstorage it led toLOGICAL_ERROR, close #82502. #92371 (Vladimir Cherkasov). - Use partial match for SKIP REGEXP in JSON type by default. Closes #79250. #92847 (Pavel Kruglov).
- Revert “Allow INSERT into simple ALIAS columns” (Reverts ClickHouse/ClickHouse#84154). It does not work with custom formats, and is not guarded with a setting. #92849 (Azat Khuzhin).
- Setting to throw an error if a data lake catalog doesn’t have access to object storage. #93606 (Konstantin Vedernikov).
- The
Lazydatabase engine is removed and no longer available. Closes #91231. #93627 (Alexey Milovidov). - Remove the
transposed_with_wide_viewmode of themetric_log- it is unusable due to a bug. It is no longer possible to definesystem.metric_logwith this mode. This partially reverts #78412. #93867 (Alexey Milovidov). - CPU scheduling for workloads is now preemptive by default. See
cpu_slot_preemptionserver setting. #94060 (Sergei Trifonov). - Escape index filenames to prevent broken parts. With this change ClickHouse will fail to load indices with non-ascii characters in their name created by previous versions. To handle it you can use the merge tree setting
escape_index_filenames. #94079 (Raúl Marín). - Format settings
exact_rows_before_limit,rows_before_aggregation,cross_to_inner_join_rewrite,regexp_dict_allow_hyperscan,regexp_dict_flag_case_insensitive,regexp_dict_flag_dotallanddictionary_use_async_executorwere changed to be regular (non-format) settings now. This is a purely internal change without user-visible side effects except in the (unlikely) case that you specified any of these settings in Iceberg or DeltaLake or Kafka or S3 or S3Queue or Azure or Hive or RabbitMQ or Set or FileLog or NATS table engine definitions. In these cases, these settings were previously ignored, now such definitions throw an error. #94106 (Robert Schulze). - The
joinGet/joinGetOrNullfunctions now enforceSELECTprivileges on the underlying Join table. After this change, executingjoinGet('db.table', 'column', key)requires the user to haveSELECTprivilege on both the key columns defined in the Join table and the attribute column being retrieved. Queries lacking these privileges will fail withACCESS_DENIED. To migrate, grant the necessary permissions usingGRANT SELECT ON db.join_table TO userfor full table access, orGRANT SELECT(key_col, attr_col) ON db.join_table TO userfor column-level access. This change affects all users and applications relying onjoinGet/joinGetOrNullwhere explicitSELECTgrants were not previously configured. #94307 (Vladimir Cherkasov). - Check
SHOW COLUMNSforCREATE TABLE ... AS ...queries. Previously, it checkedSHOW TABLES, which is an incorrect grant for this type of permission check. #94556 (pufit). - Make the
Hashoutput format independent of block sizes. #94503 (Alexey Milovidov). Note that this changes the output hash values compared to previous versions.
New Feature
- HTTP API and embedded Web UI for ClickHouse Keeper. #78181 (pufit and speeedmaster).
- Async insert deduplication now works with dependent materialized views. When collision by block_id occurs, the original block is filtered to remove rows associated with the block_id, and the remaining rows are transformed with all relevant materialized views select queries, this rebuilds original block without conflicting rows. #89140 (Sema Checherinda). It is allowed to use deduplication with async inserts when materialized views are involved. #93957 (Sema Checherinda).
- Introduced a new syntax and framework to simplify and extend projection index feature. This follows up https://github.com/ClickHouse/ClickHouse/pull/81021. #91844 (Amos Bird).
- Add text index support for
Arraycolumns. #89895 (Jimmy Aguilar Mena). - Enable
use_variant_as_common_typeby default, which lets you use incompatible types inside anArray, inUNIONqueries, and in branches ofif/multiIf/case. #90677 (Alexey Milovidov). - New system table
zookeeper_info. Implements #88014. #90809 (Smita Kulkarni). - Support the
Varianttype in all functions. #90900 (Bharat Nallan). - Adds a
ClickHouse_Infometric to the Prometheus/metricsendpoint containing mainly version information so it’s possible to build charts tracking detailed version information over time. #91125 (Christoph Wurm). - Introduce a new four letter
rcfgcommand for keeper which allows to change cluster configuration. This command provides broader possibilities for configuration changes than standardreconfigurerequest. Command takesjsonstring as an argument. The whole set of bytes sent to TCP interface should look like this:rcfg{json_string_length_big_endian}{json_string}. Some examples of command may look like this:{"preconditions": {"leaders": [1, 2], "members": [1, 2, 3, 4, 5]}, "actions": [{"transfer_leadership": [3]}, {"remove_members": [1, 2]}, {"set_priority": [{"id": 4, "priority": 100}, {"id": 5, "priority": 100}]}, {"transfer_leadership": [4, 5]}, {"set_priority": [{"id": 3, "priority": 0}]}]}. #91354 (alesapin). - Add function
reverseBySeparatorwhich reverses the order of substrings in a string separated by a specified separator. Close #91463. #91780 (Xuewei Wang). - Adds new setting
max_insert_block_size_byteswhich control the formation of inserted blocks in finer detail. #92833 (Kirill Kopnev). - It is possible to execute DDL queries with
ON CLUSTERclause for a Replicated database if theignore_on_cluster_for_replicated_databasesetting is enabled. In this case, the cluster name will be ignored. #92872 (Kirill). - Implement
mergeTreeAnalyzeIndexesfunction. #92954 (Azat Khuzhin). - Add new setting
use_primary_key. Set it tofalseto disable granule pruning based on the primary key. #93319 (Nihal Z. Miaji). - Add
icebergLocalClustertable function. #93323 (Anton Ivashkin). - Added
cosineDistanceTransposedfunction that approximates the cosine distance between two points. #93621 (Raufs Dunamalijevs). - Add
filescolumn to system.parts table that shows the number of files in each data part. #94337 (Match). - Adds a max-min fair scheduler for concurrency control. Provides better fairness under high oversubscription, where many queries compete for limited CPU slots. Short-running queries are not penalized by long-running queries that have accumulated more slots over time. Enabled by the
concurrent_threads_schedulerserver settingmax_min_fairvalue. #94732 (Sergei Trifonov). - Added the ability for ClickHouse client to override TLS SNI when connecting to the server. #89761 (Matt Klein).
- Support temporary tables in
joinGetfunction calls. #92973 (Eduard Karacharov). - Support deletion vectors in
DeltaLaketable engine. #93852 (Kseniia Sumarokova). - Support deletion vectors for
deltaLakeCluster. #94365 (Kseniia Sumarokova). - Google cloud storage support for data lakes. #93866 (Konstantin Vedernikov).
Experimental Feature
- Move
QBitfrom Experimental to Beta. #93816 (Raufs Dunamalijevs). - Add support for
Nullable(Tuple). Setallow_experimental_nullable_tuple_type = 1to enable it. #89643 (Nihal Z. Miaji). - Support Paimon REST catalog, continuing from https://github.com/ClickHouse/ClickHouse/pull/84423. #92011 (JIaQi Tang).
Performance Improvement
- Setting
use_skip_indexes_on_data_readis now enabled by default. This setting allows filtering in a streaming fashion, at the same time as reading, improving query performance and startup time. #93407 (Shankar Iyer). - Improve performance of
DISTINCTonLowCardinalitycolumns. Closes #5917. #91639 (Nihal Z. Miaji). - Optimize
distinctJSONPathsaggregate function so it reads only JSON paths from data parts and not the whole JSON column. #92196 (Pavel Kruglov). - More filters pushed down JOINs. #85556 (Nikita Taranov).
- Support more cases for push down from join ON condition when the filter uses inputs only from one side. Support
ANY,SEMI,ANTIjoins. #92584 (Dmitry Novik). - Allow using equivalent sets to push down filters for
SEMI JOIN. Closes #85239. #92837 (Dmitry Novik). - Skip reading left side of hash join when right side is empty. Previously we were reading left side until first non-empty block, which might do a lot of work in case when there is heavy filtering or aggregation. #94062 (Alexander Gololobov).
- Using the “fastrange” (Daniel Lemire) method for partitioning data inside the query pipeline. This could improve parallel sorting and JOINs. #93080 (Alexey Milovidov).
- Improve performance of window functions when PARTITION BY matches or is a prefix of the sorting key. #87299 (Nikita Taranov).
- Outer filter is pushed down into views which allows applying PREWHERE on local and remote nodes. Resolves #88189. #88316 (Igor Nikonov).
- Implement JIT compilations for more functions. Closes #73509. #88770 (Alexey Milovidov with Taiyang Li).
- If a skip index used in a
FINALquery is on a column that is part of the primary key, the additional step to check for primary key intersection in other parts is unnecessary and now not performed. Resolves #85897. #93899 (Shankar Iyer). - Optimize performance and memory usage for fractional
LIMITandOFFSET. #91167 (Ahmed Gouda). - Fix using of faster random read logic for Parquet Reader V3 prefetcher. Closes #90890. #91435 (Arsen Muk).
- Improve performance of
icebergCluster. Closes #91462. #91537 (Yang Jiang). - Don’t filter by virtual columns on constant filters. #91588 (c-end).
- Reduce INSERT/merges memory usage with wide parts for very wide tables by enabling adaptive write buffers. Add support of adaptive write buffers for encrypted disks. #92250 (Azat Khuzhin).
- Improved performance of full text search with text index and
sparseGramstokenizer by reducing the number of searched tokens in the index. #93078 (Anton Popov). - Function
isValidASCIIwas optimized for positive outcomes, i.e. all-ASCII input values. #93347 (Robert Schulze). - The read-in-order optimization now recognizes when ORDER BY columns are constant due to WHERE conditions, enabling efficient reverse-order reads. This benefits multi-tenant queries like
WHERE tenant='42' ORDER BY tenant, event_time DESCwhich can now use InReverseOrder instead of requiring a full sort.”. #94103 (matanper). - Introduce Enum AST specialized class to store value parameters in (string, integer) pairs instead of ASTLiteral children to optimize memory consumption. #94178 (Ilya Yatsishin).
- Distributed index analysis on multiple replicas. Beneficial for shared storage and huge amount of data in cluster. This is applicable for SharedMergeTree (ClickHouse Cloud) and could be applicable for other types of MergeTree tables on a shared storage. #86786 (Azat Khuzhin).
- Reduce overhead of join runtime filters by disabling them in the following cases: - too many bits are set in the bloom filter - too few rows are filtered out at runtime. #91578 (Alexander Gololobov).
- Use an in-memory buffer for correlated subqueries input to avoid evaluating it multiple times. Part of #79890. #91205 (Dmitry Novik).
- Allow all replicas to steal orphaned ranges in parallel replicas reading. This improves load balancing and reduces long-tail latency. #91374 (zoomxi).
- External aggregation/sorting/join now respects query setting
temporary_files_codecin all contexts. Fixed missing profile events for grace hash join. #92388 (Vladimir Cherkasov). - Make query memory usage detection for spilling to disk during aggregation/sorting more robust. #92500 (Azat Khuzhin).
- Estimate total rows count and NDV (number of distinct values) statistics of aggregation key columns. #92812 (Alexander Gololobov).
- Optimize postings list compression with simdcomp. #92871 (Peng Jian).
- Refactor S3Queue Ordered mode processing with buckets. This should also improve performance, reducing the number of keeper requests. #92889 (Kseniia Sumarokova).
- Functions
mapContainsKeyLikeandmapContainsValueLikecan now leverage a text index onmapKeys()ormapValues(), respectively. #93049 (Michael Jarrett). - Reduce memory usage on non-Linux systems (enable immediate purging of jemalloc dirty pages). #93360 (Eduard Karacharov).
- Force purging of jemalloc arenas in case the ratio of dirty pages size to
max_server_memory_usageexceedsmemory_worker_purge_dirty_pages_threshold_ratio. #93500 (Eduard Karacharov). - Reduce memory usage for AST. #93601 (Nikolai Kochetov).
- In some cases we’ve seen ClickHouse doesn’t respect a memory limit when reading from a table. This behaviour is fixed. #93715 (Nikita Mikhaylov).
- Enable
CHECK_STATandTRY_REMOVEKeeper extension by default. #93886 (Mikhail Artemenko). - Parse lower and upper bounds of file names corresponding to position deletes from Iceberg manifest file entries for better selection of corresponding data files. #93980 (Daniil Ivanik).
- Add two more settings to control maximum number of dynamic subcolumns in JSON column. First is MergeTree setting
merge_max_dynamic_subcolumns_in_compact_part(similar to already addedmerge_max_dynamic_subcolumns_in_wide_part) that limits number of dynamic subcolumns created during merge into a Compact part. Second is query level settingmax_dynamic_subcolumns_in_json_type_parsingthat limits number of dynamic subcolumns created during parsing of JSON data, it will allow to specify the limit on insert. #94184 (Pavel Kruglov). - Slightly optimize squashing of JSON columns for some cases. #94247 (Pavel Kruglov).
- Lower the thread pool queue sizes based on the production experience. Add an explicit memory consumption check before reading any data from the MergeTree. #94692 (Nikita Mikhaylov).
- Make sure the scheduler would prefer MemoryWorker thread under the CPU starvation, because it protects ClickHouse process from an existential threat. #94864 (Nikita Mikhaylov).
- Run purging of jemalloc dirty pages in a different thread from main thread of MemoryWorker. If purging is slow, it could delay updates of RSS usage which could lead to out of memory kills of the process. Introduce new config
memory_worker_purge_total_memory_threshold_ratioto start purging dirty pages based on ratio of total memory usage. #94902 (Antonio Andelic).
Improvement
system.blob_storage_logis now available for Azure Blob Storage. #93105 (Alexey Milovidov).- Implement
blob_storage_logfor Local and HDFS. Fix an error whenS3Queueused something other than the disk name for logging inblob_storage_log. Adderror_codecolumn toblob_storage_log. Split the test configuration file to simplify local testing. #93106 (Alexey Milovidov). clickhouse-clientandclickhouse-localwill highlight digit groups (thousands, millions, etc.) inside numeric literals while typing. This closes #93100. #93108 (Alexey Milovidov).- Adds support in
clickhouse-clientfor command-line arguments with a space surrounding the equals sign. Closes #93077. #93174 (Cole Smith). - With
<interactive_history_legacy_keymap>true</interactive_history_legacy_keymap>, the CLI client can now fall back to Ctrl-R for regular search like before, while Ctrl-T does fuzzy search. #87785 (Larry Snizek). - The statement to clear caches
SYSTEM DROP [...] CACHEgave the false impression that the statement disables the cache. ClickHouse now supports statementSYSTEM CLEAR [...] CACHEwhich is more obvious. The old syntax remains available. #93727 (Pranav Tiwari). - Support multiple columns as primary key in
EmbeddedRocksDB. Closes #32819. #33917 (usurai). - It is now possible to use non-constant IN for scalars (queries like
val1 NOT IN if(cond, val2, val3)). #93495 (Yarik Briukhovetskyi). - Prevent
x-amz-server-side-encryptionheaders from being propagated toHeadObject,UploadPart&CompleteMultipartUploadS3 requests as they’re not supported. #64577 (Francisco J. Jurado Moreno). - Tracking hive partitioning for ordered mode in S3Queue. Resolves #71161. #81040 (Anton Ivashkin).
- Optimize space reservation in filesystem cache.
FileCache::collectCandidatesForEvictionwill be executed without unique lock. #82764 (Kseniia Sumarokova). - Support composite rotation strategy (size + time) for server log. #87620 (Jianmei Zhang).
- CLI client can now specify
<warnings>false</warnings>instead of the command line--no-warnings. #87783 (Larry Snizek). - Add support for the
avgaggregate function with Date, DateTime and Time values as arguments. Closes #82267. #87845 (Yarik Briukhovetskyi). - The optimization
use_join_disjunctions_push_downis enabled by default. #89313 (Alexey Milovidov). - Support more table engines and data source kinds in the correlated subqueries. Closes #80775. #90175 (Dmitry Novik).
- If the schema of parameterized view is specified explicitly, it is shown. Close #88875, #81385. #90220 (Grigorii Sokolik).
- Correctly handle the gap in Keeper log entries if logs are before the last committed index. #90403 (Antonio Andelic).
- Improve
min_free_disk_bytes_to_perform_insertsetting to work correctly with JBOD volumes. #90878 (Aleksandr Musorin). - Make it possible to specify
storage_class_namesetting in named collections forS3table engine ands3table function. #91926 (János Benjamin Antal). - Support inserting auxiliary zookeeper by
system.zookeeper. #92092 (RinChanNOW). - Add new metrics for the keeper:
KeeperChangelogWrittenBytes,KeeperChangelogFileSyncMicroseconds,KeeperSnapshotWrittenBytesandKeeperSnapshotFileSyncMicrosecondsprofile events as well asKeeperBatchSizeElementsandKeeperBatchSizeByteshistogram metrics. #92149 (Miсhael Stetsyuk). - Add a new setting,
trace_profile_events_list, which limits tracing withtrace_profile_eventto the specified list of event names. This allows more precise data collection on large workloads. #92298 (Alexey Milovidov). - Support SYSTEM NOTIFY FAILPOINT for pausable failpoints. - Support SYSTEM WAIT FAILPOINT fp PAUSE/RESUME. #92368 (Shaohua Wang).
- Add
creation(implicit/explicit) column tosystem.data_skipping_indices. #92378 (Raúl Marín). - Allow passing the description of columns for YTsaurus dyn tables to the dictionary source. #92391 (MikhailBurdukov).
- In #63985, we made it possible to specify all the parameters needed for TLS configuration on a per-port basis (see composable protocols), so we don’t have to rely on global TLS config. However, the implementation still implicitly requires a global
openSSL.serverconfig section to exist, which conflicts with setups where different TLS configurations are needed for different ports. For example, in keeper-in-server deployments, we need separate TLS configs for inter-keeper communication and clickhouse client connections. #92457 (Miсhael Stetsyuk). - Introduce a new setting
input_format_binary_max_type_complexitythat limits the total number of type nodes that can be decoded in binary format to prevent malicious payloads. #92519 (Raufs Dunamalijevs). - Reflect running tasks in
system.background_schedule_pool{,_log}. Add documentation. #92587 (Azat Khuzhin). - Execute current query in Ctrl+R search in client if no history match found. #92749 (Azat Khuzhin).
- Support
EXPLAIN indices = 1as an alias forEXPLAIN indexes = 1. Closes #92483. #92774 (Pranav Tiwari). - Parquet reader now allows reading Tuple or Map columns as JSON:
select x from file(f.parquet, auto, 'x JSON')works even if the type of columnxinf.parquetis tuple or map. #92864 (Michael Kolupaev). - Support empty tuples in parquet reader. #92868 (Michael Kolupaev).
- Fallback to read-write copy for Azure Blob Storage when native copy fails with BadRequest (e.g. invalid block list). Previously this was only done for Unauthorized error which was seen while copying blob to different storage accounts. But we also sometimes see “The specified block list is invalid” error. So now updated the condition to fallback to read & write for all native copy fails. #92888 (Smita Kulkarni).
- Fix EC2 metadata endpoint throttling when running many concurrent S3 queries with EC2 instance profile credentials. Previously, each query created its own
AWSInstanceProfileCredentialsProvider, causing concurrent requests to the EC2 metadata service which could result in timeouts andHTTP response code: 403errors. Now the credentials provider is cached and shared across all queries. #92891 (Sav). - Rework
insert_select_deduplicatesetting to add an ability to keep backward compatibility. #92951 (Sema Checherinda). - Log background tasks that are slower than average (
background_schedule_pool_log.duration_threshold_milliseconds=30) to avoid excessive tasks logging. #92965 (Azat Khuzhin). - In previous versions, some of C++ function names were displayed incorrectly (“mangled”) in the
system.trace_logandsystem.symbols, and thedemanglefunction didn’t process them well. Closes #93074. #93075 (Alexey Milovidov). - Introduced the
backup_data_from_refreshable_materialized_view_targetsbackup setting to skip back up of refreshable materialized views. RMVs with APPEND refresh strategy which are always backed up. #93076 (Julia Kartseva). #93658 (Julia Kartseva) - Use minimal debug info instead of no debug info for heavy translation units, such as functions. #93079 (Alexey Milovidov).
- Added MinIO compatibility support to AWS S3 C++ SDK by implementing error code mapping for MinIO-specific errors. This change allows ClickHouse to properly handle and retry MinIO server errors when using MinIO deployments instead of AWS S3, improving reliability for users running object storage on self-hosted MinIO clusters. #93082 (XiaoBinMu).
- Write symbolized jemalloc profiles (eliminating the need for a binary during heap profile generation). #93099 (Azat Khuzhin).
- Resurrect
clickhouse git-importtool - it was broken on large and invalid commits. See https://presentations.clickhouse.com/2020-matemarketing/. #93202 (Alexey Milovidov). - Don’t show passwords from URL storage in query log. #93245 (Konstantin Vedernikov).
- Support
Geometrytype forflipCoordinates. #93303 (Bharat Nallan). - Improve the UX of SYSTEM INSTRUMENT ADD/REMOVE: use String literals for function names, patch all functions that match and allow using function_name in
REMOVE. #93345 (Pablo Marcos). - Add a new setting
materialize_statistics_on_mergewhich enables/disables materializing statistics during merge. The default value is1. #93379 (Han Fei). - ClickHouse can now parse
SELECTwithout parentheses aroundDESCRIBE SELECTqueries. Closes #58382. #93429 (Yarik Briukhovetskyi). - Add randomization of cache correctness checks under probability. #93439 (Kseniia Sumarokova).
- Add setting
type_json_allow_duplicated_key_with_literal_and_nested_objectto allow duplicated paths in JSON where one is a literal and another is a nested object, e.g.{"a" : 42, "a" : {"b" : 42}}. Some data could be created before this restriction on duplicated paths was added in https://github.com/ClickHouse/ClickHouse/pull/79317 and further manipulation with this data can lead to errors now. With this setting, such old data cane still be used with no errors. #93604 (Pavel Kruglov). - Don’t print values of simple types on separate lines in Pretty JSON. #93836 (Pavel Kruglov).
- When there are many
alter table ... modify setting ...statements, it’s possible not to acquire lock for 5 seconds. Better to returntimeoutthanlogical error. #93856 (Han Fei). - Prevent excessive output on a syntax error. Before this change, it output the whole SQL script, which could contain a lot of queries. #93876 (Alexey Milovidov).
- Do proper byte size calculation of the
checkrequest with stats in Keeper. #93907 (Mikhail Artemenko). - Added
use_hash_table_stats_for_join_reorderingsetting to control whether runtime hash table size statistics are used for join reordering. This setting is enabled by default, preserving the existing behavior ofcollect_hash_table_stats_during_joins. #93912 (Vladimir Cherkasov). - Users can now partially view nested global server settings in the
system.server_settingstable (e.g.logger.level). This only covers settings with a fixed structure (no lists, enumerations, repetitions etc.). #94001 (Hechem Selmi). QBitcan now be compared for equality. #94078 (Raufs Dunamalijevs).- When Keeper detects broken snapshot or inconsistent changelogs, throw exception instead of manually aborting or cleaning up files automatically. This should lead to a safer behaviour of Keeper relying on manual intervention. #94168 (Antonio Andelic).
- Fix leaving possible leftovers in case of
CREATE TABLEfails. #94174 (Azat Khuzhin). - Fix uninitialized memory access (a bug in OpenSSL) when password protected TLS key is used. #94182 (Konstantin Bogdanov).
- Bump chdig to v26.1.1. #94290 (Azat Khuzhin).
- Support more generic partitioning for S3Queue ordered mode. #94321 (Bharat Nallan).
- Added alias
use_statisticsfor settingallow_statistics_optimize. This is more consistent with existing settingsuse_primary_keyanduse_skip_indexes. #94366 (Robert Schulze). - Enabled setting
input_format_numbers_enum_on_conversion_errorfor conversion from Numbers to Enums to check whether the element exists. #94384 (Elmi Ahmadov). - In S3(Azure)Queue ordered mode clean up failed nodes by tracking limits (before that was done only in Unordered mode for both failed and processed, so now this will also be done for Ordered but only for failed nodes). #94412 (Kseniia Sumarokova).
- Enable access management for
defaultuser in clickhouse-local. The default user inclickhouse-localwas missing the access_management privilege, which caused operations likeDROP ROW POLICY IF EXISTSto fail withACCESS_DENIEDerror, even though the user should be unrestricted. #94501 (Alexey Milovidov). - Enable named collection for YTsaurus dictionaries and tables. #94582 (MikhailBurdukov).
- Add support for SQL-defined named collections in BACKUP/RESTORE for S3 and Azure Blob Storage. Closes #94604. #94605 (Pablo Marcos).
- Support bucketing based on partition key for S3Queue in ordered mode. #94698 (Bharat Nallan).
- Add an asynchronous metric with the longest running merge elapsed time. #94825 (Raúl Marín).
- Add belonging file check before apply position delete using IcebergBitmapPositionDeleteTransform. #94897 (Yang Jiang).
- Now
view_duration_msshows the time when group was active, not the sum of the threads duration in it. #94966 (Sema Checherinda). - Remove limit of the max number of search tokens in
hasAnyTokensandhasAllTokensfunctions which was limited to 64. Example:SELECT count() FROM table WHERE hasAllTokens(text, ['token_1', 'token_2', [...], 'token_65']]);The query would result in aBAD_ARGUMENTSerror because there are 65 search tokens. With this PR, the limit has been removed completely and the same query would run without an error. #95152 (Elmi Ahmadov). - Add a setting
input_format_numbers_enum_on_conversion_errorfor conversion from Numbers to Enums to check whether the element exists. Closes: #56144. #56240 (Nikolay Degterinsky). - Share format parser resources between data file and position delete file reading in Iceberg tables to reduce memory allocations. #94701 (Yang Jiang).
Bug Fix (user-visible misbehavior in an official stable release)
- Fixes a bug where predefined query handlers would have trailing whitespace interpreted as data during inserts. #83604 (Fabian Ponce).
- Fix INCOMPATIBLE_TYPE_OF_JOIN error for Join storage and outer to inner join optimization applied. Resolves #80794. #84292 (Vladimir Cherkasov).
- Fix exception “Invalid number of rows in Chunk” when using hash join with
allow_experimental_join_right_table_sortingenabled. #86440 (yanglongwei). - Always replace file names to hash in MergeTree if filesystem is case insensitive. Previously on systems with case insensitive filesystem (like MacOS) it could lead to data corruption when several column/subcolumn names differs only in the case. #86559 (Pavel Kruglov).
- Add a full permissions check on the create stage for the underlying query inside a materialized view. #89180 (pufit).
- Fixed crash in
icebergHashfunction on constant argument. #90335 (Michael Kolupaev). - Fix logical error when mutation without transaction mutates parts in an active transaction, which is rolled back finally. #90469 (Shaohua Wang).
- Update
system.warningscorrectly after an ordinary database was converted to an atomic database. #90473 (sdk2). - Fixes an assertion when reading from Parquet file, and part of a prewhere expression is used elsewhere in the query. #90635 (Max Kainov).
- Fix crash in a single-node cluster when reading from Iceberg in split-by-buckets mode. This closes #90913. #91553 (Konstantin Vedernikov).
- Fix possible logical error in Log engine during subcolumns reading. Closes #91710. #91711 (Pavel Kruglov).
- Fix Logical error: ‘Storage does not support transaction’ during ATTACH AS REPLICATED. #91772 (Shaohua Wang).
- Fix for runtime filters working incorrectly when LEFT ANTI JOIN has extra post-condition. #91824 (Alexander Gololobov).
- Fixes an error where we have a null-safe comparison involving the Nothing type. Closes #91834. Closes #84870. Closes #91821. #91884 (Yarik Briukhovetskyi).
- Fix DELTA_BYTE_ARRAY decoding bugs in native Parquet reader affecting highly repetitive string data. #91929 (Daniel Muino).
- Cache schema only for the file it was inferred from in globs instead of all files during schema inference. Closes #91745. #92006 (Pavel Kruglov).
- Fix the
Couldn't pack tar archive: Failed to write all byteserror caused by an incorrect archive entry size header. Fixes #89075. #92122 (Julia Kartseva). - Release request stream in insert select to prevent closing http connection. #92175 (Sema Checherinda).
- Fix logical error for queries with multiple JOINs with
USINGclause andjoin_use_nulls. #92251 (Vladimir Cherkasov). - Fix logical error while join reordering with join_use_nulls, close https://github.com/clickhouse/clickhouse/issues/90795. #92289 (Vladimir Cherkasov).
- Fix inconsistent AST formatting of arrayElement with negate literal. Closes #92288 Closes #92212 Closes #91832 Closes #91789 Closes #91735 Closes #88495 Closes #92386. #92293 (Pavel Kruglov).
- Fix a possible crash with
join_on_disk_max_files_to_mergesetting. #92335 (Bharat Nallan). - Related issue #https://github.com/ClickHouse/support-escalation/issues/6365. #92339 (Tuan Pham Anh).
- Fix missing access check in
SYSTEM SYNC FILE CACHE. Closes #92101. #92372 (Kseniia Sumarokova). - Fix
count_distinct_optimizationpass over window functions and over multiple arguments. #92376 (Raúl Marín). - Fix “Cannot write to finalized buffer” error when using certain aggregate functions with window functions. Closes #91415. #92395 (Jimmy Aguilar Mena).
- Fix logical error with
CREATE TABLE ... AS urlCluster()and database engineReplicated. Closes #92216. #92418 (Kseniia Sumarokova). - Inherit source part serialization info settings during mutation in MergeTree. It fixes possible incorrect result of the query over mutated part after changes in data types serialization. #92419 (Pavel Kruglov).
- Fix possible conflict in column and subcolumn with the same name leading in using wrong serialization and query failures. Closes #90219. Closes #85161. #92453 (Pavel Kruglov).
- Fix a
LOGICAL_ERRORs that caused by not wanted modification of query plan when converting outer join to inner join. Also relax the requirements of optimization to be able to apply it in cases when injective functions are applied to the aggregating keys during joins. #92503 (János Benjamin Antal). - Fix possible error
SIZES_OF_COLUMNS_DOESNT_MATCHduring sorting of emty tuple column. Closes #92422. #92520 (Pavel Kruglov). - Check for incompatible typed paths in JSON type. Closes #91577. #92539 (Pavel Kruglov).
- Fix deadlock for SHOW CREATE DATABASE for Backup database. #92541 (Azat Khuzhin).
- Use proper error code when validating hypothesis index. #92559 (Raúl Marín).
- Fix dynamic subcolumns resolution in column aliases in analyzer. Previously dynamic subcolumn in column alias was wrapped in
getSubcolumnand in some cases could be not resolved at all. Closes #91434. #92583 (Pavel Kruglov). - Prevent crash in tokens() with null second argument. #92586 (Raúl Marín).
- Fix potential crash caused by in place mutation of underlying const PREWHERE columns. This could’ve happened at column shrinking (
IColumn::shrinkToFit) or filtering (IColumn::filter), which could’ve triggered concurrently from several threads. #92588 (Arsen Muk). - Creating and materializing text indexes on tables containing large parts (over 4,294,967,295 rows) is temporarily disabled. This limitation prevents incorrect query results, as the current index implementation does not yet support such large parts. #92644 (Anton Popov).
- Fixes a logical error
Too large size (A) passed to allocatorwhile executing JOINs. Closes #92043. #92667 (Yarik Briukhovetskyi). - Remove a bug that
ngrambf_v1indexes with ngram length (1st parameter) > 8 would throw an exception. #92672 (Robert Schulze). - Fix uncaught exception during background named collections reload when zookeeper storage is used. Closes https://github.com/ClickHouse/clickhouse-private/issues/44180. #92717 (Kseniia Sumarokova).
- Reworks incorrect logic in access grant checks for wildcard grants. The previous attempt https://github.com/ClickHouse/ClickHouse/pull/90928 addressed a critical vulnerability but ended up being too restrictive, resulting in some wildcard
GRANTstatements failing due to unrelated revokes. #92725 (pufit). - Fix bug in data skipping logic when
not match(...)is used inWHEREcausing incorrect results. Closes #92492. #92726 (Nihal Z. Miaji). - Do not attempt to delete temporary directories at startup if a MergeTree table is created over a read-only disk. #92748 (Alexey Milovidov).
- Fix “Cannot add action to empty ExpressionActionsChain” for ALTER TABLE REWRITE PARTS (v2). #92754 (Azat Khuzhin).
- Avoid crash due to reading from a disconnected
Connection. #92807 (Raufs Dunamalijevs). - Fix logical error
Failed to set file processing within 100 retriesin storgaeS3QueueinOrderedmode. It is now replaced with a warning. This error could happen before 25.10 version if keeper session expired, however it will still be a warning in 25.10+ versions, as it is still theoretically possible to get this error in case of high processing concurrency inOrderedmode. #92814 (Kseniia Sumarokova). - Previously, some queries that used PK sharding with a false condition were failing. Now they’re not. Needed for https://github.com/ClickHouse/ClickHouse/pull/89313. #92815 (Yarik Briukhovetskyi).
- Fixed calculation of uncompressed sizes of text indexes in the
system.partstable. #92832 (Anton Popov). - Fixed usage of primary index in lightweight updates that have an
INclause with subqueries in the predicate of theWHEREclause. #92838 (Anton Popov). - Fix creating type hint for path ‘skip’ in JSON. Closes #92731. #92842 (Pavel Kruglov).
- In the S3 table engine, we should avoid caching the partition key if there are non-deterministic functions. #92844 (Miсhael Stetsyuk).
- Fix possible error
FILE_DOESNT_EXISTafter mutation of a sparse column withratio_of_defaults_for_sparse_serialization=0.0. Closes #92633. #92860 (Pavel Kruglov). - Fix parquet schema inference in the old parquet reader (not used by default) when a JSON column comes after a Tupe column. Fix the old parquet reader (not used by default) failing on empty tuples. #92867 (Michael Kolupaev).
- Fix logical error with multiple joins on constant condition and
join_use_nulls, close #92640. #92892 (Vladimir Cherkasov). - Fix possible error
NOT_FOUND_COLUMN_IN_BLOCKduring insert into a table with subcolumn in partition expression. Closes #93210. Closes #83406. #92905 (Pavel Kruglov). - Fix error
NO_SUCH_COLUMN_IN_TABLEin Merge engine over tables with aliases. Closes #88665. #92910 (Pavel Kruglov). - Fix NULL != NULL case for full_sorting_join on LowCardinality(Nullable(T)) column. #92924 (Vladimir Cherkasov).
- Fixed several crashes during merges of text indexes in
MergeTreetables. #92925 (Anton Popov). - Restore LowCardinality wrappers on SET expression results if needed during TTL aggregation to prevent exceptions during table optimization. #92971 (Seva Potapov).
- Fix logical error during index analysis when empty array is used in
hasfunction. Closes #92906. #92995 (Nihal Z. Miaji). - Fix possible hung on terminating background schedule pool (may lead to server hungs on shutdown). #93008 (Azat Khuzhin).
- Fix possible error FILE_DOESNT_EXIST after sparse column mutation when setting
ratio_of_defaults_for_sparse_serializationwas changed to1.0via alter. #93016 (Pavel Kruglov). - Fix bug in data skipping logic when
not materialize(...)ornot CAST(...)is used in WHERE causing incorrect results. Closes #88536. #93017 (Nihal Z. Miaji). - Fix possible usage of outdated parts due to TOCTOU race for shared parts. #93022 (Azat Khuzhin).
- Fix crash when deserialising malformed
groupConcataggregate state with out-of-bounds offsets. #93028 (Raufs Dunamalijevs). - Fix leaving connection in a broken state after preliminary cancellation distributed queries. #93029 (Azat Khuzhin).
- Fix join results when the right-side join key is a sparse column. This closes #92920. I can only reproduce the bug with
set compatibility='23.3'. Not sure if it should be backported. #93038 (Amos Bird). - Fix possible
Cannot finalize buffer after cancellationinestimateCompressionRatio(). Fixes: #87380. #93068 (Azat Khuzhin). - Fixed merges of text indexes built on top of the complex expressions (such as
concat(col1, col2)). #93073 (Anton Popov). - Fix applying projection when filter contains subcolumns. Closes #92882. #93141 (Pavel Kruglov).
- Fix logical error in some cases triggered when join runtime filters are added to query plan. It was caused by incorrectly returning duplicated const columns from one of join sides. #93144 (Alexander Gololobov).
- Special function
__applyFilterused by join runtime filters was returning ILLEGAL_TYPE_OF_ARGUMENT in some valid cases. #93187 (Alexander Gololobov). - Prevent different interpolated columns from collapse into the same column in a block when interpolated columns are effectively aliases of the same column. #93197 (Yakov Olkhovskiy).
- Do not add runtime filter when joining with already filled right table. #93211 (Alexander Gololobov).
- Fix keeper persistent watches cleanup after dead session. This closes #92480. #93213 (Konstantin Vedernikov).
- Fix order by tuple in iceberg. This closes #92977. #93225 (Konstantin Vedernikov).
- Fix bug with S3Queue setting
s3queue_migrate_old_metadata_to_buckets. Closes #93392, #93196, #81739. #93232 (Kseniia Sumarokova). - Remove unused columns when the projection is rebuilt during the merge. It reduces memory usage and creates fewer temporary parts. #93233 (Nikolai Kochetov).
- Fix unused columns removal from subqueries in the presence of a scalar correlated subquery. Before the fix column could have been removed if it was used only in the correlated subquery, and the query would fail with
NOT_FOUND_COLUMN_IN_BLOCKerror. #93273 (Dmitry Novik). - Fix possible missing subcolumn in MV during alter of source table. Closes #93231. #93276 (Pavel Kruglov).
- Fix the
Mergetable engine query planning with the analyzer that could throw ILLEGAL_COLUMN forhostName()when merging local and remote/Distributed tables. Closes #92059. #93286 (Jinlin). - Fixes a case where NOT IN with non-constant array arguments was returning the wrong value + Support for non-constant Array functions. Closes #14980. #93314 (Yarik Briukhovetskyi).
- Fix
Not found columnforuse_top_k_dynamic_filteringoptimization. Fixes #93186. #93316 (Nikolai Kochetov). - Fixed rebuilding of text indexes created on top of subcolumns. #93326 (Anton Popov).
- Fixed handling of empty array as a second argument in
hasAllTokensandhasAnyTokensfunctions. #93328 (Anton Popov). - Fix logical error when runtime filters are used in a query with totals for right side table. #93330 (Alexander Gololobov).
- The server no longer crashes if function
tokensis called with non-const tokenizer parameters (the 2th, 3rd, 4th parameter), e.g.,SELECT tokens(NULL, 1, materialize(1)). #93383 (Robert Schulze). - Fixed integer overflow vulnerability in
groupConcatstate deserialisation that could cause memory safety issues with crafted aggregate states. #93426 (Raufs Dunamalijevs). - Fixed text index analysis on array columns when the index contains no tokens (all arrays are empty or all tokens are skipped by the tokenizer). #93457 (Anton Popov).
- Avoids oauth login in ClickHouse Client when username/password are within the connection string. #93459 (Krishna Mannem).
- Fix Azure ADLS Gen2 vended credentials support in DataLakeCatalog - parse
adls.sas-token.*keys from Iceberg REST catalogs and fix ABFSS URL parsing. #93477 (Karun Anantharaman). - Fix GLOBAL IN support with analyzer (previously set was created on the remote node again). #93507 (Azat Khuzhin).
- Fix extracting subcolumn during deserialization directly into Sparse columns. #93512 (Pavel Kruglov).
- Fixed direct reading from text index with duplicate search queries. #93516 (Anton Popov).
- Fix for NOT_FOUND_COLUMN_IN_BLOCK error when runtime filter is enabled and joined tables have the same column returned multiple times (e.g. SELECT a, a, a FROM t). #93526 (Alexander Gololobov).
- Fix a bug where clickhouse-client would ask for password twice when connecting using ssh. #93547 (Isak Ellmer).
- Make sure that zookeeper is finalized on shutdown (fix possible hung on shutdown in very unlikely cases). #93602 (Azat Khuzhin).
- Fix LOGICAL_ERROR when restoring ReplicatedMergeTree with deduplication race. #93612 (Pablo Marcos).
- Fix using Sparse column for TTL update during direct deserialization into Sparse columns in some input formats. It fixes possible logical error
Unexpected type of result TTL column. #93619 (Pavel Kruglov). - Fixed h3 index functions sometimes crashing or getting stuck when called on invalid inputs. #93657 (Michael Kolupaev).
- The usage of
ngram_bfindex on a non-UTF-8 data led to an uninitialized memory read, with values that could reside in the resulting index structure. Closes #92576. #93663 (Alexey Milovidov). - Validate that the decompressed buffer size is as expected. #93690 (Raúl Marín).
- Prevent users to get the list of columns from a table without checking
SHOW COLUMNSpermission using themergetable engine. #93695 (János Benjamin Antal). - Fixed materialization of skip indexes created on top of subcolumns. #93708 (Anton Popov).
- We store storages’ shared pointers in
QueryPipeline::resources::storage_holdersto make sure that theIStorageobjects are not destroyed whilePipelineExecutoris alive. #93746 (Miсhael Stetsyuk). - Fix attaching Replicated DBs when the interserver host changed after restarting. #93779 (Tuan Pham Anh).
- Fix assert
!read_until_positioninReadBufferFromS3which happened when cache is enabled. #93809 (Kseniia Sumarokova). - Fix logical error in a rare case when empty tuple is used with
Mapcolumn. Closes #93784. #93814 (Nihal Z. Miaji). - Fixed
_part_offsetcorruption when projections are rebuilt during merges, and optimized projection processing by avoiding unnecessary reads of the_part_offsetcolumn and skipping unneeded columns in projection calculations. This continues the optimizations introduced in #93233. #93827 (Amos Bird). - Remove ‘Bad version’ handling. #93843 (Anton Ivashkin).
- Fix
optimize_inverse_dictionary_lookupnot working with distributed query when key is signed integral type. Closes #93259. #93848 (Nihal Z. Miaji). - Fix
lag/leadnot working with distributedremote()query. Closes #90014. #93858 (Nihal Z. Miaji). - Fix system instrument dispatch bug. #93937 (Pablo Marcos).
- In https://github.com/ClickHouse/ClickHouse/pull/89173, we added an extra field to the structure that
TraceSendersends through an internal pipe. However, the buffer size was not updated (here), therefore we are writing more data to buffer thanbuffer_sizewhich results in multiple flushes. And becauseTraceSender::sendis called from different threads, different threads’ flushes may interleave which breaks the invariant that the receiving end (TraceCollector) relies on. #93966 (Miсhael Stetsyuk). - Fix type conversion to super type during the join operation of the storage
JoinwithUSINGclause. Fixes #91672. Fixes #78572. #94000 (Dmitry Novik). - Fix for FilterStep not properly added when join runtime filter is applied over Merge table. #94021 (Alexander Gololobov).
- A
SELECTquery containing a predicate on multiple columns with bloom filter skip indexes and bothORandNOTconditions are present could return inconsistent results. That is fixed now. #94026 (Shankar Iyer). - Fix CLEAR column with dependent indices. #94057 (Raúl Marín).
- Fix use-of-uninitialized-value in
ReadWriteBufferFromHTTP. #94058 (Alexey Milovidov). - Fix bad check for typed paths in JSON. The check was introduced in https://github.com/ClickHouse/ClickHouse/pull/92842 and can lead to an error during existing tables startup. #94070 (Pavel Kruglov).
- Fix the crash during filter analysis in the presence of OUTER JOIN. Fixes #90979. #94080 (Dmitry Novik).
- Fix accuracy of
uniqThetawhen using UInt8 aggregation keys in parallel (max_threads> 1 - default). #94095 (Azat Khuzhin). - Fix crash caused by exception thrown from a
socket.setBlocking(true)call insideSCOPE_EXIT. #94100 (Miсhael Stetsyuk). - Fix data loss when
DROP PARTITIONremoves parts created by later log entries in ReplicatedMergeTree. #94123 (Tuan Pham Anh). - Fixed parquet reader v3 incorrectly handling arrays that cross page boundaries. This happens e.g. for files written by Arrow without enabling page statistics or page index. Affects only columns of Array data type. Likely symptom is that one array every ~1 MB of data gets truncated. Before this fix, use this setting as workaround:
input_format_parquet_use_native_reader_v3 = 0. #94125 (Michael Kolupaev). - Fix too many watches in ReplicatedMergeTree while waiting for log entry. #94133 (Azat Khuzhin).
- Functions
arrayShuffle,arrayPartialShuffleandarrayRandomSampleto materialize const columns - so that different rows get different results. #94134 (Joanna Hulboj). - Fix data race in evaluating table functions in materialized views. #94171 (Alexey Milovidov).
- Fix nullptr dereference in
PostgreSQLdatabase engines (when the query is incorrect). Closes #92887. #94180 (Alexey Milovidov). - Fix memory leak in refreshable materialized views using
SELECTqueries with multiple subqueries. #94200 (Antonio Andelic). - Fix data race in
DataPartStorageOnDiskBase::removevssystem.parts. Closes #49076. #94262 (Alexey Milovidov). - Remove the wrong
noexceptspecifier at HashTable copy assignment that may lead to crash (std::terminate) on memory exceptions. #94275 (Nikita Taranov). - Previously, creating a projection with duplicate columns in GROUP BY (e.g.,
GROUP BY c0, c0) and inserting data caused astd::length_errorifoptimize_row_orderis enabled. Closes #94065. #94277 (Alexey Milovidov). - Fix obscure bug in ZooKeeper client on connect which leads to hungs and crashes. #94320 (Azat Khuzhin).
- Fix function to subcolumns optimization not applied to subcolumns. #94323 (Pavel Kruglov).
- Fix possibly incorrect result in nested RIGHT JOINs when
enable_lazy_columns_replicationis enabled. The bug caused all rows in replicated columns to incorrectly return the same value instead of their distinct values. Close #93891. #94339 (Vladimir Cherkasov). - Fix filter pushdown for SEMI JOIN using equivalence sets. Do not push the filter down if argument types have changed. Fixes #93264. #94340 (Dmitry Novik).
- Fix usage of DeltaLake CDF with database DataLake database engine (delta lake catalogs integration). Closes #94122. #94342 (Kseniia Sumarokova).
- Fix incorrect value of current metric
FilesystemCacheSizeLimitin caseSLRUcache policy was used. #94363 (Kseniia Sumarokova). - Creating a Backup database engine with less than two arguments now returns a more descriptive error message (
Wrong number of argumentsinstead ofstd::out_of_range: InlinedVector::at(size_type) const failed bounds check.). #94374 (Robert Schulze). - Ignores impossible revokes of global grants on the database level for grants with grant option. #94386 (pufit).
- Fix reading sparse offsets from compact parts. Closes #94385. #94399 (Pavel Kruglov).
- Don’t prevent ALTER of columns using implicit indexes, even if
alter_column_secondary_index_mode’sthrowmode is used. #94425 (Raúl Marín). - Fix crash in
TCPHandlerwhen multiplereceivePacketsExpectQuerycalls readProtocol::Client::IgnoredPartUUIDs. #94434 (Miсhael Stetsyuk). - Fix masking sensitive data in
system.functions. #94436 (Vitaly Baranov). - Fix nullptr dereference with disabled
send_profile_events. This feature was introduced recently for the ClickHouse Python driver. Closes #92488. #94466 (Alexey Milovidov). - Fix text index .mrk incompatibility during merges. #94494 (Peng Jian).
- When
read_in_order_use_virtual_rowis enabled, the code was accessing index columns based on the full primary key size without checking if the index was truncated, leading to use-after-free / uninitialized memory. Closes #85596. #94500 (Alexey Milovidov). - Fix an error due to a type mismatch when sending external tables for subqueries with GLOBAL IN if the types are Nullable. Closes #94097. #94511 (Alexey Milovidov).
- In previous versions, queries with multiple index conditions over the same expression may erroneously throw an exception
Not found column. Closes #60660. #94515 (Alexey Milovidov). - Fix incorrect handling of Nullable join column in runtime filters. #94555 (Alexander Gololobov).
- Creating a workload in another workload that is currently in use no longer causes a crash. #94599 (Sergei Trifonov).
- Fix a crash during ANY LEFT JOIN optimization when
isNotNullis evaluated on a missing column. #94600 (Molly). - Fix default expression evaluation when referencing other columns with computed defaults. #94615 (Alexey Milovidov).
- Fix permission issues in BACKUP/RESTORE operations. #94617 (Pablo Marcos).
- Fix crash due to incorrect type cast when the data type is
Nullable(DateTime64). #94627 (Miсhael Stetsyuk). - Fixes a bug where certain distributed queries with
ORDER BYcould returnALIAScolumns with swapped values (i.e., columnashowing columnb’s data and vice versa). #94644 (filimonov). - Fix storing results of keeper-bench to file. #94654 (Antonio Andelic).
- Fix incorrect estimations with MinMax-type statistics when the column contains negative floating-point values. #94665 (zoomxi).
- Fix reading Parquet files when a map’s key is a struct. #94670 (Konstantin Vedernikov).
- Fix possibly incorrect RIGHT join result when using complex ON conditions. Close #92913. #94680 (Vladimir Cherkasov).
- Preserve constant index granularity (use_const_adaptive_granularity) after Vertical merges. #94725 (Azat Khuzhin).
- Fix mutation bug with scalar subqueries and table dependencies. If a table had dependencies (index or projections) over a column, scalar subqueries might be evaluated and cached without data and lead to incorrect changes. #94731 (Raúl Marín).
- Fix AsynchronousMetrics cpu_pressure fallback on error. #94827 (Raúl Marín).
- The
getURLHostRFCfunction was missing bounds checks before dereferencing pointers. When an empty string was passed todomainRFC, it would read uninitialized memory, triggering MSan errors. #94851 (Alexey Milovidov). - Fix readonlyness of encrypted disks. #94852 (Azat Khuzhin).
- Fix logical error in fractional
LIMIT/OFFSETwhen using the old analyzer with Distributed tables. Closes #94712. #94999 (Ahmed Gouda). - Fix crash under some conditions when join runtime filters are enabled by default. #95000 (Alexander Gololobov).
- Improve masking passwords in url used in table engine
URL()and table functionurl(). #95006 (Vitaly Baranov). - Function
toStartOfIntervalnow works in the same way astoStartOfX, whereXisDay, Week, Month, Quarter, Yearwhen theenable_extended_results_for_datetime_functionsis on. #95011 (Kirill Kopnev). - Fix constant string comparisons not respecting the settings
cast_string_to_date_time_mode,bool_true_representation,bool_false_representation, andinput_format_null_as_default. Closes #91681. #95040 (Nihal Z. Miaji). - Fix data race in the filesystem cache. #95064 (Alexey Milovidov).
- Fix a rare race condition in the Parquet reader. #95068 (Alexey Milovidov).
- Fix crash in the top K optimization when
LIMITis zero. Closes #93893. #95072 (Alexey Milovidov). - Converting from DateTime/integers to Time64 extracts the time-of-day component using
toTime, which is not monotonic. TheToDateTimeMonotonicitytemplate incorrectly claimed this conversion was monotonic, causing “Invalid binary search result in MergeTreeSetIndex” exception in debug builds. #95125 (Alexey Milovidov). - Recreated list of manifest file entries only if necessary (previously it was done on each iteration). #95162 (Daniil Ivanik).
Build/Testing/Packaging Improvement
- Add a set of tools for profiling memory allocations in the ClickHouse SQL parser using jemalloc’s heap profiling capabilities. #94072 (Ilya Yatsishin).
- Added a tool that simplifies debugging of memory allocations in parser. It uses jemalloc
stats.allocatedmetric before and after we parse query to AST representation to show what is allocated. Also it supports memory profiling mode that dumps profile before and after to build reports where allocations occurred. #93523 (Ilya Yatsishin). - Remove transitive libc++ includes. #92523 (Raúl Marín).
- Make some sequential tests parallel: https://github.com/ClickHouse/ClickHouse/pull/93030/changes#diff-c3a73510dae653c9bbfa24300b32f5d6ec663fd4e72cc4a3d5daa6e4342915df. #93030 (Nikita Fomichev).
- Cleanup some build flags. #93679 (Raúl Marín).
- Bump c-ares from v1.34.5 to v1.34.6. This addresses c-ares’
CVE-2025-62408, which is not relevant for ClickHouse. #94129 (Govind R Nair). - Use
curl8.18.0. #94742 (Konstantin Bogdanov).