Skip to content

Commit 9e9152a

Browse files
authored
backport named collection updates (#1020)
1 parent 76eb5df commit 9e9152a

22 files changed

+800
-358
lines changed

src/Common/NamedCollections/NamedCollectionConfiguration.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#include <Common/NamedCollections/NamedCollectionConfiguration.h>
22
#include <Poco/Util/XMLConfiguration.h>
33
#include <Common/Exception.h>
4-
#include <Common/SettingsChanges.h>
54
#include <Common/FieldVisitorToString.h>
5+
#include <Common/SettingsChanges.h>
66
#include <magic_enum.hpp>
77

88

src/Common/NamedCollections/NamedCollections.cpp

Lines changed: 136 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
#include "NamedCollections.h"
1+
#include <Common/NamedCollections/NamedCollections.h>
22

33
#include <Interpreters/Context.h>
44
#include <IO/WriteBufferFromString.h>
55
#include <IO/Operators.h>
66
#include <Common/NamedCollections/NamedCollectionConfiguration.h>
77
#include <Poco/Util/AbstractConfiguration.h>
8+
#include <Common/FieldVisitorToString.h>
9+
10+
#include <fmt/ranges.h>
811

912

1013
namespace DB
1114
{
1215

1316
namespace ErrorCodes
1417
{
15-
extern const int NAMED_COLLECTION_DOESNT_EXIST;
16-
extern const int NAMED_COLLECTION_ALREADY_EXISTS;
1718
extern const int NAMED_COLLECTION_IS_IMMUTABLE;
19+
extern const int BAD_ARGUMENTS;
20+
extern const int NOT_IMPLEMENTED;
1821
}
1922

2023
namespace Configuration = NamedCollectionConfiguration;
@@ -175,27 +178,14 @@ class NamedCollection::Impl
175178
NamedCollection::NamedCollection(
176179
ImplPtr pimpl_,
177180
const std::string & collection_name_,
178-
SourceId source_id_,
179-
bool is_mutable_)
181+
const bool is_mutable_)
180182
: pimpl(std::move(pimpl_))
181183
, collection_name(collection_name_)
182-
, source_id(source_id_)
183184
, is_mutable(is_mutable_)
184185
{
185186
}
186187

187-
MutableNamedCollectionPtr NamedCollection::create(
188-
const Poco::Util::AbstractConfiguration & config,
189-
const std::string & collection_name,
190-
const std::string & collection_path,
191-
const Keys & keys,
192-
SourceId source_id,
193-
bool is_mutable)
194-
{
195-
auto impl = Impl::create(config, collection_name, collection_path, keys);
196-
return std::unique_ptr<NamedCollection>(
197-
new NamedCollection(std::move(impl), collection_name, source_id, is_mutable));
198-
}
188+
NamedCollection::~NamedCollection() = default;
199189

200190
bool NamedCollection::has(const Key & key) const
201191
{
@@ -296,8 +286,7 @@ MutableNamedCollectionPtr NamedCollection::duplicate() const
296286
std::lock_guard lock(mutex);
297287
auto impl = pimpl->createCopy(collection_name);
298288
return std::unique_ptr<NamedCollection>(
299-
new NamedCollection(
300-
std::move(impl), collection_name, SourceId::NONE, true));
289+
new NamedCollection(std::move(impl), collection_name, true));
301290
}
302291

303292
NamedCollection::Keys NamedCollection::getKeys(ssize_t depth, const std::string & prefix) const
@@ -333,6 +322,133 @@ std::unique_lock<std::mutex> NamedCollection::lock()
333322
return std::unique_lock(mutex);
334323
}
335324

