summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/ha_partition.cc69
-rw-r--r--sql/ha_partition.h1
-rw-r--r--sql/partition_info.h7
-rw-r--r--sql/sql_partition.cc35
4 files changed, 77 insertions, 35 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 31f59c662d4..e4924e8e8f2 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -2961,8 +2961,34 @@ int ha_partition::rnd_init(bool scan)
uint32 part_id;
DBUG_ENTER("ha_partition::rnd_init");
- include_partition_fields_in_used_fields();
-
+ /*
+ For operations that may need to change data, we may need to extend
+ read_set.
+ */
+ if (m_lock_type == F_WRLCK)
+ {
+ /*
+ If write_set contains any of the fields used in partition and
+ subpartition expression, we need to set all bits in read_set because
+ the row may need to be inserted in a different [sub]partition. In
+ other words update_row() can be converted into write_row(), which
+ requires a complete record.
+ */
+ if (bitmap_is_overlapping(&m_part_info->full_part_field_set,
+ table->write_set))
+ bitmap_set_all(table->read_set);
+ else
+ {
+ /*
+ Some handlers only read fields as specified by the bitmap for the
+ read set. For partitioned handlers we always require that the
+ fields of the partition functions are read such that we can
+ calculate the partition id to place updated and deleted records.
+ */
+ bitmap_union(table->read_set, &m_part_info->full_part_field_set);
+ }
+ }
+
/* Now we see what the index of our first important partition is */
DBUG_PRINT("info", ("m_part_info->used_partitions: 0x%lx",
(long) m_part_info->used_partitions.bitmap));
@@ -3276,7 +3302,15 @@ int ha_partition::index_init(uint inx, bool sorted)
m_start_key.length= 0;
m_ordered= sorted;
m_curr_key_info= table->key_info+inx;
- include_partition_fields_in_used_fields();
+ /*
+ Some handlers only read fields as specified by the bitmap for the
+ read set. For partitioned handlers we always require that the
+ fields of the partition functions are read such that we can
+ calculate the partition id to place updated and deleted records.
+ But this is required for operations that may need to change data only.
+ */
+ if (m_lock_type == F_WRLCK)
+ bitmap_union(table->read_set, &m_part_info->full_part_field_set);
file= m_file;
do
{
@@ -4145,35 +4179,6 @@ int ha_partition::handle_ordered_prev(uchar *buf)
}
-/*
- Set fields in partition functions in read set for underlying handlers
-
- SYNOPSIS
- include_partition_fields_in_used_fields()
-
- RETURN VALUE
- NONE
-
- DESCRIPTION
- Some handlers only read fields as specified by the bitmap for the
- read set. For partitioned handlers we always require that the
- fields of the partition functions are read such that we can
- calculate the partition id to place updated and deleted records.
-*/
-
-void ha_partition::include_partition_fields_in_used_fields()
-{
- Field **ptr= m_part_field_array;
- DBUG_ENTER("ha_partition::include_partition_fields_in_used_fields");
-
- do
- {
- bitmap_set_bit(table->read_set, (*ptr)->field_index);
- } while (*(++ptr));
- DBUG_VOID_RETURN;
-}
-
-
/****************************************************************************
MODULE information calls
****************************************************************************/
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index a168007ea04..895f001fa6a 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -449,7 +449,6 @@ private:
int handle_ordered_next(uchar * buf, bool next_same);
int handle_ordered_prev(uchar * buf);
void return_top_record(uchar * buf);
- void include_partition_fields_in_used_fields();
public:
/*
-------------------------------------------------------------------------
diff --git a/sql/partition_info.h b/sql/partition_info.h
index ce2f2a7b358..10edea074c0 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -81,6 +81,13 @@ public:
*/
Field **full_part_field_array;
Field **full_part_charset_field_array;
+ /*
+ Set of all fields used in partition and subpartition expression.
+ Required for testing of partition fields in write_set when
+ updating. We need to set all bits in read_set because the row may
+ need to be inserted in a different [sub]partition.
+ */
+ MY_BITMAP full_part_field_set;
/*
When we have a field that requires transformation before calling the
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index ad3cf2d3e7a..a44af968d9f 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -523,6 +523,7 @@ static bool set_up_field_array(TABLE *table,
SYNOPSIS
create_full_part_field_array()
+ thd Thread handle
table TABLE object for which partition fields are set-up
part_info Reference to partitioning data structure
@@ -537,11 +538,12 @@ static bool set_up_field_array(TABLE *table,
This function is called from fix_partition_func
*/
-static bool create_full_part_field_array(TABLE *table,
+static bool create_full_part_field_array(THD *thd, TABLE *table,
partition_info *part_info)
{
bool result= FALSE;
Field **ptr;
+ my_bitmap_map *bitmap_buf;
DBUG_ENTER("create_full_part_field_array");
if (!part_info->is_sub_partitioned())
@@ -578,6 +580,35 @@ static bool create_full_part_field_array(TABLE *table,
part_info->full_part_field_array= field_array;
part_info->no_full_part_fields= no_part_fields;
}
+
+ /*
+ Initialize the set of all fields used in partition and subpartition
+ expression. Required for testing of partition fields in write_set
+ when updating. We need to set all bits in read_set because the row
+ may need to be inserted in a different [sub]partition.
+ */
+ if (!(bitmap_buf= (my_bitmap_map*)
+ thd->alloc(bitmap_buffer_size(table->s->fields))))
+ {
+ mem_alloc_error(bitmap_buffer_size(table->s->fields));
+ result= TRUE;
+ goto end;
+ }
+ if (bitmap_init(&part_info->full_part_field_set, bitmap_buf,
+ table->s->fields, FALSE))
+ {
+ mem_alloc_error(table->s->fields);
+ result= TRUE;
+ goto end;
+ }
+ /*
+ full_part_field_array may be NULL if storage engine supports native
+ partitioning.
+ */
+ if ((ptr= part_info->full_part_field_array))
+ while (*ptr)
+ bitmap_set_bit(&part_info->full_part_field_set, (*ptr++)->field_index);
+
end:
DBUG_RETURN(result);
}
@@ -1636,7 +1667,7 @@ bool fix_partition_func(THD *thd, TABLE *table,
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
goto end;
}
- if (unlikely(create_full_part_field_array(table, part_info)))
+ if (unlikely(create_full_part_field_array(thd, table, part_info)))
goto end;
if (unlikely(check_primary_key(table)))
goto end;