Skip to content

Commit 946796e

Browse files
committed
Merge remote-tracking branch 'blessed/master' into dependabot/pip/docker/test/integration/base/setuptools-78.1.1
2 parents 1f3675c + 824a937 commit 946796e

File tree

130 files changed

+2974
-316
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+2974
-316
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
* Gives the possibility to truncate specific tables from a database, filtered with the `LIKE` keyword. [#78597](https://github.com/ClickHouse/ClickHouse/pull/78597) ([Yarik Briukhovetskyi](https://github.com/yariks5s)).
4242
* Support `_part_starting_offset` virtual column in `MergeTree`-family tables. This column represents the cumulative row count of all preceding parts, calculated at query time based on the current part list. The cumulative values are retained throughout query execution and remain effective even after part pruning. Related internal logic has been refactored to support this behavior. [#79417](https://github.com/ClickHouse/ClickHouse/pull/79417) ([Amos Bird](https://github.com/amosbird)).
4343
* Add functions `divideOrNull`,`moduloOrNull`, `intDivOrNull`,`positiveModuloOrNull` to return NULL when right argument is zero. [#78276](https://github.com/ClickHouse/ClickHouse/pull/78276) ([kevinyhzou](https://github.com/KevinyhZou)).
44-
* TODO: WTF is that? Explain it in a way your gradma will understand. Support for Iceberg partition pruning bucket transform. [#79262](https://github.com/ClickHouse/ClickHouse/pull/79262) ([Daniil Ivanik](https://github.com/divanik)).
44+
* Add [`icebergHash`](https://iceberg.apache.org/spec/#appendix-b-32-bit-hash-requirements) and [`icebergBucketTransform`](https://iceberg.apache.org/spec/#bucket-transform-details) functions. Support data files pruning in `Iceberg` tables partitioned with [`bucket transfom`](https://iceberg.apache.org/spec/#partitioning). [#79262](https://github.com/ClickHouse/ClickHouse/pull/79262) ([Daniil Ivanik](https://github.com/divanik)).
4545

4646
#### Experimental Feature
4747
* Hive metastore catalog for Iceberg datalake. [#77677](https://github.com/ClickHouse/ClickHouse/pull/77677) ([scanhex12](https://github.com/scanhex12)).

docs/en/operations/settings/constraints-on-settings.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ Constraints are defined as follows:
4646
<max>upper_boundary</max>
4747
<changeable_in_readonly/>
4848
</setting_name_5>
49+
<setting_name_6>
50+
<min>lower_boundary</min>
51+
<max>upper_boundary</max>
52+
<disallowed>value1</disallowed>
53+
<disallowed>value2</disallowed>
54+
<disallowed>value3</disallowed>
55+
<changeable_in_readonly/>
56+
</setting_name_6>
4957
</constraints>
5058
</user_name>
5159
</profiles>
@@ -59,12 +67,16 @@ setting remains unchanged.
5967
There are a few types of constraints supported in ClickHouse:
6068
- `min`
6169
- `max`
70+
- `disallowed`
6271
- `readonly` (with alias `const`)
6372
- `changeable_in_readonly`
6473

6574
The `min` and `max` constraints specify upper and lower boundaries for a numeric
6675
setting and can be used in combination with each other.
6776

77+
The `disallowed` constraint can be used to specify specific value(s) which should not
78+
be allowed for a specific setting.
79+
6880
The `readonly` or `const` constraint specifies that the user cannot change the
6981
corresponding setting at all.
7082

docs/en/sql-reference/table-functions/s3Cluster.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Allows processing files from [Amazon S3](https://aws.amazon.com/s3/) and Google
1717
**Syntax**
1818

1919
```sql
20-
s3Cluster(cluster_name, url [, NOSIGN | access_key_id, secret_access_key, [session_token]] [,format] [,structure] [,compression_method],[,headers])
20+
s3Cluster(cluster_name, url[, NOSIGN | access_key_id, secret_access_key,[session_token]][, format][, structure][, compression_method][, headers][, extra_credentials])
2121
s3Cluster(cluster_name, named_collection[, option=value [,..]])
2222
```
2323

@@ -31,7 +31,8 @@ s3Cluster(cluster_name, named_collection[, option=value [,..]])
3131
- `format` — The [format](/sql-reference/formats) of the file.
3232
- `structure` — Structure of the table. Format `'column1_name column1_type, column2_name column2_type, ...'`.
3333
- `compression_method` — Parameter is optional. Supported values: `none`, `gzip` or `gz`, `brotli` or `br`, `xz` or `LZMA`, `zstd` or `zst`. By default, it will autodetect compression method by file extension.
34-
- `headers` - Parameter is optional. Allows headers to be passed in the S3 request. Pass in the format `headers(key=value)` e.g. `headers('x-amz-request-payer' = 'requester')`. See [here](/sql-reference/table-functions/s3#accessing-requester-pays-buckets) for example of use.
34+
- `headers` - Optional. Allows headers to be passed in the S3 request. Pass in the format `headers(key=value)` e.g. `headers('x-amz-request-payer' = 'requester')`. See [here](/sql-reference/table-functions/s3#accessing-requester-pays-buckets) for an example.
35+
- `extra_credentials` - Optional. `roleARN` can be passed via this parameter. See [here](/cloud/security/secure-s3#access-your-s3-bucket-with-the-clickhouseaccess-role) for an example.
3536

3637
Arguments can also be passed using [named collections](operations/named-collections.md). In this case `url`, `access_key_id`, `secret_access_key`, `format`, `structure`, `compression_method` work in the same way, and some extra parameters are supported:
3738

programs/keeper/keeper_main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,5 +219,7 @@ int main(int argc_, char ** argv_)
219219
dumpCoverage();
220220
#endif
221221

222+
DB::OpenSSLInitializer::cleanup();
223+
222224
return exit_code;
223225
}

programs/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,5 +307,7 @@ int main(int argc_, char ** argv_)
307307
dumpCoverage();
308308
#endif
309309

310+
DB::OpenSSLInitializer::cleanup();
311+
310312
return exit_code;
311313
}

src/Access/SettingsConstraints.cpp

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void SettingsConstraints::clear()
7777
settings_alias_cache.clear();
7878
}
7979

80-
void SettingsConstraints::set(const String & full_name, const Field & min_value, const Field & max_value, SettingConstraintWritability writability)
80+
void SettingsConstraints::set(const String & full_name, const Field & min_value, const Field & max_value, const std::vector<Field> & disallowed_values, SettingConstraintWritability writability)
8181
{
8282
std::string resolved_name{resolveSettingName(full_name)};
8383

@@ -90,23 +90,30 @@ void SettingsConstraints::set(const String & full_name, const Field & min_value,
9090
constraint.min_value = settingCastValueUtil(resolved_name, min_value);
9191
if (!max_value.isNull())
9292
constraint.max_value = settingCastValueUtil(resolved_name, max_value);
93+
if (!disallowed_values.empty())
94+
{
95+
for (const auto & allowed_value : disallowed_values)
96+
constraint.disallowed_values.emplace_back(settingCastValueUtil(resolved_name, allowed_value));
97+
}
9398
constraint.writability = writability;
9499
}
95100

96-
void SettingsConstraints::get(const Settings & current_settings, std::string_view short_name, Field & min_value, Field & max_value, SettingConstraintWritability & writability) const
101+
void SettingsConstraints::get(const Settings & current_settings, std::string_view short_name, Field & min_value, Field & max_value, std::vector<Field> & disallowed_values, SettingConstraintWritability & writability) const
97102
{
98103
// NOTE: for `Settings` short name is equal to full name
99104
auto checker = getChecker(current_settings, short_name);
100105
min_value = checker.constraint.min_value;
101106
max_value = checker.constraint.max_value;
107+
disallowed_values = checker.constraint.disallowed_values;
102108
writability = checker.constraint.writability;
103109
}
104110

105-
void SettingsConstraints::get(const MergeTreeSettings &, std::string_view short_name, Field & min_value, Field & max_value, SettingConstraintWritability & writability) const
111+
void SettingsConstraints::get(const MergeTreeSettings &, std::string_view short_name, Field & min_value, Field & max_value, std::vector<Field> & disallowed_values, SettingConstraintWritability & writability) const
106112
{
107113
auto checker = getMergeTreeChecker(short_name);
108114
min_value = checker.constraint.min_value;
109115
max_value = checker.constraint.max_value;
116+
disallowed_values = checker.constraint.disallowed_values;
110117
writability = checker.constraint.writability;
111118
}
112119

@@ -128,6 +135,8 @@ void SettingsConstraints::merge(const SettingsConstraints & other)
128135
constraint.min_value = other_constraint.min_value;
129136
if (!other_constraint.max_value.isNull())
130137
constraint.max_value = other_constraint.max_value;
138+
if (!other_constraint.disallowed_values.empty())
139+
constraint.disallowed_values = other_constraint.disallowed_values;
131140
if (other_constraint.writability == SettingConstraintWritability::CONST)
132141
constraint.writability = SettingConstraintWritability::CONST; // NOTE: In this mode <readonly/> flag cannot be overridden to be false
133142
}
@@ -170,6 +179,10 @@ void SettingsConstraints::check(const Settings & current_settings, const Setting
170179
check(current_settings, value, source);
171180
}
172181

182+
/// Don't check disallowed_values here in the profile elements because they make constrains more restrictive
183+
/// and don't allow to bypass constraints from config by creating a user with custom constraints. The check
184+
/// for disallowed values are instead implemented in SettingsConstraints::Checker::check.
185+
173186
SettingConstraintWritability new_value = SettingConstraintWritability::WRITABLE;
174187
SettingConstraintWritability old_value = SettingConstraintWritability::WRITABLE;
175188

@@ -336,6 +349,20 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
336349
}
337350
};
338351

352+
auto equals_or_cannot_compare = [=](const Field & left, const Field & right)
353+
{
354+
if (reaction == THROW_ON_VIOLATION)
355+
return accurateEquals(left, right);
356+
try
357+
{
358+
return accurateEquals(left, right);
359+
}
360+
catch (...)
361+
{
362+
return true;
363+
}
364+
};
365+
339366

340367
if (constraint.writability == SettingConstraintWritability::CONST)
341368
{
@@ -346,6 +373,7 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
346373

347374
const auto & min_value = constraint.min_value;
348375
const auto & max_value = constraint.max_value;
376+
const auto & disallowed_values = constraint.disallowed_values;
349377

350378
if (!min_value.isNull() && !max_value.isNull() && less_or_cannot_compare(max_value, min_value))
351379
{
@@ -379,6 +407,14 @@ bool SettingsConstraints::Checker::check(SettingChange & change,
379407
change.value = max_value;
380408
}
381409

410+
for (const auto & value : disallowed_values)
411+
{
412+
bool equals = equals_or_cannot_compare(value, new_value);
413+
if (equals)
414+
throw Exception(ErrorCodes::SETTING_CONSTRAINT_VIOLATION, "Setting {} shouldn't be {}",
415+
setting_name, applyVisitor(FieldVisitorToString(), value));
416+
}
417+
382418
if (!getSettingSourceRestrictions(setting_name).isSourceAllowed(source))
383419
{
384420
if (reaction == THROW_ON_VIOLATION)
@@ -460,7 +496,7 @@ SettingsConstraints::Checker SettingsConstraints::getMergeTreeChecker(std::strin
460496

461497
bool SettingsConstraints::Constraint::operator==(const Constraint & other) const
462498
{
463-
return writability == other.writability && min_value == other.min_value && max_value == other.max_value;
499+
return writability == other.writability && min_value == other.min_value && max_value == other.max_value && disallowed_values == other.disallowed_values;
464500
}
465501

466502
bool operator ==(const SettingsConstraints & left, const SettingsConstraints & right)

src/Access/SettingsConstraints.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ class SettingsConstraints
7171
void clear();
7272
bool empty() const { return constraints.empty(); }
7373

74-
void set(const String & full_name, const Field & min_value, const Field & max_value, SettingConstraintWritability writability);
75-
void get(const Settings & current_settings, std::string_view short_name, Field & min_value, Field & max_value, SettingConstraintWritability & writability) const;
76-
void get(const MergeTreeSettings & current_settings, std::string_view short_name, Field & min_value, Field & max_value, SettingConstraintWritability & writability) const;
74+
void set(const String & full_name, const Field & min_value, const Field & max_value, const std::vector<Field> & allowed_values, SettingConstraintWritability writability);
75+
void get(const Settings & current_settings, std::string_view short_name, Field & min_value, Field & max_value, std::vector<Field> & allowed_values, SettingConstraintWritability & writability) const;
76+
void get(const MergeTreeSettings & current_settings, std::string_view short_name, Field & min_value, Field & max_value, std::vector<Field> & allowed_values, SettingConstraintWritability & writability) const;
7777

7878
void merge(const SettingsConstraints & other);
7979

@@ -107,6 +107,7 @@ class SettingsConstraints
107107
SettingConstraintWritability writability = SettingConstraintWritability::WRITABLE;
108108
Field min_value{};
109109
Field max_value{};
110+
std::vector<Field> disallowed_values{};
110111

111112
bool operator ==(const Constraint & other) const;
112113
bool operator !=(const Constraint & other) const { return !(*this == other); }

src/Access/SettingsProfileElement.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,22 @@ void SettingsProfileElement::init(const ASTSettingsProfileElement & ast, const A
6565
min_value = ast.min_value;
6666
max_value = ast.max_value;
6767
writability = ast.writability;
68+
disallowed_values = ast.disallowed_values;
6869

6970
if (value)
7071
value = Settings::castValueUtil(setting_name, *value);
7172
if (min_value)
7273
min_value = Settings::castValueUtil(setting_name, *min_value);
7374
if (max_value)
7475
max_value = Settings::castValueUtil(setting_name, *max_value);
76+
for (auto & allowed_value : disallowed_values)
77+
value = Settings::castValueUtil(setting_name, allowed_value);
7578
}
7679
}
7780

7881
bool SettingsProfileElement::isConstraint() const
7982
{
80-
return this->writability || this->min_value || this->max_value;
83+
return this->writability || this->min_value || this->max_value || !this->disallowed_values.empty();
8184
}
8285

8386
std::shared_ptr<ASTSettingsProfileElement> SettingsProfileElement::toAST() const
@@ -92,6 +95,7 @@ std::shared_ptr<ASTSettingsProfileElement> SettingsProfileElement::toAST() const
9295
ast->value = value;
9396
ast->min_value = min_value;
9497
ast->max_value = max_value;
98+
ast->disallowed_values = disallowed_values;
9599
ast->writability = writability;
96100

97101
return ast;
@@ -113,6 +117,7 @@ std::shared_ptr<ASTSettingsProfileElement> SettingsProfileElement::toASTWithName
113117
ast->value = value;
114118
ast->min_value = min_value;
115119
ast->max_value = max_value;
120+
ast->disallowed_values = disallowed_values;
116121
ast->writability = writability;
117122

118123
return ast;
@@ -277,6 +282,7 @@ SettingsConstraints SettingsProfileElements::toSettingsConstraints(const AccessC
277282
elem.setting_name,
278283
elem.min_value ? *elem.min_value : Field{},
279284
elem.max_value ? *elem.max_value : Field{},
285+
elem.disallowed_values,
280286
elem.writability ? *elem.writability : SettingConstraintWritability::WRITABLE);
281287
return res;
282288
}
@@ -360,6 +366,8 @@ void SettingsProfileElements::normalize()
360366
first_element.min_value = element.min_value;
361367
if (element.max_value)
362368
first_element.max_value = element.max_value;
369+
if (!element.disallowed_values.empty())
370+
first_element.disallowed_values = element.disallowed_values;
363371
if (element.writability)
364372
first_element.writability = element.writability;
365373
element.setting_name.clear();
@@ -484,6 +492,7 @@ void SettingsProfileElements::applyChanges(const AlterSettingsProfileElements &
484492
new_element.value = modify.value;
485493
new_element.min_value = modify.min_value;
486494
new_element.max_value = modify.max_value;
495+
new_element.disallowed_values = modify.disallowed_values;
487496
new_element.writability = modify.writability;
488497
push_back(new_element); /// normalizeProfileElements() will merge this new element with the previous elements.
489498
};

src/Access/SettingsProfileElement.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ struct SettingsProfileElement
2828
std::optional<Field> value;
2929
std::optional<Field> min_value;
3030
std::optional<Field> max_value;
31+
std::vector<Field> disallowed_values;
3132
std::optional<SettingConstraintWritability> writability;
3233

33-
auto toTuple() const { return std::tie(parent_profile, setting_name, value, min_value, max_value, writability); }
34+
auto toTuple() const { return std::tie(parent_profile, setting_name, value, min_value, max_value, disallowed_values, writability); }
3435
friend bool operator==(const SettingsProfileElement & lhs, const SettingsProfileElement & rhs) { return lhs.toTuple() == rhs.toTuple(); }
3536
friend bool operator!=(const SettingsProfileElement & lhs, const SettingsProfileElement & rhs) { return !(lhs == rhs); }
3637
friend bool operator <(const SettingsProfileElement & lhs, const SettingsProfileElement & rhs) { return lhs.toTuple() < rhs.toTuple(); }
@@ -46,7 +47,7 @@ struct SettingsProfileElement
4647
std::shared_ptr<ASTSettingsProfileElement> toAST() const;
4748
std::shared_ptr<ASTSettingsProfileElement> toASTWithNames(const AccessControl & access_control) const;
4849

49-
bool empty() const { return !parent_profile && (setting_name.empty() || (!value && !min_value && !max_value && !writability)); }
50+
bool empty() const { return !parent_profile && (setting_name.empty() || (!value && !min_value && !max_value && disallowed_values.empty() && !writability)); }
5051

5152
bool isConstraint() const;
5253

src/Access/UsersConfigAccessStorage.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,19 @@ namespace
699699
profile_element.min_value = settingStringToValueUtil(setting_name, config.getString(path_to_name + "." + constraint_type));
700700
else if (constraint_type == "max")
701701
profile_element.max_value = settingStringToValueUtil(setting_name, config.getString(path_to_name + "." + constraint_type));
702+
/// When the xml config is parsed, the first constraint_type is parsed as `disallowed` and the subsequent ones are parsed as
703+
/// disallowed[1], disallowed[2] and so on. So, both `disallowed` and `disallowed[` should be considered as valid constraint types.
704+
/// Example:
705+
/// <constraints>
706+
/// <max_execution_time>
707+
/// <max>50</max>
708+
/// <disallowed>3</disallowed>
709+
/// <disallowed>4</disallowed>
710+
/// <disallowed>5</disallowed>
711+
/// </max_execution_time>
712+
/// </constraints>
713+
else if (constraint_type == "disallowed" || constraint_type.starts_with("disallowed["))
714+
profile_element.disallowed_values.push_back(settingStringToValueUtil(setting_name, config.getString(path_to_name + "." + constraint_type)));
702715
else if (constraint_type == "readonly" || constraint_type == "const")
703716
{
704717
writability_count++;

0 commit comments

Comments
 (0)