Skip to content

Commit 5ef5899

Browse files
Add create_query, source columns to system.named_collections
1 parent 4baea3a commit 5ef5899

File tree

9 files changed

+295
-130
lines changed

9 files changed

+295
-130
lines changed

src/Common/NamedCollections/NamedCollections.cpp

Lines changed: 145 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <IO/Operators.h>
66
#include <Common/NamedCollections/NamedCollectionConfiguration.h>
77
#include <Poco/Util/AbstractConfiguration.h>
8+
#include <Common/FieldVisitorToString.h>
89

910
#include <fmt/ranges.h>
1011

@@ -16,6 +17,7 @@ namespace ErrorCodes
1617
{
1718
extern const int NAMED_COLLECTION_IS_IMMUTABLE;
1819
extern const int BAD_ARGUMENTS;
20+
extern const int NOT_IMPLEMENTED;
1921
}
2022

2123
namespace Configuration = NamedCollectionConfiguration;
@@ -173,30 +175,27 @@ class NamedCollection::Impl
173175
}
174176
};
175177

178+
String NamedCollection::sourceIdToString(NamedCollection::SourceId id)
179+
{
180+
switch (id)
181+
{
182+
case NamedCollection::SourceId::NONE: return "NONE";
183+
case NamedCollection::SourceId::CONFIG: return "CONFIG";
184+
case NamedCollection::SourceId::SQL: return "SQL";
185+
}
186+
}
187+
176188
NamedCollection::NamedCollection(
177189
ImplPtr pimpl_,
178190
const std::string & collection_name_,
179-
SourceId source_id_,
180-
bool is_mutable_)
191+
const bool is_mutable_)
181192
: pimpl(std::move(pimpl_))
182193
, collection_name(collection_name_)
183-
, source_id(source_id_)
184194
, is_mutable(is_mutable_)
185195
{
186196
}
187197

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

201200
bool NamedCollection::has(const Key & key) const
202201
{
@@ -297,8 +296,7 @@ MutableNamedCollectionPtr NamedCollection::duplicate() const
297296
std::lock_guard lock(mutex);
298297
auto impl = pimpl->createCopy(collection_name);
299298
return std::unique_ptr<NamedCollection>(
300-
new NamedCollection(
301-
std::move(impl), collection_name, SourceId::NONE, true));
299+
new NamedCollection(std::move(impl), collection_name, true));
302300
}
303301

304302
NamedCollection::Keys NamedCollection::getKeys(ssize_t depth, const std::string & prefix) const
@@ -334,6 +332,136 @@ std::unique_lock<std::mutex> NamedCollection::lock()
334332
return std::unique_lock(mutex);
335333
}
336334

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

src/Common/NamedCollections/NamedCollections.h

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#pragma once
22
#include <Interpreters/Context.h>
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

@@ -29,13 +32,7 @@ class NamedCollection
2932
SQL = 2,
3033
};
3134

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_);
35+
static String sourceIdToString(SourceId id);
3936

4037
bool has(const Key & key) const;
4138

@@ -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+
const 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+
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
}

src/Common/NamedCollections/NamedCollectionsFactory.cpp

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ namespace
200200
keys.emplace(path.substr(collection_prefix.size() + 1));
201201
}
202202

203-
return NamedCollection::create(
204-
config, collection_name, collection_prefix, keys, NamedCollection::SourceId::CONFIG, /* is_mutable */false);
203+
return NamedCollectionFromConfig::create(
204+
config, collection_name, collection_prefix, keys);
205205
}
206206

207207
NamedCollectionsMap getNamedCollections(const Poco::Util::AbstractConfiguration & config)
@@ -321,33 +321,31 @@ void NamedCollectionFactory::updateFromSQL(const ASTAlterNamedCollectionQuery &
321321
std::lock_guard lock(mutex);
322322
loadIfNot(lock);
323323

324-
if (!exists(query.collection_name, lock))
324+
auto collection_name = query.collection_name;
325+
if (!exists(collection_name, lock))
325326
{
326327
if (query.if_exists)
327328
return;
328329

329330
throw Exception(
330331
ErrorCodes::NAMED_COLLECTION_DOESNT_EXIST,
331-
"Cannot remove collection `{}`, because it doesn't exist",
332-
query.collection_name);
332+
"Cannot update collection `{}`, because it doesn't exist",
333+
collection_name);
333334
}
335+
auto updated_collection_ptr = metadata_storage->update(query);
334336

335-
metadata_storage->update(query);
336-
337-
auto collection = getMutable(query.collection_name, lock);
338-
auto collection_lock = collection->lock();
337+
auto it = loaded_named_collections.find(collection_name);
338+
chassert(it != loaded_named_collections.end());
339339

340-
for (const auto & [name, value] : query.changes)
340+
if (!it->second->isMutable())
341341
{
342-
auto it_override = query.overridability.find(name);
343-
if (it_override != query.overridability.end())
344-
collection->setOrUpdate<String, true>(name, convertFieldToString(value), it_override->second);
345-
else
346-
collection->setOrUpdate<String, true>(name, convertFieldToString(value), {});
342+
throw Exception(
343+
ErrorCodes::NAMED_COLLECTION_IS_IMMUTABLE,
344+
"Cannot get collection `{}` for modification, "
345+
"because collection was defined as immutable",
346+
collection_name);
347347
}
348-
349-
for (const auto & key : query.delete_keys)
350-
collection->remove<true>(key);
348+
it->second = updated_collection_ptr;
351349
}
352350

353351
void NamedCollectionFactory::reloadFromSQL()

0 commit comments

Comments
 (0)