Skip to content

Commit

Permalink
Early constant folding.
Browse files Browse the repository at this point in the history
  • Loading branch information
amosbird committed Oct 31, 2019
1 parent f8a401b commit e04cdd4
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 81 deletions.
4 changes: 4 additions & 0 deletions dbms/src/Columns/ColumnSet.h
@@ -1,6 +1,7 @@
#pragma once

#include <Columns/IColumnDummy.h>
#include <Core/Field.h>


namespace DB
Expand Down Expand Up @@ -28,6 +29,9 @@ class ColumnSet final : public COWHelper<IColumnDummy, ColumnSet>

ConstSetPtr getData() const { return data; }

// Used only for debugging, making it DUMPABLE
Field operator[](size_t) const override { return {}; }

private:
ConstSetPtr data;
};
Expand Down
3 changes: 3 additions & 0 deletions dbms/src/DataTypes/DataTypeSet.h
Expand Up @@ -17,6 +17,9 @@ class DataTypeSet final : public IDataTypeDummy
TypeIndex getTypeId() const override { return TypeIndex::Set; }
bool equals(const IDataType & rhs) const override { return typeid(rhs) == typeid(*this); }
bool isParametric() const override { return true; }

// Used only for debugging, making it DUMPABLE
Field getDefault() const override { return Tuple(); }
};

}
Expand Down
6 changes: 5 additions & 1 deletion dbms/src/Functions/in.cpp
Expand Up @@ -73,13 +73,17 @@ class FunctionIn : public IFunction
return std::make_shared<DataTypeUInt8>();
}

bool useDefaultImplementationForConstants() const override { return true; }

void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
{
/// NOTE: after updating this code, check that FunctionIgnoreExceptNull returns the same type of column.

/// Second argument must be ColumnSet.
ColumnPtr column_set_ptr = block.getByPosition(arguments[1]).column;
const ColumnSet * column_set = typeid_cast<const ColumnSet *>(&*column_set_ptr);
const ColumnSet * column_set = checkAndGetColumnConstData<const ColumnSet>(column_set_ptr.get());
if (!column_set)
column_set = checkAndGetColumn<const ColumnSet>(column_set_ptr.get());
if (!column_set)
throw Exception("Second argument for function '" + getName() + "' must be Set; found " + column_set_ptr->getName(),
ErrorCodes::ILLEGAL_COLUMN);
Expand Down
36 changes: 23 additions & 13 deletions dbms/src/Interpreters/ActionsVisitor.cpp
Expand Up @@ -328,10 +328,9 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &
/// Let's find the type of the first argument (then getActionsImpl will be called again and will not affect anything).
visit(node.arguments->children.at(0), data);

if (!data.no_subqueries)
if ((prepared_set = makeSet(node, data, data.no_subqueries)))
{
/// Transform tuple or subquery into a set.
prepared_set = makeSet(node, data);
}
else
{
Expand Down Expand Up @@ -423,8 +422,13 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &

if (!data.hasColumn(column.name))
{
column.column = ColumnSet::create(1, prepared_set);

auto column_set = ColumnSet::create(1, prepared_set);
/// If prepared_set is not empty, we have a set made with literals.
/// Create a const ColumnSet to make constant folding work
if (!prepared_set->empty())
column.column = ColumnConst::create(std::move(column_set), 1);
else
column.column = std::move(column_set);
data.addAction(ExpressionAction::addColumn(column));
}

Expand Down Expand Up @@ -542,21 +546,24 @@ void ActionsMatcher::visit(const ASTLiteral & literal, const ASTPtr & ast, Data
data.addAction(ExpressionAction::addColumn(column));
}

SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data)
SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data, bool no_subqueries)
{
/** You need to convert the right argument to a set.
* This can be a table name, a value, a value enumeration, or a subquery.
* The enumeration of values is parsed as a function `tuple`.
*/
const IAST & args = *node.arguments;
const ASTPtr & arg = args.children.at(1);
const ASTPtr & left_in_operand = args.children.at(0);
const ASTPtr & right_in_operand = args.children.at(1);
const Block & sample_block = data.getSampleBlock();

/// If the subquery or table name for SELECT.
const auto * identifier = arg->as<ASTIdentifier>();
if (arg->as<ASTSubquery>() || identifier)
const auto * identifier = right_in_operand->as<ASTIdentifier>();
if (right_in_operand->as<ASTSubquery>() || identifier)
{
auto set_key = PreparedSetKey::forSubquery(*arg);
if (no_subqueries)
return {};
auto set_key = PreparedSetKey::forSubquery(*right_in_operand);
if (data.prepared_sets.count(set_key))
return data.prepared_sets.at(set_key);

Expand All @@ -579,7 +586,7 @@ SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data)
}

/// We get the stream of blocks for the subquery. Create Set and put it in place of the subquery.
String set_id = arg->getColumnName();
String set_id = right_in_operand->getColumnName();

SubqueryForSet & subquery_for_set = data.subqueries_for_sets[set_id];

Expand All @@ -599,7 +606,7 @@ SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data)
*/
if (!subquery_for_set.source && data.no_storage_or_local)
{
auto interpreter = interpretSubquery(arg, data.context, data.subquery_depth, {});
auto interpreter = interpretSubquery(right_in_operand, data.context, data.subquery_depth, {});
subquery_for_set.source = std::make_shared<LazyBlockInputStream>(
interpreter->getSampleBlock(), [interpreter]() mutable { return interpreter->execute().in; });

Expand Down Expand Up @@ -637,8 +644,11 @@ SetPtr ActionsMatcher::makeSet(const ASTFunction & node, Data & data)
}
else
{
/// An explicit enumeration of values in parentheses.
return makeExplicitSet(&node, sample_block, false, data.context, data.set_size_limit, data.prepared_sets);
if (sample_block.has(left_in_operand->getColumnName()))
/// An explicit enumeration of values in parentheses.
return makeExplicitSet(&node, sample_block, false, data.context, data.set_size_limit, data.prepared_sets);
else
return {};
}
}

Expand Down
2 changes: 1 addition & 1 deletion dbms/src/Interpreters/ActionsVisitor.h
Expand Up @@ -125,7 +125,7 @@ class ActionsMatcher
static void visit(const ASTFunction & node, const ASTPtr & ast, Data & data);
static void visit(const ASTLiteral & literal, const ASTPtr & ast, Data & data);

static SetPtr makeSet(const ASTFunction & node, Data & data);
static SetPtr makeSet(const ASTFunction & node, Data & data, bool no_subqueries);
};

using ActionsVisitor = ActionsMatcher::Visitor;
Expand Down
4 changes: 3 additions & 1 deletion dbms/src/Interpreters/ExpressionActions.cpp
Expand Up @@ -15,6 +15,7 @@
#include <set>
#include <optional>
#include <Columns/ColumnSet.h>
#include <Functions/FunctionHelpers.h>


namespace ProfileEvents
Expand Down Expand Up @@ -1208,7 +1209,8 @@ bool ExpressionActions::checkColumnIsAlwaysFalse(const String & column_name) con
{
if (action.type == action.ADD_COLUMN && action.result_name == set_to_check)
{
if (auto * column_set = typeid_cast<const ColumnSet *>(action.added_column.get()))
// Constant ColumnSet cannot be empty, so we only need to check non-constant ones.
if (auto * column_set = checkAndGetColumn<const ColumnSet>(action.added_column.get()))
{
if (column_set->getData()->getTotalRowCount() == 0)
return true;
Expand Down

0 comments on commit e04cdd4

Please sign in to comment.