Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
db372c1
Backport #101798 to 25.8: Prevent server termination when unregisteri…
robot-clickhouse Apr 10, 2026
0e25e81
Backport #102384 to 25.8: Coalescing merge tree fix array
robot-clickhouse Apr 11, 2026
c14a192
Fix very weird issue
alesapin Sep 24, 2025
8cc0fb1
Backport #103552 to 25.8: Fix masking nested credentials in logs
robot-clickhouse Apr 30, 2026
aedd933
Backport #103773 to 25.8: Fix UB while parsing dateTime
robot-clickhouse Apr 30, 2026
ac95f6f
Backport #100758 to 25.8: Erase sorted_dynamic_paths entries before d…
robot-clickhouse May 4, 2026
e72c1c3
Update autogenerated version to 25.8.23.13 and contributors
robot-clickhouse May 4, 2026
4cea897
Backport #104047 to 25.8: Bump libarchive form 3.8.6 to 3.8.7
robot-clickhouse May 5, 2026
12622ab
Merge pull request #104104 from ClickHouse/backport/25.8/104047
rschu1ze May 5, 2026
e27c3d4
Backport #102921 to 25.8: Disable trivial LIMIT optimization with row…
robot-clickhouse May 5, 2026
64d8b8e
Backport #104141 to 25.8: Fix write out of bounds in quantileTiming d…
robot-clickhouse May 6, 2026
1432515
Fix reference
azat May 6, 2026
a438525
Backport #102961 to 25.8: Use max_insert_threads for plain INSERTs wi…
robot-clickhouse May 6, 2026
37e92a0
Update tests/queries/0_stateless/04201_trivial_count_with_additional_…
azat May 6, 2026
1c59144
Merge pull request #104148 from ClickHouse/backport/25.8/102921
azat May 6, 2026
7af0faf
Backport #104063 to 25.8: Bypass index uncompressed cache when its si…
robot-ch-test-poll3 May 7, 2026
c059e14
Merge pull request #104210 from ClickHouse/backport/25.8/102961
antonio2368 May 7, 2026
942ead5
Merge branch '25.8' of github.com:ClickHouse/ClickHouse into backport…
Slach May 7, 2026
393f47f
Merge pull request #103542 from Slach/backport-checksum-fix-to-25.8
alexey-milovidov May 7, 2026
677f8d8
Merge pull request #104189 from ClickHouse/backport/25.8/104141
alexey-milovidov May 7, 2026
f05c134
Backport fix for IPv6StringToNumOrDefault to 25.8
Avogar May 11, 2026
1896d6b
Backport #103277 to 25.8: Fix data race in dictionaries
robot-clickhouse May 11, 2026
eb558ec
Merge pull request #103793 from ClickHouse/backport/25.8/103773
fm4v May 12, 2026
7f5666c
Update gtest_column_object.cpp
Avogar May 12, 2026
3991b41
Merge pull request #104577 from Avogar/backport/25.8/93543
Avogar May 12, 2026
1acc89f
Backport #104322 to 25.8: fixing a possible underflow while parsing p…
robot-clickhouse May 13, 2026
4cea51f
Backport #98460 to 25.8: Fix null pointer dereference in dictGetOrDef…
robot-clickhouse May 13, 2026
565a588
Backport #104751 to 25.8: Fix use-after-free in `AvroConfluentRowInpu…
robot-clickhouse May 13, 2026
372f102
Merge pull request #102430 from ClickHouse/backport/25.8/101798
fm4v May 13, 2026
d7d4adc
Merge pull request #102447 from ClickHouse/backport/25.8/102384
fm4v May 13, 2026
feccefc
Merge pull request #103752 from ClickHouse/backport/25.8/103552
fm4v May 13, 2026
e15bfd7
removing unrelated tests that got accidentally dragged in during merge
grantholly-clickhouse May 13, 2026
cd7a0a5
Merge pull request #104613 from ClickHouse/backport/25.8/103277
fm4v May 14, 2026
768e0ac
Merge pull request #104842 from ClickHouse/backport/25.8/104751
mstetsyuk May 14, 2026
f73bb43
Backport #104673 to 25.8: Fix data race in FutureSetFromTuple
robot-clickhouse May 14, 2026
e4089b9
updating reference files
grantholly-clickhouse May 14, 2026
a6fcfe0
Merge pull request #104775 from ClickHouse/backport/25.8/104322
grantholly-clickhouse May 15, 2026
c4a3d15
Merge pull request #104953 from ClickHouse/backport/25.8/104673
mstetsyuk May 15, 2026
1a9cf6a
Backport #103890 to 25.8: Fix use-after-free in KeeperHandlingConsume…
robot-clickhouse May 15, 2026
7f17941
Merge pull request #105077 from ClickHouse/backport/25.8/103890
antaljanosbenjamin May 15, 2026
5bb75ee
Merge pull request #104797 from ClickHouse/backport/25.8/98460
mstetsyuk May 18, 2026
221d172
Backport #104663 to 25.8: Fix Keeper termination on get `/keeper/avai…
robot-clickhouse May 18, 2026
be0cc8f
Backport #103536 to 25.8: Fix heap-use-after-free in `executeAggregat…
robot-ch-test-poll4 May 19, 2026
33dcce4
Merge pull request #105234 from ClickHouse/backport/25.8/104663
antonio2368 May 19, 2026
497e61c
Merge pull request #104022 from ClickHouse/backport/25.8/100758
Avogar May 19, 2026
1b88742
Merge tag 'v25.8.24.21-lts' into bump/stable-25.8/25.8.24
zvonand May 20, 2026
62e05a6
Backport #104296 to 25.8: Disable additional_table_filters with paral…
robot-clickhouse May 20, 2026
f5cfc69
Revert "Fix reference"
zvonand May 22, 2026
2da7a6b
Adapt 04207_pr_additional_filters for 25.8
zvonand May 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cmake/autogenerated_versions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

