Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 22 additions & 4 deletions src/Common/ClickHouseVersion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,37 @@ ClickHouseVersion::ClickHouseVersion(std::string_view version)
if (split.empty())
throw Exception{ErrorCodes::BAD_ARGUMENTS, "Cannot parse ClickHouse version here: {}", version};

for (const auto & split_element : split)
for (size_t i = 0; i < split.size(); ++i)
{
size_t component;
ReadBufferFromString buf(split_element);
ReadBufferFromString buf(split[i]);
if (!tryReadIntText(component, buf) || !buf.eof())
throw Exception{ErrorCodes::BAD_ARGUMENTS, "Cannot parse ClickHouse version here: {}", version};
{
/// A non-numeric part is only allowed as a non-empty terminal suffix after at least
/// one numeric component (e.g. "altinityantalya" in "26.1.3.20001.altinityantalya").
const bool is_terminal = (i + 1 == split.size());
if (components.empty() || !is_terminal || split[i].empty())
throw Exception{ErrorCodes::BAD_ARGUMENTS, "Cannot parse ClickHouse version here: {}", version};
suffix = split[i];
break;
}
components.push_back(component);
}
}

String ClickHouseVersion::toString() const
{
return fmt::format("{}", fmt::join(components, "."));
String result = fmt::format("{}", fmt::join(components, "."));
if (!suffix.empty())
result += "." + suffix;
return result;
}

std::strong_ordering ClickHouseVersion::operator<=>(const ClickHouseVersion & other) const
{
if (auto cmp = components <=> other.components; cmp != 0)
return cmp;
return suffix <=> other.suffix;
}

}
5 changes: 4 additions & 1 deletion src/Common/ClickHouseVersion.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <compare>
#include <string>
#include <vector>
#include <string_view>

Expand All @@ -14,10 +15,12 @@ class ClickHouseVersion

std::string toString() const;

std::strong_ordering operator<=>(const ClickHouseVersion & other) const = default;
std::strong_ordering operator<=>(const ClickHouseVersion & other) const;

private:
std::vector<size_t> components;
/// Non-numeric suffix (e.g. "altinityantalya" for "26.1.3.20001.altinityantalya"); empty for standard versions
std::string suffix;
};

}
47 changes: 47 additions & 0 deletions src/Common/tests/gtest_clickhouse_version.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <Common/ClickHouseVersion.h>
#include <Common/Exception.h>

#include <gtest/gtest.h>

using namespace DB;

TEST(ClickHouseVersion, ParseNumeric)
{
EXPECT_EQ(ClickHouseVersion("26.4").toString(), "26.4");
EXPECT_EQ(ClickHouseVersion("18.12.17").toString(), "18.12.17");
EXPECT_EQ(ClickHouseVersion("26").toString(), "26");
EXPECT_EQ(ClickHouseVersion("26.1.3.20001").toString(), "26.1.3.20001");
}

TEST(ClickHouseVersion, ParseSuffixed)
{
/// A single terminal non-numeric suffix is allowed after numeric components.
EXPECT_EQ(ClickHouseVersion("26.1.3.20001.altinityantalya").toString(), "26.1.3.20001.altinityantalya");
EXPECT_EQ(ClickHouseVersion("25.8.16.20001.altinityantalya").toString(), "25.8.16.20001.altinityantalya");
}

TEST(ClickHouseVersion, RejectMalformed)
{
/// Empty component in the middle.
EXPECT_THROW(ClickHouseVersion("26..1"), Exception);
/// Trailing dot (empty terminal component).
EXPECT_THROW(ClickHouseVersion("26.1."), Exception);
/// Non-numeric component that is not the terminal one.
EXPECT_THROW(ClickHouseVersion("26.x.1"), Exception);
/// A suffix split by a dot is two non-numeric tokens, so the first is intermediate.
EXPECT_THROW(ClickHouseVersion("26.1.altinity.antalya"), Exception);
/// Leading dot (no numeric component before the suffix).
EXPECT_THROW(ClickHouseVersion(".1"), Exception);
/// No numeric component at all.
EXPECT_THROW(ClickHouseVersion("altinityantalya"), Exception);
EXPECT_THROW(ClickHouseVersion(""), Exception);
}

