Analyzer AutoFinalOnQueryPass fix

This commit is contained in:
Maksim Kita 2023-02-22 15:51:13 +01:00
parent 5788deeadd
commit 40d2798cb4
5 changed files with 82 additions and 39 deletions

View File

@ -1,8 +1,11 @@
#include "AutoFinalOnQueryPass.h" #include "AutoFinalOnQueryPass.h"
#include <Analyzer/TableNode.h>
#include <Analyzer/TableExpressionModifiers.h>
#include <Storages/IStorage.h> #include <Storages/IStorage.h>
#include <Analyzer/Utils.h>
#include <Analyzer/TableNode.h>
#include <Analyzer/TableFunctionNode.h>
#include <Analyzer/TableExpressionModifiers.h>
#include <Analyzer/InDepthQueryTreeVisitor.h> #include <Analyzer/InDepthQueryTreeVisitor.h>
namespace DB namespace DB
@ -10,52 +13,64 @@ namespace DB
namespace namespace
{ {
class AutoFinalOnQueryPassVisitor : public InDepthQueryTreeVisitorWithContext<AutoFinalOnQueryPassVisitor>
class AutoFinalOnQueryPassVisitor : public InDepthQueryTreeVisitorWithContext<AutoFinalOnQueryPassVisitor>
{
public:
using Base = InDepthQueryTreeVisitorWithContext<AutoFinalOnQueryPassVisitor>;
using Base::Base;
void visitImpl(QueryTreeNodePtr & node)
{ {
public: const auto & context = getContext();
using Base = InDepthQueryTreeVisitorWithContext<AutoFinalOnQueryPassVisitor>; if (!context->getSettingsRef().final)
using Base::Base; return;
void visitImpl(QueryTreeNodePtr & node) const auto * query_node = node->as<QueryNode>();
if (!query_node)
return;
auto table_expressions = extractTableExpressions(query_node->getJoinTree());
for (auto & table_expression : table_expressions)
applyFinalIfNeeded(table_expression);
}
private:
static void applyFinalIfNeeded(QueryTreeNodePtr & node)
{
auto * table_node = node->as<TableNode>();
auto * table_function_node = node->as<TableFunctionNode>();
if (!table_node && !table_function_node)
return;
const auto & storage = table_node ? table_node->getStorage() : table_function_node->getStorage();
bool is_final_supported = storage && storage->supportsFinal() && !storage->isRemote();
if (!is_final_supported)
return;
TableExpressionModifiers table_expression_modifiers_with_final(true /*has_final*/, {}, {});
if (table_node)
{ {
if (auto * table_node = node->as<TableNode>()) if (table_node->hasTableExpressionModifiers())
{ table_node->getTableExpressionModifiers()->setHasFinal(true);
if (autoFinalOnQuery(*table_node, table_node->getStorage(), getContext())) else
{ table_node->setTableExpressionModifiers(table_expression_modifiers_with_final);
auto modifier = TableExpressionModifiers(true, std::nullopt, std::nullopt);
table_node->setTableExpressionModifiers(modifier);
}
}
} }
else if (table_function_node)
private:
static bool autoFinalOnQuery(TableNode & table_node, StoragePtr storage, ContextPtr context)
{ {
bool is_auto_final_setting_on = context->getSettingsRef().final; if (table_function_node->hasTableExpressionModifiers())
bool is_final_supported = storage && storage->supportsFinal() && !storage->isRemote(); table_function_node->getTableExpressionModifiers()->setHasFinal(true);
bool is_query_already_final = table_node.hasTableExpressionModifiers() ? table_node.getTableExpressionModifiers().has_value() : false; else
table_function_node->setTableExpressionModifiers(table_expression_modifiers_with_final);
return is_auto_final_setting_on && !is_query_already_final && is_final_supported;
} }
}
};
};
}
String AutoFinalOnQueryPass::getName()
{
return "AutoFinalOnQueryPass";
}
String AutoFinalOnQueryPass::getDescription()
{
return "Automatically applies final modifier to queries if it is supported and if user level final setting is set.";
} }
void AutoFinalOnQueryPass::run(QueryTreeNodePtr query_tree_node, ContextPtr context) void AutoFinalOnQueryPass::run(QueryTreeNodePtr query_tree_node, ContextPtr context)
{ {
auto visitor = AutoFinalOnQueryPassVisitor(std::move(context)); auto visitor = AutoFinalOnQueryPassVisitor(std::move(context));
visitor.visit(query_tree_node); visitor.visit(query_tree_node);
} }

View File

@ -7,13 +7,23 @@
namespace DB namespace DB
{ {
/** Automatically applies final modifier to table expressions in queries if it is supported and if user level final setting is set.
*
* Example: SELECT id, value FROM test_table;
* Result: SELECT id, value FROM test_table FINAL;
*/
class AutoFinalOnQueryPass final : public IQueryTreePass class AutoFinalOnQueryPass final : public IQueryTreePass
{ {
public: public:
String getName() override; String getName() override
{
return "AutoFinalOnQueryPass";
}
String getDescription() override; String getDescription() override
{
return "Automatically applies final modifier to table expressions in queries if it is supported and if user level final setting is set";
}
void run(QueryTreeNodePtr query_tree_node, ContextPtr context) override; void run(QueryTreeNodePtr query_tree_node, ContextPtr context) override;
}; };

View File

@ -28,6 +28,12 @@ public:
return has_final; return has_final;
} }
/// Set has final value
void setHasFinal(bool value)
{
has_final = value;
}
/// Returns true if sample size ratio is specified, false otherwise /// Returns true if sample size ratio is specified, false otherwise
bool hasSampleSizeRatio() const bool hasSampleSizeRatio() const
{ {

View File

@ -116,6 +116,12 @@ public:
return table_expression_modifiers; return table_expression_modifiers;
} }
/// Get table expression modifiers
std::optional<TableExpressionModifiers> & getTableExpressionModifiers()
{
return table_expression_modifiers;
}
/// Set table expression modifiers /// Set table expression modifiers
void setTableExpressionModifiers(TableExpressionModifiers table_expression_modifiers_value) void setTableExpressionModifiers(TableExpressionModifiers table_expression_modifiers_value)
{ {

View File

@ -68,6 +68,12 @@ public:
return table_expression_modifiers; return table_expression_modifiers;
} }
/// Get table expression modifiers
std::optional<TableExpressionModifiers> & getTableExpressionModifiers()
{
return table_expression_modifiers;
}
/// Set table expression modifiers /// Set table expression modifiers
void setTableExpressionModifiers(TableExpressionModifiers table_expression_modifiers_value) void setTableExpressionModifiers(TableExpressionModifiers table_expression_modifiers_value)
{ {