summaryrefslogtreecommitdiff
path: root/sql/ha_partition.cc
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-08-18 16:51:52 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-08-18 16:51:52 +0300
commitf84e28c119b495da77e197f7cd18af4048fc3126 (patch)
tree5957008a7725e23cc6331b1251ff5d3f6b725076 /sql/ha_partition.cc
parentac2857a5fbf851d90171ac55f23385869ee6ba83 (diff)
parente4901d9523ab838ea13bb0278980f8707aa2c581 (diff)
downloadmariadb-git-f84e28c119b495da77e197f7cd18af4048fc3126.tar.gz
Merge 10.3 into 10.4
Diffstat (limited to 'sql/ha_partition.cc')
-rw-r--r--sql/ha_partition.cc215
1 files changed, 152 insertions, 63 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 50b9149ef0c..c8d5d68b5d6 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5289,58 +5289,68 @@ bool ha_partition::init_record_priority_queue()
/*
Initialize the ordered record buffer.
*/
- if (!m_ordered_rec_buffer)
- {
- size_t alloc_len;
- uint used_parts= bitmap_bits_set(&m_part_info->read_partitions);
-
- if (used_parts == 0) /* Do nothing since no records expected. */
- DBUG_RETURN(false);
+ size_t 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 += get_open_file_sample()->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 (used_parts == 0) /* Do nothing since no records expected. */
+ DBUG_RETURN(false);
- if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME))))
- DBUG_RETURN(true);
+ /* 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+= get_open_file_sample()->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 *blob_storage,
+ &objs, n_all * sizeof *objs, 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))
+ /*
+ 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)
{
- DBUG_PRINT("info", ("init rec-buf for part %u", i));
- int2store(ptr, i);
- ptr+= m_priority_queue_rec_len;
+ 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;
}
- m_start_key.key= (const uchar*)ptr;
+ 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= (void*) this;
- if (!m_using_extended_keys && !(table_flags() & HA_SLOW_CMP_REF))
- cmp_func= cmp_key_rowid_part_id;
- else
- cmp_func= cmp_key_part_id;
- DBUG_PRINT("info", ("partition queue_init(1) used_parts: %u", used_parts));
- if (init_queue(&m_queue, used_parts, 0, 0, cmp_func, cmp_arg, 0, 0))
- {
- my_free(m_ordered_rec_buffer);
- m_ordered_rec_buffer= NULL;
- DBUG_RETURN(true);
- }
+ /* Initialize priority queue, initialized to reading forward. */
+ int (*cmp_func)(void *, uchar *, uchar *);
+ void *cmp_arg= (void*) this;
+ if (!m_using_extended_keys && !(table_flags() & HA_SLOW_CMP_REF))
+ cmp_func= cmp_key_rowid_part_id;
+ else
+ cmp_func= cmp_key_part_id;
+ DBUG_PRINT("info", ("partition queue_init(1) used_parts: %u", used_parts));
+ 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);
}
@@ -5355,6 +5365,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;
@@ -5582,12 +5606,10 @@ static int cmp_part_ids(uchar *ref1, uchar *ref2)
extern "C" int cmp_key_part_id(void *ptr, uchar *ref1, uchar *ref2)
{
ha_partition *file= (ha_partition*)ptr;
- int res;
- if ((res= key_rec_cmp(file->m_curr_key_info, ref1 + PARTITION_BYTES_IN_POS,
- ref2 + PARTITION_BYTES_IN_POS)))
- {
+ if (int res= key_rec_cmp(file->m_curr_key_info,
+ ref1 + PARTITION_BYTES_IN_POS,
+ ref2 + PARTITION_BYTES_IN_POS))
return res;
- }
return cmp_part_ids(ref1, ref2);
}
@@ -6836,6 +6858,48 @@ int ha_partition::pre_ft_end()
}
+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);
+}
+
+
/**
Initialize a full text search using the extended API.
@@ -7549,8 +7613,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;
handler *file= m_file[i];
switch (m_index_scan_type) {
@@ -7630,6 +7694,12 @@ 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)
{
@@ -7672,7 +7742,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
DBUG_PRINT("info", ("partition !bitmap_is_set(&m_mrr_used_partitions, i)"));
continue;
}
- DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr));
+ DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr + ORDERED_PART_NUM_OFFSET));
if (smallest_range_seq == m_stock_range_seq[i])
{
m_stock_range_seq[i]= 0;
@@ -7719,12 +7789,17 @@ 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;
DBUG_ENTER("ha_partition::return_top_record");
DBUG_PRINT("enter", ("partition this: %p", this));
- 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;
DBUG_PRINT("info", ("partition m_last_part: %u", m_last_part));
m_top_entry= part_id;
@@ -7776,7 +7851,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);
@@ -7827,7 +7902,8 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
DBUG_RETURN(HA_ERR_END_OF_FILE);
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;
if (m_key_not_found)
@@ -7869,7 +7945,16 @@ 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 (likely(!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 (m_index_scan_type == partition_read_multi_range)
{
@@ -7906,6 +7991,11 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
DBUG_PRINT("info", ("m_mrr_range_current->id: %u",
m_mrr_range_current->id));
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);
+ }
if (((PARTITION_KEY_MULTI_RANGE *) m_range_info[part_id])->id !=
m_mrr_range_current->id)
{
@@ -7956,9 +8046,8 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
DBUG_PRINT("info",("partition !bitmap_is_set(&m_mrr_used_partitions, i)"));
continue;
}
- DBUG_PRINT("info",("partition uint2korr: %u",
- uint2korr(part_rec_buf_ptr)));
- DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr));
+ DBUG_ASSERT(i == uint2korr(part_rec_buf_ptr +
+ ORDERED_PART_NUM_OFFSET));
DBUG_PRINT("info", ("partition m_stock_range_seq[%u]: %u",
i, m_stock_range_seq[i]));
if (smallest_range_seq == m_stock_range_seq[i])
@@ -8047,7 +8136,7 @@ int ha_partition::handle_ordered_prev(uchar *buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
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];
if (unlikely((error= file->ha_index_prev(rec_buf))))