TEST(ClickHouseVersion, Ordering)
{
EXPECT_LT(ClickHouseVersion("26.3"), ClickHouseVersion("26.4"));
EXPECT_GT(ClickHouseVersion("26.4"), ClickHouseVersion("26.3"));
EXPECT_TRUE((ClickHouseVersion("26.4") <=> ClickHouseVersion("26.4")) == std::strong_ordering::equal);
/// A pure numeric version sorts before its suffixed sibling (empty suffix < non-empty suffix).
EXPECT_LT(ClickHouseVersion("26.1.3.20001"), ClickHouseVersion("26.1.3.20001.altinityantalya"));
}
44 changes: 44 additions & 0 deletions src/Core/SettingsChangesHistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ const VersionToSettingsChangesMap & getSettingsChangesHistory()
{"variant_throw_on_type_mismatch", true, true, "New setting to control type mismatch behavior in default Variant implementation"},
{"dynamic_throw_on_type_mismatch", true, true, "New setting to control type mismatch behavior in default Dynamic implementation"},
});
addSettingsChanges(settings_changes_history, "26.3.10.20001.altinityantalya",
{
// {"export_merge_tree_partition_task_timeout_seconds", "3600", "86400", "Increase default value to make it more realistic"},
});
addSettingsChanges(settings_changes_history, "26.3",
{
{"defer_partition_pruning_after_final", false, true, "Gates the FINAL planner's unconditional skipping of partition pruning when the partition-key column is not in the sorting key. The behavior change itself shipped silently in 26.3 via https://github.com/ClickHouse/ClickHouse/pull/98242; this entry retroactively documents it so `compatibility = '26.2'` restores the pre-regression behavior (0 = prune before FINAL, fast; 1 = defer pruning, correctness-safe)."},
Expand Down Expand Up @@ -218,6 +222,13 @@ const VersionToSettingsChangesMap & getSettingsChangesHistory()
{"opentelemetry_start_keeper_trace_probability", "auto", "auto", "New setting"},
{"functions_h3_default_if_invalid", true, false, "A new setting for legacy behaviour to allow invalid inputs to h3 functions"},
});
addSettingsChanges(settings_changes_history, "26.1.3.20001.altinityantalya",
{
// {"iceberg_partition_timezone", "", "", "New setting."},
// {"s3_propagate_credentials_to_other_storages", false, false, "New setting"},
// {"export_merge_tree_part_filename_pattern", "", "{part_name}_{checksum}", "New setting"},
// {"input_format_parquet_use_metadata_cache", true, false, "Obsolete. No-op"}, // https://github.com/Altinity/ClickHouse/pull/586
});
addSettingsChanges(settings_changes_history, "26.1",
{
{"use_statistics", true, true, "Enable this optimization by default."},
Expand Down Expand Up @@ -398,6 +409,39 @@ const VersionToSettingsChangesMap & getSettingsChangesHistory()
{"os_threads_nice_value_materialized_view", 0, 0, "New setting."},
{"os_thread_priority", 0, 0, "Alias for os_threads_nice_value_query."},
});
addSettingsChanges(settings_changes_history, "25.8.16.20001.altinityantalya",
{
// {"allow_experimental_database_iceberg", false, true, "Turned ON by default for Antalya."},
// {"allow_experimental_database_unity_catalog", false, true, "Turned ON by default for Antalya."},
// {"allow_experimental_database_glue_catalog", false, true, "Turned ON by default for Antalya."},
// {"allow_database_iceberg", false, true, "Turned ON by default for Antalya (alias)."},
// {"allow_database_unity_catalog", false, true, "Turned ON by default for Antalya (alias)."},
// {"allow_database_glue_catalog", false, true, "Turned ON by default for Antalya (alias)."},
// {"input_format_parquet_use_metadata_cache", true, true, "New setting, turned ON by default"}, // https://github.com/Altinity/ClickHouse/pull/586
// {"iceberg_timezone_for_timestamptz", "UTC", "UTC", "New setting."},
// {"object_storage_remote_initiator", false, false, "New setting."},
// {"allow_experimental_iceberg_read_optimization", true, true, "New setting."},
// {"object_storage_cluster_join_mode", "allow", "allow", "New setting"},
// {"lock_object_storage_task_distribution_ms", 500, 500, "New setting."},
// {"allow_retries_in_cluster_requests", false, false, "New setting"},
// {"allow_experimental_export_merge_tree_part", false, true, "Turned ON by default for Antalya."},
// {"export_merge_tree_part_overwrite_file_if_exists", false, false, "New setting."},
// {"export_merge_tree_partition_force_export", false, false, "New setting."},
// {"export_merge_tree_partition_max_retries", 3, 3, "New setting."},
// {"export_merge_tree_partition_manifest_ttl", 180, 180, "New setting."},
// {"export_merge_tree_part_file_already_exists_policy", "skip", "skip", "New setting."},
// {"hybrid_table_auto_cast_columns", true, true, "New setting to automatically cast Hybrid table columns when segments disagree on types. Default enabled."},
// {"allow_experimental_hybrid_table", false, false, "Added new setting to allow the Hybrid table engine."},
// {"enable_alias_marker", true, true, "New setting."},
// {"export_merge_tree_part_max_bytes_per_file", 0, 0, "New setting."},
// {"export_merge_tree_part_max_rows_per_file", 0, 0, "New setting."},
// {"export_merge_tree_partition_lock_inside_the_task", false, false, "New setting."},
// {"export_merge_tree_partition_system_table_prefer_remote_information", true, true, "New setting."},
// {"export_merge_tree_part_throw_on_pending_mutations", true, true, "New setting."},
// {"export_merge_tree_part_throw_on_pending_patch_parts", true, true, "New setting."},
// {"object_storage_cluster", "", "", "Antalya: New setting"},
// {"object_storage_max_nodes", 0, 0, "Antalya: New setting"},
});
addSettingsChanges(settings_changes_history, "25.8",
{
{"output_format_json_quote_64bit_integers", true, false, "Disable quoting of the 64 bit integers in JSON by default"},
Expand Down
45 changes: 41 additions & 4 deletions tests/queries/0_stateless/02995_new_settings_history.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,23 @@ fi
# Baselines generated with v26.4.1 (pre-release)
# clickhouse local --query "select name, default from system.settings order by name format TSV" > 02995_settings_26_4_1.tsv
# clickhouse local --query "select name, value from system.merge_tree_settings order by name format TSV" > 02995_merge_tree_settings_settings_26_4_1.tsv
# Previous Antalya release baseline: 26.3.10.20001.altinityantalya (same format as 02995_settings_26_3_1.tsv).
# Settings listed there are considered known; keep empty or generate from previous Antalya build.

# To generate the previous Antalya release baseline:
# docker run --rm --entrypoint clickhouse <antalya_docker_image> \
# local -q "select name, default from system.settings order by name format TSV" \
# > 02995_settings_26_3_10_20001_antalya.tsv

$CLICKHOUSE_LOCAL --query "
WITH old_settings AS
(
SELECT * FROM file('${CUR_DIR}/02995_settings_26_4_1.tsv', 'TSV', 'name String, default String')
),
old_antalya_settings AS
(
SELECT * FROM file('${CUR_DIR}/02995_settings_26_3_10_20001_antalya.tsv', 'TSV', 'name String, default String')
),
old_merge_tree_settings AS
(
SELECT * FROM file('${CUR_DIR}/02995_merge_tree_settings_settings_26_4_1.tsv', 'TSV', 'name String, default String')
Expand All @@ -52,7 +64,7 @@ $CLICKHOUSE_LOCAL --query "
)) AND (name NOT IN (
SELECT arrayJoin(tupleElement(changes, 'name'))
FROM system.settings_changes
WHERE type = 'Session' AND splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4)
WHERE type = 'Session' AND (splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4) OR position(version, 'altinityantalya') > 0)
))
UNION ALL
(
Expand All @@ -64,7 +76,7 @@ $CLICKHOUSE_LOCAL --query "
)) AND (name NOT IN (
SELECT arrayJoin(tupleElement(changes, 'name'))
FROM system.settings_changes
WHERE type = 'MergeTree' AND splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4)
WHERE type = 'MergeTree' AND (splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4) OR position(version, 'altinityantalya') > 0)
))
)
UNION ALL
Expand All @@ -75,7 +87,7 @@ $CLICKHOUSE_LOCAL --query "
WHERE (new_settings.default != old_settings.default) AND (name NOT IN (
SELECT arrayJoin(tupleElement(changes, 'name'))
FROM system.settings_changes
WHERE type = 'Session' AND splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4)
WHERE type = 'Session' AND (splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4) OR position(version, 'altinityantalya') > 0)
)) AND ${IGNORE_SETTINGS_FOR_SANITIZERS}
)
UNION ALL
Expand All @@ -86,8 +98,33 @@ $CLICKHOUSE_LOCAL --query "
WHERE (new_merge_tree_settings.default != old_merge_tree_settings.default) AND (name NOT IN (
SELECT arrayJoin(tupleElement(changes, 'name'))
FROM system.settings_changes
WHERE type = 'MergeTree' AND splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4)
WHERE type = 'MergeTree' AND (splitByChar('.', version)[1]::UInt64 > 26 OR (splitByChar('.', version)[1]::UInt64 == 26 AND splitByChar('.', version)[2]::UInt64 > 4) OR position(version, 'altinityantalya') > 0)
)) AND ${IGNORED_MERGETREE_SETTINGS_FOR_CLOUD}
)
UNION ALL
(
SELECT 'PLEASE ADD THE NEW SETTING TO SettingsChangesHistory.cpp (Antalya): ' || name || ' WAS ADDED'
FROM new_settings
WHERE (name NOT IN (SELECT name FROM old_antalya_settings))
AND (name NOT IN (
SELECT arrayJoin(tupleElement(changes, 'name'))
FROM system.settings_changes
WHERE type = 'Session'
))
AND (SELECT count() FROM old_antalya_settings) > 0
)
UNION ALL
(
SELECT 'PLEASE ADD THE SETTING VALUE CHANGE TO SettingsChangesHistory.cpp (Antalya): ' || name || ' WAS CHANGED FROM ' || old_antalya_settings.default || ' TO ' || new_settings.default
FROM new_settings
JOIN old_antalya_settings ON new_settings.name = old_antalya_settings.name
WHERE (new_settings.default != old_antalya_settings.default)
AND (name NOT IN (
SELECT arrayJoin(tupleElement(changes, 'name'))
FROM system.settings_changes
WHERE type = 'Session'
))
AND ${IGNORE_SETTINGS_FOR_SANITIZERS}
)
)
"
Loading
Loading