2017-04-01 09:19:00 +00:00
# include <Storages/MergeTree/ActiveDataPartSet.h>
2021-05-13 11:29:59 +00:00
# include <Common/Exception.h>
2022-04-27 15:05:45 +00:00
# include <Common/logger_useful.h>
2018-06-18 12:17:46 +00:00
# include <algorithm>
2021-06-01 13:25:23 +00:00
# include <cassert>
2016-06-07 08:23:15 +00:00
namespace DB
{
2021-07-01 12:12:27 +00:00
namespace ErrorCodes
{
extern const int LOGICAL_ERROR ;
}
2021-05-13 11:29:59 +00:00
2017-08-25 20:41:45 +00:00
ActiveDataPartSet : : ActiveDataPartSet ( MergeTreeDataFormatVersion format_version_ , const Strings & names )
: format_version ( format_version_ )
2016-06-07 08:23:15 +00:00
{
for ( const auto & name : names )
2018-05-10 15:01:10 +00:00
add ( name ) ;
2016-06-07 08:23:15 +00:00
}
2021-06-30 12:29:09 +00:00
bool ActiveDataPartSet : : add ( const String & name , Strings * out_replaced_parts )
2016-06-07 08:23:15 +00:00
{
2021-05-13 11:29:59 +00:00
/// TODO make it exception safe (out_replaced_parts->push_back(...) may throw)
2017-08-25 20:41:45 +00:00
auto part_info = MergeTreePartInfo : : fromPartName ( name , format_version ) ;
2017-04-01 07:20:54 +00:00
2018-05-10 15:01:10 +00:00
if ( getContainingPartImpl ( part_info ) ! = part_info_to_name . end ( ) )
2018-06-18 12:17:46 +00:00
return false ;
2017-04-01 07:20:54 +00:00
2017-08-15 16:21:13 +00:00
/// Parts contained in `part` are located contiguously in `part_info_to_name`, overlapping with the place where the part itself would be inserted.
2017-08-15 11:59:08 +00:00
auto it = part_info_to_name . lower_bound ( part_info ) ;
2017-04-01 07:20:54 +00:00
2018-06-18 12:17:46 +00:00
if ( out_replaced_parts )
out_replaced_parts - > clear ( ) ;
2017-03-13 18:01:46 +00:00
/// Let's go left.
2017-08-15 11:59:08 +00:00
while ( it ! = part_info_to_name . begin ( ) )
2016-06-07 08:23:15 +00:00
{
- - it ;
2017-08-15 11:59:08 +00:00
if ( ! part_info . contains ( it - > first ) )
2016-06-07 08:23:15 +00:00
{
2021-05-13 11:29:59 +00:00
if ( ! part_info . isDisjoint ( it - > first ) )
2021-10-06 12:28:52 +00:00
throw Exception ( ErrorCodes : : LOGICAL_ERROR , " Part {} intersects previous part {}. It is a bug or a result of manual intervention in the ZooKeeper data. " , name , it - > first . getPartName ( ) ) ;
2016-06-07 08:23:15 +00:00
+ + it ;
break ;
}
2018-06-18 12:17:46 +00:00
if ( out_replaced_parts )
out_replaced_parts - > push_back ( it - > second ) ;
2021-12-20 10:42:31 +00:00
it = part_info_to_name . erase ( it ) ;
2016-06-07 08:23:15 +00:00
}
2017-04-01 07:20:54 +00:00
2018-06-18 12:17:46 +00:00
if ( out_replaced_parts )
std : : reverse ( out_replaced_parts - > begin ( ) , out_replaced_parts - > end ( ) ) ;
2017-03-13 18:01:46 +00:00
/// Let's go to the right.
2017-08-15 11:59:08 +00:00
while ( it ! = part_info_to_name . end ( ) & & part_info . contains ( it - > first ) )
2016-06-07 08:23:15 +00:00
{
2021-06-01 13:25:23 +00:00
assert ( part_info ! = it - > first ) ;
2018-06-18 12:17:46 +00:00
if ( out_replaced_parts )
out_replaced_parts - > push_back ( it - > second ) ;
2021-12-20 10:42:31 +00:00
it = part_info_to_name . erase ( it ) ;
2016-06-07 08:23:15 +00:00
}
2017-04-01 07:20:54 +00:00
2021-05-13 11:29:59 +00:00
if ( it ! = part_info_to_name . end ( ) & & ! part_info . isDisjoint ( it - > first ) )
2022-11-18 15:33:43 +00:00
throw Exception ( ErrorCodes : : LOGICAL_ERROR , " Part {} intersects part {}. It is a bug or a result of manual intervention in the ZooKeeper data. " , name , it - > first . getPartName ( ) ) ;
2021-05-13 11:29:59 +00:00
2017-08-15 11:59:08 +00:00
part_info_to_name . emplace ( part_info , name ) ;
2018-06-18 12:17:46 +00:00
return true ;
2016-06-07 08:23:15 +00:00
}
2018-05-10 15:01:10 +00:00
String ActiveDataPartSet : : getContainingPart ( const MergeTreePartInfo & part_info ) const
{
auto it = getContainingPartImpl ( part_info ) ;
if ( it ! = part_info_to_name . end ( ) )
return it - > second ;
return { } ;
}
String ActiveDataPartSet : : getContainingPart ( const String & name ) const
2016-06-07 08:23:15 +00:00
{
2018-05-10 15:01:10 +00:00
auto it = getContainingPartImpl ( MergeTreePartInfo : : fromPartName ( name , format_version ) ) ;
if ( it ! = part_info_to_name . end ( ) )
return it - > second ;
return { } ;
2016-06-08 13:08:20 +00:00
}
2016-06-07 08:23:15 +00:00
2018-05-10 15:01:10 +00:00
std : : map < MergeTreePartInfo , String > : : const_iterator
ActiveDataPartSet : : getContainingPartImpl ( const MergeTreePartInfo & part_info ) const
2016-06-08 13:08:20 +00:00
{
2017-08-15 16:21:13 +00:00
/// A part can only be covered/overlapped by the previous or next one in `part_info_to_name`.
2017-08-15 11:59:08 +00:00
auto it = part_info_to_name . lower_bound ( part_info ) ;
2017-04-01 07:20:54 +00:00
2017-08-15 11:59:08 +00:00
if ( it ! = part_info_to_name . end ( ) )
2016-06-07 08:23:15 +00:00
{
2017-08-15 11:59:08 +00:00
if ( it - > first . contains ( part_info ) )
2018-05-10 15:01:10 +00:00
return it ;
2016-06-07 08:23:15 +00:00
}
2017-04-01 07:20:54 +00:00
2017-08-15 11:59:08 +00:00
if ( it ! = part_info_to_name . begin ( ) )
2016-06-07 08:23:15 +00:00
{
- - it ;
2017-08-15 11:59:08 +00:00
if ( it - > first . contains ( part_info ) )
2018-05-10 15:01:10 +00:00
return it ;
2016-06-07 08:23:15 +00:00
}
2017-04-01 07:20:54 +00:00
2018-05-10 15:01:10 +00:00
return part_info_to_name . end ( ) ;
2016-06-07 08:23:15 +00:00
}
2018-05-10 15:01:10 +00:00
Strings ActiveDataPartSet : : getPartsCoveredBy ( const MergeTreePartInfo & part_info ) const
2016-06-07 08:23:15 +00:00
{
2018-05-10 15:01:10 +00:00
auto it_middle = part_info_to_name . lower_bound ( part_info ) ;
auto begin = it_middle ;
while ( begin ! = part_info_to_name . begin ( ) )
{
auto prev = std : : prev ( begin ) ;
if ( ! part_info . contains ( prev - > first ) )
{
if ( prev - > first . contains ( part_info ) )
return { } ;
break ;
}
2016-06-07 08:23:15 +00:00
2018-05-10 15:01:10 +00:00
begin = prev ;
}
auto end = it_middle ;
while ( end ! = part_info_to_name . end ( ) )
{
if ( ! part_info . contains ( end - > first ) )
{
if ( end - > first . contains ( part_info ) )
return { } ;
break ;
}
+ + end ;
}
Strings covered ;
for ( auto it = begin ; it ! = end ; + + it )
covered . push_back ( it - > second ) ;
return covered ;
}
Strings ActiveDataPartSet : : getParts ( ) const
{
2016-06-07 08:23:15 +00:00
Strings res ;
2017-08-15 11:59:08 +00:00
res . reserve ( part_info_to_name . size ( ) ) ;
for ( const auto & kv : part_info_to_name )
res . push_back ( kv . second ) ;
2016-06-07 08:23:15 +00:00
return res ;
}
size_t ActiveDataPartSet : : size ( ) const
{
2017-08-15 11:59:08 +00:00
return part_info_to_name . size ( ) ;
2016-06-07 08:23:15 +00:00
}
}