Skip to content

Commit 2000540

Browse files
GrigoryPervakovzvonand
authored andcommitted
Merge pull request ClickHouse#81833 from ClickHouse/redis_get_keys
Fix read Redis and KeeperMap by keys
1 parent bb85c02 commit 2000540

File tree

12 files changed

+413
-211
lines changed

12 files changed

+413
-211
lines changed

src/Storages/KVStorageUtils.cpp

Lines changed: 1 addition & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
#include <Columns/ColumnSet.h>
44
#include <Columns/ColumnConst.h>
55

6-
#include <Parsers/ASTFunction.h>
76
#include <Parsers/ASTIdentifier.h>
8-
#include <Parsers/ASTSubquery.h>
97
#include <Parsers/ASTLiteral.h>
108
#include <Parsers/ASTSelectQuery.h>
119

@@ -15,7 +13,6 @@
1513

1614
#include <Functions/IFunction.h>
1715

18-
1916
namespace DB
2017
{
2118

@@ -26,106 +23,8 @@ namespace ErrorCodes
2623

2724
namespace
2825
{
29-
// returns keys may be filter by condition
30-
bool traverseASTFilter(
31-
const std::string & primary_key, const DataTypePtr & primary_key_type, const ASTPtr & elem, const PreparedSetsPtr & prepared_sets, const ContextPtr & context, FieldVectorPtr & res)
32-
{
33-
const auto * function = elem->as<ASTFunction>();
34-
if (!function)
35-
return false;
36-
37-
if (function->name == "and")
38-
{
39-
// one child has the key filter condition is ok
40-
for (const auto & child : function->arguments->children)
41-
if (traverseASTFilter(primary_key, primary_key_type, child, prepared_sets, context, res))
42-
return true;
43-
return false;
44-
}
45-
if (function->name == "or")
46-
{
47-
// make sure every child has the key filter condition
48-
for (const auto & child : function->arguments->children)
49-
if (!traverseASTFilter(primary_key, primary_key_type, child, prepared_sets, context, res))
50-
return false;
51-
return true;
52-
}
53-
if (function->name == "equals" || function->name == "in")
54-
{
55-
const auto & args = function->arguments->as<ASTExpressionList &>();
56-
const ASTIdentifier * ident;
57-
std::shared_ptr<IAST> value;
58-
59-
if (args.children.size() != 2)
60-
return false;
61-
62-
if (function->name == "in")
63-
{
64-
if (!prepared_sets)
65-
return false;
66-
67-
ident = args.children.at(0)->as<ASTIdentifier>();
68-
if (!ident)
69-
return false;
70-
71-
if (ident->name() != primary_key)
72-
return false;
73-
value = args.children.at(1);
74-
75-
PreparedSets::Hash set_key = value->getTreeHash(/*ignore_aliases=*/true);
76-
FutureSetPtr future_set;
77-
78-
if ((value->as<ASTSubquery>() || value->as<ASTIdentifier>()))
79-
future_set = prepared_sets->findSubquery(set_key);
80-
else
81-
future_set = prepared_sets->findTuple(set_key, {primary_key_type});
82-
83-
if (!future_set)
84-
return false;
85-
86-
future_set->buildOrderedSetInplace(context);
87-
88-
auto set = future_set->get();
89-
if (!set)
90-
return false;
91-
92-
if (!set->hasExplicitSetElements())
93-
return false;
94-
95-
set->checkColumnsNumber(1);
96-
const auto & set_column = *set->getSetElements()[0];
97-
98-
if (set_column.getDataType() != primary_key_type->getTypeId())
99-
return false;
100-
101-
for (size_t row = 0; row < set_column.size(); ++row)
102-
res->push_back(set_column[row]);
103-
return true;
104-
}
105-
106-
if ((ident = args.children.at(0)->as<ASTIdentifier>()))
107-
value = args.children.at(1);
108-
else if ((ident = args.children.at(1)->as<ASTIdentifier>()))
109-
value = args.children.at(0);
110-
else
111-
return false;
112-
113-
if (ident->name() != primary_key)
114-
return false;
115-
116-
const auto node = evaluateConstantExpressionAsLiteral(value, context);
117-
/// function->name == "equals"
118-
if (const auto * literal = node->as<ASTLiteral>())
119-
{
120-
auto converted_field = convertFieldToType(literal->value, *primary_key_type);
121-
if (!converted_field.isNull())
122-
res->push_back(converted_field);
123-
return true;
124-
}
125-
}
126-
return false;
127-
}
12826

27+
// returns keys may be filtered by condition
12928
bool traverseDAGFilter(
13029
const std::string & primary_key, const DataTypePtr & primary_key_type, const ActionsDAG::Node * elem, const ContextPtr & context, FieldVectorPtr & res)
13130
{
@@ -239,18 +138,6 @@ std::pair<FieldVectorPtr, bool> getFilterKeys(
239138
return std::make_pair(res, !matched_keys);
240139
}
241140

242-
std::pair<FieldVectorPtr, bool> getFilterKeys(
243-
const String & primary_key, const DataTypePtr & primary_key_type, const SelectQueryInfo & query_info, const ContextPtr & context)
244-
{
245-
const auto & select = query_info.query->as<ASTSelectQuery &>();
246-
if (!select.where())
247-
return {{}, true};
248-
249-
FieldVectorPtr res = std::make_shared<FieldVector>();
250-
auto matched_keys = traverseASTFilter(primary_key, primary_key_type, select.where(), query_info.prepared_sets, context, res);
251-
return std::make_pair(res, !matched_keys);
252-
}
253-
254141
std::vector<std::string> serializeKeysToRawString(
255142
FieldVector::const_iterator & it,
256143
FieldVector::const_iterator end,

src/Storages/RocksDB/StorageEmbeddedRocksDB.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <Storages/StorageFactory.h>
88
#include <Storages/KVStorageUtils.h>
9+
#include <Storages/AlterCommands.h>
10+
#include <Storages/RocksDB/RocksDBSettings.h>
911

1012
#include <Parsers/ASTCreateQuery.h>
1113

@@ -29,9 +31,9 @@
2931
#include <Common/Logger.h>
3032
#include <Common/logger_useful.h>
3133
#include <Common/Exception.h>
34+
#include <Common/JSONBuilder.h>
3235
#include <Core/Settings.h>
33-
#include <Storages/AlterCommands.h>
34-
#include <Storages/RocksDB/RocksDBSettings.h>
36+
3537
#include <IO/SharedThreadPools.h>
3638
#include <Disks/DiskLocal.h>
3739
#include <base/sort.h>
@@ -566,6 +568,8 @@ class ReadFromEmbeddedRocksDB : public SourceStepWithFilter
566568
std::string getName() const override { return "ReadFromEmbeddedRocksDB"; }
567569
void initializePipeline(QueryPipelineBuilder & pipeline, const BuildQueryPipelineSettings &) override;
568570
void applyFilters(ActionDAGNodes added_filter_nodes) override;
571+
void describeActions(FormatSettings & format_settings) const override;
572+
void describeActions(JSONBuilder::JSONMap & map) const override;
569573

570574
ReadFromEmbeddedRocksDB(
571575
const Names & column_names_,
@@ -666,6 +670,29 @@ void ReadFromEmbeddedRocksDB::applyFilters(ActionDAGNodes added_filter_nodes)
666670
std::tie(keys, all_scan) = getFilterKeys(storage.primary_key, primary_key_data_type, filter_actions_dag, context);
667671
}
668672

673+
void ReadFromEmbeddedRocksDB::describeActions(FormatSettings & format_settings) const
674+
{
675+
std::string prefix(format_settings.offset, format_settings.indent_char);
676+
if (!all_scan)
677+
{
678+
format_settings.out << prefix << "ReadType: GetKeys\n";
679+
format_settings.out << prefix << "Keys: " << keys->size() << '\n';
680+
}
681+
else
682+
format_settings.out << prefix << "ReadType: FullScan\n";
683+
}
684+
685+
void ReadFromEmbeddedRocksDB::describeActions(JSONBuilder::JSONMap & map) const
686+
{
687+
if (!all_scan)
688+
{
689+
map.add("Read Type", "GetKeys");
690+
map.add("Keys", keys->size());
691+
}
692+
else
693+
map.add("Read Type", "FullScan");
694+
}
695+
669696
SinkToStoragePtr StorageEmbeddedRocksDB::write(
670697
const ASTPtr & /*query*/, const StorageMetadataPtr & metadata_snapshot, ContextPtr query_context, bool /*async_insert*/)
671698
{

src/Storages/SelectQueryInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ struct SelectQueryInfo
190190
InputOrderInfoPtr input_order_info;
191191

192192
/// Prepared sets are used for indices by storage engine.
193+
/// New analyzer stores prepared sets in planner_context and hashes computed of QueryTree instead of AST.
193194
/// Example: x IN (1, 2, 3)
194195
PreparedSetsPtr prepared_sets;
195196

0 commit comments

Comments
 (0)