Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix early constant folding for isNull/isNotNul and analyzer. #64695

Merged
merged 8 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/DataTypes/DataTypeNullable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <DataTypes/DataTypeFactory.h>
#include <DataTypes/Serializations/SerializationNullable.h>
#include <DataTypes/DataTypeLowCardinality.h>
#include <DataTypes/DataTypeVariant.h>
#include <Columns/ColumnNullable.h>
#include <Columns/ColumnConst.h>
#include <Core/Field.h>
Expand Down Expand Up @@ -174,4 +175,17 @@ DataTypePtr removeNullableOrLowCardinalityNullable(const DataTypePtr & type)

}

bool canContainNull(const IDataType & type)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange formatting

if (type.isNullable() || type.isLowCardinalityNullable() || isDynamic(type))
return true;

if (const auto * variant = typeid_cast<const DataTypeVariant *>(&type))
for (const auto & elem : variant->getVariants())
if (canContainNull(*elem))
return true;

return false;
}

}
2 changes: 2 additions & 0 deletions src/DataTypes/DataTypeNullable.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ DataTypePtr makeNullableOrLowCardinalityNullableSafe(const DataTypePtr & type);
/// Nullable(T) -> T, LowCardinality(Nullable(T)) -> T
DataTypePtr removeNullableOrLowCardinalityNullable(const DataTypePtr & type);

bool canContainNull(const IDataType & type);

}
12 changes: 12 additions & 0 deletions src/Functions/isNotNull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ class FunctionIsNotNull : public IFunction
return name;
}

ColumnPtr getConstantResultForNonConstArguments(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type) const override
{
const ColumnWithTypeAndName & elem = arguments[0];
if (elem.type->onlyNull())
return result_type->createColumnConst(1, UInt8(0));

if (canContainNull(*elem.type))
return nullptr;

return result_type->createColumnConst(1, UInt8(1));
}

size_t getNumberOfArguments() const override { return 1; }
bool useDefaultImplementationForNulls() const override { return false; }
bool useDefaultImplementationForConstants() const override { return true; }
Expand Down
12 changes: 12 additions & 0 deletions src/Functions/isNull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ class FunctionIsNull : public IFunction
return name;
}

ColumnPtr getConstantResultForNonConstArguments(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type) const override
{
const ColumnWithTypeAndName & elem = arguments[0];
if (elem.type->onlyNull())
return result_type->createColumnConst(1, UInt8(1));

if (canContainNull(*elem.type))
return nullptr;

return result_type->createColumnConst(1, UInt8(0));
}

size_t getNumberOfArguments() const override { return 1; }
bool useDefaultImplementationForNulls() const override { return false; }
bool useDefaultImplementationForLowCardinalityColumns() const override { return false; }
Expand Down
10 changes: 10 additions & 0 deletions src/Functions/isNullable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <Functions/FunctionFactory.h>
#include <DataTypes/DataTypesNumber.h>
#include <Columns/ColumnsNumber.h>
#include <DataTypes/DataTypeNullable.h>

namespace DB
{
Expand All @@ -23,6 +24,15 @@ class FunctionIsNullable : public IFunction
return name;
}

ColumnPtr getConstantResultForNonConstArguments(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type) const override
{
const ColumnWithTypeAndName & elem = arguments[0];
if (elem.type->onlyNull() || canContainNull(*elem.type))
return result_type->createColumnConst(1, UInt8(1));

return result_type->createColumnConst(1, UInt8(0));
}

bool useDefaultImplementationForNulls() const override { return false; }

bool useDefaultImplementationForNothing() const override { return false; }
Expand Down
9 changes: 7 additions & 2 deletions src/Planner/PlannerExpressionAnalysis.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <Planner/PlannerExpressionAnalysis.h>

#include <Columns/ColumnNullable.h>
#include <Columns/FilterDescription.h>

#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeNullable.h>
Expand Down Expand Up @@ -37,15 +38,19 @@ namespace
* Actions before filter are added into into actions chain.
* It is client responsibility to update filter analysis result if filter column must be removed after chain is finalized.
*/
FilterAnalysisResult analyzeFilter(const QueryTreeNodePtr & filter_expression_node,
std::optional<FilterAnalysisResult> analyzeFilter(const QueryTreeNodePtr & filter_expression_node,
const ColumnsWithTypeAndName & input_columns,
const PlannerContextPtr & planner_context,
ActionsChain & actions_chain)
{
FilterAnalysisResult result;

result.filter_actions = buildActionsDAGFromExpressionNode(filter_expression_node, input_columns, planner_context);
result.filter_column_name = result.filter_actions->getOutputs().at(0)->result_name;
const auto * output = result.filter_actions->getOutputs().at(0);
if (output->column && ConstantFilterDescription(*output->column).always_true)
return {};

result.filter_column_name = output->result_name;
actions_chain.addStep(std::make_unique<ActionsChainStep>(result.filter_actions));

return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ReadFromPreparedSource (Optimized trivial count)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
CREATE TABLE checks
(
`pull_request_number` UInt32,
`commit_sha` LowCardinality(String),
`check_name` LowCardinality(String),
`check_status` LowCardinality(String),
`check_duration_ms` UInt64,
`check_start_time` DateTime,
`test_name` LowCardinality(String),
`test_status` LowCardinality(String),
`test_duration_ms` UInt64,
`report_url` String,
`pull_request_url` String,
`commit_url` String,
`task_url` String,
`base_ref` String,
`base_repo` String,
`head_ref` String,
`head_repo` String,
`test_context_raw` String,
`instance_type` LowCardinality(String),
`instance_id` String,
`date` Date MATERIALIZED toDate(check_start_time)
)
ENGINE = MergeTree ORDER BY (date, pull_request_number, commit_sha, check_name, test_name, check_start_time);

insert into checks select * from generateRandom() limit 1;


select trimLeft(explain) from (explain SELECT count(1) FROM checks WHERE test_name IS NOT NULL SETTINGS allow_experimental_analyzer = 1, allow_experimental_parallel_reading_from_replicas = 0) where explain like '%ReadFromPreparedSource%';
Loading