# NOTE: VERSION_REVISION has nothing common with DBMS_TCP_PROTOCOL_VERSION,
# only DBMS_TCP_PROTOCOL_VERSION should be incremented on protocol changes.
SET(VERSION_REVISION 54523)
SET(VERSION_REVISION 54524)
SET(VERSION_MAJOR 25)
SET(VERSION_MINOR 8)
SET(VERSION_PATCH 23)
SET(VERSION_GITHASH 6d29497525664acca46a1d1cd0d5787e9ad0857d)
SET(VERSION_DESCRIBE v25.8.23.10001.altinitytest)
SET(VERSION_STRING 25.8.23.10001.altinitytest)
SET(VERSION_PATCH 24)
SET(VERSION_GITHASH 443620d152ed64184d6f221c988c569334311055)
SET(VERSION_DESCRIBE v25.8.24.10001.altinitytest)
SET(VERSION_STRING 25.8.24.10001.altinitytest)
# end of autochange

SET(VERSION_TWEAK 10001)
Expand Down
2 changes: 1 addition & 1 deletion contrib/libarchive
Submodule libarchive updated 77 files
+1 −0 CMakeLists.txt
+8 −3 Makefile.am
+2 −0 NEWS
+6 −3 README.md
+3 −0 build/cmake/config.h.in
+1 −1 build/version
+2 −2 configure.ac
+1 −0 contrib/android/Android.mk
+2 −2 contrib/untar.c
+2 −0 cpio/CMakeLists.txt
+11 −4 cpio/cmdline.c
+67 −56 cpio/cpio.c
+0 −2 cpio/cpio.h
+2 −2 libarchive/archive.h
+2 −2 libarchive/archive_check_magic.c
+1 −1 libarchive/archive_entry.h
+3 −1 libarchive/archive_options.c
+2 −2 libarchive/archive_pathmatch.c
+11 −11 libarchive/archive_ppmd8.c
+0 −25 libarchive/archive_ppmd8_private.h
+6 −6 libarchive/archive_read.c
+4 −0 libarchive/archive_read_append_filter.c
+3 −3 libarchive/archive_read_disk_posix.c
+3 −3 libarchive/archive_read_disk_windows.c
+1 −1 libarchive/archive_read_support_filter_grzip.c
+2 −2 libarchive/archive_read_support_filter_lz4.c
+1 −1 libarchive/archive_read_support_filter_lzop.c
+5 −5 libarchive/archive_read_support_format_7zip.c
+15 −5 libarchive/archive_read_support_format_cab.c
+2 −2 libarchive/archive_read_support_format_cpio.c
+17 −9 libarchive/archive_read_support_format_iso9660.c
+2 −2 libarchive/archive_read_support_format_lha.c
+40 −33 libarchive/archive_read_support_format_rar.c
+9 −9 libarchive/archive_read_support_format_rar5.c
+3 −3 libarchive/archive_read_support_format_tar.c
+7 −7 libarchive/archive_read_support_format_xar.c
+11 −11 libarchive/archive_read_support_format_zip.c
+1 −1 libarchive/archive_string.c
+1 −1 libarchive/archive_write.c
+19 −3 libarchive/archive_write_add_filter_b64encode.c
+5 −2 libarchive/archive_write_add_filter_bzip2.c
+9 −3 libarchive/archive_write_add_filter_gzip.c
+15 −6 libarchive/archive_write_add_filter_lrzip.c
+10 −4 libarchive/archive_write_add_filter_lz4.c
+5 −2 libarchive/archive_write_add_filter_lzop.c
+19 −3 libarchive/archive_write_add_filter_uuencode.c
+20 −7 libarchive/archive_write_add_filter_xz.c
+38 −14 libarchive/archive_write_add_filter_zstd.c
+4 −4 libarchive/archive_write_disk_posix.c
+1 −1 libarchive/archive_write_disk_windows.c
+7 −2 libarchive/archive_write_set_format_7zip.c
+2 −2 libarchive/archive_write_set_format_cpio_binary.c
+1 −1 libarchive/archive_write_set_format_cpio_newc.c
+1 −1 libarchive/archive_write_set_format_cpio_odc.c
+9 −9 libarchive/archive_write_set_format_iso9660.c
+1 −1 libarchive/archive_write_set_format_mtree.c
+3 −3 libarchive/archive_write_set_format_pax.c
+4 −2 libarchive/archive_write_set_format_xar.c
+8 −5 libarchive/archive_write_set_format_zip.c
+3 −0 libarchive/test/CMakeLists.txt
+18 −0 libarchive/test/test_archive_pathmatch.c
+45 −0 libarchive/test/test_read_format_cab_lzx_oob.c
+11 −0 libarchive/test/test_read_format_cab_lzx_oob.cab.uu
+41 −0 libarchive/test/test_read_format_cab_skip_malformed.c
+95 −0 libarchive/test/test_read_format_cab_skip_malformed.cab.uu
+104 −0 libarchive/test/test_read_format_iso_zisofs_overflow.c
+1,096 −0 libarchive/test/test_read_format_iso_zisofs_overflow.iso.uu
+34 −0 libarchive/test/test_read_set_format.c
+1 −1 libarchive/test/test_warn_missing_hardlink_target.c
+8 −3 libarchive_fe/lafe_getline.c
+11 −4 libarchive_fe/lafe_getline.h
+10 −10 tar/bsdtar.c
+1 −1 tar/read.c
+4 −4 tar/util.c
+8 −8 tar/write.c
+2 −2 unzip/CMakeLists.txt
+1 −1 unzip/bsdunzip.c
3 changes: 3 additions & 0 deletions contrib/libarchive-cmake/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,9 @@ typedef uint64_t uintmax_t;
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1

