28 #include "opt_range.h"
29 #include "sql_class.h"
36 static int rr_unpack_from_tempfile(
READ_RECORD *info);
37 static int rr_unpack_from_buffer(
READ_RECORD *info);
40 static int init_rr_cache(THD *thd,
READ_RECORD *info);
68 bool print_error, uint idx,
bool reverse)
72 memset(info, 0,
sizeof(*info));
75 info->record= table->record[0];
76 info->print_error= print_error;
80 if (!table->file->inited &&
89 info->read_record= reverse ? rr_index_last : rr_index_first;
184 int use_record_cache,
bool print_error,
185 bool disable_rr_cache)
189 DBUG_ENTER(
"init_read_record");
191 memset(info, 0,
sizeof(*info));
194 info->forms= &info->table;
196 if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
197 !table->sort.addon_field)
198 (void) table->file->extra(HA_EXTRA_MMAP);
200 if (table->sort.addon_field)
202 info->rec_buf= table->sort.addon_buf;
203 info->ref_length= table->sort.addon_length;
208 info->record= table->record[0];
212 info->print_error=print_error;
214 info->ignore_not_found_rows= 0;
217 if (select && my_b_inited(&select->file))
218 tempfile= &select->file;
219 else if (select && select->quick && select->quick->clustered_pk_range())
229 tempfile= table->sort.io_cache;
230 if (tempfile && my_b_inited(tempfile))
232 DBUG_PRINT(
"info",(
"using rr_from_tempfile"));
233 info->read_record= (table->sort.addon_field ?
234 rr_unpack_from_tempfile : rr_from_tempfile);
235 info->io_cache=tempfile;
236 reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
237 info->ref_pos=table->file->ref;
238 if (!table->file->inited &&
247 if (!disable_rr_cache &&
248 !table->sort.addon_field &&
249 thd->variables.read_rnd_buff_size &&
251 (table->db_stat & HA_READ_ONLY ||
252 table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
253 (ulonglong) table->s->reclength* (table->file->stats.records+
254 table->file->stats.deleted) >
255 (ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
256 info->io_cache->end_of_file/info->ref_length * table->s->reclength >
257 (my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
258 !table->s->blob_fields &&
259 info->ref_length <= MAX_REFLENGTH)
261 if (init_rr_cache(thd, info))
263 DBUG_PRINT(
"info",(
"using rr_from_cache"));
264 info->read_record=rr_from_cache;
267 else if (select && select->quick)
269 DBUG_PRINT(
"info",(
"using rr_quick"));
270 info->read_record=rr_quick;
272 else if (table->sort.record_pointers)
274 DBUG_PRINT(
"info",(
"using record_pointers"));
277 info->cache_pos=table->sort.record_pointers;
278 info->cache_end=info->cache_pos+
279 table->sort.found_records*info->ref_length;
280 info->read_record= (table->sort.addon_field ?
281 rr_unpack_from_buffer : rr_from_pointers);
285 DBUG_PRINT(
"info",(
"using rr_sequential"));
286 info->read_record=rr_sequential;
290 if (!table->no_cache &&
291 (use_record_cache > 0 ||
292 (
int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
293 !(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
294 (use_record_cache < 0 &&
296 (void) table->file->extra_opt(HA_EXTRA_CACHE,
297 thd->variables.read_buff_size);
304 if (thd->optimizer_switch_flag(OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) &&
305 select && select->cond &&
306 (select->cond->used_tables() & table->map) &&
307 !table->file->pushed_cond)
324 my_free_lock(info->cache);
327 if (info->table && info->table->
key_read)
329 info->table->set_keyread(FALSE);
333 filesort_free_buffers(info->table,0);
334 (void) info->table->file->extra(HA_EXTRA_NO_CACHE);
335 if (info->read_record != rr_quick)
336 (void) info->table->file->ha_index_or_rnd_end();
341 static int rr_handle_error(
READ_RECORD *info,
int error)
343 if (info->thd->killed)
345 info->thd->send_kill_message();
349 if (error == HA_ERR_END_OF_FILE)
353 if (info->print_error)
367 while ((tmp= info->select->quick->get_next()))
369 if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
371 tmp= rr_handle_error(info, tmp);
395 info->read_record= rr_index;
397 tmp= rr_handle_error(info, tmp);
418 info->read_record= rr_index_desc;
420 tmp= rr_handle_error(info, tmp);
445 tmp= rr_handle_error(info, tmp);
470 tmp= rr_handle_error(info, tmp);
478 while ((tmp=info->table->file->
ha_rnd_next(info->record)))
484 if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
486 tmp= rr_handle_error(info, tmp);
499 if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
501 if (!(tmp=info->table->file->
ha_rnd_pos(info->record,info->ref_pos)))
504 if (tmp == HA_ERR_RECORD_DELETED ||
505 (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
507 tmp= rr_handle_error(info, tmp);
530 static int rr_unpack_from_tempfile(
READ_RECORD *info)
532 if (my_b_read(info->io_cache, info->rec_buf, info->ref_length))
534 TABLE *table= info->table;
535 (*table->sort.unpack)(table->sort.addon_field, info->rec_buf);
547 if (info->cache_pos == info->cache_end)
549 cache_pos= info->cache_pos;
550 info->cache_pos+= info->ref_length;
552 if (!(tmp=info->table->file->
ha_rnd_pos(info->record,cache_pos)))
556 if (tmp == HA_ERR_RECORD_DELETED ||
557 (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
559 tmp= rr_handle_error(info, tmp);
581 static int rr_unpack_from_buffer(
READ_RECORD *info)
583 if (info->cache_pos == info->cache_end)
585 TABLE *table= info->table;
586 (*table->sort.unpack)(table->sort.addon_field, info->cache_pos);
587 info->cache_pos+= info->ref_length;
593 static int init_rr_cache(THD *thd,
READ_RECORD *info)
596 DBUG_ENTER(
"init_rr_cache");
598 info->struct_length= 3+MAX_REFLENGTH;
599 info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
600 if (info->reclength < info->struct_length)
601 info->reclength= ALIGN_SIZE(info->struct_length);
603 info->error_offset= info->table->s->reclength;
604 info->cache_records= (thd->variables.read_rnd_buff_size /
605 (info->reclength+info->struct_length));
606 rec_cache_size= info->cache_records*info->reclength;
607 info->rec_cache_size= info->cache_records*info->ref_length;
610 if (info->cache_records <= 2 ||
611 !(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records*
612 info->struct_length+1,
616 DBUG_PRINT(
"info",(
"Allocated buffert for %d records",info->cache_records));
617 info->read_positions=info->cache+rec_cache_size;
618 info->cache_pos=info->cache_end=info->cache;
623 static int rr_cmp(
const void *p_ref_length,
const void *a,
const void *b)
625 size_t ref_length= *(
static_cast<size_t*
>(
const_cast<void*
>(p_ref_length)));
626 DBUG_ASSERT(ref_length <= MAX_REFLENGTH);
627 return memcmp(a, b, ref_length);
635 my_off_t rest_of_file;
637 uchar *position,*ref_position,*record_pos;
642 if (info->cache_pos != info->cache_end)
644 if (info->cache_pos[info->error_offset])
646 shortget(error,info->cache_pos);
647 if (info->print_error)
653 memcpy(info->record,info->cache_pos,
654 (
size_t) info->table->s->reclength);
656 info->cache_pos+=info->reclength;
657 return ((
int) error);
659 length=info->rec_cache_size;
660 rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
661 if ((my_off_t) length > rest_of_file)
662 length= (ulong) rest_of_file;
663 if (!length || my_b_read(info->io_cache,info->cache,length))
665 DBUG_PRINT(
"info",(
"Found end of file"));
669 length/=info->ref_length;
670 position=info->cache;
671 ref_position=info->read_positions;
672 for (i=0 ; i < length ; i++,position+=info->ref_length)
674 memcpy(ref_position,position,(
size_t) info->ref_length);
675 ref_position+=MAX_REFLENGTH;
676 int3store(ref_position,(
long) i);
679 size_t ref_length= info->ref_length;
680 my_qsort2(info->read_positions, length, info->struct_length,
681 rr_cmp, &ref_length);
683 position=info->read_positions;
684 for (i=0 ; i < length ; i++)
686 memcpy(info->ref_pos,position,(
size_t) info->ref_length);
687 position+=MAX_REFLENGTH;
688 record=uint3korr(position);
690 record_pos=info->cache+record*info->reclength;
691 error= (int16) info->table->file->
ha_rnd_pos(record_pos, info->ref_pos);
694 record_pos[info->error_offset]=1;
695 shortstore(record_pos,error);
696 DBUG_PRINT(
"error",(
"Got error: %d:%d when reading row",
697 my_errno, (
int) error));
700 record_pos[info->error_offset]=0;
702 info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
715 info->table->file->unlock_row();