MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
records.cc
Go to the documentation of this file.
1 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
23 #include "records.h"
24 #include "sql_priv.h"
25 #include "records.h"
26 #include "sql_list.h"
27 #include "filesort.h" // filesort_free_buffers
28 #include "opt_range.h" // SQL_SELECT
29 #include "sql_class.h" // THD
30 #include "sql_select.h" // JOIN_TAB
31 
32 
33 static int rr_quick(READ_RECORD *info);
34 int rr_sequential(READ_RECORD *info);
35 static int rr_from_tempfile(READ_RECORD *info);
36 static int rr_unpack_from_tempfile(READ_RECORD *info);
37 static int rr_unpack_from_buffer(READ_RECORD *info);
38 static int rr_from_pointers(READ_RECORD *info);
39 static int rr_from_cache(READ_RECORD *info);
40 static int init_rr_cache(THD *thd, READ_RECORD *info);
41 static int rr_index_first(READ_RECORD *info);
42 static int rr_index_last(READ_RECORD *info);
43 static int rr_index(READ_RECORD *info);
44 static int rr_index_desc(READ_RECORD *info);
45 
46 
68  bool print_error, uint idx, bool reverse)
69 {
70  int error;
71  empty_record(table);
72  memset(info, 0, sizeof(*info));
73  info->thd= thd;
74  info->table= table;
75  info->record= table->record[0];
76  info->print_error= print_error;
77  info->unlock_row= rr_unlock_row;
78 
79  table->status=0; /* And it's always found */
80  if (!table->file->inited &&
81  (error= table->file->ha_index_init(idx, 1)))
82  {
83  if (print_error)
84  table->file->print_error(error, MYF(0));
85  return true;
86  }
87 
88  /* read_record will be changed to rr_index in rr_index_first */
89  info->read_record= reverse ? rr_index_last : rr_index_first;
90  return false;
91 }
92 
93 
94 /*
95  init_read_record is used to scan by using a number of different methods.
96  Which method to use is set-up in this call so that later calls to
97  the info->read_record will call the appropriate method using a function
98  pointer.
99 
100  There are five methods that relate completely to the sort function
101  filesort. The result of a filesort is retrieved using read_record
102  calls. The other two methods are used for normal table access.
103 
104  The filesort will produce references to the records sorted, these
105  references can be stored in memory or in a temporary file.
106 
107  The temporary file is normally used when the references doesn't fit into
108  a properly sized memory buffer. For most small queries the references
109  are stored in the memory buffer.
110  SYNOPSIS
111  init_read_record()
112  info OUT read structure
113  thd Thread handle
114  table Table the data [originally] comes from.
115  select SQL_SELECT structure. We may select->quick or
116  select->file as data source
117  use_record_cache Call file->extra_opt(HA_EXTRA_CACHE,...)
118  if we're going to do sequential read and some
119  additional conditions are satisfied.
120  print_error Copy this to info->print_error
121  disable_rr_cache Don't use rr_from_cache (used by sort-union
122  index-merge which produces rowid sequences that
123  are already ordered)
124 
125  DESCRIPTION
126  This function sets up reading data via one of the methods:
127 
128  The temporary file is also used when performing an update where a key is
129  modified.
130 
131  Methods used when ref's are in memory (using rr_from_pointers):
132  rr_unpack_from_buffer:
133  ----------------------
134  This method is used when table->sort.addon_field is allocated.
135  This is allocated for most SELECT queries not involving any BLOB's.
136  In this case the records are fetched from a memory buffer.
137  rr_from_pointers:
138  -----------------
139  Used when the above is not true, UPDATE, DELETE and so forth and
140  SELECT's involving BLOB's. It is also used when the addon_field
141  buffer is not allocated due to that its size was bigger than the
142  session variable max_length_for_sort_data.
143  In this case the record data is fetched from the handler using the
144  saved reference using the rnd_pos handler call.
145 
146  Methods used when ref's are in a temporary file (using rr_from_tempfile)
147  rr_unpack_from_tempfile:
148  ------------------------
149  Same as rr_unpack_from_buffer except that references are fetched from
150  temporary file. Should obviously not really happen other than in
151  strange configurations.
152 
153  rr_from_tempfile:
154  -----------------
155  Same as rr_from_pointers except that references are fetched from
156  temporary file instead of from
157  rr_from_cache:
158  --------------
159  This is a special variant of rr_from_tempfile that can be used for
160  handlers that is not using the HA_FAST_KEY_READ table flag. Instead
161  of reading the references one by one from the temporary file it reads
162  a set of them, sorts them and reads all of them into a buffer which
163  is then used for a number of subsequent calls to rr_from_cache.
164  It is only used for SELECT queries and a number of other conditions
165  on table size.
166 
167  All other accesses use either index access methods (rr_quick) or a full
168  table scan (rr_sequential).
169  rr_quick:
170  ---------
171  rr_quick uses one of the QUICK_SELECT classes in opt_range.cc to
172  perform an index scan. There are loads of functionality hidden
173  in these quick classes. It handles all index scans of various kinds.
174  rr_sequential:
175  --------------
176  This is the most basic access method of a table using rnd_init,
177  ha_rnd_next and rnd_end. No indexes are used.
178 
179  @retval true error
180  @retval false success
181 */
182 bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
183  SQL_SELECT *select,
184  int use_record_cache, bool print_error,
185  bool disable_rr_cache)
186 {
187  int error= 0;
188  IO_CACHE *tempfile;
189  DBUG_ENTER("init_read_record");
190 
191  memset(info, 0, sizeof(*info));
192  info->thd=thd;
193  info->table=table;
194  info->forms= &info->table; /* Only one table */
195 
196  if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
197  !table->sort.addon_field)
198  (void) table->file->extra(HA_EXTRA_MMAP);
199 
200  if (table->sort.addon_field)
201  {
202  info->rec_buf= table->sort.addon_buf;
203  info->ref_length= table->sort.addon_length;
204  }
205  else
206  {
207  empty_record(table);
208  info->record= table->record[0];
209  info->ref_length= table->file->ref_length;
210  }
211  info->select=select;
212  info->print_error=print_error;
213  info->unlock_row= rr_unlock_row;
214  info->ignore_not_found_rows= 0;
215  table->status=0; /* And it's always found */
216 
217  if (select && my_b_inited(&select->file))
218  tempfile= &select->file;
219  else if (select && select->quick && select->quick->clustered_pk_range())
220  {
221  /*
222  In case of QUICK_INDEX_MERGE_SELECT with clustered pk range we have to
223  use its own access method(i.e QUICK_INDEX_MERGE_SELECT::get_next()) as
224  sort file does not contain rowids which satisfy clustered pk range.
225  */
226  tempfile= 0;
227  }
228  else
229  tempfile= table->sort.io_cache;
230  if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
231  {
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 &&
239  (error= table->file->ha_rnd_init(0)))
240  goto err;
241 
242  /*
243  table->sort.addon_field is checked because if we use addon fields,
244  it doesn't make sense to use cache - we don't read from the table
245  and table->sort.io_cache is read sequentially
246  */
247  if (!disable_rr_cache &&
248  !table->sort.addon_field &&
249  thd->variables.read_rnd_buff_size &&
250  !(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
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)
260  {
261  if (init_rr_cache(thd, info))
262  DBUG_RETURN(true);
263  DBUG_PRINT("info",("using rr_from_cache"));
264  info->read_record=rr_from_cache;
265  }
266  }
267  else if (select && select->quick)
268  {
269  DBUG_PRINT("info",("using rr_quick"));
270  info->read_record=rr_quick;
271  }
272  else if (table->sort.record_pointers)
273  {
274  DBUG_PRINT("info",("using record_pointers"));
275  if ((error= table->file->ha_rnd_init(0)))
276  goto err;
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);
282  }
283  else
284  {
285  DBUG_PRINT("info",("using rr_sequential"));
286  info->read_record=rr_sequential;
287  if ((error= table->file->ha_rnd_init(1)))
288  goto err;
289  /* We can use record cache if we don't update dynamic length tables */
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 &&
295  !(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
296  (void) table->file->extra_opt(HA_EXTRA_CACHE,
297  thd->variables.read_buff_size);
298  }
299  /*
300  Do condition pushdown for UPDATE/DELETE.
301  TODO: Remove this from here as it causes two condition pushdown calls
302  when we're running a SELECT and the condition cannot be pushed down.
303  */
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)
308  table->file->cond_push(select->cond);
309 
310  DBUG_RETURN(false);
311 
312 err:
313  if (print_error)
314  table->file->print_error(error, MYF(0));
315  DBUG_RETURN(true);
316 } /* init_read_record */
317 
318 
319 
320 void end_read_record(READ_RECORD *info)
321 { /* free cache if used */
322  if (info->cache)
323  {
324  my_free_lock(info->cache);
325  info->cache=0;
326  }
327  if (info->table && info->table->key_read)
328  {
329  info->table->set_keyread(FALSE);
330  }
331  if (info->table && info->table->is_created())
332  {
333  filesort_free_buffers(info->table,0);
334  (void) info->table->file->extra(HA_EXTRA_NO_CACHE);
335  if (info->read_record != rr_quick) // otherwise quick_range does it
336  (void) info->table->file->ha_index_or_rnd_end();
337  info->table=0;
338  }
339 }
340 
341 static int rr_handle_error(READ_RECORD *info, int error)
342 {
343  if (info->thd->killed)
344  {
345  info->thd->send_kill_message();
346  return 1;
347  }
348 
349  if (error == HA_ERR_END_OF_FILE)
350  error= -1;
351  else
352  {
353  if (info->print_error)
354  info->table->file->print_error(error, MYF(0));
355  if (error < 0) // Fix negative BDB errno
356  error= 1;
357  }
358  return error;
359 }
360 
361 
364 static int rr_quick(READ_RECORD *info)
365 {
366  int tmp;
367  while ((tmp= info->select->quick->get_next()))
368  {
369  if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
370  {
371  tmp= rr_handle_error(info, tmp);
372  break;
373  }
374  }
375  return tmp;
376 }
377 
378 
392 static int rr_index_first(READ_RECORD *info)
393 {
394  int tmp= info->table->file->ha_index_first(info->record);
395  info->read_record= rr_index;
396  if (tmp)
397  tmp= rr_handle_error(info, tmp);
398  return tmp;
399 }
400 
401 
415 static int rr_index_last(READ_RECORD *info)
416 {
417  int tmp= info->table->file->ha_index_last(info->record);
418  info->read_record= rr_index_desc;
419  if (tmp)
420  tmp= rr_handle_error(info, tmp);
421  return tmp;
422 }
423 
424 
441 static int rr_index(READ_RECORD *info)
442 {
443  int tmp= info->table->file->ha_index_next(info->record);
444  if (tmp)
445  tmp= rr_handle_error(info, tmp);
446  return tmp;
447 }
448 
449 
466 static int rr_index_desc(READ_RECORD *info)
467 {
468  int tmp= info->table->file->ha_index_prev(info->record);
469  if (tmp)
470  tmp= rr_handle_error(info, tmp);
471  return tmp;
472 }
473 
474 
475 int rr_sequential(READ_RECORD *info)
476 {
477  int tmp;
478  while ((tmp=info->table->file->ha_rnd_next(info->record)))
479  {
480  /*
481  ha_rnd_next can return RECORD_DELETED for MyISAM when one thread is
482  reading and another deleting without locks.
483  */
484  if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
485  {
486  tmp= rr_handle_error(info, tmp);
487  break;
488  }
489  }
490  return tmp;
491 }
492 
493 
494 static int rr_from_tempfile(READ_RECORD *info)
495 {
496  int tmp;
497  for (;;)
498  {
499  if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
500  return -1; /* End of file */
501  if (!(tmp=info->table->file->ha_rnd_pos(info->record,info->ref_pos)))
502  break;
503  /* The following is extremely unlikely to happen */
504  if (tmp == HA_ERR_RECORD_DELETED ||
505  (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
506  continue;
507  tmp= rr_handle_error(info, tmp);
508  break;
509  }
510  return tmp;
511 } /* rr_from_tempfile */
512 
513 
530 static int rr_unpack_from_tempfile(READ_RECORD *info)
531 {
532  if (my_b_read(info->io_cache, info->rec_buf, info->ref_length))
533  return -1;
534  TABLE *table= info->table;
535  (*table->sort.unpack)(table->sort.addon_field, info->rec_buf);
536 
537  return 0;
538 }
539 
540 static int rr_from_pointers(READ_RECORD *info)
541 {
542  int tmp;
543  uchar *cache_pos;
544 
545  for (;;)
546  {
547  if (info->cache_pos == info->cache_end)
548  return -1; /* End of file */
549  cache_pos= info->cache_pos;
550  info->cache_pos+= info->ref_length;
551 
552  if (!(tmp=info->table->file->ha_rnd_pos(info->record,cache_pos)))
553  break;
554 
555  /* The following is extremely unlikely to happen */
556  if (tmp == HA_ERR_RECORD_DELETED ||
557  (tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
558  continue;
559  tmp= rr_handle_error(info, tmp);
560  break;
561  }
562  return tmp;
563 }
564 
581 static int rr_unpack_from_buffer(READ_RECORD *info)
582 {
583  if (info->cache_pos == info->cache_end)
584  return -1; /* End of buffer */
585  TABLE *table= info->table;
586  (*table->sort.unpack)(table->sort.addon_field, info->cache_pos);
587  info->cache_pos+= info->ref_length;
588 
589  return 0;
590 }
591  /* cacheing of records from a database */
592 
593 static int init_rr_cache(THD *thd, READ_RECORD *info)
594 {
595  uint rec_cache_size;
596  DBUG_ENTER("init_rr_cache");
597 
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);
602 
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;
608 
609  // We have to allocate one more byte to use uint3korr (see comments for it)
610  if (info->cache_records <= 2 ||
611  !(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records*
612  info->struct_length+1,
613  MYF(0))))
614  DBUG_RETURN(1);
615 
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;
619  DBUG_RETURN(0);
620 } /* init_rr_cache */
621 
622 
623 static int rr_cmp(const void *p_ref_length, const void *a, const void *b)
624 {
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);
628 }
629 
630 
631 static int rr_from_cache(READ_RECORD *info)
632 {
633  reg1 uint i;
634  ulong length;
635  my_off_t rest_of_file;
636  int16 error;
637  uchar *position,*ref_position,*record_pos;
638  ulong record;
639 
640  for (;;)
641  {
642  if (info->cache_pos != info->cache_end)
643  {
644  if (info->cache_pos[info->error_offset])
645  {
646  shortget(error,info->cache_pos);
647  if (info->print_error)
648  info->table->file->print_error(error,MYF(0));
649  }
650  else
651  {
652  error=0;
653  memcpy(info->record,info->cache_pos,
654  (size_t) info->table->s->reclength);
655  }
656  info->cache_pos+=info->reclength;
657  return ((int) error);
658  }
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))
664  {
665  DBUG_PRINT("info",("Found end of file"));
666  return -1; /* End of file */
667  }
668 
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)
673  {
674  memcpy(ref_position,position,(size_t) info->ref_length);
675  ref_position+=MAX_REFLENGTH;
676  int3store(ref_position,(long) i);
677  ref_position+=3;
678  }
679  size_t ref_length= info->ref_length;
680  my_qsort2(info->read_positions, length, info->struct_length,
681  rr_cmp, &ref_length);
682 
683  position=info->read_positions;
684  for (i=0 ; i < length ; i++)
685  {
686  memcpy(info->ref_pos,position,(size_t) info->ref_length);
687  position+=MAX_REFLENGTH;
688  record=uint3korr(position);
689  position+=3;
690  record_pos=info->cache+record*info->reclength;
691  error= (int16) info->table->file->ha_rnd_pos(record_pos, info->ref_pos);
692  if (error)
693  {
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));
698  }
699  else
700  record_pos[info->error_offset]=0;
701  }
702  info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
703  }
704 } /* rr_from_cache */
705 
706 
713 {
714  READ_RECORD *info= &tab->read_record;
715  info->table->file->unlock_row();
716 }
717 
718