1
/* Copyright (C) 2000-2006 MySQL AB
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.
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.
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
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
21
Functions for easy reading of records, possible through a cache
24
#include "mysql_priv.h"
26
static int rr_quick(READ_RECORD *info);
27
int rr_sequential(READ_RECORD *info);
28
static int rr_from_tempfile(READ_RECORD *info);
29
static int rr_unpack_from_tempfile(READ_RECORD *info);
30
static int rr_unpack_from_buffer(READ_RECORD *info);
31
static int rr_from_pointers(READ_RECORD *info);
32
static int rr_from_cache(READ_RECORD *info);
33
static int init_rr_cache(THD *thd, READ_RECORD *info);
34
static int rr_cmp(uchar *a,uchar *b);
35
static int rr_index_first(READ_RECORD *info);
36
static int rr_index(READ_RECORD *info);
40
Initialize READ_RECORD structure to perform full index scan (in forward
41
direction) using read_record.read_record() interface.
43
This function has been added at late stage and is used only by
44
UPDATE/DELETE. Other statements perform index scans using
45
join_read_first/next functions.
47
@param info READ_RECORD structure to initialize.
48
@param thd Thread handle
49
@param table Table to be accessed
50
@param print_error If true, call table->file->print_error() if an error
51
occurs (except for end-of-records error)
52
@param idx index to scan
55
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
56
bool print_error, uint idx)
59
bzero((char*) info,sizeof(*info));
62
info->file= table->file;
63
info->record= table->record[0];
64
info->print_error= print_error;
65
info->unlock_row= rr_unlock_row;
67
table->status=0; /* And it's always found */
68
if (!table->file->inited)
69
table->file->ha_index_init(idx, 1);
70
/* read_record will be changed to rr_index in rr_index_first */
71
info->read_record= rr_index_first;
76
init_read_record is used to scan by using a number of different methods.
77
Which method to use is set-up in this call so that later calls to
78
the info->read_record will call the appropriate method using a function
81
There are five methods that relate completely to the sort function
82
filesort. The result of a filesort is retrieved using read_record
83
calls. The other two methods are used for normal table access.
85
The filesort will produce references to the records sorted, these
86
references can be stored in memory or in a temporary file.
88
The temporary file is normally used when the references doesn't fit into
89
a properly sized memory buffer. For most small queries the references
90
are stored in the memory buffer.
93
info OUT read structure
95
table Table the data [originally] comes from.
96
select SQL_SELECT structure. We may select->quick or
97
select->file as data source
98
use_record_cache Call file->extra_opt(HA_EXTRA_CACHE,...)
99
if we're going to do sequential read and some
100
additional conditions are satisfied.
101
print_error Copy this to info->print_error
102
disable_rr_cache Don't use rr_from_cache (used by sort-union
103
index-merge which produces rowid sequences that
107
This function sets up reading data via one of the methods:
109
The temporary file is also used when performing an update where a key is
112
Methods used when ref's are in memory (using rr_from_pointers):
113
rr_unpack_from_buffer:
114
----------------------
115
This method is used when table->sort.addon_field is allocated.
116
This is allocated for most SELECT queries not involving any BLOB's.
117
In this case the records are fetched from a memory buffer.
120
Used when the above is not true, UPDATE, DELETE and so forth and
121
SELECT's involving BLOB's. It is also used when the addon_field
122
buffer is not allocated due to that its size was bigger than the
123
session variable max_length_for_sort_data.
124
In this case the record data is fetched from the handler using the
125
saved reference using the rnd_pos handler call.
127
Methods used when ref's are in a temporary file (using rr_from_tempfile)
128
rr_unpack_from_tempfile:
129
------------------------
130
Same as rr_unpack_from_buffer except that references are fetched from
131
temporary file. Should obviously not really happen other than in
132
strange configurations.
136
Same as rr_from_pointers except that references are fetched from
137
temporary file instead of from
140
This is a special variant of rr_from_tempfile that can be used for
141
handlers that is not using the HA_FAST_KEY_READ table flag. Instead
142
of reading the references one by one from the temporary file it reads
143
a set of them, sorts them and reads all of them into a buffer which
144
is then used for a number of subsequent calls to rr_from_cache.
145
It is only used for SELECT queries and a number of other conditions
148
All other accesses use either index access methods (rr_quick) or a full
149
table scan (rr_sequential).
152
rr_quick uses one of the QUICK_SELECT classes in opt_range.cc to
153
perform an index scan. There are loads of functionality hidden
154
in these quick classes. It handles all index scans of various kinds.
157
This is the most basic access method of a table using rnd_init,
158
rnd_next and rnd_end. No indexes are used.
160
void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
162
int use_record_cache, bool print_error,
163
bool disable_rr_cache)
166
DBUG_ENTER("init_read_record");
168
bzero((char*) info,sizeof(*info));
171
info->file= table->file;
172
info->forms= &info->table; /* Only one table */
174
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE &&
175
!table->sort.addon_field)
176
VOID(table->file->extra(HA_EXTRA_MMAP));
178
if (table->sort.addon_field)
180
info->rec_buf= table->sort.addon_buf;
181
info->ref_length= table->sort.addon_length;
186
info->record= table->record[0];
187
info->ref_length= table->file->ref_length;
190
info->print_error=print_error;
191
info->unlock_row= rr_unlock_row;
192
info->ignore_not_found_rows= 0;
193
table->status=0; /* And it's always found */
195
if (select && my_b_inited(&select->file))
196
tempfile= &select->file;
198
tempfile= table->sort.io_cache;
199
if (tempfile && my_b_inited(tempfile)) // Test if ref-records was used
201
DBUG_PRINT("info",("using rr_from_tempfile"));
202
info->read_record= (table->sort.addon_field ?
203
rr_unpack_from_tempfile : rr_from_tempfile);
204
info->io_cache=tempfile;
205
reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
206
info->ref_pos=table->file->ref;
207
if (!table->file->inited)
208
table->file->ha_rnd_init(0);
211
table->sort.addon_field is checked because if we use addon fields,
212
it doesn't make sense to use cache - we don't read from the table
213
and table->sort.io_cache is read sequentially
215
if (!disable_rr_cache &&
216
!table->sort.addon_field &&
217
! (specialflag & SPECIAL_SAFE_MODE) &&
218
thd->variables.read_rnd_buff_size &&
219
!(table->file->ha_table_flags() & HA_FAST_KEY_READ) &&
220
(table->db_stat & HA_READ_ONLY ||
221
table->reginfo.lock_type <= TL_READ_NO_INSERT) &&
222
(ulonglong) table->s->reclength* (table->file->stats.records+
223
table->file->stats.deleted) >
224
(ulonglong) MIN_FILE_LENGTH_TO_USE_ROW_CACHE &&
225
info->io_cache->end_of_file/info->ref_length * table->s->reclength >
226
(my_off_t) MIN_ROWS_TO_USE_TABLE_CACHE &&
227
!table->s->blob_fields &&
228
info->ref_length <= MAX_REFLENGTH)
230
if (! init_rr_cache(thd, info))
232
DBUG_PRINT("info",("using rr_from_cache"));
233
info->read_record=rr_from_cache;
237
else if (select && select->quick)
239
DBUG_PRINT("info",("using rr_quick"));
240
info->read_record=rr_quick;
242
else if (table->sort.record_pointers)
244
DBUG_PRINT("info",("using record_pointers"));
245
table->file->ha_rnd_init(0);
246
info->cache_pos=table->sort.record_pointers;
247
info->cache_end=info->cache_pos+
248
table->sort.found_records*info->ref_length;
249
info->read_record= (table->sort.addon_field ?
250
rr_unpack_from_buffer : rr_from_pointers);
254
DBUG_PRINT("info",("using rr_sequential"));
255
info->read_record=rr_sequential;
256
table->file->ha_rnd_init(1);
257
/* We can use record cache if we don't update dynamic length tables */
258
if (!table->no_cache &&
259
(use_record_cache > 0 ||
260
(int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY ||
261
!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) ||
262
(use_record_cache < 0 &&
263
!(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE))))
264
VOID(table->file->extra_opt(HA_EXTRA_CACHE,
265
thd->variables.read_buff_size));
267
/* Condition pushdown to storage engine */
268
if (thd->variables.engine_condition_pushdown &&
269
select && select->cond &&
270
(select->cond->used_tables() & table->map) &&
271
!table->file->pushed_cond)
272
table->file->cond_push(select->cond);
275
} /* init_read_record */
279
void end_read_record(READ_RECORD *info)
280
{ /* free cache if used */
283
my_free_lock((char*) info->cache,MYF(0));
288
filesort_free_buffers(info->table,0);
289
(void) info->file->extra(HA_EXTRA_NO_CACHE);
290
if (info->read_record != rr_quick) // otherwise quick_range does it
291
(void) info->file->ha_index_or_rnd_end();
296
static int rr_handle_error(READ_RECORD *info, int error)
298
if (info->thd->killed)
300
info->thd->send_kill_message();
304
if (error == HA_ERR_END_OF_FILE)
308
if (info->print_error)
309
info->table->file->print_error(error, MYF(0));
310
if (error < 0) // Fix negative BDB errno
317
/** Read a record from head-database. */
319
static int rr_quick(READ_RECORD *info)
322
while ((tmp= info->select->quick->get_next()))
324
if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
326
tmp= rr_handle_error(info, tmp);
335
Reads first row in an index scan.
337
@param info Scan info
347
static int rr_index_first(READ_RECORD *info)
349
int tmp= info->file->index_first(info->record);
350
info->read_record= rr_index;
352
tmp= rr_handle_error(info, tmp);
358
Reads index sequentially after first row.
360
Read the next index record (in forward direction) and translate return
363
@param info Scan info
373
static int rr_index(READ_RECORD *info)
375
int tmp= info->file->index_next(info->record);
377
tmp= rr_handle_error(info, tmp);
382
int rr_sequential(READ_RECORD *info)
385
while ((tmp=info->file->rnd_next(info->record)))
388
rnd_next can return RECORD_DELETED for MyISAM when one thread is
389
reading and another deleting without locks.
391
if (info->thd->killed || (tmp != HA_ERR_RECORD_DELETED))
393
tmp= rr_handle_error(info, tmp);
401
static int rr_from_tempfile(READ_RECORD *info)
406
if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
407
return -1; /* End of file */
408
if (!(tmp=info->file->rnd_pos(info->record,info->ref_pos)))
410
/* The following is extremely unlikely to happen */
411
if (tmp == HA_ERR_RECORD_DELETED ||
412
(tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
414
tmp= rr_handle_error(info, tmp);
418
} /* rr_from_tempfile */
422
Read a result set record from a temporary file after sorting.
424
The function first reads the next sorted record from the temporary file.
425
into a buffer. If a success it calls a callback function that unpacks
426
the fields values use in the result set from this buffer into their
427
positions in the regular record buffer.
429
@param info Reference to the context including record descriptors
432
0 Record successfully read.
434
-1 There is no record to be read anymore.
437
static int rr_unpack_from_tempfile(READ_RECORD *info)
439
if (my_b_read(info->io_cache, info->rec_buf, info->ref_length))
441
TABLE *table= info->table;
442
(*table->sort.unpack)(table->sort.addon_field, info->rec_buf);
447
static int rr_from_pointers(READ_RECORD *info)
454
if (info->cache_pos == info->cache_end)
455
return -1; /* End of file */
456
cache_pos= info->cache_pos;
457
info->cache_pos+= info->ref_length;
459
if (!(tmp=info->file->rnd_pos(info->record,cache_pos)))
462
/* The following is extremely unlikely to happen */
463
if (tmp == HA_ERR_RECORD_DELETED ||
464
(tmp == HA_ERR_KEY_NOT_FOUND && info->ignore_not_found_rows))
466
tmp= rr_handle_error(info, tmp);
473
Read a result set record from a buffer after sorting.
475
The function first reads the next sorted record from the sort buffer.
476
If a success it calls a callback function that unpacks
477
the fields values use in the result set from this buffer into their
478
positions in the regular record buffer.
480
@param info Reference to the context including record descriptors
483
0 Record successfully read.
485
-1 There is no record to be read anymore.
488
static int rr_unpack_from_buffer(READ_RECORD *info)
490
if (info->cache_pos == info->cache_end)
491
return -1; /* End of buffer */
492
TABLE *table= info->table;
493
(*table->sort.unpack)(table->sort.addon_field, info->cache_pos);
494
info->cache_pos+= info->ref_length;
498
/* cacheing of records from a database */
500
static int init_rr_cache(THD *thd, READ_RECORD *info)
503
DBUG_ENTER("init_rr_cache");
505
info->struct_length= 3+MAX_REFLENGTH;
506
info->reclength= ALIGN_SIZE(info->table->s->reclength+1);
507
if (info->reclength < info->struct_length)
508
info->reclength= ALIGN_SIZE(info->struct_length);
510
info->error_offset= info->table->s->reclength;
511
info->cache_records= (thd->variables.read_rnd_buff_size /
512
(info->reclength+info->struct_length));
513
rec_cache_size= info->cache_records*info->reclength;
514
info->rec_cache_size= info->cache_records*info->ref_length;
516
// We have to allocate one more byte to use uint3korr (see comments for it)
517
if (info->cache_records <= 2 ||
518
!(info->cache=(uchar*) my_malloc_lock(rec_cache_size+info->cache_records*
519
info->struct_length+1,
523
// Avoid warnings in qsort
524
bzero(info->cache,rec_cache_size+info->cache_records* info->struct_length+1);
526
DBUG_PRINT("info",("Allocated buffert for %d records",info->cache_records));
527
info->read_positions=info->cache+rec_cache_size;
528
info->cache_pos=info->cache_end=info->cache;
530
} /* init_rr_cache */
533
static int rr_from_cache(READ_RECORD *info)
537
my_off_t rest_of_file;
539
uchar *position,*ref_position,*record_pos;
544
if (info->cache_pos != info->cache_end)
546
if (info->cache_pos[info->error_offset])
548
shortget(error,info->cache_pos);
549
if (info->print_error)
550
info->table->file->print_error(error,MYF(0));
555
memcpy(info->record,info->cache_pos,
556
(size_t) info->table->s->reclength);
558
info->cache_pos+=info->reclength;
559
return ((int) error);
561
length=info->rec_cache_size;
562
rest_of_file=info->io_cache->end_of_file - my_b_tell(info->io_cache);
563
if ((my_off_t) length > rest_of_file)
564
length= (ulong) rest_of_file;
565
if (!length || my_b_read(info->io_cache,info->cache,length))
567
DBUG_PRINT("info",("Found end of file"));
568
return -1; /* End of file */
571
length/=info->ref_length;
572
position=info->cache;
573
ref_position=info->read_positions;
574
for (i=0 ; i < length ; i++,position+=info->ref_length)
576
memcpy(ref_position,position,(size_t) info->ref_length);
577
ref_position+=MAX_REFLENGTH;
578
int3store(ref_position,(long) i);
581
my_qsort(info->read_positions, length, info->struct_length,
584
position=info->read_positions;
585
for (i=0 ; i < length ; i++)
587
memcpy(info->ref_pos,position,(size_t) info->ref_length);
588
position+=MAX_REFLENGTH;
589
record=uint3korr(position);
591
record_pos=info->cache+record*info->reclength;
592
if ((error=(int16) info->file->rnd_pos(record_pos,info->ref_pos)))
594
record_pos[info->error_offset]=1;
595
shortstore(record_pos,error);
596
DBUG_PRINT("error",("Got error: %d:%d when reading row",
600
record_pos[info->error_offset]=0;
602
info->cache_end=(info->cache_pos=info->cache)+length*info->reclength;
604
} /* rr_from_cache */
607
static int rr_cmp(uchar *a,uchar *b)
610
return (int) a[0] - (int) b[0];
612
return (int) a[1] - (int) b[1];
614
return (int) a[2] - (int) b[2];
615
#if MAX_REFLENGTH == 4
616
return (int) a[3] - (int) b[3];
619
return (int) a[3] - (int) b[3];
621
return (int) a[4] - (int) b[4];
623
return (int) a[1] - (int) b[5];
625
return (int) a[6] - (int) b[6];
626
return (int) a[7] - (int) b[7];