325+
326+
void NamedCollection::update(const ASTAlterNamedCollectionQuery & /*query*/)
327+
{
328+
throw Exception(
329+
ErrorCodes::NOT_IMPLEMENTED,
330+
"update() not implemented for NamedCollection base class.");
331+
}
332+
333+
NamedCollectionFromConfig::NamedCollectionFromConfig(
334+
const Poco::Util::AbstractConfiguration & config_,
335+
const std::string & collection_name_,
336+
const std::string & collection_path_,
337+
const Keys & keys_)
338+
: NamedCollection(Impl::create(config_, collection_name_, collection_path_, keys_), collection_name_, /* is_mutable */ false)
339+
{
340+
}
341+
342+
MutableNamedCollectionPtr NamedCollectionFromConfig::create(
343+
const Poco::Util::AbstractConfiguration & config_,
344+
const std::string & collection_name_,
345+
const std::string & collection_path_,
346+
const Keys & keys_)
347+
{
348+
return std::unique_ptr<NamedCollection>(
349+
new NamedCollectionFromConfig(config_, collection_name_, collection_path_, keys_));
350+
}
351+
352+
353+
MutableNamedCollectionPtr NamedCollectionFromSQL::create(const ASTCreateNamedCollectionQuery & query)
354+
{
355+
return std::unique_ptr<NamedCollection>(new NamedCollectionFromSQL(query));
356+
}
357+
358+
NamedCollectionFromSQL::NamedCollectionFromSQL(const ASTCreateNamedCollectionQuery & query_)
359+
: NamedCollection(nullptr, query_.collection_name, true)
360+
, create_query_ptr(query_.clone()->as<ASTCreateNamedCollectionQuery &>())
361+
{
362+
const auto config = NamedCollectionConfiguration::createConfiguration(collection_name, create_query_ptr.changes, create_query_ptr.overridability);
363+
364+
std::set<std::string, std::less<>> keys;
365+
for (const auto & [name, _] : create_query_ptr.changes)
366+
keys.insert(name);
367+
368+
pimpl = Impl::create(*config, collection_name, "", keys);
369+
}
370+
371+
String NamedCollectionFromSQL::getCreateStatement(bool show_secrects)
372+
{
373+
auto & changes = create_query_ptr.changes;
374+
std::sort(
375+
changes.begin(), changes.end(),
376+
[](const SettingChange & lhs, const SettingChange & rhs) { return lhs.name < rhs.name; });
377+
378+
return create_query_ptr.formatWithPossiblyHidingSensitiveData(
379+
/*max_length=*/0,
380+
/*one_line=*/true,
381+
/*show_secrets=*/show_secrects);
382+
}
383+
384+
void NamedCollectionFromSQL::update(const ASTAlterNamedCollectionQuery & alter_query)
385+
{
386+
std::lock_guard lock(mutex);
387+
388+
std::unordered_map<std::string, Field> result_changes_map;
389+
for (const auto & [name, value] : alter_query.changes)
390+
{
391+
auto [it, inserted] = result_changes_map.emplace(name, value);
392+
if (!inserted)
393+
{
394+
throw Exception(
395+
ErrorCodes::BAD_ARGUMENTS,
396+
"Value with key `{}` is used twice in the SET query (collection name: {})",
397+
name, alter_query.collection_name);
398+
}
399+
}
400+
401+
for (const auto & [name, value] : create_query_ptr.changes)
402+
result_changes_map.emplace(name, value);
403+
404+
std::unordered_map<std::string, bool> result_overridability_map;
405+
for (const auto & [name, value] : alter_query.overridability)
406+
result_overridability_map.emplace(name, value);
407+
for (const auto & [name, value] : create_query_ptr.overridability)
408+
result_overridability_map.emplace(name, value);
409+
410+
for (const auto & delete_key : alter_query.delete_keys)
411+
{
412+
auto it = result_changes_map.find(delete_key);
413+
if (it == result_changes_map.end())
414+
{
415+
throw Exception(
416+
ErrorCodes::BAD_ARGUMENTS,
417+
"Cannot delete key `{}` because it does not exist in collection",
418+
delete_key);
419+
}
420+
421+
result_changes_map.erase(it);
422+
auto it_override = result_overridability_map.find(delete_key);
423+
if (it_override != result_overridability_map.end())
424+
result_overridability_map.erase(it_override);
425+
}
426+
427+
create_query_ptr.changes.clear();
428+
for (const auto & [name, value] : result_changes_map)
429+
create_query_ptr.changes.emplace_back(name, value);
430+
create_query_ptr.overridability = std::move(result_overridability_map);
431+
432+
if (create_query_ptr.changes.empty())
433+
throw Exception(
434+
ErrorCodes::BAD_ARGUMENTS,
435+
"Named collection cannot be empty (collection name: {})",
436+
collection_name);
437+
438+
chassert(create_query_ptr.collection_name == alter_query.collection_name);
439+
for (const auto & [name, value] : alter_query.changes)
440+
{
441+
auto it_override = alter_query.overridability.find(name);
442+
if (it_override != alter_query.overridability.end())
443+
setOrUpdate<String, true>(name, convertFieldToString(value), it_override->second);
444+
else
445+
setOrUpdate<String, true>(name, convertFieldToString(value), {});
446+
}
447+
448+
for (const auto & key : alter_query.delete_keys)
449+
remove<true>(key);
450+
}
451+
336452
template String NamedCollection::get<String>(const NamedCollection::Key & key) const;
337453
template UInt64 NamedCollection::get<UInt64>(const NamedCollection::Key & key) const;
338454
template Int64 NamedCollection::get<Int64>(const NamedCollection::Key & key) const;