/* Define to 1 if you have the <stdio.h> header file. */
#define HAVE_STDIO_H 1

/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1

Expand Down
2 changes: 2 additions & 0 deletions src/AggregateFunctions/QuantileTiming.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ namespace detail
readBinaryLittleEndian(index, buf);
if (index == BIG_THRESHOLD)
break;
if (index - SMALL_THRESHOLD >= BIG_SIZE)
throw Exception(ErrorCodes::INCORRECT_DATA, "Incorrect index {} in 'large' kind of quantileTiming deserialization", index);

UInt64 elem_count = 0;
readBinaryLittleEndian(elem_count, buf);
Expand Down
2 changes: 2 additions & 0 deletions src/Columns/ColumnObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ bool ColumnObject::tryInsert(const Field & x)
for (const auto & path : new_dynamic_paths)
{
dynamic_paths_ptrs.erase(path);
sorted_dynamic_paths.erase(path);
dynamic_paths.erase(path);
}

Expand Down Expand Up @@ -566,6 +567,7 @@ bool ColumnObject::tryInsert(const Field & x)
}
else if (auto * dynamic_path_column = tryToAddNewDynamicPath(path))
{
new_dynamic_paths.insert(String(path));
if (!dynamic_path_column->tryInsert(value_field))
{
restore_sizes();
Expand Down
47 changes: 47 additions & 0 deletions src/Columns/tests/gtest_column_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,3 +444,50 @@ TEST(ColumnObject, RepairDuplicatesInDynamicPathsAndSharedData)
ASSERT_EQ((*column_object)[2], (Object{{"b", Field(1u)}, {"c", Field(1u)}, {"d", Field(1u)}}));
ASSERT_EQ((*column_object)[3], (Object{{"d", Field(1u)}}));
}

TEST(ColumnObject, TryInsertRestoresSortedDynamicPaths)
{
/// "b" is a typed UInt32 path; everything else becomes a dynamic path.
auto type = DataTypeFactory::instance().get("JSON(max_dynamic_types=10, max_dynamic_paths=10, b UInt32)");
auto col = type->createColumn();
auto & col_object = assert_cast<ColumnObject &>(*col);
const auto & dynamic_paths = col_object.getDynamicPaths();

/// One valid row so we have something to serialize later.
col_object.insert(Object{{"b", Field{5u}}});
ASSERT_EQ(col_object.size(), 1u);
ASSERT_EQ(dynamic_paths.size(), 0u);

/// tryInsert with Object{"a_new": 1, "b": "not_a_number"}.
/// Fields are processed in alphabetical order ("a_new" before "b"), so:
/// 1. "a_new" is new → tryToAddNewDynamicPath succeeds, "a_new" is added to all
/// three structures including sorted_dynamic_paths.
/// 2. ColumnDynamic::tryInsert(1u) for "a_new" succeeds.
/// 3. ColumnUInt32::tryInsert(String) for "b" returns false.
/// 4. restore_sizes() is called.
/// BUG 1: new_dynamic_paths was never populated, so the loop that removes
/// newly-added paths is a no-op — "a_new" is left in dynamic_paths,
/// dynamic_paths_ptrs, and sorted_dynamic_paths with a rolled-back size.
/// BUG 2: even after populating new_dynamic_paths, the old code erased from
/// dynamic_paths before sorted_dynamic_paths, leaving a dangling view.
/// FIX: record the path in new_dynamic_paths immediately after
/// tryToAddNewDynamicPath succeeds, and erase sorted_dynamic_paths
/// before dynamic_paths.
bool result = col_object.tryInsert(Object{{"a_new", Field{1u}}, {"b", Field{String("not_a_number")}}});
ASSERT_FALSE(result);

ASSERT_EQ(col_object.size(), 1u);
ASSERT_EQ(dynamic_paths.size(), 0u); /// "a_new" must be fully rolled back

/// serializeValueIntoArena iterates sorted_dynamic_paths.
/// Without the fix the stale "a_new" entry causes undefined behavior here (see comment above).
Arena arena;
const char * begin = nullptr;
auto ref = col_object.serializeValueIntoArena(0, arena, begin, nullptr);

/// Round-trip sanity check.
ReadBufferFromMemory buf(ref.data, ref.size);
col_object.deserializeAndInsertFromArena(buf, nullptr);
ASSERT_EQ(col_object.size(), 2u);
ASSERT_EQ(col_object[1], col_object[0]);
}
3 changes: 1 addition & 2 deletions src/Coordination/KeeperStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1789,8 +1789,7 @@ std::list<KeeperStorageBase::Delta> preprocess(
ProfileEvents::increment(ProfileEvents::KeeperGetRequest);

if (zk_request.path == Coordination::keeper_api_feature_flags_path
|| zk_request.path == Coordination::keeper_config_path
|| zk_request.path == Coordination::keeper_availability_zone_path)
|| zk_request.path == Coordination::keeper_config_path)
return {};

if (!storage.uncommitted_state.getNode(zk_request.path))
Expand Down
3 changes: 3 additions & 0 deletions src/Core/PostgreSQL/insertPostgreSQLValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ void insertPostgreSQLValue(
{
max_dimension = std::max(max_dimension, dimension);

if (dimension == 0)
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unexpected array closing bracket");

--dimension;
if (dimension == 0)
break;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/ServerSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ void ServerSettings::dumpToSystemServerSettingsColumns(ServerSettingColumnsParam
{"mark_cache_size", {std::to_string(context->getMarkCache()->maxSizeInBytes()), ChangeableWithoutRestart::Yes}},
{"uncompressed_cache_size", {std::to_string(context->getUncompressedCache()->maxSizeInBytes()), ChangeableWithoutRestart::Yes}},
{"index_mark_cache_size", {std::to_string(context->getIndexMarkCache()->maxSizeInBytes()), ChangeableWithoutRestart::Yes}},
{"index_uncompressed_cache_size", {std::to_string(context->getIndexUncompressedCache()->maxSizeInBytes()), ChangeableWithoutRestart::Yes}},
{"index_uncompressed_cache_size", {std::to_string(context->getIndexUncompressedCache(/*only_if_enabled=*/ false)->maxSizeInBytes()), ChangeableWithoutRestart::Yes}},
{"mmap_cache_size", {std::to_string(context->getMMappedFileCache()->maxSizeInBytes()), ChangeableWithoutRestart::Yes}},
{"query_condition_cache_size", {std::to_string(context->getQueryConditionCache()->maxSizeInBytes()), ChangeableWithoutRestart::Yes}},

Expand Down
96 changes: 96 additions & 0 deletions src/Core/tests/gtest_insertPostgreSQLValue.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "config.h"

#if USE_LIBPQXX

#include <gtest/gtest.h>

#include <Core/PostgreSQL/insertPostgreSQLValue.h>
#include <Core/ExternalResultDescription.h>
#include <Columns/ColumnArray.h>
#include <Columns/ColumnsNumber.h>
#include <DataTypes/DataTypeArray.h>
#include <DataTypes/DataTypesNumber.h>


using namespace DB;

namespace DB::ErrorCodes
{
extern const int BAD_ARGUMENTS;
}

/// Regression test for dimension underflow in PostgreSQL array parser.
/// When pqxx::array_parser emits row_end before any row_start (e.g. malformed
/// input starting with '}'), the dimension counter must not underflow from 0.
/// See https://github.com/ClickHouse/clickhouse-core-incidents/issues/1693

TEST(InsertPostgreSQLValue, MalformedArrayClosingBracketThrows)
{
auto nested_type = std::make_shared<DataTypeInt32>();
auto array_type = std::make_shared<DataTypeArray>(nested_type);
auto column = ColumnArray::create(ColumnInt32::create());

std::unordered_map<size_t, PostgreSQLArrayInfo> array_info;
preparePostgreSQLArrayInfo(array_info, 0, array_type);

/// Input "}" causes row_end at dimension 0 — must throw BAD_ARGUMENTS,
/// not underflow size_t to SIZE_MAX and crash.
try
{
insertPostgreSQLValue(
*column, "}",
ExternalResultDescription::ValueType::vtArray,
array_type, array_info, 0);
FAIL() << "Expected BAD_ARGUMENTS exception for malformed array '}'";
}
catch (const Exception & e)
{
EXPECT_EQ(e.code(), ErrorCodes::BAD_ARGUMENTS);
}
}

TEST(InsertPostgreSQLValue, MalformedArrayClosingThenOpeningThrows)
{
auto nested_type = std::make_shared<DataTypeInt32>();
auto array_type = std::make_shared<DataTypeArray>(nested_type);
auto column = ColumnArray::create(ColumnInt32::create());

std::unordered_map<size_t, PostgreSQLArrayInfo> array_info;
preparePostgreSQLArrayInfo(array_info, 0, array_type);

/// Input "}{" also starts with row_end at dimension 0.
try
{
insertPostgreSQLValue(
*column, "}{",
ExternalResultDescription::ValueType::vtArray,
array_type, array_info, 0);
FAIL() << "Expected BAD_ARGUMENTS exception for malformed array '}{'" ;
}
catch (const Exception & e)
{
EXPECT_EQ(e.code(), ErrorCodes::BAD_ARGUMENTS);
}
}

TEST(InsertPostgreSQLValue, WellFormedArraySucceeds)
{
auto nested_type = std::make_shared<DataTypeInt32>();
auto array_type = std::make_shared<DataTypeArray>(nested_type);
auto column = ColumnArray::create(ColumnInt32::create());

std::unordered_map<size_t, PostgreSQLArrayInfo> array_info;
preparePostgreSQLArrayInfo(array_info, 0, array_type);

/// Well-formed "{1,2,3}" must succeed without exceptions.
EXPECT_NO_THROW(
insertPostgreSQLValue(
*column, "{1,2,3}",
ExternalResultDescription::ValueType::vtArray,
array_type, array_info, 0));

/// Verify the column now has one row with 3 elements.
ASSERT_EQ(column->size(), 1u);
}

#endif
6 changes: 2 additions & 4 deletions src/Dictionaries/ClickHouseDictionarySource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,8 @@ bool ClickHouseDictionarySource::isModified() const
if (!configuration.invalidate_query.empty())
{
auto response = doInvalidateQuery(configuration.invalidate_query);
LOG_TRACE(log, "Invalidate query has returned: {}, previous value: {}", response, invalidate_query_response);
if (invalidate_query_response == response)
return false;
invalidate_query_response = response;
LOG_TRACE(log, "Invalidate query has returned: {}", response);
return invalidate_query_response.updateAndCheckModified(response);
}
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Dictionaries/ClickHouseDictionarySource.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Dictionaries/DictionaryStructure.h>
#include <Dictionaries/ExternalQueryBuilder.h>
#include <Dictionaries/IDictionarySource.h>
#include <Dictionaries/InvalidateQueryResponse.h>


namespace DB
Expand Down Expand Up @@ -81,7 +82,7 @@ class ClickHouseDictionarySource final : public IDictionarySource
std::chrono::time_point<std::chrono::system_clock> update_time;
const DictionaryStructure dict_struct;
const Configuration configuration;
mutable std::string invalidate_query_response;
mutable InvalidateQueryResponse invalidate_query_response;
ExternalQueryBuilderPtr query_builder;
Block sample_block;
ContextMutablePtr context;
Expand Down
21 changes: 21 additions & 0 deletions src/Dictionaries/InvalidateQueryResponse.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <Dictionaries/InvalidateQueryResponse.h>

namespace DB
{

InvalidateQueryResponse::InvalidateQueryResponse(const InvalidateQueryResponse & other)
{
std::lock_guard lock(other.mutex);
response = other.response;
}

bool InvalidateQueryResponse::updateAndCheckModified(const std::string & new_response)
{
std::lock_guard lock(mutex);
if (response == new_response)
return false;
response = new_response;
return true;
}

}
24 changes: 24 additions & 0 deletions src/Dictionaries/InvalidateQueryResponse.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <mutex>
#include <string>

namespace DB
{

/// Thread-safe holder for the last value returned by a dictionary source's invalidate query.
class InvalidateQueryResponse
{
public:
InvalidateQueryResponse() = default;
InvalidateQueryResponse(const InvalidateQueryResponse & other);
InvalidateQueryResponse & operator=(const InvalidateQueryResponse &) = delete;

bool updateAndCheckModified(const std::string & new_response);

private:
mutable std::mutex mutex;
std::string response;
};

}
6 changes: 1 addition & 5 deletions src/Dictionaries/MySQLDictionarySource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,7 @@ bool MySQLDictionarySource::isModified() const
{
LOG_TRACE(log, "Executing invalidate query: {}", configuration.invalidate_query);
auto response = doInvalidateQuery(configuration.invalidate_query);
if (response == invalidate_query_response)
return false;

invalidate_query_response = response;
return true;
return invalidate_query_response.updateAndCheckModified(response);
}

return true;
Expand Down
3 changes: 2 additions & 1 deletion src/Dictionaries/MySQLDictionarySource.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# include <Dictionaries/DictionaryStructure.h>
# include <Dictionaries/ExternalQueryBuilder.h>
# include <Dictionaries/IDictionarySource.h>
# include <Dictionaries/InvalidateQueryResponse.h>
# include <Processors/Sources/MySQLSource.h>

namespace Poco
Expand Down Expand Up @@ -89,7 +90,7 @@ class MySQLDictionarySource final : public IDictionarySource
Block sample_block;
ExternalQueryBuilder query_builder;
const std::string load_all_query;
mutable std::string invalidate_query_response;
mutable InvalidateQueryResponse invalidate_query_response;
const StreamSettings settings;
};

Expand Down
4 changes: 1 addition & 3 deletions src/Dictionaries/PostgreSQLDictionarySource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,7 @@ bool PostgreSQLDictionarySource::isModified() const
if (!configuration.invalidate_query.empty())
{
auto response = doInvalidateQuery(configuration.invalidate_query);
if (response == invalidate_query_response)
return false;
invalidate_query_response = response;
return invalidate_query_response.updateAndCheckModified(response);
}
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Dictionaries/PostgreSQLDictionarySource.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "config.h"
#include <Dictionaries/DictionaryStructure.h>
#include <Dictionaries/IDictionarySource.h>
#include <Dictionaries/InvalidateQueryResponse.h>

#if USE_LIBPQXX
#include <Dictionaries/ExternalQueryBuilder.h>
Expand Down Expand Up @@ -65,7 +66,7 @@ class PostgreSQLDictionarySource final : public IDictionarySource
ExternalQueryBuilder query_builder;
const std::string load_all_query;
std::chrono::time_point<std::chrono::system_clock> update_time;
mutable std::string invalidate_query_response;
mutable InvalidateQueryResponse invalidate_query_response;

};

Expand Down
4 changes: 1 addition & 3 deletions src/Dictionaries/XDBCDictionarySource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,7 @@ bool XDBCDictionarySource::isModified() const
if (!configuration.invalidate_query.empty())
{
auto response = doInvalidateQuery(configuration.invalidate_query);
if (invalidate_query_response == response)
return false;
invalidate_query_response = response;
return invalidate_query_response.updateAndCheckModified(response);
}
return true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Dictionaries/XDBCDictionarySource.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <Dictionaries/DictionaryStructure.h>
#include <Dictionaries/ExternalQueryBuilder.h>
#include <Dictionaries/IDictionarySource.h>
#include <Dictionaries/InvalidateQueryResponse.h>


namespace Poco
Expand Down Expand Up @@ -83,7 +84,7 @@ class XDBCDictionarySource final : public IDictionarySource, WithContext
Block sample_block;
ExternalQueryBuilder query_builder;
const std::string load_all_query;
mutable std::string invalidate_query_response;
mutable InvalidateQueryResponse invalidate_query_response;

BridgeHelperPtr bridge_helper;
Poco::URI bridge_url;
Expand Down
Loading
Loading