1#pragma once
2
3#include <algorithm>
4#include <Processors/Chunk.h>
5#include <Columns/IColumn.h>
6#include <boost/smart_ptr/intrusive_ptr.hpp>
7
8
9namespace DB
10{
11
12/// Allows you refer to the row in the block and hold the block ownership,
13/// and thus avoid creating a temporary row object.
14/// Do not use std::shared_ptr, since there is no need for a place for `weak_count` and `deleter`;
15/// does not use Poco::SharedPtr, since you need to allocate a block and `refcount` in one piece;
16/// does not use Poco::AutoPtr, since it does not have a `move` constructor and there are extra checks for nullptr;
17/// The reference counter is not atomic, since it is used from one thread.
18namespace detail
19{
20struct SharedChunk : Chunk
21{
22 int refcount = 0;
23
24 ColumnRawPtrs all_columns;
25 ColumnRawPtrs sort_columns;
26
27 SharedChunk(Chunk && chunk) : Chunk(std::move(chunk)) {}
28};
29
30}
31
32inline void intrusive_ptr_add_ref(detail::SharedChunk * ptr)
33{
34 ++ptr->refcount;
35}
36
37inline void intrusive_ptr_release(detail::SharedChunk * ptr)
38{
39 if (0 == --ptr->refcount)
40 delete ptr;
41}
42
43using SharedChunkPtr = boost::intrusive_ptr<detail::SharedChunk>;
44
45
46struct SharedChunkRowRef
47{
48 ColumnRawPtrs * columns = nullptr;
49 size_t row_num;
50 SharedChunkPtr shared_block;
51
52 void swap(SharedChunkRowRef & other)
53 {
54 std::swap(columns, other.columns);
55 std::swap(row_num, other.row_num);
56 std::swap(shared_block, other.shared_block);
57 }
58
59 /// The number and types of columns must match.
60 bool operator==(const SharedChunkRowRef & other) const
61 {
62 size_t size = columns->size();
63 for (size_t i = 0; i < size; ++i)
64 if (0 != (*columns)[i]->compareAt(row_num, other.row_num, *(*other.columns)[i], 1))
65 return false;
66 return true;
67 }
68
69 bool operator!=(const SharedChunkRowRef & other) const
70 {
71 return !(*this == other);
72 }
73
74 void reset()
75 {
76 SharedChunkRowRef empty;
77 swap(empty);
78 }
79
80 bool empty() const { return columns == nullptr; }
81 size_t size() const { return empty() ? 0 : columns->size(); }
82
83 void set(SharedChunkPtr & shared_block_, ColumnRawPtrs * columns_, size_t row_num_)
84 {
85 shared_block = shared_block_;
86 columns = columns_;
87 row_num = row_num_;
88 }
89};
90
91}
92