src/Common/NamedCollections/NamedCollections.h

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#pragma once
2-
#include <Interpreters/Context.h>
2+
33
#include <Common/NamedCollections/NamedCollections_fwd.h>
4+
#include <Parsers/ASTCreateNamedCollectionQuery.h>
5+
#include <Parsers/ASTAlterNamedCollectionQuery.h>
6+
47

58
namespace Poco { namespace Util { class AbstractConfiguration; } }
69

@@ -24,19 +27,13 @@ class NamedCollection
2427
using Keys = std::set<Key, std::less<>>;
2528
enum class SourceId : uint8_t
2629
{
30+
/// None source_id is possible only if the object is a
31+
/// duplicate of some named collection. See `duplicate` method.
2732
NONE = 0,
2833
CONFIG = 1,
2934
SQL = 2,
3035
};
3136

32-
static MutableNamedCollectionPtr create(
33-
const Poco::Util::AbstractConfiguration & config,
34-
const std::string & collection_name,
35-
const std::string & collection_path,
36-
const Keys & keys,
37-
SourceId source_id_,
38-
bool is_mutable_);
39-
4037
bool has(const Key & key) const;
4138

4239
bool hasAny(const std::initializer_list<Key> & keys) const;
@@ -61,6 +58,7 @@ class NamedCollection
6158

6259
template <bool locked = false> void remove(const Key & key);
6360

61+
/// Creates mutable, with NONE source id full copy.
6462
MutableNamedCollectionPtr duplicate() const;
6563

6664
Keys getKeys(ssize_t depth = -1, const std::string & prefix = "") const;
@@ -76,25 +74,72 @@ class NamedCollection
7674

7775
bool isMutable() const { return is_mutable; }
7876

79-
SourceId getSourceId() const { return source_id; }
77+
virtual SourceId getSourceId() const { return SourceId::NONE; }
8078

81-
private:
79+
virtual String getCreateStatement(bool /*show_secrects*/) { return {}; }
80+
81+
virtual void update(const ASTAlterNamedCollectionQuery & query);
82+
83+
virtual ~NamedCollection();
84+
85+
protected:
8286
class Impl;
8387
using ImplPtr = std::unique_ptr<Impl>;
84-
8588
NamedCollection(
8689
ImplPtr pimpl_,
8790
const std::string & collection_name,
88-
SourceId source_id,
89-
bool is_mutable);
91+
bool is_mutable_
92+
);
9093

9194
void assertMutable() const;
9295

96+
9397
ImplPtr pimpl;
9498
const std::string collection_name;
95-
const SourceId source_id;
9699
const bool is_mutable;
97100
mutable std::mutex mutex;
98101
};
99102

103+
class NamedCollectionFromSQL final : public NamedCollection
104+
{
105+
public:
106+
static MutableNamedCollectionPtr create(const ASTCreateNamedCollectionQuery & query);
107+
108+
String getCreateStatement(bool show_secrects) override;
109+
110+
void update(const ASTAlterNamedCollectionQuery & query) override;
111+
112+
NamedCollection::SourceId getSourceId() const override { return SourceId::SQL; }
113+
114+
private:
115+
explicit NamedCollectionFromSQL(const ASTCreateNamedCollectionQuery & query_);
116+
117+
ASTCreateNamedCollectionQuery create_query_ptr;
118+
};
119+
120+
class NamedCollectionFromConfig final : public NamedCollection
121+
{
122+
public:
123+
124+
static MutableNamedCollectionPtr create(
125+
const Poco::Util::AbstractConfiguration & config,
126+
const std::string & collection_name,
127+
const std::string & collection_path,
128+
const Keys & keys);
129+
130+
String getCreateStatement(bool /*show_secrects*/) override { return {}; }
131+
132+
void update(const ASTAlterNamedCollectionQuery & /*query*/) override { NamedCollection::assertMutable(); }
133+
134+
NamedCollection::SourceId getSourceId() const override { return SourceId::CONFIG; }
135+
136+
private:
137+
138+
NamedCollectionFromConfig(
139+
const Poco::Util::AbstractConfiguration & config,
140+
const std::string & collection_name,
141+
const std::string & collection_path,
142+
const Keys & keys);
143+
};
144+
100145
}

0 commit comments

Comments
 (0)