MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / appendBlock

Function appendBlock

src/Storages/StorageBuffer.cpp:596–705  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

594
595
596static void appendBlock(LoggerPtr log, const Block & from, Block & to)
597{
598 size_t rows = from.rows();
599 size_t old_bytes = to.bytes();
600
601 if (to.empty())
602 to = from.cloneEmpty();
603
604 assertBlocksHaveEqualStructure(from, to, "Buffer");
605
606 from.checkNumberOfRows();
607 to.checkNumberOfRows();
608
609 /// Take checkpoints of all destination columns before any modifications
610 /// to be able to rollback in case of an exception in the middle of insertion.
611 ColumnCheckpoints checkpoints;
612 checkpoints.reserve(to.columns());
613 for (size_t column_no = 0; column_no < to.columns(); ++column_no)
614 checkpoints.push_back(to.getByPosition(column_no).column->getCheckpoint());
615
616 MutableColumnPtr last_col;
617 size_t mutated_columns = 0;
618 try
619 {
620 MemoryTrackerBlockerInThread temporarily_disable_memory_tracker;
621
622 for (size_t column_no = 0, columns = to.columns(); column_no < columns; ++column_no)
623 {
624 const IColumn & col_from = *from.getByPosition(column_no).column.get();
625 {
626 /// Usually IColumn::mutate() here will simply move pointers,
627 /// however in case of parallel reading from it via SELECT, it
628 /// is possible for the full IColumn::clone() here, and in this
629 /// case it may fail due to MEMORY_LIMIT_EXCEEDED, and this
630 /// breaks the rollback, since the column got lost, it is
631 /// neither in last_col nor in "to" block.
632 ///
633 /// The safest option here, is to do a full clone every time,
634 /// however, it is overhead. And it looks like the only
635 /// exception that is possible here is MEMORY_LIMIT_EXCEEDED,
636 /// and it is better to simply suppress it, to avoid overhead
637 /// for every INSERT into Buffer (Anyway we have a
638 /// LOGICAL_ERROR in rollback that will bail if something else
639 /// will happens here).
640 LockMemoryExceptionInThread temporarily_ignore_any_memory_limits(VariableContext::Global);
641 last_col = IColumn::mutate(std::move(to.getByPosition(column_no).column));
642 }
643 ++mutated_columns;
644
645 /// In case of ColumnAggregateFunction aggregate states will
646 /// be allocated from the query context but can be destroyed from the
647 /// server context (in case of background flush), and thus memory
648 /// will be leaked from the query, but only tracked memory, not
649 /// memory itself.
650 ///
651 /// To avoid this, prohibit sharing the aggregate states.
652 last_col->ensureOwnership();
653 last_col->insertRangeFrom(col_from, 0, rows);

Callers 1

insertIntoBufferMethod · 0.85

Calls 15

checkNumberOfRowsMethod · 0.80
columnsMethod · 0.80
mutateFunction · 0.50
addFunction · 0.50
tryLogCurrentExceptionFunction · 0.50
ExceptionClass · 0.50
rowsMethod · 0.45
bytesMethod · 0.45
emptyMethod · 0.45
cloneEmptyMethod · 0.45
reserveMethod · 0.45

Tested by

no test coverage detected