2018-05-24 01:02:16 +00:00
|
|
|
#include <Processors/Formats/IOutputFormat.h>
|
2019-02-19 18:41:18 +00:00
|
|
|
#include <IO/WriteBuffer.h>
|
2018-05-24 01:02:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2019-08-03 11:02:40 +00:00
|
|
|
IOutputFormat::IOutputFormat(const Block & header_, WriteBuffer & out_)
|
|
|
|
: IProcessor({header_, header_, header_}, {}), out(out_)
|
2018-05-24 01:02:16 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
IOutputFormat::Status IOutputFormat::prepare()
|
|
|
|
{
|
2019-02-07 18:51:53 +00:00
|
|
|
if (has_input)
|
2018-05-24 01:02:16 +00:00
|
|
|
return Status::Ready;
|
|
|
|
|
|
|
|
for (auto kind : {Main, Totals, Extremes})
|
|
|
|
{
|
2019-02-27 11:24:14 +00:00
|
|
|
auto & input = getPort(kind);
|
2018-05-24 01:02:16 +00:00
|
|
|
|
2019-02-07 18:51:53 +00:00
|
|
|
if (kind != Main && !input.isConnected())
|
|
|
|
continue;
|
2018-05-24 01:02:16 +00:00
|
|
|
|
2019-02-07 18:51:53 +00:00
|
|
|
if (input.isFinished())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
input.setNeeded();
|
|
|
|
|
|
|
|
if (!input.hasData())
|
2018-05-24 01:02:16 +00:00
|
|
|
return Status::NeedData;
|
2019-02-07 18:51:53 +00:00
|
|
|
|
2021-01-03 18:51:57 +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;
|
2018-05-24 01:02:16 +00:00
|
|
|
}
|
|
|
|
|
2019-02-19 18:41:18 +00:00
|
|
|
finished = true;
|
|
|
|
|
|
|
|
if (!finalized)
|
|
|
|
return Status::Ready;
|
|
|
|
|
2018-05-24 01:02:16 +00:00
|
|
|
return Status::Finished;
|
|
|
|
}
|
|
|
|
|
2021-01-03 18:51:57 +00:00
|
|
|
static Chunk prepareTotals(Chunk chunk)
|
2020-09-07 17:49:23 +00:00
|
|
|
{
|
2021-01-03 18:51:57 +00:00
|
|
|
if (!chunk.hasRows())
|
2020-09-07 17:49:23 +00:00
|
|
|
return {};
|
|
|
|
|
2021-01-03 18:51:57 +00:00
|
|
|
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.
|
2021-01-03 18:51:57 +00:00
|
|
|
auto columns = chunk.detachColumns();
|
2020-09-07 17:49:23 +00:00
|
|
|
for (auto & column : columns)
|
|
|
|
column = column->cut(0, 1);
|
|
|
|
|
2021-01-03 18:51:57 +00:00
|
|
|
chunk.setColumns(std::move(columns), 1);
|
2020-09-07 17:49:23 +00:00
|
|
|
}
|
|
|
|
|
2021-01-03 18:51:57 +00:00
|
|
|
return chunk;
|
2020-09-07 17:49:23 +00:00
|
|
|
}
|
|
|
|
|
2018-05-24 01:02:16 +00:00
|
|
|
void IOutputFormat::work()
|
|
|
|
{
|
2021-11-02 13:40:41 +00:00
|
|
|
writePrefixIfNot();
|
2020-08-04 21:09:36 +00:00
|
|
|
|
2019-02-19 18:41:18 +00:00
|
|
|
if (finished && !finalized)
|
|
|
|
{
|
2020-03-19 11:45:52 +00:00
|
|
|
if (rows_before_limit_counter && rows_before_limit_counter->hasAppliedLimit())
|
|
|
|
setRowsBeforeLimit(rows_before_limit_counter->get());
|
|
|
|
|
2021-11-17 20:51:46 +00:00
|
|
|
finalize();
|
2019-02-19 18:41:18 +00:00
|
|
|
finalized = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-24 01:02:16 +00:00
|
|
|
switch (current_block_kind)
|
|
|
|
{
|
|
|
|
case Main:
|
2021-01-03 18:51:57 +00:00
|
|
|
result_rows += current_chunk.getNumRows();
|
|
|
|
result_bytes += current_chunk.allocatedBytes();
|
2019-02-18 16:36:07 +00:00
|
|
|
consume(std::move(current_chunk));
|
2018-05-24 01:02:16 +00:00
|
|
|
break;
|
|
|
|
case Totals:
|
2021-11-17 20:51:46 +00:00
|
|
|
writeSuffixIfNot();
|
2021-01-03 18:51:57 +00:00
|
|
|
if (auto totals = prepareTotals(std::move(current_chunk)))
|
2021-11-17 20:51:46 +00:00
|
|
|
{
|
2020-09-07 17:49:23 +00:00
|
|
|
consumeTotals(std::move(totals));
|
2021-11-17 20:51:46 +00:00
|
|
|
are_totals_written = true;
|
|
|
|
}
|
2018-05-24 01:02:16 +00:00
|
|
|
break;
|
|
|
|
case Extremes:
|
2021-11-17 20:51:46 +00:00
|
|
|
writeSuffixIfNot();
|
2019-02-18 16:36:07 +00:00
|
|
|
consumeExtremes(std::move(current_chunk));
|
2018-05-24 01:02:16 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-02-07 18:51:53 +00:00
|
|
|
|
2020-04-19 19:02:36 +00:00
|
|
|
if (auto_flush)
|
|
|
|
flush();
|
|
|
|
|
2019-02-07 18:51:53 +00:00
|
|
|
has_input = false;
|
2018-05-24 01:02:16 +00:00
|
|
|
}
|
|
|
|
|
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();
|
2021-11-17 20:51:46 +00:00
|
|
|
writeSuffixIfNot();
|
2021-11-11 18:09:21 +00:00
|
|
|
finalizeImpl();
|
2021-11-02 13:40:41 +00:00
|
|
|
}
|
|
|
|
|
2018-05-24 01:02:16 +00:00
|
|
|
}
|