mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-19 22:22:00 +00:00
replace settings limit and offset with corresponding expression nodes
This commit is contained in:
parent
ce2b044532
commit
cf493d1dfb
@ -233,22 +233,43 @@ QueryTreeNodePtr QueryTreeBuilder::buildSelectExpression(const ASTPtr & select_q
|
||||
auto select_settings = select_query_typed.settings();
|
||||
SettingsChanges settings_changes;
|
||||
|
||||
if (is_subquery)
|
||||
/// We are going to remove settings LIMIT and OFFSET and
|
||||
/// further replace them with corresponding expression nodes
|
||||
UInt64 limit = 0;
|
||||
UInt64 offset = 0;
|
||||
|
||||
/// remove global settings limit and offset
|
||||
if (const Settings & settings_ref = updated_context->getSettingsRef(); settings_ref.limit || settings_ref.offset)
|
||||
{
|
||||
if (const Settings & settings_ref = updated_context->getSettingsRef(); settings_ref.limit || settings_ref.offset)
|
||||
{
|
||||
Settings settings = updated_context->getSettings();
|
||||
settings.limit = 0;
|
||||
settings.offset = 0;
|
||||
updated_context->setSettings(settings);
|
||||
}
|
||||
Settings settings = updated_context->getSettings();
|
||||
limit = settings.limit;
|
||||
offset = settings.offset;
|
||||
settings.limit = 0;
|
||||
settings.offset = 0;
|
||||
updated_context->setSettings(settings);
|
||||
}
|
||||
|
||||
if (select_settings)
|
||||
{
|
||||
auto & set_query = select_settings->as<ASTSetQuery &>();
|
||||
updated_context->applySettingsChanges(set_query.changes);
|
||||
settings_changes = set_query.changes;
|
||||
|
||||
/// remove expression settings limit and offset
|
||||
if (auto * limit_field = set_query.changes.tryGet("limit"))
|
||||
{
|
||||
limit = limit_field->safeGet<UInt64>();
|
||||
set_query.changes.removeSetting("limit");
|
||||
}
|
||||
if (auto * offset_field = set_query.changes.tryGet("offset"))
|
||||
{
|
||||
offset = offset_field->safeGet<UInt64>();
|
||||
set_query.changes.removeSetting("offset");
|
||||
}
|
||||
|
||||
if (!set_query.changes.empty())
|
||||
{
|
||||
updated_context->applySettingsChanges(set_query.changes);
|
||||
settings_changes = set_query.changes;
|
||||
}
|
||||
}
|
||||
|
||||
auto current_query_tree = std::make_shared<QueryNode>(std::move(updated_context), std::move(settings_changes));
|
||||
@ -334,12 +355,32 @@ QueryTreeNodePtr QueryTreeBuilder::buildSelectExpression(const ASTPtr & select_q
|
||||
if (select_limit_by)
|
||||
current_query_tree->getLimitByNode() = buildExpressionList(select_limit_by, current_context);
|
||||
|
||||
/// combine limit expression with limit setting
|
||||
auto select_limit = select_query_typed.limitLength();
|
||||
if (select_limit)
|
||||
if (select_limit && limit)
|
||||
{
|
||||
auto function_node = std::make_shared<FunctionNode>("least");
|
||||
function_node->getArguments().getNodes().push_back(buildExpression(select_limit, current_context));
|
||||
function_node->getArguments().getNodes().push_back(std::make_shared<ConstantNode>(limit));
|
||||
current_query_tree->getLimit() = function_node;
|
||||
}
|
||||
else if (limit)
|
||||
current_query_tree->getLimit() = std::make_shared<ConstantNode>(limit);
|
||||
else if (select_limit)
|
||||
current_query_tree->getLimit() = buildExpression(select_limit, current_context);
|
||||
|
||||
/// combine offset expression with offset setting
|
||||
auto select_offset = select_query_typed.limitOffset();
|
||||
if (select_offset)
|
||||
if (select_offset && offset)
|
||||
{
|
||||
auto function_node = std::make_shared<FunctionNode>("plus");
|
||||
function_node->getArguments().getNodes().push_back(buildExpression(select_offset, current_context));
|
||||
function_node->getArguments().getNodes().push_back(std::make_shared<ConstantNode>(offset));
|
||||
current_query_tree->getOffset() = function_node;
|
||||
}
|
||||
else if (offset)
|
||||
current_query_tree->getOffset() = std::make_shared<ConstantNode>(offset);
|
||||
else if (select_offset)
|
||||
current_query_tree->getOffset() = buildExpression(select_offset, current_context);
|
||||
|
||||
return current_query_tree;
|
||||
|
@ -46,4 +46,29 @@ Field * SettingsChanges::tryGet(std::string_view name)
|
||||
return &change->value;
|
||||
}
|
||||
|
||||
bool SettingsChanges::insertSetting(std::string_view name, const Field & value)
|
||||
{
|
||||
if (std::find_if(begin(), end(), [&name](const SettingChange & change) { return change.name == name; }) != end())
|
||||
return false;
|
||||
emplace_back(name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SettingsChanges::setSetting(std::string_view name, const Field & value)
|
||||
{
|
||||
if (auto * v = tryGet(name))
|
||||
*v = value;
|
||||
else
|
||||
insertSetting(name, value);
|
||||
}
|
||||
|
||||
bool SettingsChanges::removeSetting(std::string_view name)
|
||||
{
|
||||
auto it = std::find_if(begin(), end(), [&name](const SettingChange & change) { return change.name == name; });
|
||||
if (it == end())
|
||||
return false;
|
||||
erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,13 @@ public:
|
||||
bool tryGet(std::string_view name, Field & out_value) const;
|
||||
const Field * tryGet(std::string_view name) const;
|
||||
Field * tryGet(std::string_view name);
|
||||
|
||||
/// inserts element if doesn't exists and returns true, else just returns false
|
||||
bool insertSetting(std::string_view name, const Field & value);
|
||||
/// sets element to value, inserts if doesn't exist
|
||||
void setSetting(std::string_view name, const Field & value);
|
||||
/// if element exists - removes it and returns true, else returns false
|
||||
bool removeSetting(std::string_view name);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -216,17 +216,12 @@ public:
|
||||
limit_length = query_node.getLimit()->as<ConstantNode &>().getValue().safeGet<UInt64>();
|
||||
}
|
||||
|
||||
if (settings.limit)
|
||||
limit_length = limit_length ? std::min(limit_length, settings.limit.value) : settings.limit;
|
||||
|
||||
if (query_node.hasOffset())
|
||||
{
|
||||
/// Constness of offset is validated during query analysis stage
|
||||
limit_offset = query_node.getOffset()->as<ConstantNode &>().getValue().safeGet<UInt64>();
|
||||
}
|
||||
|
||||
limit_offset += settings.offset;
|
||||
|
||||
/// Partial sort can be done if there is LIMIT, but no DISTINCT, LIMIT WITH TIES, LIMIT BY, ARRAY JOIN
|
||||
if (limit_length != 0 &&
|
||||
!query_node.isDistinct() &&
|
||||
|
@ -52,3 +52,19 @@ SELECT count(*) FROM view(SELECT * FROM numbers(10) SETTINGS limit=5);
|
||||
5
|
||||
SELECT count(*) FROM view(SELECT * FROM numbers(10)) SETTINGS limit=5;
|
||||
10
|
||||
SET limit = 4;
|
||||
SET offset = 1;
|
||||
SELECT * FROM numbers(10);
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
SELECT * FROM numbers(10) LIMIT 3 OFFSET 2;
|
||||
3
|
||||
4
|
||||
5
|
||||
SELECT * FROM numbers(10) LIMIT 5 OFFSET 2;
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
|
@ -21,4 +21,10 @@ SELECT count(*) FROM (SELECT * FROM numbers(10)) SETTINGS limit=5;
|
||||
SELECT count(*) FROM view(SELECT * FROM numbers(10));
|
||||
SELECT count(*) FROM view(SELECT * FROM numbers(10) SETTINGS limit=5);
|
||||
SELECT count(*) FROM view(SELECT * FROM numbers(10)) SETTINGS limit=5;
|
||||
|
||||
SET limit = 4;
|
||||
SET offset = 1;
|
||||
SELECT * FROM numbers(10);
|
||||
SELECT * FROM numbers(10) LIMIT 3 OFFSET 2;
|
||||
SELECT * FROM numbers(10) LIMIT 5 OFFSET 2;
|
||||
-- { echoOff }
|
||||
|
Loading…
Reference in New Issue
Block a user