summaryrefslogtreecommitdiff
path: root/sql/ha_partition.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/ha_partition.cc')
-rw-r--r--sql/ha_partition.cc75
1 files changed, 67 insertions, 8 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 67406627e20..248b95751af 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -80,18 +80,18 @@ static handler *partition_create_handler(handlerton *hton,
static uint partition_flags();
static uint alter_table_flags(uint flags);
+extern "C" int cmp_key_then_part_id(void *key_p, uchar *ref1, uchar *ref2);
+
/*
If frm_error() is called then we will use this to to find out what file
extensions exist for the storage engine. This is also used by the default
rename_table and delete_table method in handler.cc.
*/
-
static const char *ha_partition_ext[]=
{
ha_par_ext, NullS
};
-
static int partition_initialize(void *p)
{
@@ -4527,8 +4527,8 @@ bool ha_partition::init_record_priority_queue()
} while (++i < m_tot_parts);
m_start_key.key= (const uchar*)ptr;
/* Initialize priority queue, initialized to reading forward. */
- if (init_queue(&m_queue, used_parts, (uint) PARTITION_BYTES_IN_POS,
- 0, key_rec_cmp, (void*)m_curr_key_info, 0, 0))
+ if (init_queue(&m_queue, used_parts, 0,
+ 0, cmp_key_then_part_id, (void*)m_curr_key_info, 0, 0))
{
my_free(m_ordered_rec_buffer);
m_ordered_rec_buffer= NULL;
@@ -4724,6 +4724,52 @@ int ha_partition::index_read_map(uchar *buf, const uchar *key,
}
+/*
+ @brief
+ Provide ordering by (key_value, partition_id).
+
+ @detail
+ Ordering by partition id is required so that key scans on key=const
+ return rows in rowid order (this is required for some variants of
+ index_merge to work).
+
+ In ha_partition, rowid is a (partition_id, underlying_table_rowid).
+ handle_ordered_index_scan must return rows ordered by (key, rowid).
+
+ If two rows have the same key value and come from different partitions,
+ it is sufficient to return them in the order of their partition_id.
+*/
+
+extern "C" int cmp_key_then_part_id(void *key_p, uchar *ref1, uchar *ref2)
+{
+ my_ptrdiff_t diff1, diff2;
+ int res;
+
+ if ((res= key_rec_cmp(key_p, ref1 + PARTITION_BYTES_IN_POS,
+ ref2 + PARTITION_BYTES_IN_POS)))
+ {
+ return res;
+ }
+
+ /* The following was taken from ha_partition::cmp_ref */
+ diff1= ref2[1] - ref1[1];
+ diff2= ref2[0] - ref1[0];
+ if (!diff1 && !diff2)
+ return 0;
+
+ if (diff1 > 0)
+ return(-1);
+
+ if (diff1 < 0)
+ return(+1);
+
+ if (diff2 > 0)
+ return(-1);
+
+ return(+1);
+}
+
+
/**
Common routine for a number of index_read variants
@@ -5551,7 +5597,7 @@ void ha_partition::return_top_record(uchar *buf)
int ha_partition::handle_ordered_index_scan_key_not_found()
{
int error;
- uint i;
+ uint i, old_elements= m_queue.elements;
uchar *part_buf= m_ordered_rec_buffer;
uchar *curr_rec_buf= NULL;
DBUG_ENTER("ha_partition::handle_ordered_index_scan_key_not_found");
@@ -5586,9 +5632,12 @@ int ha_partition::handle_ordered_index_scan_key_not_found()
bitmap_clear_all(&m_key_not_found_partitions);
m_key_not_found= false;
- /* Update m_top_entry, which may have changed. */
- uchar *key_buffer= queue_top(&m_queue);
- m_top_entry= uint2korr(key_buffer);
+ if (m_queue.elements > old_elements)
+ {
+ /* Update m_top_entry, which may have changed. */
+ uchar *key_buffer= queue_top(&m_queue);
+ m_top_entry= uint2korr(key_buffer);
+ }
DBUG_RETURN(0);
}
@@ -7619,6 +7668,16 @@ uint ha_partition::min_record_length(uint options) const
If they belong to different partitions we decide that they are not
the same record. Otherwise we use the particular handler to decide if
they are the same. Sort in partition id order if not equal.
+
+ MariaDB note:
+ Please don't merge the code from MySQL that does this:
+
+ We get two references and need to check if those records are the same.
+ If they belong to different partitions we decide that they are not
+ the same record. Otherwise we use the particular handler to decide if
+ they are the same. Sort in partition id order if not equal.
+
+ It is incorrect, MariaDB has an alternative fix.
*/
int ha_partition::cmp_ref(const uchar *ref1, const uchar *ref2)