summaryrefslogtreecommitdiff
path: root/sql/opt_range.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r--sql/opt_range.cc348
1 files changed, 204 insertions, 144 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index ffaf3fad6c8..c905d8aada7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -822,6 +822,10 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
bool no_alloc, MEM_ROOT *parent_alloc)
:dont_free(0),error(0),free_file(0),in_range(0),cur_range(NULL),range(0)
{
+ my_bitmap_map *bitmap;
+ DBUG_ENTER("QUICK_RANGE_SELECT::QUICK_RANGE_SELECT");
+
+ in_ror_merged_scan= 0;
sorted= 0;
index= key_nr;
head= table;
@@ -845,6 +849,19 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
bzero((char*) &alloc,sizeof(alloc));
file= head->file;
record= head->record[0];
+ save_read_set= head->read_set;
+ save_write_set= head->write_set;
+
+ /* Allocate a bitmap for used columns */
+ if (!(bitmap= (my_bitmap_map*) my_malloc(head->s->column_bitmap_size,
+ MYF(MY_WME))))
+ {
+ column_bitmap.bitmap= 0;
+ error= 1;
+ }
+ else
+ bitmap_init(&column_bitmap, bitmap, head->s->fields, FALSE);
+ DBUG_VOID_RETURN;
}
@@ -874,24 +891,26 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
if (file)
{
range_end();
- file->extra(HA_EXTRA_NO_KEYREAD);
if (free_file)
{
DBUG_PRINT("info", ("Freeing separate handler %p (free=%d)", file,
free_file));
- file->ha_reset();
file->ha_external_lock(current_thd, F_UNLCK);
file->close();
delete file;
}
+ else
+ {
+ file->extra(HA_EXTRA_NO_KEYREAD);
+ }
}
delete_dynamic(&ranges); /* ranges are allocated in alloc */
free_root(&alloc,MYF(0));
+ my_free((char*) column_bitmap.bitmap, MYF(MY_ALLOW_ZERO_PTR));
}
- if (multi_range)
- my_free((char*) multi_range, MYF(0));
- if (multi_range_buff)
- my_free((char*) multi_range_buff, MYF(0));
+ head->column_bitmaps_set(save_read_set, save_write_set);
+ x_free(multi_range);
+ x_free(multi_range_buff);
DBUG_VOID_RETURN;
}
@@ -1011,20 +1030,21 @@ int QUICK_ROR_INTERSECT_SELECT::init()
int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
{
- handler *save_file= file;
+ handler *save_file= file, *org_file;
THD *thd;
+ MY_BITMAP *bitmap;
DBUG_ENTER("QUICK_RANGE_SELECT::init_ror_merged_scan");
+ in_ror_merged_scan= 1;
if (reuse_handler)
{
- DBUG_PRINT("info", ("Reusing handler %p", file));
- if (file->extra(HA_EXTRA_KEYREAD) ||
- file->ha_retrieve_all_pk() ||
- init() || reset())
+ DBUG_PRINT("info", ("Reusing handler 0x%lx", (long) file));
+ if (init() || reset())
{
DBUG_RETURN(1);
}
- DBUG_RETURN(0);
+ head->column_bitmaps_set(&column_bitmap, &column_bitmap);
+ goto end;
}
/* Create a separate handler object for this quick select */
@@ -1037,19 +1057,20 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
thd= head->in_use;
if (!(file= get_new_handler(head->s, thd->mem_root, head->s->db_type)))
goto failure;
- DBUG_PRINT("info", ("Allocated new handler %p", file));
+ DBUG_PRINT("info", ("Allocated new handler 0x%lx", (long) file));
if (file->ha_open(head, head->s->normalized_path.str, head->db_stat,
HA_OPEN_IGNORE_IF_LOCKED))
{
/* Caller will free the memory */
goto failure;
}
+
+ head->column_bitmaps_set(&column_bitmap, &column_bitmap);
+
if (file->ha_external_lock(thd, F_RDLCK))
goto failure;
- if (file->extra(HA_EXTRA_KEYREAD) ||
- file->ha_retrieve_all_pk() ||
- init() || reset())
+ if (init() || reset())
{
file->ha_external_lock(thd, F_UNLCK);
file->close();
@@ -1057,11 +1078,28 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
}
free_file= TRUE;
last_rowid= file->ref;
+
+end:
+ /*
+ We are only going to read key fields and call position() on 'file'
+ The following sets head->tmp_set to only use this key and then updates
+ head->read_set and head->write_set to use this bitmap.
+ The now bitmap is stored in 'column_bitmap' which is used in ::get_next()
+ */
+ org_file= head->file;
+ head->file= file;
+ /* We don't have to set 'head->keyread' here as the 'file' is unique */
+ head->mark_columns_used_by_index(index);
+ head->prepare_for_position();
+ head->file= org_file;
+ bitmap_copy(&column_bitmap, head->read_set);
+ head->column_bitmaps_set(&column_bitmap, &column_bitmap);
+
DBUG_RETURN(0);
failure:
- if (file)
- delete file;
+ head->column_bitmaps_set(save_read_set, save_write_set);
+ delete file;
file= save_file;
DBUG_RETURN(1);
}
@@ -1766,32 +1804,26 @@ public:
static int fill_used_fields_bitmap(PARAM *param)
{
TABLE *table= param->table;
- param->fields_bitmap_size= bitmap_buffer_size(table->s->fields+1);
- uint32 *tmp;
+ my_bitmap_map *tmp;
uint pk;
- if (!(tmp= (uint32*) alloc_root(param->mem_root,param->fields_bitmap_size)) ||
- bitmap_init(&param->needed_fields, tmp, param->fields_bitmap_size*8,
- FALSE))
+ param->fields_bitmap_size= table->s->column_bitmap_size;
+ if (!(tmp= (my_bitmap_map*) alloc_root(param->mem_root,
+ param->fields_bitmap_size)) ||
+ bitmap_init(&param->needed_fields, tmp, table->s->fields, FALSE))
return 1;
- bitmap_clear_all(&param->needed_fields);
- for (uint i= 0; i < table->s->fields; i++)
- {
- if (param->thd->query_id == table->field[i]->query_id)
- bitmap_set_bit(&param->needed_fields, i+1);
- }
+ bitmap_copy(&param->needed_fields, table->read_set);
+ bitmap_union(&param->needed_fields, table->write_set);
pk= param->table->s->primary_key;
- if (param->table->file->primary_key_is_clustered() && pk != MAX_KEY)
+ if (pk != MAX_KEY && param->table->file->primary_key_is_clustered())
{
/* The table uses clustered PK and it is not internally generated */
KEY_PART_INFO *key_part= param->table->key_info[pk].key_part;
KEY_PART_INFO *key_part_end= key_part +
param->table->key_info[pk].key_parts;
for (;key_part != key_part_end; ++key_part)
- {
- bitmap_clear_bit(&param->needed_fields, key_part->fieldnr);
- }
+ bitmap_clear_bit(&param->needed_fields, key_part->fieldnr-1);
}
return 0;
}
@@ -1843,7 +1875,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
keys_to_use.to_ulonglong(), (ulong) prev_tables,
(ulong) const_tables));
- DBUG_PRINT("info", ("records=%lu", (ulong)head->file->records));
+ DBUG_PRINT("info", ("records: %lu", (ulong) head->file->stats.records));
delete quick;
quick=0;
needed_reg.clear_all();
@@ -1853,7 +1885,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_RETURN(0); /* purecov: inspected */
if (keys_to_use.is_clear_all())
DBUG_RETURN(0);
- records= head->file->records;
+ records= head->file->stats.records;
if (!records)
records++; /* purecov: inspected */
scan_time= (double) records / TIME_FOR_COMPARE + 1;
@@ -1878,7 +1910,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
/* set up parameter that is passed to all functions */
param.thd= thd;
- param.baseflag=head->file->table_flags();
+ param.baseflag=head->file->ha_table_flags();
param.prev_tables=prev_tables | const_tables;
param.read_tables=read_tables;
param.current_table= head->map;
@@ -2296,6 +2328,7 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
PART_PRUNE_PARAM prune_param;
MEM_ROOT alloc;
RANGE_OPT_PARAM *range_par= &prune_param.range_param;
+ my_bitmap_map *old_read_set, *old_write_set;
prune_param.part_info= part_info;
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
@@ -2309,6 +2342,8 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
DBUG_RETURN(FALSE);
}
+ old_write_set= dbug_tmp_use_all_columns(table, table->write_set);
+ old_read_set= dbug_tmp_use_all_columns(table, table->read_set);
range_par->thd= thd;
range_par->table= table;
/* range_par->cond doesn't need initialization */
@@ -2398,6 +2433,8 @@ all_used:
retval= FALSE; // some partitions are used
mark_all_partitions_as_used(prune_param.part_info);
end:
+ dbug_tmp_restore_column_map(table->write_set, old_write_set);
+ dbug_tmp_restore_column_map(table->read_set, old_read_set);
thd->no_errors=0;
thd->mem_root= range_par->old_root;
free_root(&alloc,MYF(0)); // Return memory & allocator
@@ -2424,6 +2461,8 @@ end:
void store_key_image_to_rec(Field *field, char *ptr, uint len)
{
/* Do the same as print_key() does */
+ my_bitmap_map *old_map;
+
if (field->real_maybe_null())
{
if (*ptr)
@@ -2434,7 +2473,10 @@ void store_key_image_to_rec(Field *field, char *ptr, uint len)
field->set_notnull();
ptr++;
}
+ old_map= dbug_tmp_use_all_columns(field->table,
+ field->table->write_set);
field->set_key_image(ptr, len);
+ dbug_tmp_restore_column_map(field->table->write_set, old_map);
}
@@ -2514,11 +2556,11 @@ static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar,
{
MY_BITMAP all_merges;
uint bitmap_bytes;
- uint32 *bitmap_buf;
+ my_bitmap_map *bitmap_buf;
uint n_bits= ppar->part_info->used_partitions.n_bits;
bitmap_bytes= bitmap_buffer_size(n_bits);
- if (!(bitmap_buf= (uint32*)alloc_root(ppar->range_param.mem_root,
- bitmap_bytes)))
+ if (!(bitmap_buf= (my_bitmap_map*) alloc_root(ppar->range_param.mem_root,
+ bitmap_bytes)))
{
/*
Fallback, process just the first SEL_IMERGE. This can leave us with more
@@ -2764,7 +2806,8 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
uint32 subpart_id;
bitmap_clear_all(&ppar->subparts_bitmap);
- while ((subpart_id= subpart_iter.get_next(&subpart_iter)) != NOT_A_PARTITION_ID)
+ while ((subpart_id= subpart_iter.get_next(&subpart_iter)) !=
+ NOT_A_PARTITION_ID)
bitmap_set_bit(&ppar->subparts_bitmap, subpart_id);
/* Mark each partition as used in each subpartition. */
@@ -2870,7 +2913,8 @@ process_next_key_part:
/* Got "full range" for subpartitioning fields */
uint32 part_id;
bool found= FALSE;
- while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) != NOT_A_PARTITION_ID)
+ while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) !=
+ NOT_A_PARTITION_ID)
{
ppar->mark_full_partition_used(ppar->part_info, part_id);
found= TRUE;
@@ -3017,11 +3061,12 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
if (ppar->subpart_fields)
{
- uint32 *buf;
+ my_bitmap_map *buf;
uint32 bufsize= bitmap_buffer_size(ppar->part_info->no_subparts);
- if (!(buf= (uint32*)alloc_root(alloc, bufsize)))
+ if (!(buf= (my_bitmap_map*) alloc_root(alloc, bufsize)))
return TRUE;
- bitmap_init(&ppar->subparts_bitmap, buf, ppar->part_info->no_subparts, FALSE);
+ bitmap_init(&ppar->subparts_bitmap, buf, ppar->part_info->no_subparts,
+ FALSE);
}
range_par->key_parts= key_part;
Field **field= (ppar->part_fields)? part_info->part_field_array :
@@ -3188,7 +3233,8 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records)
else
{
double n_blocks=
- ceil(ulonglong2double(param->table->file->data_file_length) / IO_SIZE);
+ ceil(ulonglong2double(param->table->file->stats.data_file_length) /
+ IO_SIZE);
double busy_blocks=
n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(records)));
if (busy_blocks < 1.0)
@@ -3357,7 +3403,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
DBUG_PRINT("info", ("index_merge scans cost=%g", imerge_cost));
if (imerge_too_expensive || (imerge_cost > read_time) ||
- (non_cpk_scan_records+cpk_scan_records >= param->table->file->records) &&
+ (non_cpk_scan_records+cpk_scan_records >= param->table->file->stats.records) &&
read_time != DBL_MAX)
{
/*
@@ -3415,7 +3461,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
imerge_trp->read_cost= imerge_cost;
imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
imerge_trp->records= min(imerge_trp->records,
- param->table->file->records);
+ param->table->file->stats.records);
imerge_trp->range_scans= range_scans;
imerge_trp->range_scans_end= range_scans + n_child_scans;
read_time= imerge_cost;
@@ -3476,7 +3522,7 @@ skip_to_ror_scan:
((TRP_ROR_INTERSECT*)(*cur_roru_plan))->index_scan_costs;
roru_total_records += (*cur_roru_plan)->records;
roru_intersect_part *= (*cur_roru_plan)->records /
- param->table->file->records;
+ param->table->file->stats.records;
}
/*
@@ -3486,7 +3532,7 @@ skip_to_ror_scan:
in disjunction do not share key parts.
*/
roru_total_records -= (ha_rows)(roru_intersect_part*
- param->table->file->records);
+ param->table->file->stats.records);
/* ok, got a ROR read plan for each of the disjuncts
Calculate cost:
cost(index_union_scan(scan_1, ... scan_n)) =
@@ -3547,7 +3593,7 @@ static double get_index_only_read_time(const PARAM* param, ha_rows records,
int keynr)
{
double read_time;
- uint keys_per_block= (param->table->file->block_size/2/
+ uint keys_per_block= (param->table->file->stats.block_size/2/
(param->table->key_info[keynr].key_length+
param->table->file->ref_length) + 1);
read_time=((double) (records+keys_per_block-1)/
@@ -3599,7 +3645,7 @@ static
ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg)
{
ROR_SCAN_INFO *ror_scan;
- uint32 *bitmap_buf;
+ my_bitmap_map *bitmap_buf;
uint keynr;
DBUG_ENTER("make_ror_scan");
@@ -3614,12 +3660,12 @@ ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg)
ror_scan->sel_arg= sel_arg;
ror_scan->records= param->table->quick_rows[keynr];
- if (!(bitmap_buf= (uint32*)alloc_root(param->mem_root,
- param->fields_bitmap_size)))
+ if (!(bitmap_buf= (my_bitmap_map*) alloc_root(param->mem_root,
+ param->fields_bitmap_size)))
DBUG_RETURN(NULL);
if (bitmap_init(&ror_scan->covered_fields, bitmap_buf,
- param->fields_bitmap_size*8, FALSE))
+ param->table->s->fields, FALSE))
DBUG_RETURN(NULL);
bitmap_clear_all(&ror_scan->covered_fields);
@@ -3628,8 +3674,8 @@ ROR_SCAN_INFO *make_ror_scan(const PARAM *param, int idx, SEL_ARG *sel_arg)
param->table->key_info[keynr].key_parts;
for (;key_part != key_part_end; ++key_part)
{
- if (bitmap_is_set(&param->needed_fields, key_part->fieldnr))
- bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr);
+ if (bitmap_is_set(&param->needed_fields, key_part->fieldnr-1))
+ bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr-1);
}
ror_scan->index_read_cost=
get_index_only_read_time(param, param->table->quick_rows[ror_scan->keynr],
@@ -3729,21 +3775,21 @@ static
ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param)
{
ROR_INTERSECT_INFO *info;
- uint32* buf;
+ my_bitmap_map* buf;
if (!(info= (ROR_INTERSECT_INFO*)alloc_root(param->mem_root,
sizeof(ROR_INTERSECT_INFO))))
return NULL;
info->param= param;
- if (!(buf= (uint32*)alloc_root(param->mem_root,
- param->fields_bitmap_size)))
+ if (!(buf= (my_bitmap_map*) alloc_root(param->mem_root,
+ param->fields_bitmap_size)))
return NULL;
- if (bitmap_init(&info->covered_fields, buf, param->fields_bitmap_size*8,
+ if (bitmap_init(&info->covered_fields, buf, param->table->s->fields,
FALSE))
return NULL;
info->is_covering= FALSE;
info->index_scan_costs= 0.0;
info->index_records= 0;
- info->out_rows= param->table->file->records;
+ info->out_rows= param->table->file->stats.records;
bitmap_clear_all(&info->covered_fields);
return info;
}
@@ -3862,14 +3908,14 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
SEL_ARG *sel_arg, *tuple_arg= NULL;
bool cur_covered;
bool prev_covered= test(bitmap_is_set(&info->covered_fields,
- key_part->fieldnr));
+ key_part->fieldnr-1));
key_range min_range;
key_range max_range;
min_range.key= (byte*) key_val;
min_range.flag= HA_READ_KEY_EXACT;
max_range.key= (byte*) key_val;
max_range.flag= HA_READ_AFTER_KEY;
- ha_rows prev_records= info->param->table->file->records;
+ ha_rows prev_records= info->param->table->file->stats.records;
DBUG_ENTER("ror_intersect_selectivity");
for (sel_arg= scan->sel_arg; sel_arg;
@@ -3877,7 +3923,7 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info,
{
DBUG_PRINT("info",("sel_arg step"));
cur_covered= test(bitmap_is_set(&info->covered_fields,
- key_part[sel_arg->part].fieldnr));
+ key_part[sel_arg->part].fieldnr-1));
if (cur_covered != prev_covered)
{
/* create (part1val, ..., part{n-1}val) tuple. */
@@ -4006,15 +4052,15 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
}
info->total_cost= info->index_scan_costs;
- DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost));
+ DBUG_PRINT("info", ("info->total_cost: %g", info->total_cost));
if (!info->is_covering)
{
info->total_cost +=
get_sweep_read_cost(info->param, double2rows(info->out_rows));
DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost));
}
- DBUG_PRINT("info", ("New out_rows= %g", info->out_rows));
- DBUG_PRINT("info", ("New cost= %g, %scovering", info->total_cost,
+ DBUG_PRINT("info", ("New out_rows: %g", info->out_rows));
+ DBUG_PRINT("info", ("New cost: %g, %scovering", info->total_cost,
info->is_covering?"" : "non-"));
DBUG_RETURN(TRUE);
}
@@ -4093,7 +4139,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
double min_cost= DBL_MAX;
DBUG_ENTER("get_best_ror_intersect");
- if ((tree->n_ror_scans < 2) || !param->table->file->records)
+ if ((tree->n_ror_scans < 2) || !param->table->file->stats.records)
DBUG_RETURN(NULL);
/*
@@ -4262,7 +4308,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
F=set of all fields to cover
S={}
- do {
+ do
+ {
Order I by (#covered fields in F desc,
#components asc,
number of first not covered component asc);
@@ -4280,7 +4327,6 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
ROR_SCAN_INFO **ror_scan_mark;
ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end;
DBUG_ENTER("get_best_covering_ror_intersect");
- uint nbits= param->fields_bitmap_size*8;
for (ROR_SCAN_INFO **scan= tree->ror_scans; scan != ror_scans_end; ++scan)
(*scan)->key_components=
@@ -4294,9 +4340,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
/*I=set of all covering indexes */
ror_scan_mark= tree->ror_scans;
- uint32 int_buf[MAX_KEY/32+1];
+ my_bitmap_map int_buf[MAX_KEY/(sizeof(my_bitmap_map)*8)+1];
MY_BITMAP covered_fields;
- if (bitmap_init(&covered_fields, int_buf, nbits, FALSE))
+ if (bitmap_init(&covered_fields, int_buf, param->table->s->fields, FALSE))
DBUG_RETURN(0);
bitmap_clear_all(&covered_fields);
@@ -4545,7 +4591,8 @@ QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param,
if ((quick_intrsect=
new QUICK_ROR_INTERSECT_SELECT(param->thd, param->table,
- retrieve_full_rows? (!is_covering):FALSE,
+ (retrieve_full_rows? (!is_covering) :
+ FALSE),
parent_alloc)))
{
DBUG_EXECUTE("info", print_ror_scans_arr(param->table,
@@ -7218,7 +7265,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
goto err;
quick->records= records;
- if (cp_buffer_from_ref(thd,ref) && thd->is_fatal_error ||
+ if (cp_buffer_from_ref(thd, table, ref) && thd->is_fatal_error ||
!(range= new(alloc) QUICK_RANGE()))
goto err; // out of memory
@@ -7281,10 +7328,9 @@ err:
rowids into Unique, get the sorted sequence and destroy the Unique.
If table has a clustered primary key that covers all rows (TRUE for bdb
- and innodb currently) and one of the index_merge scans is a scan on PK,
- then
- rows that will be retrieved by PK scan are not put into Unique and
- primary key scan is not performed here, it is performed later separately.
+ and innodb currently) and one of the index_merge scans is a scan on PK,
+ then rows that will be retrieved by PK scan are not put into Unique and
+ primary key scan is not performed here, it is performed later separately.
RETURN
0 OK
@@ -7297,21 +7343,17 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
QUICK_RANGE_SELECT* cur_quick;
int result;
Unique *unique;
- DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::prepare_unique");
+ MY_BITMAP *save_read_set, *save_write_set;
+ handler *file= head->file;
+ DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::read_keys_and_merge");
/* We're going to just read rowids. */
- if (head->file->extra(HA_EXTRA_KEYREAD))
- DBUG_RETURN(1);
-
- /*
- Make innodb retrieve all PK member fields, so
- * ha_innobase::position (which uses them) call works.
- * We can filter out rows that will be retrieved by clustered PK.
- (This also creates a deficiency - it is possible that we will retrieve
- parts of key that are not used by current query at all.)
- */
- if (head->file->ha_retrieve_all_pk())
- DBUG_RETURN(1);
+ save_read_set= head->read_set;
+ save_write_set= head->write_set;
+ file->extra(HA_EXTRA_KEYREAD);
+ bitmap_clear_all(&head->tmp_set);
+ head->column_bitmaps_set(&head->tmp_set, &head->tmp_set);
+ head->prepare_for_position();
cur_quick_it.rewind();
cur_quick= cur_quick_it++;
@@ -7324,8 +7366,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
if (cur_quick->init() || cur_quick->reset())
DBUG_RETURN(1);
- unique= new Unique(refpos_order_cmp, (void *)head->file,
- head->file->ref_length,
+ unique= new Unique(refpos_order_cmp, (void *)file,
+ file->ref_length,
thd->variables.sortbuff_size);
if (!unique)
DBUG_RETURN(1);
@@ -7368,15 +7410,16 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
}
+ DBUG_PRINT("info", ("ok"));
/* ok, all row ids are in Unique */
result= unique->get(head);
delete unique;
doing_pk_scan= FALSE;
+ /* index_merge currently doesn't support "using index" at all */
+ file->extra(HA_EXTRA_NO_KEYREAD);
+ head->column_bitmaps_set(save_read_set, save_write_set);
/* start table scan */
init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1, 1);
- /* index_merge currently doesn't support "using index" at all */
- head->file->extra(HA_EXTRA_NO_KEYREAD);
-
DBUG_RETURN(result);
}
@@ -7398,9 +7441,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
if (doing_pk_scan)
DBUG_RETURN(pk_quick_select->get_next());
- result= read_record.read_record(&read_record);
-
- if (result == -1)
+ if ((result= read_record.read_record(&read_record)) == -1)
{
result= HA_ERR_END_OF_FILE;
end_read_record(&read_record);
@@ -7408,7 +7449,8 @@ int QUICK_INDEX_MERGE_SELECT::get_next()
if (pk_quick_select)
{
doing_pk_scan= TRUE;
- if ((result= pk_quick_select->init()) || (result= pk_quick_select->reset()))
+ if ((result= pk_quick_select->init()) ||
+ (result= pk_quick_select->reset()))
DBUG_RETURN(result);
DBUG_RETURN(pk_quick_select->get_next());
}
@@ -7450,16 +7492,12 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
{
/* Get a rowid for first quick and save it as a 'candidate' */
quick= quick_it++;
+ error= quick->get_next();
if (cpk_quick)
{
- do
- {
+ while (!error && !cpk_quick->row_in_ranges())
error= quick->get_next();
- }while (!error && !cpk_quick->row_in_ranges());
}
- else
- error= quick->get_next();
-
if (error)
DBUG_RETURN(error);
@@ -7505,7 +7543,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next()
}
}
- /* We get here iff we got the same row ref in all scans. */
+ /* We get here if we got the same row ref in all scans. */
if (need_to_fetch_row)
error= head->file->rnd_pos(head->record[0], last_rowid);
} while (error == HA_ERR_RECORD_DELETED);
@@ -7578,6 +7616,7 @@ int QUICK_ROR_UNION_SELECT::get_next()
DBUG_RETURN(error);
}
+
int QUICK_RANGE_SELECT::reset()
{
uint mrange_bufsiz;
@@ -7617,7 +7656,7 @@ int QUICK_RANGE_SELECT::reset()
}
/* Allocate the handler buffer if necessary. */
- if (file->table_flags() & HA_NEED_READ_RANGE_BUFFER)
+ if (file->ha_table_flags() & HA_NEED_READ_RANGE_BUFFER)
{
mrange_bufsiz= min(multi_range_bufsiz,
(QUICK_SELECT_I::records + 1)* head->s->reclength);
@@ -7682,6 +7721,15 @@ int QUICK_RANGE_SELECT::get_next()
(cur_range >= (QUICK_RANGE**) ranges.buffer) &&
(cur_range <= (QUICK_RANGE**) ranges.buffer + ranges.elements));
+ if (in_ror_merged_scan)
+ {
+ /*
+ We don't need to signal the bitmap change as the bitmap is always the
+ same for this head->file
+ */
+ head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
+ }
+
for (;;)
{
if (in_range)
@@ -7689,10 +7737,7 @@ int QUICK_RANGE_SELECT::get_next()
/* We did already start to read this key. */
result= file->read_multi_range_next(&mrange);
if (result != HA_ERR_END_OF_FILE)
- {
- in_range= ! result;
- DBUG_RETURN(result);
- }
+ goto end;
}
uint count= min(multi_range_length, ranges.elements -
@@ -7701,6 +7746,8 @@ int QUICK_RANGE_SELECT::get_next()
{
/* Ranges have already been used up before. None is left for read. */
in_range= FALSE;
+ if (in_ror_merged_scan)
+ head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
DBUG_RETURN(HA_ERR_END_OF_FILE);
}
KEY_MULTI_RANGE *mrange_slot, *mrange_end;
@@ -7732,12 +7779,18 @@ int QUICK_RANGE_SELECT::get_next()
result= file->read_multi_range_first(&mrange, multi_range, count,
sorted, multi_range_buff);
if (result != HA_ERR_END_OF_FILE)
- {
- in_range= ! result;
- DBUG_RETURN(result);
- }
+ goto end;
in_range= FALSE; /* No matching rows; go to next set of ranges. */
}
+
+end:
+ in_range= ! result;
+ if (in_ror_merged_scan)
+ {
+ /* Restore bitmaps set on entry */
+ head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
+ }
+ DBUG_RETURN(result);
}
@@ -7914,7 +7967,7 @@ bool QUICK_RANGE_SELECT::row_in_ranges()
QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q,
uint used_key_parts)
- : QUICK_RANGE_SELECT(*q), rev_it(rev_ranges)
+ :QUICK_RANGE_SELECT(*q), rev_it(rev_ranges)
{
QUICK_RANGE *r;
@@ -8390,9 +8443,10 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
groups, and thus can be applied after the grouping.
GA4. There are no expressions among G_i, just direct column references.
NGA1.If in the index I there is a gap between the last GROUP attribute G_k,
- and the MIN/MAX attribute C, then NGA must consist of exactly the index
- attributes that constitute the gap. As a result there is a permutation
- of NGA that coincides with the gap in the index <B_1, ..., B_m>.
+ and the MIN/MAX attribute C, then NGA must consist of exactly the
+ index attributes that constitute the gap. As a result there is a
+ permutation of NGA that coincides with the gap in the index
+ <B_1, ..., B_m>.
NGA2.If BA <> {}, then the WHERE clause must contain a conjunction EQ of
equality conditions for all NG_i of the form (NG_i = const) or
(const = NG_i), such that each NG_i is referenced in exactly one
@@ -8400,9 +8454,10 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
gap in the index.
WA1. There are no other attributes in the WHERE clause except the ones
referenced in predicates RNG, PA, PC, EQ defined above. Therefore
- WA is subset of (GA union NGA union C) for GA,NGA,C that pass the above
- tests. By transitivity then it also follows that each WA_i participates
- in the index I (if this was already tested for GA, NGA and C).
+ WA is subset of (GA union NGA union C) for GA,NGA,C that pass the
+ above tests. By transitivity then it also follows that each WA_i
+ participates in the index I (if this was already tested for GA, NGA
+ and C).
C) Overall query form:
SELECT EXPR([A_1,...,A_k], [B_1,...,B_m], [MIN(C)], [MAX(C)])
@@ -8464,12 +8519,12 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
TABLE *table= param->table;
bool have_min= FALSE; /* TRUE if there is a MIN function. */
bool have_max= FALSE; /* TRUE if there is a MAX function. */
- Item_field *min_max_arg_item= NULL;/* The argument of all MIN/MAX functions.*/
+ Item_field *min_max_arg_item= NULL; // The argument of all MIN/MAX functions
KEY_PART_INFO *min_max_arg_part= NULL; /* The corresponding keypart. */
uint group_prefix_len= 0; /* Length (in bytes) of the key prefix. */
KEY *index_info= NULL; /* The index chosen for data access. */
uint index= 0; /* The id of the chosen index. */
- uint group_key_parts= 0; /* Number of index key parts in the group prefix. */
+ uint group_key_parts= 0; // Number of index key parts in the group prefix.
uint used_key_parts= 0; /* Number of index key parts used for access. */
byte key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
uint key_infix_len= 0; /* Length of key_infix. */
@@ -8587,28 +8642,19 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
we check that all query fields are indeed covered by 'cur_index'.
*/
if (pk < MAX_KEY && cur_index != pk &&
- (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
+ (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
{
/* For each table field */
for (uint i= 0; i < table->s->fields; i++)
{
Field *cur_field= table->field[i];
/*
- If the field is used in the current query, check that the
- field is covered by some keypart of the current index.
+ If the field is used in the current query ensure that it's
+ part of 'cur_index'
*/
- if (thd->query_id == cur_field->query_id)
- {
- KEY_PART_INFO *key_part= cur_index_info->key_part;
- KEY_PART_INFO *key_part_end= key_part + cur_index_info->key_parts;
- for (;;)
- {
- if (key_part->field == cur_field)
- break;
- if (++key_part == key_part_end)
- goto next_index; // Field was not part of key
- }
- }
+ if (bitmap_is_set(table->read_set, cur_field->field_index) &&
+ !cur_field->part_of_key_not_clustered.is_set(cur_index))
+ goto next_index; // Field was not part of key
}
}
@@ -8762,7 +8808,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
key_part_range[1]= last_part;
/* Check if cur_part is referenced in the WHERE clause. */
- if (join->conds->walk(&Item::find_item_in_field_list_processor,
+ if (join->conds->walk(&Item::find_item_in_field_list_processor, 0,
(byte*) key_part_range))
goto next_index;
}
@@ -8776,7 +8822,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
{
for (cur_part= first_non_infix_part; cur_part != last_part; cur_part++)
{
- if (cur_part->field->query_id == thd->query_id)
+ if (bitmap_is_set(table->read_set, cur_part->field->field_index))
goto next_index;
}
}
@@ -9240,8 +9286,8 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
double cpu_cost= 0; /* TODO: CPU cost of index_read calls? */
DBUG_ENTER("cost_group_min_max");
- table_records= table->file->records;
- keys_per_block= (table->file->block_size / 2 /
+ table_records= table->file->stats.records;
+ keys_per_block= (table->file->stats.block_size / 2 /
(index_info->key_length + table->file->ref_length)
+ 1);
num_blocks= (table_records / keys_per_block) + 1;
@@ -10414,6 +10460,10 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
const char *key_end= key+used_length;
String tmp(buff,sizeof(buff),&my_charset_bin);
uint store_length;
+ TABLE *table= key_part->field->table;
+ my_bitmap_map *old_write_set, *old_read_set;
+ old_write_set= dbug_tmp_use_all_columns(table, table->write_set);
+ old_read_set= dbug_tmp_use_all_columns(table, table->read_set);
for (; key < key_end; key+=store_length, key_part++)
{
@@ -10439,18 +10489,28 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
if (key+store_length < key_end)
fputc('/',DBUG_FILE);
}
+ dbug_tmp_restore_column_map(table->write_set, old_write_set);
+ dbug_tmp_restore_column_map(table->read_set, old_read_set);
}
static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg)
{
char buf[MAX_KEY/8+1];
+ TABLE *table;
+ my_bitmap_map *old_read_map, *old_write_map;
DBUG_ENTER("print_quick");
if (!quick)
DBUG_VOID_RETURN;
DBUG_LOCK_FILE;
+ table= quick->head;
+ old_read_map= dbug_tmp_use_all_columns(table, table->read_set);
+ old_write_map= dbug_tmp_use_all_columns(table, table->write_set);
quick->dbug_dump(0, TRUE);
+ dbug_tmp_restore_column_map(table->read_set, old_read_map);
+ dbug_tmp_restore_column_map(table->write_set, old_write_map);
+
fprintf(DBUG_FILE,"other_keys: 0x%s:\n", needed_reg->print(buf));
DBUG_UNLOCK_FILE;