1#pragma once
2
3#include <algorithm>
4#include <Core/Block.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{
20 struct SharedBlock : Block
21 {
22 int refcount = 0;
23
24 ColumnRawPtrs all_columns;
25 ColumnRawPtrs sort_columns;
26
27 SharedBlock(Block && block) : Block(std::move(block)) {}
28 };
29}
30
31inline void intrusive_ptr_add_ref(detail::SharedBlock * ptr)
32{
33 ++ptr->refcount;
34}
35
36inline void intrusive_ptr_release(detail::SharedBlock * ptr)
37{
38 if (0 == --ptr->refcount)
39 delete ptr;
40}
41
42using SharedBlockPtr = boost::intrusive_ptr<detail::SharedBlock>;
43
44struct SharedBlockRowRef
45{
46 ColumnRawPtrs * columns = nullptr;
47 size_t row_num;
48 SharedBlockPtr shared_block;
49
50 void swap(SharedBlockRowRef & other)
51 {
52 std::swap(columns, other.columns);
53 std::swap(row_num, other.row_num);
54 std::swap(shared_block, other.shared_block);
55 }
56
57 /// The number and types of columns must match.
58 bool operator==(const SharedBlockRowRef & other) const
59 {
60 size_t size = columns->size();
61 for (size_t i = 0; i < size; ++i)
62 if (0 != (*columns)[i]->compareAt(row_num, other.row_num, *(*other.columns)[i], 1))
63 return false;
64 return true;
65 }
66
67 bool operator!=(const SharedBlockRowRef & other) const
68 {
69 return !(*this == other);
70 }
71
72 void reset()
73 {
74 SharedBlockRowRef empty;
75 swap(empty);
76 }
77
78 bool empty() const { return columns == nullptr; }
79 size_t size() const { return empty() ? 0 : columns->size(); }
80
81 void set(SharedBlockPtr & shared_block_, ColumnRawPtrs * columns_, size_t row_num_)
82 {
83 shared_block = shared_block_;
84 columns = columns_;
85 row_num = row_num_;
86 }
87};
88
89}
90