Added method "getHeader" in IBlockOutputStream: development [#CLICKHOUSE-2]

This commit is contained in:
Alexey Milovidov 2018-02-19 23:23:25 +03:00
parent b747c83b15
commit ee4b5d2527
5 changed files with 28 additions and 63 deletions

View File

@ -71,9 +71,6 @@ void AddingDefaultBlockOutputStream::write(const Block & block)
} }
/// Computes explicitly specified values (in column_defaults) by default. /// Computes explicitly specified values (in column_defaults) by default.
/** @todo if somehow block does not contain values for implicitly-defaulted columns that are prerequisites
* for explicitly-defaulted ones, exception will be thrown during evaluating such columns
* (implicitly-defaulted columns are evaluated on the line after following one. */
evaluateMissingDefaults(res, required_columns, column_defaults, context); evaluateMissingDefaults(res, required_columns, column_defaults, context);
output->write(res); output->write(res);

View File

@ -142,39 +142,11 @@ ExpressionAction ExpressionAction::ordinaryJoin(std::shared_ptr<const Join> join
} }
ExpressionActions::Actions ExpressionAction::getPrerequisites(Block & sample_block)
{
ExpressionActions::Actions res;
if (type == APPLY_FUNCTION)
{
if (sample_block.has(result_name))
throw Exception("Column '" + result_name + "' already exists", ErrorCodes::DUPLICATE_COLUMN);
ColumnsWithTypeAndName arguments(argument_names.size());
for (size_t i = 0; i < argument_names.size(); ++i)
{
if (!sample_block.has(argument_names[i]))
throw Exception("Unknown identifier: '" + argument_names[i] + "'", ErrorCodes::UNKNOWN_IDENTIFIER);
arguments[i] = sample_block.getByName(argument_names[i]);
}
function = function_builder->build(arguments);
result_type = function->getReturnType();
}
return res;
}
void ExpressionAction::prepare(Block & sample_block) void ExpressionAction::prepare(Block & sample_block)
{ {
// std::cerr << "preparing: " << toString() << std::endl; // std::cerr << "preparing: " << toString() << std::endl;
/** Constant expressions should be evaluated, and put the result in sample_block. /** Constant expressions should be evaluated, and put the result in sample_block.
* For non-constant columns, put the nullptr as the column in sample_block.
*
* The fact that only for constant expressions column != nullptr,
* can be used later when optimizing the query.
*/ */
switch (type) switch (type)
@ -567,40 +539,43 @@ void ExpressionActions::addInput(const NameAndTypePair & column)
void ExpressionActions::add(const ExpressionAction & action, Names & out_new_columns) void ExpressionActions::add(const ExpressionAction & action, Names & out_new_columns)
{ {
NameSet temp_names; addImpl(action, out_new_columns);
addImpl(action, temp_names, out_new_columns);
} }
void ExpressionActions::add(const ExpressionAction & action) void ExpressionActions::add(const ExpressionAction & action)
{ {
NameSet temp_names;
Names new_names; Names new_names;
addImpl(action, temp_names, new_names); addImpl(action, new_names);
} }
void ExpressionActions::addImpl(ExpressionAction action, NameSet & current_names, Names & new_names) void ExpressionActions::addImpl(ExpressionAction action, Names & new_names)
{ {
if (sample_block.has(action.result_name)) if (sample_block.has(action.result_name))
return; return;
if (current_names.count(action.result_name))
throw Exception("Cyclic function prerequisites: " + action.result_name, ErrorCodes::LOGICAL_ERROR);
current_names.insert(action.result_name);
if (action.result_name != "") if (action.result_name != "")
new_names.push_back(action.result_name); new_names.push_back(action.result_name);
new_names.insert(new_names.end(), action.array_joined_columns.begin(), action.array_joined_columns.end()); new_names.insert(new_names.end(), action.array_joined_columns.begin(), action.array_joined_columns.end());
Actions prerequisites = action.getPrerequisites(sample_block); if (action.type == ExpressionAction::APPLY_FUNCTION)
{
if (sample_block.has(action.result_name))
throw Exception("Column '" + action.result_name + "' already exists", ErrorCodes::DUPLICATE_COLUMN);
for (size_t i = 0; i < prerequisites.size(); ++i) ColumnsWithTypeAndName arguments(action.argument_names.size());
addImpl(prerequisites[i], current_names, new_names); for (size_t i = 0; i < action.argument_names.size(); ++i)
{
if (!sample_block.has(action.argument_names[i]))
throw Exception("Unknown identifier: '" + action.argument_names[i] + "'", ErrorCodes::UNKNOWN_IDENTIFIER);
arguments[i] = sample_block.getByName(action.argument_names[i]);
}
action.function = action.function_builder->build(arguments);
action.result_type = action.function->getReturnType();
}
action.prepare(sample_block); action.prepare(sample_block);
actions.push_back(action); actions.push_back(action);
current_names.erase(action.result_name);
} }
void ExpressionActions::prependProjectInput() void ExpressionActions::prependProjectInput()

View File

@ -99,7 +99,6 @@ public:
static ExpressionAction ordinaryJoin(std::shared_ptr<const Join> join_, const NamesAndTypesList & columns_added_by_join_); static ExpressionAction ordinaryJoin(std::shared_ptr<const Join> join_, const NamesAndTypesList & columns_added_by_join_);
/// Which columns necessary to perform this action. /// Which columns necessary to perform this action.
/// If this `Action` is not already added to `ExpressionActions`, the returned list may be incomplete, because `prerequisites` are not taken into account.
Names getNeededColumns() const; Names getNeededColumns() const;
std::string toString() const; std::string toString() const;
@ -107,7 +106,6 @@ public:
private: private:
friend class ExpressionActions; friend class ExpressionActions;
std::vector<ExpressionAction> getPrerequisites(Block & sample_block);
void prepare(Block & sample_block); void prepare(Block & sample_block);
void execute(Block & block) const; void execute(Block & block) const;
void executeOnTotals(Block & block) const; void executeOnTotals(Block & block) const;
@ -147,8 +145,7 @@ public:
void add(const ExpressionAction & action); void add(const ExpressionAction & action);
/// Adds new column names to out_new_columns /// Adds new column names to out_new_columns (formed as a result of the added action).
/// (formed as a result of the added action and its prerequisites).
void add(const ExpressionAction & action, Names & out_new_columns); void add(const ExpressionAction & action, Names & out_new_columns);
/// Adds to the beginning the removal of all extra columns. /// Adds to the beginning the removal of all extra columns.
@ -208,9 +205,7 @@ private:
void checkLimits(Block & block) const; void checkLimits(Block & block) const;
/// Adds all `prerequisites` first, then the action itself. void addImpl(ExpressionAction action, Names & new_names);
/// current_names - columns whose `prerequisites` are currently being processed.
void addImpl(ExpressionAction action, NameSet & current_names, Names & new_names);
/// Try to improve something without changing the lists of input and output columns. /// Try to improve something without changing the lists of input and output columns.
void optimize(); void optimize();

View File

@ -2653,7 +2653,13 @@ Block ExpressionAnalyzer::getSelectSampleBlock()
temp_actions->add(ExpressionAction::project(result_columns)); temp_actions->add(ExpressionAction::project(result_columns));
return temp_actions->getSampleBlock(); Block res = temp_actions->getSampleBlock();
for (auto & elem : res)
if (!elem.column)
elem.column = elem.type->createColumn();
return res;
} }
void ExpressionAnalyzer::getActionsBeforeAggregation(const ASTPtr & ast, ExpressionActionsPtr & actions, bool no_subqueries) void ExpressionAnalyzer::getActionsBeforeAggregation(const ASTPtr & ast, ExpressionActionsPtr & actions, bool no_subqueries)

View File

@ -374,15 +374,7 @@ DataTypes InterpreterSelectQuery::getReturnTypes()
Block InterpreterSelectQuery::getSampleBlock() Block InterpreterSelectQuery::getSampleBlock()
{ {
Block block = query_analyzer->getSelectSampleBlock(); return query_analyzer->getSelectSampleBlock();
/// create non-zero columns so that SampleBlock can be
/// written (read) with BlockOut(In)putStreams
for (size_t i = 0; i < block.columns(); ++i)
{
ColumnWithTypeAndName & col = block.safeGetByPosition(i);
col.column = col.type->createColumn();
}
return block;
} }