ClickHouse/src/Processors/Formats/IOutputFormat.cpp

129 lines
2.6 KiB
C++
Raw Normal View History

#include <Processors/Formats/IOutputFormat.h>
2019-02-19 18:41:18 +00:00
#include <IO/WriteBuffer.h>
namespace DB
{
2019-08-03 11:02:40 +00:00
IOutputFormat::IOutputFormat(const Block & header_, WriteBuffer & out_)
: IProcessor({header_, header_, header_}, {}), out(out_)
{
}
IOutputFormat::Status IOutputFormat::prepare()
{
2019-02-07 18:51:53 +00:00
if (has_input)
return Status::Ready;
for (auto kind : {Main, Totals, Extremes})
{
auto & input = getPort(kind);
2019-02-07 18:51:53 +00:00
if (kind != Main && !input.isConnected())
continue;
2019-02-07 18:51:53 +00:00
if (input.isFinished())
continue;
input.setNeeded();
if (!input.hasData())
return Status::NeedData;
2019-02-07 18:51:53 +00:00
current_chunk = input.pull(true);
2019-02-07 18:51:53 +00:00
current_block_kind = kind;
has_input = true;
return Status::Ready;
}
2019-02-19 18:41:18 +00:00
finished = true;
if (!finalized)
return Status::Ready;
return Status::Finished;
}
static Chunk prepareTotals(Chunk chunk)
2020-09-07 17:49:23 +00:00
{
if (!chunk.hasRows())
2020-09-07 17:49:23 +00:00
return {};
if (chunk.getNumRows() > 1)
2020-09-07 17:49:23 +00:00
{
/// This may happen if something like ARRAY JOIN was executed on totals.
/// Skip rows except the first one.
auto columns = chunk.detachColumns();
2020-09-07 17:49:23 +00:00
for (auto & column : columns)
column = column->cut(0, 1);
chunk.setColumns(std::move(columns), 1);
2020-09-07 17:49:23 +00:00
}
return chunk;
2020-09-07 17:49:23 +00:00
}
void IOutputFormat::work()
{
2021-11-02 13:40:41 +00:00
writePrefixIfNot();
2019-02-19 18:41:18 +00:00
if (finished && !finalized)
{
if (rows_before_limit_counter && rows_before_limit_counter->hasAppliedLimit())
setRowsBeforeLimit(rows_before_limit_counter->get());
finalize();
2019-02-19 18:41:18 +00:00
finalized = true;
return;
}
switch (current_block_kind)
{
case Main:
result_rows += current_chunk.getNumRows();
result_bytes += current_chunk.allocatedBytes();
consume(std::move(current_chunk));
break;
case Totals:
writeSuffixIfNot();
if (auto totals = prepareTotals(std::move(current_chunk)))
{
2020-09-07 17:49:23 +00:00
consumeTotals(std::move(totals));
are_totals_written = true;
}
break;
case Extremes:
writeSuffixIfNot();
consumeExtremes(std::move(current_chunk));
break;
}
2019-02-07 18:51:53 +00:00
if (auto_flush)
flush();
2019-02-07 18:51:53 +00:00
has_input = false;
}
2019-02-19 18:41:18 +00:00
void IOutputFormat::flush()
{
2021-08-19 11:07:47 +00:00
out.next();
2019-02-19 18:41:18 +00:00
}
2020-04-27 18:15:55 +00:00
void IOutputFormat::write(const Block & block)
{
2021-11-02 13:40:41 +00:00
writePrefixIfNot();
2020-04-27 18:15:55 +00:00
consume(Chunk(block.getColumns(), block.rows()));
if (auto_flush)
flush();
}
2021-11-11 18:09:21 +00:00
void IOutputFormat::finalize()
2021-11-02 13:40:41 +00:00
{
writePrefixIfNot();
writeSuffixIfNot();
2021-11-11 18:09:21 +00:00
finalizeImpl();
2021-11-02 13:40:41 +00:00
}
}