@ -5103,59 +5103,69 @@ bool ha_partition::init_record_priority_queue()
/*
Initialize the ordered record buffer .
*/
if ( ! m_ordered_rec_buffer )
{
uint alloc_len ;
uint used_parts = bitmap_bits_set ( & m_part_info - > read_partitions ) ;
/* Allocate record buffer for each used partition. */
m_priority_queue_rec_len = m_rec_length + PARTITION_BYTES_IN_POS ;
if ( ! m_using_extended_keys )
m_priority_queue_rec_len + = m_file [ 0 ] - > ref_length ;
alloc_len = used_parts * m_priority_queue_rec_len ;
/* Allocate a key for temporary use when setting up the scan. */
alloc_len + = table_share - > max_key_length ;
if ( ! ( m_ordered_rec_buffer = ( uchar * ) my_malloc ( alloc_len , MYF ( MY_WME ) ) ) )
DBUG_RETURN ( true ) ;
uint alloc_len ;
uint used_parts = bitmap_bits_set ( & m_part_info - > read_partitions ) ;
/* Allocate record buffer for each used partition. */
m_priority_queue_rec_len = m_rec_length + ORDERED_REC_OFFSET ;
if ( ! m_using_extended_keys )
m_priority_queue_rec_len + = m_file [ 0 ] - > ref_length ;
alloc_len = used_parts * m_priority_queue_rec_len ;
/* Allocate a key for temporary use when setting up the scan. */
alloc_len + = table_share - > max_key_length ;
Ordered_blob_storage * * blob_storage ;
Ordered_blob_storage * objs ;
const size_t n_all = used_parts * table - > s - > blob_fields ;
if ( ! my_multi_malloc ( MYF ( MY_WME ) , & m_ordered_rec_buffer , alloc_len ,
& blob_storage , n_all * sizeof ( Ordered_blob_storage * ) ,
& objs , n_all * sizeof ( Ordered_blob_storage ) , NULL ) )
DBUG_RETURN ( true ) ;
/*
We set - up one record per partition and each record has 2 bytes in
front where the partition id is written . This is used by ordered
index_read .
We also set - up a reference to the first record for temporary use in
setting up the scan .
*/
char * ptr = ( char * ) m_ordered_rec_buffer ;
uint i ;
for ( i = bitmap_get_first_set ( & m_part_info - > read_partitions ) ;
i < m_tot_parts ;
i = bitmap_get_next_set ( & m_part_info - > read_partitions , i ) )
{
DBUG_PRINT ( " info " , ( " init rec-buf for part %u " , i ) ) ;
int2store ( ptr , i ) ;
ptr + = m_priority_queue_rec_len ;
}
m_start_key . key = ( const uchar * ) ptr ;
/* Initialize priority queue, initialized to reading forward. */
int ( * cmp_func ) ( void * , uchar * , uchar * ) ;
void * cmp_arg ;
if ( ! m_using_extended_keys )
{
cmp_func = cmp_key_rowid_part_id ;
cmp_arg = ( void * ) this ;
}
else
{
cmp_func = cmp_key_part_id ;
cmp_arg = ( void * ) m_curr_key_info ;
}
if ( init_queue ( & m_queue , used_parts , 0 , 0 , cmp_func , cmp_arg , 0 , 0 ) )
/*
We set - up one record per partition and each record has 2 bytes in
front where the partition id is written . This is used by ordered
index_read .
We also set - up a reference to the first record for temporary use in
setting up the scan .
*/
char * ptr = ( char * ) m_ordered_rec_buffer ;
uint i ;
for ( i = bitmap_get_first_set ( & m_part_info - > read_partitions ) ;
i < m_tot_parts ;
i = bitmap_get_next_set ( & m_part_info - > read_partitions , i ) )
{
DBUG_PRINT ( " info " , ( " init rec-buf for part %u " , i ) ) ;
if ( table - > s - > blob_fields )
{
my_free ( m_ordered_rec_buffer ) ;
m_ordered_rec_buffer = NULL ;
DBUG_RETURN ( true ) ;
for ( uint j = 0 ; j < table - > s - > blob_fields ; + + j , + + objs )
blob_storage [ j ] = new ( objs ) Ordered_blob_storage ;
* ( ( Ordered_blob_storage * * * ) ptr ) = blob_storage ;
blob_storage + = table - > s - > blob_fields ;
}
int2store ( ptr + sizeof ( String * * ) , i ) ;
ptr + = m_priority_queue_rec_len ;
}
m_start_key . key = ( const uchar * ) ptr ;
/* Initialize priority queue, initialized to reading forward. */
int ( * cmp_func ) ( void * , uchar * , uchar * ) ;
void * cmp_arg ;
if ( ! m_using_extended_keys )
{
cmp_func = cmp_key_rowid_part_id ;
cmp_arg = ( void * ) this ;
}
else
{
cmp_func = cmp_key_part_id ;
cmp_arg = ( void * ) m_curr_key_info ;
}
if ( init_queue ( & m_queue , used_parts , ORDERED_PART_NUM_OFFSET ,
0 , cmp_func , cmp_arg , 0 , 0 ) )
{
my_free ( m_ordered_rec_buffer ) ;
m_ordered_rec_buffer = NULL ;
DBUG_RETURN ( true ) ;
}
DBUG_RETURN ( false ) ;
}
@ -5170,6 +5180,20 @@ void ha_partition::destroy_record_priority_queue()
DBUG_ENTER ( " ha_partition::destroy_record_priority_queue " ) ;
if ( m_ordered_rec_buffer )
{
if ( table - > s - > blob_fields )
{
char * ptr = ( char * ) m_ordered_rec_buffer ;
for ( uint i = bitmap_get_first_set ( & m_part_info - > read_partitions ) ;
i < m_tot_parts ;
i = bitmap_get_next_set ( & m_part_info - > read_partitions , i ) )
{
Ordered_blob_storage * * blob_storage = * ( ( Ordered_blob_storage * * * ) ptr ) ;
for ( uint b = 0 ; b < table - > s - > blob_fields ; + + b )
blob_storage [ b ] - > blob . free ( ) ;
ptr + = m_priority_queue_rec_len ;
}
}
delete_queue ( & m_queue ) ;
my_free ( m_ordered_rec_buffer ) ;
m_ordered_rec_buffer = NULL ;
@ -5394,7 +5418,7 @@ static int cmp_part_ids(uchar *ref1, uchar *ref2)
extern " C " int cmp_key_part_id ( void * key_p , uchar * ref1 , uchar * ref2 )
{
int res ;
if ( ( res = key_rec_cmp ( key_p , ref1 + PARTITION_BYTES_IN_POS ,
if ( ( res = key_rec_cmp ( key_p , ref1 + PARTITION_BYTES_IN_POS ,
ref2 + PARTITION_BYTES_IN_POS ) ) )
{
return res ;
@ -6133,8 +6157,8 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
{
DBUG_PRINT ( " info " , ( " reading from part %u (scan_type: %u) " ,
i , m_index_scan_type ) ) ;
DBUG_ASSERT ( i = = uint2korr ( part_rec_buf_ptr ) ) ;
uchar * rec_buf_ptr = part_rec_buf_ptr + PARTITION_BYTES_IN_POS ;
DBUG_ASSERT ( i = = uint2korr ( part_rec_buf_ptr + ORDERED_PART_NUM_OFFSET ) ) ;
uchar * rec_buf_ptr = part_rec_buf_ptr + ORDERED_REC_OFFSET ;
int error ;
handler * file = m_file [ i ] ;
@ -6162,6 +6186,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
error = file - > read_range_first ( m_start_key . key ? & m_start_key : NULL ,
end_range , eq_range , TRUE ) ;
memcpy ( rec_buf_ptr , table - > record [ 0 ] , m_rec_length ) ;
reverse_order = FALSE ;
break ;
}
@ -6181,6 +6206,11 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
Initialize queue without order first , simply insert
*/
queue_element ( & m_queue , j + + ) = part_rec_buf_ptr ;
if ( table - > s - > blob_fields )
{
Ordered_blob_storage * * storage = * ( ( Ordered_blob_storage * * * ) part_rec_buf_ptr ) ;
swap_blobs ( rec_buf_ptr , storage , false ) ;
}
}
else if ( error ! = HA_ERR_KEY_NOT_FOUND & & error ! = HA_ERR_END_OF_FILE )
{
@ -6229,10 +6259,15 @@ void ha_partition::return_top_record(uchar *buf)
{
uint part_id ;
uchar * key_buffer = queue_top ( & m_queue ) ;
uchar * rec_buffer = key_buffer + PARTITION_BYTES_IN_POS ;
uchar * rec_buffer = key_buffer + ORDERED_REC_OFFSET ;
part_id = uint2korr ( key_buffer ) ;
part_id = uint2korr ( key_buffer + ORDERED_PART_NUM_OFFSET ) ;
memcpy ( buf , rec_buffer , m_rec_length ) ;
if ( table - > s - > blob_fields )
{
Ordered_blob_storage * * storage = * ( ( Ordered_blob_storage * * * ) key_buffer ) ;
swap_blobs ( buf , storage , true ) ;
}
m_last_part = part_id ;
m_top_entry = part_id ;
}
@ -6268,7 +6303,7 @@ int ha_partition::handle_ordered_index_scan_key_not_found()
This partition is used and did return HA_ERR_KEY_NOT_FOUND
in index_read_map .
*/
curr_rec_buf = part_buf + PARTITION_BYTES_IN_POS ;
curr_rec_buf = part_buf + ORDERED_REC_OFFSET ;
error = m_file [ i ] - > ha_index_next ( curr_rec_buf ) ;
/* HA_ERR_KEY_NOT_FOUND is not allowed from index_next! */
DBUG_ASSERT ( error ! = HA_ERR_KEY_NOT_FOUND ) ;
@ -6293,6 +6328,48 @@ int ha_partition::handle_ordered_index_scan_key_not_found()
}
void ha_partition : : swap_blobs ( uchar * rec_buf , Ordered_blob_storage * * storage , bool restore )
{
uint * ptr , * end ;
uint blob_n = 0 ;
table - > move_fields ( table - > field , rec_buf , table - > record [ 0 ] ) ;
for ( ptr = table - > s - > blob_field , end = ptr + table - > s - > blob_fields ;
ptr ! = end ; + + ptr , + + blob_n )
{
DBUG_ASSERT ( * ptr < table - > s - > fields ) ;
Field_blob * blob = ( Field_blob * ) table - > field [ * ptr ] ;
DBUG_ASSERT ( blob - > flags & BLOB_FLAG ) ;
DBUG_ASSERT ( blob - > field_index = = * ptr ) ;
if ( ! bitmap_is_set ( table - > read_set , * ptr ) | | blob - > is_null ( ) )
continue ;
Ordered_blob_storage & s = * storage [ blob_n ] ;
if ( restore )
{
/*
We protect only blob cache ( value or read_value ) . If the cache was
empty that doesn ' t mean the blob was empty . Blobs allocated by a
storage engine should work just fine .
*/
if ( ! s . blob . is_empty ( ) )
blob - > swap ( s . blob , s . set_read_value ) ;
}
else
{
bool set_read_value ;
String * cached = blob - > cached ( & set_read_value ) ;
if ( cached )
{
cached - > swap ( s . blob ) ;
s . set_read_value = set_read_value ;
}
}
}
table - > move_fields ( table - > field , table - > record [ 0 ] , rec_buf ) ;
}
/*
Common routine to handle index_next with ordered results
@ -6311,7 +6388,8 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
{
int error ;
uint part_id = m_top_entry ;
uchar * rec_buf = queue_top ( & m_queue ) + PARTITION_BYTES_IN_POS ;
uchar * part_rec_buf_ptr = queue_top ( & m_queue ) ;
uchar * rec_buf = part_rec_buf_ptr + ORDERED_REC_OFFSET ;
handler * file ;
DBUG_ENTER ( " ha_partition::handle_ordered_next " ) ;
@ -6354,7 +6432,15 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
if ( m_index_scan_type = = partition_read_range )
{
error = file - > read_range_next ( ) ;
memcpy ( rec_buf , table - > record [ 0 ] , m_rec_length ) ;
if ( ! error )
{
memcpy ( rec_buf , table - > record [ 0 ] , m_rec_length ) ;
if ( table - > s - > blob_fields )
{
Ordered_blob_storage * * storage = * ( ( Ordered_blob_storage * * * ) part_rec_buf_ptr ) ;
swap_blobs ( rec_buf , storage , false ) ;
}
}
}
else if ( ! is_next_same )
error = file - > ha_index_next ( rec_buf ) ;
@ -6410,7 +6496,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
{
int error ;
uint part_id = m_top_entry ;
uchar * rec_buf = queue_top ( & m_queue ) + PARTITION_BYTES_IN_POS ;
uchar * rec_buf = queue_top ( & m_queue ) + ORDERED_REC_OFFSET ;
handler * file = m_file [ part_id ] ;
DBUG_ENTER ( " ha_partition::handle_ordered_prev " ) ;