summaryrefslogtreecommitdiff
path: root/sql/ha_partition.cc
diff options
context:
space:
mode:
authorKonstantin Osipov <kostja@sun.com>2010-02-06 13:28:06 +0300
committerKonstantin Osipov <kostja@sun.com>2010-02-06 13:28:06 +0300
commita72f90bc43a809e6678e1343a1ee760878061be3 (patch)
tree16fe2efa0a3d5e40e00972a1dc3bc4e13f71170c /sql/ha_partition.cc
parentba678eef7de4a8c5fbea07928b87fef84765f22b (diff)
parentb38ef2b5f7bc231b63b770c28688ee9f0109c88b (diff)
downloadmariadb-git-a72f90bc43a809e6678e1343a1ee760878061be3.tar.gz
Merge next-mr -> next-4284.
mysql-test/t/disabled.def: Restore disabled ssl tests: SSL certificates were updated. Disable sp_sync.test, the test case can't work in next-4284. mysql-test/t/partition_innodb.test: Disable parsing of the test case for Bug#47343, the test can not work in next-4284. mysql-test/t/ps_ddl.test: Update results (CREATE TABLE IF NOT EXISTS takes into account existence of the temporary table).
Diffstat (limited to 'sql/ha_partition.cc')
-rw-r--r--sql/ha_partition.cc207
1 files changed, 138 insertions, 69 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index d994c0bf4a5..3289b529edf 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -1272,17 +1272,28 @@ int ha_partition::prepare_new_partition(TABLE *tbl,
partition_element *p_elem)
{
int error;
- bool create_flag= FALSE;
DBUG_ENTER("prepare_new_partition");
if ((error= set_up_table_before_create(tbl, part_name, create_info,
0, p_elem)))
- goto error;
+ goto error_create;
if ((error= file->ha_create(part_name, tbl, create_info)))
- goto error;
- create_flag= TRUE;
+ {
+ /*
+ Added for safety, InnoDB reports HA_ERR_FOUND_DUPP_KEY
+ if the table/partition already exists.
+ If we return that error code, then print_error would try to
+ get_dup_key on a non-existing partition.
+ So return a more reasonable error code.
+ */
+ if (error == HA_ERR_FOUND_DUPP_KEY)
+ error= HA_ERR_TABLE_EXIST;
+ goto error_create;
+ }
+ DBUG_PRINT("info", ("partition %s created", part_name));
if ((error= file->ha_open(tbl, part_name, m_mode, m_open_test_lock)))
- goto error;
+ goto error_open;
+ DBUG_PRINT("info", ("partition %s opened", part_name));
/*
Note: if you plan to add another call that may return failure,
better to do it before external_lock() as cleanup_new_partition()
@@ -1290,12 +1301,15 @@ int ha_partition::prepare_new_partition(TABLE *tbl,
Otherwise see description for cleanup_new_partition().
*/
if ((error= file->ha_external_lock(ha_thd(), m_lock_type)))
- goto error;
+ goto error_external_lock;
+ DBUG_PRINT("info", ("partition %s external locked", part_name));
DBUG_RETURN(0);
-error:
- if (create_flag)
- (void) file->ha_delete_table(part_name);
+error_external_lock:
+ (void) file->close();
+error_open:
+ (void) file->ha_delete_table(part_name);
+error_create:
DBUG_RETURN(error);
}
@@ -1329,19 +1343,23 @@ error:
void ha_partition::cleanup_new_partition(uint part_count)
{
- handler **save_m_file= m_file;
DBUG_ENTER("ha_partition::cleanup_new_partition");
- if (m_added_file && m_added_file[0])
+ if (m_added_file)
{
- m_file= m_added_file;
- m_added_file= NULL;
+ THD *thd= ha_thd();
+ handler **file= m_added_file;
+ while ((part_count > 0) && (*file))
+ {
+ (*file)->ha_external_lock(thd, F_UNLCK);
+ (*file)->close();
- external_lock(ha_thd(), F_UNLCK);
- /* delete_table also needed, a bit more complex */
- close();
+ /* Leave the (*file)->ha_delete_table(part_name) to the ddl-log */
- m_file= save_m_file;
+ file++;
+ part_count--;
+ }
+ m_added_file= NULL;
}
DBUG_VOID_RETURN;
}
@@ -1647,7 +1665,15 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->part_state= PART_TO_BE_DROPPED;
}
m_new_file= new_file_array;
- DBUG_RETURN(copy_partitions(copied, deleted));
+ if ((error= copy_partitions(copied, deleted)))
+ {
+ /*
+ Close and unlock the new temporary partitions.
+ They will later be deleted through the ddl-log.
+ */
+ cleanup_new_partition(part_count);
+ }
+ DBUG_RETURN(error);
}
@@ -1736,6 +1762,7 @@ int ha_partition::copy_partitions(ulonglong * const copied,
}
DBUG_RETURN(FALSE);
error:
+ m_reorged_file[reorg_part]->ha_rnd_end();
DBUG_RETURN(result);
}
@@ -5916,6 +5943,23 @@ const key_map *ha_partition::keys_to_use_for_scanning()
DBUG_RETURN(m_file[0]->keys_to_use_for_scanning());
}
+#define MAX_PARTS_FOR_OPTIMIZER_CALLS 10
+/*
+ Prepare start variables for estimating optimizer costs.
+
+ @param[out] num_used_parts Number of partitions after pruning.
+ @param[out] check_min_num Number of partitions to call.
+ @param[out] first first used partition.
+*/
+void ha_partition::partitions_optimizer_call_preparations(uint *first,
+ uint *num_used_parts,
+ uint *check_min_num)
+{
+ *first= bitmap_get_first_set(&(m_part_info->used_partitions));
+ *num_used_parts= bitmap_bits_set(&(m_part_info->used_partitions));
+ *check_min_num= min(MAX_PARTS_FOR_OPTIMIZER_CALLS, *num_used_parts);
+}
+
/*
Return time for a scan of the table
@@ -5929,43 +5973,67 @@ const key_map *ha_partition::keys_to_use_for_scanning()
double ha_partition::scan_time()
{
- double scan_time= 0;
- handler **file;
+ double scan_time= 0.0;
+ uint first, part_id, num_used_parts, check_min_num, partitions_called= 0;
DBUG_ENTER("ha_partition::scan_time");
- for (file= m_file; *file; file++)
- if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file)))
- scan_time+= (*file)->scan_time();
+ partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num);
+ for (part_id= first; partitions_called < num_used_parts ; part_id++)
+ {
+ if (!bitmap_is_set(&(m_part_info->used_partitions), part_id))
+ continue;
+ scan_time+= m_file[part_id]->scan_time();
+ partitions_called++;
+ if (partitions_called >= check_min_num && scan_time != 0.0)
+ {
+ DBUG_RETURN(scan_time *
+ (double) num_used_parts / (double) partitions_called);
+ }
+ }
DBUG_RETURN(scan_time);
}
/*
- Get time to read
+ Estimate rows for records_in_range or estimate_rows_upper_bound.
- SYNOPSIS
- read_time()
- index Index number used
- ranges Number of ranges
- rows Number of rows
-
- RETURN VALUE
- time for read
+ @param is_records_in_range call records_in_range instead of
+ estimate_rows_upper_bound.
+ @param inx (only for records_in_range) index to use.
+ @param min_key (only for records_in_range) start of range.
+ @param max_key (only for records_in_range) end of range.
- DESCRIPTION
- This will be optimised later to include whether or not the index can
- be used with partitioning. To achieve we need to add another parameter
- that specifies how many of the index fields that are bound in the ranges.
- Possibly added as a new call to handlers.
+ @return Number of rows or HA_POS_ERROR.
*/
-
-double ha_partition::read_time(uint index, uint ranges, ha_rows rows)
+ha_rows ha_partition::estimate_rows(bool is_records_in_range, uint inx,
+ key_range *min_key, key_range *max_key)
{
- DBUG_ENTER("ha_partition::read_time");
+ ha_rows rows, estimated_rows= 0;
+ uint first, part_id, num_used_parts, check_min_num, partitions_called= 0;
+ DBUG_ENTER("ha_partition::records_in_range");
- DBUG_RETURN(m_file[0]->read_time(index, ranges, rows));
+ partitions_optimizer_call_preparations(&first, &num_used_parts, &check_min_num);
+ for (part_id= first; partitions_called < num_used_parts ; part_id++)
+ {
+ if (!bitmap_is_set(&(m_part_info->used_partitions), part_id))
+ continue;
+ if (is_records_in_range)
+ rows= m_file[part_id]->records_in_range(inx, min_key, max_key);
+ else
+ rows= m_file[part_id]->estimate_rows_upper_bound();
+ if (rows == HA_POS_ERROR)
+ DBUG_RETURN(HA_POS_ERROR);
+ estimated_rows+= rows;
+ partitions_called++;
+ if (partitions_called >= check_min_num && estimated_rows)
+ {
+ DBUG_RETURN(estimated_rows * num_used_parts / partitions_called);
+ }
+ }
+ DBUG_RETURN(estimated_rows);
}
+
/*
Find number of records in a range
@@ -5993,22 +6061,9 @@ double ha_partition::read_time(uint index, uint ranges, ha_rows rows)
ha_rows ha_partition::records_in_range(uint inx, key_range *min_key,
key_range *max_key)
{
- handler **file;
- ha_rows in_range= 0;
DBUG_ENTER("ha_partition::records_in_range");
- file= m_file;
- do
- {
- if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file)))
- {
- ha_rows tmp_in_range= (*file)->records_in_range(inx, min_key, max_key);
- if (tmp_in_range == HA_POS_ERROR)
- DBUG_RETURN(tmp_in_range);
- in_range+= tmp_in_range;
- }
- } while (*(++file));
- DBUG_RETURN(in_range);
+ DBUG_RETURN(estimate_rows(TRUE, inx, min_key, max_key));
}
@@ -6024,22 +6079,36 @@ ha_rows ha_partition::records_in_range(uint inx, key_range *min_key,
ha_rows ha_partition::estimate_rows_upper_bound()
{
- ha_rows rows, tot_rows= 0;
- handler **file;
DBUG_ENTER("ha_partition::estimate_rows_upper_bound");
- file= m_file;
- do
- {
- if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file)))
- {
- rows= (*file)->estimate_rows_upper_bound();
- if (rows == HA_POS_ERROR)
- DBUG_RETURN(HA_POS_ERROR);
- tot_rows+= rows;
- }
- } while (*(++file));
- DBUG_RETURN(tot_rows);
+ DBUG_RETURN(estimate_rows(FALSE, 0, NULL, NULL));
+}
+
+
+/*
+ Get time to read
+
+ SYNOPSIS
+ read_time()
+ index Index number used
+ ranges Number of ranges
+ rows Number of rows
+
+ RETURN VALUE
+ time for read
+
+ DESCRIPTION
+ This will be optimised later to include whether or not the index can
+ be used with partitioning. To achieve we need to add another parameter
+ that specifies how many of the index fields that are bound in the ranges.
+ Possibly added as a new call to handlers.
+*/
+
+double ha_partition::read_time(uint index, uint ranges, ha_rows rows)
+{
+ DBUG_ENTER("ha_partition::read_time");
+
+ DBUG_RETURN(m_file[0]->read_time(index, ranges, rows));
}